ADR 0300: Checkpoint observation is drained metadata, never a verdict
Status: accepted; fills the observation seam of ADR 0299 under the Logbook charter of ADR 0160, the follow-through framework of ADR 0207, the counting rules of ADR 0229 and ADR 0256, and the recommendation bar of ADR 0276
Context
§The checkpoint contract records judgments, but nothing recorded how the mechanism itself behaves: which checkpoints fire and how often, whether declarations follow relevant revisions or land on unchanged subjects, how long a question waits for its conclusion, which land under owner-authorized variances, and which open questions an effort simply ends on. Without that memory an owner cannot tell a checkpoint earning its tax from one taxing every change, and the external design review fixed the interpretive line early: a declaration on an unchanged subject does not prove rubber-stamping — the agent may have reviewed before invoking the gate — so the record must observe without judging.
Three constraints shaped where the record could live. The done and accept envelopes are published contracts, and the observation facts (reconcile outcomes, subject-revision flags, elapsed times) are Logbook material, not caller material. The refusal that serves a question — the firing moment — must record even though no gate ran. And the unmet rationale, durable Proof evidence, is prose that must never enter the metadata-only Logbook.
Decision
§One additive checkpoints block on the verb event carries the open question and variance lifecycle as metadata, collected where each fact becomes true and drained at the recording points; every reader of it observes checkpoint fit and none can gate anything.
- The vocabulary. Servings (
fired,reopened, andadvise— advise checkpoints have no open questions, so the serving itself is the record),declaredentries carrying the conclusion, the definition hash and subject fingerprint, arevisedflag, andelapsed_ms, plusvariancesandabandonedon the landing's event. Ids, outcomes, fingerprints, and timing only: no field for the rationale exists, so the metadata bar is structural. Older events without the block stay readable; readers censor what is missing. - Mechanical honesty for the unchanged/revised split.
revisedis true exactly when the declaring invocation's own reconciliation reopened the subject — a relevant in-scope revision separated the serving from the conclusion. Elapsed time runs from the serving the agent actually answered: on a same-invocation reopen, the replaced subject's serving time, whichreconcileEpisodenow reports. - Collection by accumulator, drain at the recording points. The gate pre-flight and the acceptance transition observe into a process-local accumulator (
result_capture.ts, beside the observed-result mailbox); the CLI wrapper and the MCP completion boundary drain it into the event (the drain-parity guard already forces every mailbox through those two recording points), and the recorder's fallback take clears any remainder. Both surfaces therefore record equivalently, refusals record their firings, and a refused landing observes no variance — the landing's observations are recorded only after the trunk transition completes. - The follow-through family is stream-walked, so checkpoints auto-enrol.
checkpoint-declaredeclares a new rule kind in the ADR 0207 framework: its follow-through episodes are enumerated per (branch, checkpoint id) from the recorded blocks rather than per delivered hint — a serving opens one, a reopen while pending folds into it, the resolving declaration'srevisedflag decides followed or not followed, and a missing block, missing flag, or history's end censors. Any checkpoint id that ever appears in observations is measured; no registry names checkpoints anywhere. - One economics reader, three consumers. A single tally (
checkpoint_economics.ts) feeds the practice-stats card, thecheckpointsverb's observed-history section, and the hygiene detectors, so the numbers cannot disagree. Rows are plain counts beside their denominators, bounded to the most-served 16 with the remainder counted — the wire scales with configuration, never history. - Hygiene advisories judge configuration, never agents.
checkpoint-dead(configured, never fired) andcheckpoint-noisy(served on ≥80% of efforts) count gate-run efforts since the newest recorded[checkpoints]config change — the epoch machinery's own attribution, so a revised definition earns fresh evidence — and speak only after 8;checkpoint-variedspeaks once at least 3 variance-carrying landed efforts where the checkpoint fired exist and they cover at least half of such landings. Each recommends reviewing the trigger, question, or mode, with its counts. - The boundary is a guard, not a convention. An import-graph test walks every checkpoint decision module (the package minus the always-ok
report.ts, plus the acceptance interlock) and fails if any path reaches the Logbook; black-box tests prove the rationale never lands in a Logbook byte while the same invocations serve it as Proof evidence.
Consequences
§- The owner's questions become answerable from counts: which checkpoints fire, on what share of efforts, how conclusions arrive, and which routinely need a variance — while no number claims anything about the agent's diligence.
- The verb-event schema gains one optional field for the life of the feature; every existing reader tolerates it, and every new reader must censor its absence.
- Abandonment is observed only where an effort observably ends (a completed landing). A worktree deleted by hand ends unobserved — accepted: the Logbook records verbs, and no verb ran.
- Advise servings record once per gate run, so their
firesmeasure served context, not distinct occasions; the per-effort share carries the deduplicated view. - The dead/noisy denominator resets on any
[checkpoints]edit, since the section hashes as one unit — conservative in the delaying direction.
Alternatives considered
§- Lift observations from the result envelopes by shape, like consent and landing state. Rejected: the facts (reconcile outcomes, revision flags, elapsed times) would have to join the published done/accept contracts first, growing caller-facing surface for reader-only material — and the accept envelope's variances carry the rationale, which a shape-lift would have to deliberately strip forever.
- Dedicated event kinds (
checkpoint-fired,checkpoint-declared, …). Rejected: the lifecycle is per-invocation context, exactly what the verb event exists to carry; new kinds would multiply the compatibility surface and orphan the begin/completion pairing. - Count a declaration on an unchanged subject as not-followed evidence of neglect. Rejected on the review's correction: the revision flag records what happened to the subject, not what the agent read; interpretation stays with the owner.
- Enrol checkpoints in follow-through by id, mirroring the hint-id tables. Rejected: a registry of checkpoint ids would let project-authored checkpoints escape measurement — the observation block already names every id.
- Let the noisy detector read live config thresholds to suggest exact replacement trigger values. Rejected under the recommendation bar: the counts justify a review, not a computed configuration change.