---
name: editor-quality-pass
title: "Editor Quality Pass — Heartbeat Substrate"
description: "Engine substrate scheduling the editor's heavy quality work (full lint with semantic phase + reflect for decision records + article consolidation). NOT injected into agent prompts — pure engine config."
category: _meta
status: active
---

## Purpose

The watcher fires structural lint after every compile (Option A — pure-engine,
no LLM, fast). That catches the deterministic 95% of the duplication +
orphan + broken-link surface.

The remaining 5% — semantic merge candidates, contradictions between
articles, decision records for structural changes, append-only-drift
consolidation — needs an LLM. Running it on every watcher cycle would
burn tokens on trivial single-file ingests. Running it only manually
means it never fires for users who don't remember to click the button.

This skill schedules the editor's heavy quality pass on a fixed cadence
via the heartbeat. Runs once per `cadence_hours` (default 24h),
non-blocking, surfaces results via activity events.

## Configuration

Lives in `config/schedule.yaml`. Tuning is a YAML edit + restart — no
Python changes (Rule 12).

```yaml
enabled: true
cadence_hours: 24      # how often the full editor pass fires
on_compile_threshold: 5  # also fire IF a compile pass produced N+ articles
                         # (0 = never trigger from compile, only from cadence)
include_consolidate: true   # also run kb-consolidate to merge drift articles
include_reflect: true       # also run kb-reflect to produce decision records
max_kbs_per_pass: 5         # cap KBs processed in one heartbeat cycle to avoid
                            # hour-long bursts on multi-KB vaults
per_kb_timeout_seconds: 180 # bound each KB's pass; partial completion is OK
```

## Triggering

- **Heartbeat cron**: every tick checks `cadence_hours` since last run.
  When elapsed, fires the full editor pass on every KB up to
  `max_kbs_per_pass`.
- **Compile burst**: if a single compile pass produces ≥
  `on_compile_threshold` articles, the watcher schedules the editor pass
  as a follow-up regardless of cadence (heavier batches deserve quality
  review immediately, not 24h later).
- **Manual**: `POST /api/kb/{slug}/job` (full `run_wiki_job`) or
  `POST /api/kb/{slug}/lint` always work — manual triggers bypass the
  cadence throttle.

## Rules

- ALWAYS skippable via YAML `enabled: false` — full kill-switch.
- NEVER blocks the heartbeat cycle — failures swallowed, next tick
  retries.
- Costs LLM tokens (Phase 2 semantic lint + reflect). Default cadence
  is conservative (24h) so a personal vault sees ~$0.10/day in editor
  work rather than $0.10/file.
- Output = activity events the user sees in the UI (`lint_completed`,
  `reflect_completed`, `consolidate_completed`). Plus decision records
  in `wiki/decisions/` when reflect surfaces structural decisions.
