core/docs/handoff/ARC-CLOSE-TEMPLATE.md
Claude 71bf04fb44
feat(provenance,teaching): close the lateral gaps the assessment actually found
Squashes the arc's work into one commit; the workflow-file edit it originally
carried is excluded (see the end of this message).

## Lane 1 — Workbench recorded a proved answer as ungrounded

With deduction_serving_enabled ratified ON (ADR-0256), workbench/api.py's live
chat route builds a bare ChatRuntime(), so the deduction composer decides
Workbench turns and stamps grounding_source="deduction" — but
_coerce_grounding_source carried a hand-copied whitelist of the six pre-arc
labels and silently rewrote anything else to "none". The runtime comment
reasoned this was inert because "REPL turns do not flow through Workbench's
CognitivePipelineRecord path". True, and irrelevant: the traffic flows the
other way. Stale since 2026-07-24.

Scope is one field. workbench/api.py:818 prefers TurnEvent.epistemic_state,
which read epistemic_state_needed — honest. So the UNregistered path degraded
honestly while the hand-copied whitelist asserted a falsehood; a second copy of
a closed enum was worse than no copy. Hence registration AND derivation:
GROUNDING_SOURCES exposes the Literal's members, and the coercion reads it.
workbench-ui badges/tokens/snapshot follow; enumCoverage.test.ts forces atomicity.

## Lane 2 — the ratification ceremony

The discovery loop was instrumented but not closed. teaching/ratification.py
turns a reviewed decision into a chain record, a corpus commit, and a receipt.

Its design turns on one observation: _ratified_rows DROPS unadmissible rows
silently — correct when serving, a trap when ratifying, because the file grows,
the commit lands, and the band count does not move. So the ceremony refuses to
call an append a ratification until it has re-read the curriculum through the
real loader and seen the chain arrive; a non-admitted append is rolled back.
Validation is a pre-flight courtesy, admission is the proof.

Arena queue entry and ledger reseal are deliberately NOT performed (bridge rule
1); the receipt names them. Front door: `core proposal-queue ratify`, a sibling
of `review` rather than a flag on it.

## Lane 3 — structural closures

- ADR-0263 gains rule 5: absence policy is DECLARED in CAPABILITY_LEDGERS, not
  passed at the call site. An AST-matched test fails if a serving path passes
  missing_ok again.
- Deductive suite added WHOLE to the pre-push gate: 285 tests in 29s against
  smoke's 216 in 62s, so no coverage trade was needed.
- Smoke/CI parity assertion made bidirectional. It was one-directional, and had
  drifted.
- test_prior_surface_deduction_binding.py pins correction binding on the
  deduction path. The review's diagnosis did NOT reproduce — hash_surface moves
  in lockstep — so it pins what is there. Mutation-checked.
- Domain-keyed ADR index over 312 flat-numbered files, explicitly partial.
- Arc-close brief template, plus this arc's own brief filled in against it.

## Lanes 4 and 5 — two premises falsified by measurement, one of them mine

Math 4.2: baseline reproduced (correct=5 wrong=0 refused=495); all four named
cases traced to one seam with each gap isolated by one-variable probes. Then the
number that changes the recommendation: the gap blocking case 0000 affects 1
case in 500, the 'than' gap blocking 0001 affects 2. ADR-0251's prohibition on
per-case growth now rests on a count. No reader change made.

CGA: versor_condition is 0.22% of a turn, not the "~10x proof latency" I claimed
— that multiplied an isolated microbenchmark by a call count and compared it to
a single verdict's latency. The real cost is geometric_product at 33,986
calls/turn (~73%) via cga_inner in search paths. The obvious closed form is NOT
bit-exact (954/4000 in f32); backend.vault_recall's serial fold IS (3000/3000,
worst-rel 0) and is the correct target. cargo test could not run —
static.crates.io is denied by the sandbox network policy — so the Rust parity
question stays open and the typestate lane is carried forward, not shipped
uncompiled.

## Not landed: three lines owed to .github/workflows/smoke.yml

The CI smoke gate is narrower than the local one —
test_pack_draft_serve_boundary.py (ADR-0253 INV-33) has been local-only, unseen
because the parity pin checked one direction. The edit was authored and rejected
at push for lacking the `workflow` OAuth scope, so it is recorded as a named,
dated PENDING_IN_CI exception rather than dropped: the assertion still fires on
any new divergence, and a second guard fires once the three land.

[Verification]: pre-push gates all green — smoke 236 passed, warmed_session 10
passed, deductive 285 passed. Ratification 14, ADR index 5, CLI suites 10.
Grounding/epistemic sweep 741 passed 1 skipped. workbench-ui 598 passed across
73 files, tsc -b clean. capability index 11 passed, digest unchanged. Math
holdout correct=5 wrong=0 refused=495. Committed chain corpora byte-unchanged
after the tests that write to them.
Environment caveat: the repo pins requires-python ==3.12.13, which uv cannot
fetch for linux-x86_64, so `uv sync --locked` fails. All Python runs used a
scratch venv on 3.12.11 with declared deps — not the locked universe, not the
full ~12k suite. The pin was left untouched. Re-run on a 3.12.13 host before
treating this as merge evidence.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FduW6Krm3PPQv3P5iwBYtx
2026-07-25 04:51:15 +00:00

4 KiB
Raw Blame History

Arc-Close Brief — TEMPLATE

Copy to docs/handoff/<arc-slug>/BRIEF-CLOSE-<arc-slug>.md when an arc ends. Delete every instruction block (>) as you fill it in.

Why this template exists

The handoff system is mature in one direction only. BRIEF-O / BRIEF-S are downward briefs: a planning tier telling an execution tier what to build. Nothing goes back up. When an arc closes, the tier that actually executed it holds the corrected ground truth — which assumptions were falsified, what the flag state now is, which "next steps" the measurements killed — and that knowledge currently survives only as commit messages and research docs, which the next arc's opener must reconstruct by re-reading every ADR from the arc's first number onward.

The generalization arc minted eight ADRs in roughly 48 hours. That is the cadence this template is sized for: an opener should be able to start scoping from this one file and reach for ADRs on demand, not as a prerequisite.

The single most important section is Falsified assumptions. A downward brief states a plan; an arc-close brief states which parts of that plan turned out to be wrong. That is the part which cannot be recovered from the diff.


Arc-Close Brief —

Arc: · Closed: · Closing tier: <Fable/Opus/Sonnet + risk tier> Plan of record: docs/plans/<plan>.md ADRs minted: <ADR-NNNN … ADR-NNNN>

1. What shipped

One line per landed capability, each naming its enforcement site. Not commit messages — capabilities. A reader should be able to tell what the system can now do that it could not before.

Capability ADR Enforcement site Evidence

2. Flag state at close

The single highest-value table here. Every flag the arc touched, its default now, and what ratified it. A flag flipped ON is a live capability whose test suite is a regression suite — say so.

Flag Default at close Ratified by Notes

3. Falsified assumptions

Do not skip this section. For each: what the plan assumed, what the measurement showed, and where the evidence lives. An assumption that was merely not reached is not falsified — say "untested" and mean it.

Plan assumed Measurement showed Evidence

4. Binding constraint going into the next arc

One paragraph. Not a list. If the next arc has one thing standing between it and progress, name it and quantify it. "Curriculum volume: every band is 24×73× short of the entailed-bucket floor" is a binding constraint; "we should improve coverage" is not.

5. Trigger state

For any phase the plan declared trigger-gated: is the trigger now met? Cite what met it. If met, say what the next tier must design before writing code — the design work that should land in a higher tier than the implementation.

6. What is NOT next, and why

The most expensive thing an opener can do is resume a thread the closing tier already killed. List the plausible-looking next steps that the arc's own evidence rules out, each with its reason. Be specific enough that someone cannot re-propose them without engaging the evidence.

7. Open items carried forward

Item Kind Where it is recorded
deferred / blocked / untested

8. Gates and their state at close

Local-first is the merge bar (AGENTS.md), so record what was actually run, with counts. "Green" without a count is not evidence.

Gate Command Result at close
smoke uv run core test --suite smoke -q
deductive uv run core test --suite deductive -q
lane pins

9. Ground truth corrections for the next opener

Free text. The things you would say out loud if you could brief the next session in person — including anything in the plan of record that is now stale. If a comment in the code reasons from a premise that has since changed, name the file and line: that is exactly the class of staleness nobody greps for.