Drift Check Cadence and Verdict
petrova intermediate 5 min read
ELI5
A drift check is the architectural smoke alarm. When the room smells weird but you can’t see the fire, you point the alarm at the room — it sniffs the rank graph and the anti-shape list and tells you whether the smell is benign, suspicious, or confirmed smoke.
Technical Deep Dive
Cadence — when to invoke
sequenceDiagram autonumber participant H as Human participant DW as drift-watcher (04-drift-check) participant NS as docs/north-star/intent.md participant M as MILESTONES.md participant P as Planner participant B as docs/backlog/frozen/
Note over H: trigger: PR / new milestone / new doc / a feeling H->>DW: paste 04-drift-check.md, name the surface alt human gave a feeling, not a surface DW->>H: "what's the most recent thing that made it feel off?" H-->>DW: walks back to a concrete artefact end DW->>NS: read intent.md, outranks: front-matter, drift_watches: DW->>DW: build implied rank DAG DW->>DW: identify which docs the change touches, rank inversion? DW->>NS: walk drift_watches: per anti-shape — pull observed? counter-anchor? DW->>M: cross-ref active phase / subphase DW->>DW: verdict: aligned | drift-suspected | drift-confirmed DW->>H: write docs/roles/auditor/outputs/drift-<DATE>-<slug>.md alt aligned DW-->>H: proceed else drift-suspected DW-->>H: human is the tiebreaker else drift-confirmed DW->>P: route for re-scope DW->>B: or file in backlog/frozen/ endThree triggers commonly fire 04-drift-check.md:
- A specific PR or proposed diff that doesn’t quite serve intent.
- A new milestone being scoped that pulls toward a named anti-shape.
- A doc that just landed and contradicts another.
The fourth — “a feeling I have I can’t articulate” — is legitimate. Step 1 of the prompt makes it concrete by walking back from “what’s the most recent thing that made it feel off?” until a file/commit/milestone-ID is named.
The five-step probe
- Get specific about the change (file path, milestone ID, commit, conversation excerpt).
- Read the rank graph — every doc’s
outranks:front-matter; build the implied DAG; identify which tiers the change touches and whether it inverts rank. - Walk the drift watches — per anti-shape in
docs/north-star/intent.md, ask: pull observed? counter-anchor? was it exercised? - Cross-reference active milestones — does the change belong to active subphase, future phase (defer), or no milestone (backlog or scope creep)?
- Produce the verdict at
docs/roles/auditor/outputs/drift-<TODAY_ISO>-<slug>.md.
Three verdicts
| Verdict | Meaning | Routing |
|---|---|---|
| aligned | serves intent + active phase, no counter-anchor needed beyond what’s exercised | proceed |
| drift-suspected | pull observed but unclear if counter-anchored | surface to human — the human is the tiebreaker; both aligned and drift-confirmed are easy, suspected is exactly when the human earns their seat |
| drift-confirmed | inverts a rank, pulls toward an unanchored anti-shape, or doesn’t belong to any milestone | route to planner for re-scope, or file in docs/backlog/frozen/ |
Indeterminacy is not a verdict. If the agent tries to refuse a verdict (because the change is genuinely architecturally novel), force drift-suspected and route to the human.
Active-milestone alignment
Step 4 produces three sub-verdicts:
- belongs to active milestone → aligned (assuming Step 3 cleared).
- belongs-future-phase → not drift, but should be deferred until that phase opens; surface this.
- scope-creep → doesn’t belong to any milestone; either backlog (frozen) or you’ve found drift.
The distinction between belongs-future-phase and scope-creep is load-bearing: future-phase items have a home; scope-creep items don’t, and trying to land them under the active phase is the most common drift pattern.
Refusal condition
The drift-watcher (AGENTS.xml.tmpl) has one refusal: the change touches surfaces in >3 phases at once. Stop and ask the planner to decompose. Cross-phase changes are how anti-shapes win silently.
When the same anti-shape keeps drifting
A repeated drift-confirmed against the same anti-shape means the anti-shape is winning. That’s a north-star revisit (potentially an MR-1 realignment), not a drift-watcher problem. Schedule the revisit; don’t keep refusing changes — eventually the team works around the watcher and the anti-shape wins anyway.
Key Terms
- Rank graph inversion — when a lower-tier doc (e.g. backlog) implicitly modifies a higher-tier doc (e.g. north-star). Always drift-confirmed.
- Counter-anchor — the code/process/doc that catches a named drift pull; without one, the pull is unanchored and drift-confirmed.
- drift-suspected — the verdict where the human, not the agent, is the right tiebreaker.
Q&A
Q: What three verdicts can a drift check return, and which is the human’s tiebreaker?
A: aligned, drift-suspected, drift-confirmed. drift-suspected is the human’s tiebreaker — aligned says proceed, drift-confirmed says stop, but suspected means the agent saw a pull and could not decide; the human resolves.
Q: Where does the drift-watcher write its verdict?
A: docs/roles/auditor/outputs/drift-<TODAY_ISO>-<slug>.md. Note: under the auditor’s outputs path, not the planner’s — the drift-watcher reports findings; the planner re-scopes.
Q: How is ‘belongs-future-phase’ different from ‘scope-creep’?
A: A future-phase item has a milestone home (it just hasn’t opened yet) — defer it; it isn’t drift. A scope-creep item belongs to no milestone — it either gets a backlog entry under docs/backlog/frozen/ or it gets refused. Trying to absorb scope-creep into the active phase is how anti-shapes silently win.
Examples
A PR adds a “user analytics dashboard” to KAHN. Drift-watcher Step 1 makes it concrete (PR #143). Step 2 finds the change touches frontend/, MILESTONES.md (no entry exists), and tries to import a metrics service from outside the active phase. Step 3 walks drift_watches: — finds a clear pull toward “treating KAHN as a CRUD product instead of an event log” with no counter-anchor exercised. Step 4 → scope-creep. Verdict: drift-confirmed. Recommended action: file in docs/backlog/frozen/user-analytics-dashboard.md with a link back to north-star intent.
neighbors on the map
- eva doctor Validation Rules diagnosing a doctor FAIL line
- Run Outcome Classification interpreting a History row's status pill
- Verifier & Verification Protocol diagnosing why verify_zk_proof returns Ok(false) for a proof that appears structurally valid