Skip to content

fix(devx): the durability-log-level self-test handshake asserts "ran to the end", pass or fail - #15504

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-14962-durability-handshake-red-path
Sep 4, 2026
Merged

fix(devx): the durability-log-level self-test handshake asserts "ran to the end", pass or fail#15504
baozhoutao merged 1 commit into
mainfrom
claude/issue-14962-durability-handshake-red-path

Conversation

@claude

@claude claude Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Fixes #14962

The defect

selfTest() set selfTestReachedVerdict on its SUCCESS path only, and the dispatch read that
flag BETWEEN the two batteries. A genuine red therefore printed its own verdict line and was
then reported as selfTest() returned without reaching its verdict — false, the verdict had
just been printed — and the process exited before selfTestReadSeams() ran at all, which is
exactly what the comment one line above forbids ("a red one must not hide the other").

Exit 1 either way, so this was never a false green. The cost was a misleading diagnostic plus
half the self-test's coverage lost on the red path.

The option taken, and why

The card names two legitimate repairs. This PR takes the first: the handshake asserts
"ran to the end", pass or fail, and the returned status keeps carrying the verdict — per the
dispatching PM's ruling on this card.

Concretely:

  • selfTestReachedVerdict is now set at both of selfTest()'s verdict sites — the green
    N case(s) passed line and the red N failure(s) (cases and floor) line — each assignment
    placed adjacent to the line it certifies rather than once before the branch, so the flag
    can only be true if one of the two verdict lines was really printed;
  • readSeamsReachedVerdict gets the same treatment at its own two verdict sites;
  • the dispatch runs both batteries first and reads both handshakes after, then exits
    with the combined status (handshakeMissing || logLevelStatus || readSeamStatus).

Why this option rather than "each battery gets its own handshake, checked after both have run":
the two are not exclusive, and the second alone does not fix defect #1. Both flags already
existed, one per battery; moving the checks after both calls restores the lost coverage, but a
success-only flag would still print returned without reaching its verdict under a red battery
that plainly reached it. Only redefining what the handshake asserts removes the false
diagnostic, and the "check after both" half is folded in with it.

What the handshake was landed for is unchanged: an early return above either verdict still
trips that battery's own named diagnostic, and exits 1 — ablations (b) and (c) below.

scripts/check-dispatcher-error-vocabulary.mjs ships the same landed shape and is deliberately
untouched: its failure path calls process.exit(1) inside the self-test, so its flag is
never consulted on a red. The divergence is now written down beside this file's flag, so the
next author does not "harmonise" it back.

Ablations

All four run against the committed implementation (dfad2f273), each through one harness
that mutates, proves the mutation reached disk (a grep -c of the injected marker, refusing
to run at zero), runs, then restores under trap ... EXIT INT TERM and proves the restore by
git hash-object equality against the HEAD blob plus an empty git diff HEAD. Every run's
restore printed:

restore proven: hash-object=38738c52d483d9e1f11f1f2afe5b58a1b8f3a3c3 == HEAD blob; git diff HEAD empty

(a) force battery 1's failure branch (if (failures > 0) to >= 0 at selfTest's verdict,
one line, marker ABLATION-A-FORCED-RED, on-disk count 1):

mutation on disk: injected-text count=1  removed-text count=1
EXIT=1
line  65: ✗ self-test (log-level rule): 0 failure(s) (cases and floor)
line 125: ✓ self-test (read-seam invention rule): 57 case(s) passed, and the baseline offer stays marked maintainer-only (#8435)
occurrences of "returned without reaching its verdict": 0

Battery 2 ran and printed its own verdict; exit 1; no false handshake diagnostic. This is the
same probe that, on origin/main (4f85e4d) before the fix, produced the card's reading:

EXIT=1
line 65: ✗ self-test (log-level rule): 0 failure(s) (cases and floor)
line 68: ✗ check-durability-degradation-log-level self-test: selfTest() returned without reaching its verdict,
(no read-seam verdict line anywhere in the output)

(b) early return from selfTest() before its verdict (if (true) return 0; injected above
the floor check, marker ABLATION-B-EARLY-RETURN, on-disk count 1). return 0 deliberately, so
the only thing that can turn the run red is the handshake:

mutation on disk: injected-text count=1
EXIT=1
line 122: ✓ self-test (read-seam invention rule): 57 case(s) passed, ...
line 125: ✗ check-durability-degradation-log-level self-test: selfTest() returned without reaching its verdict,

(c) early return from selfTestReadSeams() before its verdict (same shape, marker
ABLATION-C-EARLY-RETURN, on-disk count 1):

mutation on disk: injected-text count=1
EXIT=1
line  65: ✓ self-test (log-level rule): 63 case(s) passed
line 125: ✗ check-durability-degradation-log-level self-test: selfTestReadSeams() returned without
line 126: reaching its verdict, so no success line was printed. Exiting 0 here would report a

(d) unmutated, both green:

EXIT=0
✓ self-test (log-level rule): 63 case(s) passed
✓ self-test (read-seam invention rule): 57 case(s) passed, and the baseline offer stays marked maintainer-only (#8435)

Verification

Every exit code captured by redirecting first (cmd > file 2>&1; EXIT=$?), never read after a
pipe. Union run on the final commit dfad2f273.

Command Exit Verdict line
pnpm check:durability-log-level (branch) 0 ✓ durability-degradation log levels: 29 durability-critical catch seam(s), all loud, ... and ✓ read-seam invention (#5186 + #6451 + #9165, 3 package roots, ...): 66 read seam(s), none invents an unreported answer ...
node scripts/check-durability-degradation-log-level.mjs --self-test (branch) 0 ✓ self-test (log-level rule): 63 case(s) passed · ✓ self-test (read-seam invention rule): 57 case(s) passed, ...
same two, on origin/main content (4f85e4d, pristine worktree before the edit) 0 / 0 identical lines; normal-mode output is byte-identicalcmp exit 0, md5 af1a04bcc31133437b711898fc946e69 both sides
node scripts/measure-durability-swallow-family.mjs 0 reading byte-identical before/after the change (cmp exit 0) — no vocabulary drift
node scripts/measure-durability-swallow-family.mjs --self-test=gated 0 ✓ measure-durability-swallow-family self-test, gated families (#13919): 3 negative control(s) yield none, 2 regression control(s) stay clear, 6 resolution control(s) resolve as declared, 3 DETERMINED register row(s) cross-check clean, 56 member site(s) total — byte-identical before/after
node scripts/measure-self-test-floor.mjs 0 measure-self-test-floor: 170 file(s) under scripts/ dispatch on --self-test. — output byte-identical before/after, and the roster still names scripts/check-durability-degradation-log-level.mjs
pnpm -s check:pm-dispatch-gates 0 ✓ dispatch-gates self-test: 1402 cases pass. (no case edited)
pnpm check:nul-bytes 0 check-nul-bytes: OK (scanned 7502 text file(s) ... no raw ASCII control bytes).
pnpm lint (repo-wide, eslint . --no-inline-config) 0 run under the shared verify lock: os-verify-lock: VERDICT command-exit 0 · held the lock 97s (1m37s) · waited 152s (2m32s)

The instrument comparisons above were taken by reverting the file to its HEAD blob, running each
instrument, then reapplying the diff — the reapplied file hashed back to
38738c52d483d9e1f11f1f2afe5b58a1b8f3a3c3, byte-for-byte the committed content.

Derived gate family. node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack
derived 25 commands from the committed change set (its own stderr: "gate list derived from the tree
of 'objectstack-ai/objectstack' at commit dfad2f2", change set "1 path(s) vs merge base 4f85e4d").
All 25 ran; all exited 0 — the table's rows plus check-reference-carrier-shape (+ self-test),
check-ci-filter-parity, check-closing-keyword-parity (+ self-test), check-comment-mask-corpus,
check-self-test-wired (+ self-test: ✓ check-self-test-wired: every one of the 169 script(s) CI runs that ship a --self-test has that self-test run by CI.), check-whole-set-label-write (+ self-test),
bare-root-worklist --self-test, check:agent-test-spelling, check:bash32-floor,
check:cli-command-ids, check:cross-package-test-inputs, check:driver-memory-census,
check:entry-guard, check:parse-guard, check:pnpm-filter-targets,
check:ratchet-remedy-authority, check:refd-timer-probe, check:watch-hint-literal.

Beyond the derived set, the six artifact-roster gates the tool flags as keeping their roster under
scripts/ (where this path lives, so their silence is evidence in neither direction) were run
too: check-published-list-mirrors (+ self-test), check:console-injection,
check:engine-double-contract, check:i18n-stale-fill — all exit 0. The sixth,
pnpm check:published-readme-exports, exits 1 in a fresh worktree and is recorded NOT MEASURED,
not a red
: every one of its findings is ... whose type entry packages/PKG/dist/... does not exist. Build first, i.e. an unbuilt workspace, and its inputs are README files and dist/ type
entries — nothing this diff touches.

Scope

scripts/-only; publishes nothing from any released package, so skip-changeset. No self-test
case's expected outcome was edited, no gate's normal-mode reading changed, no dispatch-gates case
touched, and scripts/measure-durability-swallow-family.mjs (in flight on another branch) was not
edited.

🤖 Generated with Claude Code

https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk


Generated by Claude Code

…to the end", pass or fail

`selfTest()` set `selfTestReachedVerdict` on its SUCCESS path only, and the
dispatch read that flag BETWEEN the two batteries. A genuine red therefore
printed its own verdict line and was then reported as
"selfTest() returned without reaching its verdict" — false, since the verdict
had just been printed — and the process exited before `selfTestReadSeams()`
ran at all, which is exactly what the comment above the dispatch forbids
("a red one must not hide the other"). Exit 1 either way, so no false green;
the cost was a misleading diagnostic plus half the self-test coverage lost on
the red path.

Both halves of the repair:

- the flag is now set at BOTH verdict sites of each battery, adjacent to the
  line it certifies, so it can only be true if a verdict was really printed;
  the returned status keeps carrying pass/fail;
- the dispatch runs BOTH batteries first and reads both handshakes after, then
  exits with the combined status.

An early `return` above either verdict still trips that battery's own named
diagnostic — the property the handshake was landed for is unchanged.

`scripts/check-dispatcher-error-vocabulary.mjs` ships the same landed shape and
is deliberately untouched: its failure path calls `process.exit(1)` inside the
self-test, so its flag is never consulted on a red.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
@claude claude Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Sep 4, 2026
@github-actions github-actions Bot added the size/s label Sep 4, 2026
@claude

claude Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

ACCEPT — PM seat domain:devx @ objectstack (#6023), session session_012zGPuVVX3deAx9LdjK8jCk.

Reviewed against the three-dot diff origin/main...claude/issue-14962-durability-handshake-red-path (merge base 4f85e4d11, head dfad2f273): one file, scripts/check-durability-degradation-log-level.mjs, +41/−11, matching the PR file list; the ruling in claim 5544780135 taken as written — selfTestReachedVerdict / readSeamsReachedVerdict are set at BOTH verdict sites of their battery (adjacent to the line they certify), the dispatch runs both batteries, then reads both handshakes into handshakeMissing, then exits handshakeMissing || logLevelStatus || readSeamStatus; the two early process.exit(1) calls are the removed lines. Normal-mode reading byte-identical to main (md5 both sides), --self-test 63 + 57 cases green, census and instrument readings byte-identical, four trap-guarded ablations red/green exactly as owed — (a) forced red in battery 1: battery 2 still reports, exit 1, zero occurrences of the false diagnostic; (b)/(c) early returns: the named handshake diagnostic; (d) green. check-dispatcher-error-vocabulary.mjs untouched, as ruled. Derived family 25/25 green incl. dispatch-gates 1402/1402. Hot-file scan: #15504 is the only open PR on the gate. skip-changeset is right. Fixes #14962 closes the card on merge. Flip + arm follow as soon as the MCP channel recovers from its rate limit.


Generated by Claude Code

@baozhoutao
baozhoutao marked this pull request as ready for review September 4, 2026 19:14
@baozhoutao
baozhoutao enabled auto-merge September 4, 2026 19:14
@baozhoutao
baozhoutao added this pull request to the merge queue Sep 4, 2026
Merged via the queue into main with commit 582bea6 Sep 4, 2026
36 checks passed
@baozhoutao
baozhoutao deleted the claude/issue-14962-durability-handshake-red-path branch September 4, 2026 19:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

2 participants