Uh oh!
There was an error while loading. Please reload this page.
fix(devx): verdict handshake for check-platform-checklist and dispatch-gates self-tests - #14960
Merged
baozhoutao merged 1 commit intoSep 3, 2026
Merged
Conversation
…h-gates self-tests
Both dispatches discarded their self-test's completion, so a `return` above the
verdict printed nothing and still exited 0 — an unfinished self-test reported as
a verified gate.
Measured before the repair, on this tree:
* `scripts/pm/dispatch-gates.mjs` — an early return at the real definition of
`selfTest()` took the run from "1288 cases pass" to ZERO bytes of output and
exit 0. The card carried this row as NOT MEASURED because the mechanical
probe anchors on the first `function selfTest() {` in the source, which here
is a fixture STRING: the injection lands inside a template literal and only
ever yields a SyntaxError. That is a limit of the instrument, not of the
file; a hand-read anchor measures it in one run.
* `scripts/check-platform-checklist.mjs` — five batteries returning
`{ checked, failures }` and combined by the caller. A section that stops
running took the verdict from 141 assertions to 119, exited 0, and still
claimed in prose that the direction it had skipped "REFUSES an
empty/renamed/reshaped" table. A bare `return` instead yields `undefined`
and CRASHES the combine — an exit code alone reads that crash as a
handshake rather than as the accident it is.
dispatch-gates takes the landed sentinel form. check-platform-checklist takes
the landed FLAG form (`check-durability-degradation-log-level.mjs`,
`check-dispatcher-error-vocabulary.mjs`) for the reason those files state: the
return value is load-bearing, so the handshake cannot BE the return value. Its
guard is checked on both legs — including the inline one, which is the only leg
CI reaches — before the `.failures` read, so a bare `return` now reports itself
instead of crashing its reader.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
This was referenced Sep 3, 2026
baozhoutao
marked this pull request as ready for review
September 3, 2026 13:51
baozhoutao
enabled auto-merge
September 3, 2026 13:51
Uh oh!
There was an error while loading. Please reload this page.
baozhoutao
deleted the
claude/issue-13800-carry-forward-verdict-handshake
branch
September 3, 2026 14:11
This was referenced Sep 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of #13800
Hole 2 (the verdict handshake) for the four files that card carries forward. Two of the four needed no work — see the falsified premise below — so this PR repairs two and reports measurements for the other two.
Fixesis deliberately not used: two rows are delivered as readings, and the card should stay open for triage to close.Verified at
b12a5bda(the head of this branch).The premise, re-derived — and partly falsified
The card's acceptance criterion was the guard form
!== SELF_TEST_VERDICT, with a positive control of 81 files onorigin/main, each of the four returning 0.That marker gives a false zero on two of the four. A second, equally deliberate spelling landed in commit
9acddde9("Verdict handshake for 134 scripts/** self-tests that exit 0 on an early return", #14479) — a module-level flag, chosen with the rationale stated in the code: "The self-test's own exit code stays load-bearing, so the handshake is a flag rather than a returned sentinel." Counting only the sentinel cannot see it.A marker that separates before from after, proven across that commit:
!== SELF_TEST_VERDICT|ReachedVerdictat9acddde9^9acddde9check-durability-degradation-log-level.mjscheck-dispatcher-error-vocabulary.mjscheck-platform-checklist.mjsscripts/pm/dispatch-gates.mjsUnion control on
origin/main: 81 sentinel files + 77 flag files = 158 carrying a handshake in one spelling or the other.Per-row outcome, each one measured rather than read
Probes inject
return;(or a partial early verdict) at a hand-chosen anchor, write the mutation to a copy beside the original — the tracked file is never mutated — prove the mutation is on disk before running, and delete the copy in afinally.1.
scripts/pm/dispatch-gates.mjs— was NOT MEASURED, now measured, defeated, repairedThe card's NOT MEASURED was a property of the instrument, not the file.
measure-self-test-floor.mjs'sinjectEarlyReturn()anchors on the firstfunction selfTest() {in the source; in this file that match is inside a fixture string (a template literal), so the injection only ever produces a SyntaxError. The real definition is at line 10517 and the dispatch was:Anchored on the real definition, the anchor is unique (1 match) and the reading is clean:
✓ dispatch-gates self-test: 1288 cases pass.✓ dispatch-gates self-test: 1288 cases pass.✗ dispatch-gates self-test: selfTest() returned without reaching its verdict...Repaired with the landed sentinel form.
ENTRY_BY_HANDinmeasure-self-test-floor.mjsis deliberately left alone: its note stays true of the mechanical probe after this repair, and that file is outside this card's surface.2.
scripts/check-platform-checklist.mjs— was NOT MEASURED, now measured, defeated, repairedFive batteries returning
{ checked, failures }, combined by the caller. Both failure shapes the card predicted, measured before the repair:selfTestTrapVocabularyreturn;(bare)TypeError: Cannot read properties of undefined (reading 'failures')— a crash a one-function probe reads as a handshakereturn { failures: [], checked: 0 };✓ ... 119 assertions(down from 141) — and still claiming in prose that the skipped direction "REFUSES an empty/renamed/reshaped" tableAfter the repair, all three mutations exit 1 and name the battery that did not finish:
— and the same for
selfTestSourceLineCitations(), confirming a late battery is caught too, not just the first.Spelling: the flag form, not the sentinel, for exactly the reason the two sibling files state — the return value is load-bearing here (it carries
checkedandfailures), so the handshake cannot be the return value. The guard is checked on both legs, including the inline one that runs on every invocation (this gate has no--self-testleg in CI), and it is placed before the.failuresread so a barereturnreports itself instead of crashing its reader. OnerequireReachedVerdict()helper carries the landed wording to ten call sites (five batteries × two legs); the check, the message and the exit code are the landed ones — only the tenfold duplication of the prose is factored out.3.
scripts/check-durability-degradation-log-level.mjs— already repaired; untouchedReceived hole 2 in
9acddde9(flag spelling). Both of its entries probed, and both hold:selfTest→ exit 1,✗ ... selfTest() returned without reaching its verdictselfTestReadSeams→ exit 14.
scripts/check-dispatcher-error-vocabulary.mjs— already repaired; untouchedAlso from
9acddde9. Probed: exit 1 with the named diagnostic. Its hole 1 (SELF_TEST_BATTERIES, 7 hits, from #13799) is left strictly alone — the two counts are not merged.The derived list, and the irony
Derived from this worktree after the edits, with
--repoasserted:One of the two repaired files IS that script. Re-derived both ways on identical explicit inputs — the base version of the script and the repaired one — the derived list is IDENTICAL. The repair changes the self-test handshake, not the derivation.
All 21 derived families re-run at
b12a5bdaand green, includingpnpm check:pm-dispatch-gates(1288 cases) andpnpm check:parse-guard/check:entry-guard/check:nul-bytes. Every exit code was captured before any pipe.Two derived entries were NOT MEASURED rather than red, both prerequisite refusals and neither a finding:
node scripts/check-test-completeness.mjs→ exit 3,PREREQUISITE NOT MET — this gate grades a saved turbo run test log, and no log was named. Its own--self-testruns clean (exit 0).node scripts/check-durability-degradation-log-level.mjson a fresh worktree → exit 3 beforepnpm install; re-run after install, exit 0.One gate is red, and it is red on
maintoopnpm check:platform-checklistexits 1 with 4UNCLASSIFIEDcoverage findings (batch_endpoints,crud_endpoints,metadata_endpoints,route_generation). Not caused by this PR — theca3fd4b1version of the file, run in the same tree, produces the byte-identical four findings (diffof the two finding sets is empty). This gate is deliberately excluded from CI (.github/workflows/lint.yml: "validated bypnpm check:platform-checklist, but by MAINTAINER action"), which is why the drift accumulated unseen. Filed separately rather than fixed here.skip-changeset:scripts/**publishes nothing.🤖 Generated with Claude Code
https://claude.ai/code/session_012zGPuVVX3deAx9LdjK8jCk
Generated by Claude Code