docs(runtime): keys.ts's catch annotation states its measured determination instead of promising a gate entry (#12981 batch 10b) - #15472
Conversation
…nation The annotation at the `handleKeysRequest` catch promised a `FAILURE_PROPAGATION_SITES` entry "in the step that widens DURABILITY_CRITICAL_CALLEES". That promise is falsified by the widening that was actually sanctioned: the seeder wrappers `tryInsert`/`tryUpdate` match no seam in this function, and the only name that would match is bare `insert`, which the swallow-family census refuses by design. An entry keyed `keys.ts::handleKeysRequest` would be stale on arrival. The note now states the measured truth instead: the catch delivers the failure to the caller on every path (measured with the gate's own `catchDeliversFailure()`), the determination is carried by the census's DETERMINED register row for `keys.ts::handleKeysRequest` -- which re-verifies on every run that the file exists, that the determination sentence is written at the site, and that the site is still a tier-1 DARK member, going STALE loudly otherwise -- and no gate entry is owed. Comment-only. The register's anchor sentence is byte-identical, the census reading is byte-identical, and the gate verdict is unchanged (29 seams, all loud, rethrowing or propagating). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
📓 Docs Drift Check1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run. What this run could not see
Coarse fallback — 24 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin e3eaad4008fc7b1fa008417b2d0c826384810597 && git checkout e3eaad4008fc7b1fa008417b2d0c826384810597
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin e8c7956c46c0e8abda9d259ce07ba5f64e072c47 0afa8ba3ee0722b6bdf511160e2576946555d444 && git checkout -B drift-repro e8c7956c46c0e8abda9d259ce07ba5f64e072c47 && git merge --no-ff 0afa8ba3ee0722b6bdf511160e2576946555d444
node scripts/docs-audit/affected-docs.mjs --json e8c7956c46c0e8abda9d259ce07ba5f64e072c47 |
|
ACCEPT — PM seat Reviewed against the three-dot diff Generated by Claude Code |
… landed (#15459, #15473) The census `scripts/measure-durability-swallow-family.mjs` is the #12981 programme's instrument of record. PR #15458 performed the handover it had reserved for the programme's last step (`tryInsert`/`tryUpdate` into the gate's `DURABILITY_CRITICAL_CALLEES`) and PR #15472 closed the programme; four statements in this file still described both as pending. - The header's "The handover" section is past tense and names PR #15458/#15472. - "an 18-entry vocabulary" is 20, the count the gate now declares. - `tryInsert`/`tryUpdate` move from `origin: 'seed-wrapper'` to `'gate-vocabulary'` in `WRITE_SHAPED_CALLEES`: after #15458 they ARE declared in the gate, and the OVERLAP reading has to say what the tree says. `tryDelete` was not part of the handover and stays `seed-wrapper`. - The `DETERMINED` row for `keys.ts::handleKeysRequest` no longer says the site is waiting for a declaration the #12981 ruling (Q1 = A) refused. Its `anchor`, `verdict`, `scope` and key are byte-identical. - The `SELF_TEST_MODES` gated-subset note stops calling the handover reserved. The by-value copy of the gate's vocabulary stays a copy — the header says why — but a by-value copy's failure mode is silence, which is what let this file go stale under a green farm. `readGateVocabulary()` parses the gate's own declaration (never imports it) and the `--self-test` cross-checks the copy against it in BOTH modes, with a negative leg proving the comparison can fire. It announces drift; it never absorbs it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
…nded handover (#15503) The tier-1 worklist's empty reading still announced the #12981 ruling's gate handover step as "unblocked" after PR #15458 performed it (`tryInsert` / `tryUpdate` declared in the gate's `DURABILITY_CRITICAL_CALLEES`) and PR #15472 closed the programme. It is the same future-tense-over-a-landed-step defect PR #15502 repaired four times in this file, surviving in the one place no run could contradict it: this tree reaches the row-per-file branch instead (tier 1 holds one outstanding member, `auth-manager.ts::verifyMcpAccessToken`, beside three DETERMINED rows), so the sentence has never been printed. The line is now past tense and names both PRs. So that the new wording is asserted rather than read, the worklist body moves into `worklistLines()` — a producer that takes its population as arguments — and `WORKLIST_READING_CONTROLS` pins all three readings BY VALUE, in both self-test modes: the two `(none …)` lines the tree cannot reach, plus a populated fixture that must print work and neither of them, which is what keeps the two pins from passing against a producer that ignored its population. The table is pinned to its own length first (#13799's floor recipe). The pins spell each line independently of the producer on purpose; comparing against a shared constant would pass whatever that constant said. The census's own reading over `packages/**` does not move: `--sites`, `--json` and the normal report are byte-identical against a checkout of the fork point. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Fixes #12981 — batch 10b, the closing half of batch 10, under the ruling Q1 = A (#12981 comment 5543738972). Batch 10a is PR #15458.
Why
The annotation at the
handleKeysRequestcatch inpackages/runtime/src/domains/keys.tspromised aFAILURE_PROPAGATION_SITESentry, keyedkeys.ts::handleKeysRequest, "in the step that widensDURABILITY_CRITICAL_CALLEES". That promise is falsified by the ruling's own instrument: the widening that was actually sanctioned adds the seeder wrapperstryInsert/tryUpdate, and neither matches a seam inhandleKeysRequest; the only name that would match is bareinsert, which the swallow-family census refuses by design (measured at 36 quiet degradations in 30 files). So an entry keyed at that site would not be early — it would be STALE on arrival, and the gate deletes entries that excuse nothing.What changed
One file, comment-only. The note now states the measured truth:
catchDeliversFailure(): with a matching vocabulary name present, every path out of this catch reachesdeps.error;packages/runtime/src/domains/keys.ts::handleKeysRequestinscripts/measure-durability-swallow-family.mjs, which re-verifies on every run that the file exists, that the determination sentence is still written at the site, and that the site is still a tier-1 DARK member — going STALE, loudly, otherwise. A gate entry would have proved the delivery alone;The register's anchor sentence —
[#12981] This catch is silent BY DESIGN and it is NOT a durability swallow.— is kept byte-identical; only the surrounding promise is rewritten. The "do not bolt on a log" instruction and thehttp-dispatcher.keys.test.tspin pointer are unchanged.The register row, before and after
Identical, which is the point —
diffof the two census readings exits 0:listed under
DETERMINED, not outstanding 3 site(s) in 3 file(s)before and after, with--self-testreporting3 DETERMINED register row(s) cross-check cleanon both sides.The row is proved live over the edited file, not merely still printed. Ablation on the committed tree: the anchor sentence was reworded on disk (
silent BY DESIGN→quiet ON PURPOSE; injected marker count 1, original 0, counted on disk before the run), and the census answeredthen the file was restored with
git checkout HEAD -- ABSOLUTE_PATHunder atrap ... EXIT INT TERM, proved by state: restored blob1408cfb21954547ac6a1c8bd5a0e889e258f5ca8equals the HEAD blob, andgit diff HEADfor that path is empty.Verification
All on the final commit
0afa8ba3e. Exit codes captured by redirecting first, then reading$?; verdicts quoted from each tool's own line.git diff -U0filtered to lines that are not//comments produces nothing. No code changed.pnpm check:durability-log-levelexit 0, verdict line unchanged before and after (whole outputdiffexits 0):29 durability-critical catch seam(s), all loud, rethrowing or propagating to the caller (4 propagating, declared).node scripts/measure-durability-swallow-family.mjsexit 0 before and after, reading byte-identical (diffexit 0);--self-testexit 0 both sides:4 positive control(s) ... 3 DETERMINED register row(s) cross-check clean, 56 member site(s) total.pnpm --filter @objectstack/runtime typecheckexit 0 (tsc --noEmitpluscheck:test-typecheck: OK), after building the dependency closure (pnpm --workspace-concurrency=2 --filter '@objectstack/runtime^...' build, exit 0 under the shared verify lock,VERDICT command-exit 0). A bare first attempt failed on unbuilt deps (TS2307), which reads exactly like a broken import.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(no paths passed; it read the change set itself) — 33 commands, every one run. 32 exit 0, includingcheck:nul-bytes.check:pm-dispatch-gatesis not in this card's family, so nothing was owed under the lock there.pnpm check:dual-build-cjs-loadsexits 3 —PREREQUISITE NOT MET — this gate reads built output, and some package has no dist/ ... ⛔ This is NOT a pass: nothing was measured.Its self-test passed (93 cases). A fullpnpm buildwas not run for a comment-only diff; CI measures it.pnpm lint(eslint . --no-inline-config) exit 0 — run in full, no narrowing, so no narrowing evidence is owed.grep -naPover the C0 range plus DEL): no hits.Changeset
skip-changeset: the diff is a comment in a published package (@objectstack/runtime) — no behaviour, no types, no exports, nothing to publish. Label applied on this PR by the additive endpoint and read back.🤖 Generated with Claude Code
https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Generated by Claude Code