Uh oh!
There was an error while loading. Please reload this page.
tooling(pm): give dispatch-gates --ran an explained bucket for the value-bearing class - #15165
Merged
Merged
Conversation
…lue-bearing class `runReconciliation` classified a recorded command that is not in the derived runnable set into three outcomes, two of which are "explained, not a mistake": a CI-measured-only family and a pending-changeset family. The value-bearing class added for #15083 — an invocation whose argv takes a value from the workflow, which `commandsFor` subtracts from the union for the same reason it subtracts the CI-measured one — had no such bucket, so a dev who recorded one landed in `extra` under a caption that reads "named by nothing this run derived": the one sentence that is false about it, because this run derived it and then classified it out. Third bucket, built from `notRunnableCommandSet` off the same rows the CI-measured set is built from, checked beside it (the two subtractions `commandsFor` makes, in that order) and before the `extra` fallback, and rendered on its own labelled line naming the reason. Diagnostic only: `recon.ok` still reads `unrun.length`, `--commands` is untouched, and no derivation key moves. Measured at the merge base 4283b72: a record of the 15 derived commands for a changeset path plus the live `node scripts/check-empty-changeset.mjs --base "$MERGE_BASE"` invocation reported Outside this card's derivation (1) — recorded, and named by nothing this run derived. - node scripts/check-empty-changeset.mjs --base "$MERGE_BASE" and the same record on this tree reports the labelled bucket instead, with the remainder heading gone and the verdict unmoved (15 derived, 15 run, exit 0). Self-test: seven cases, three of them a real CLI run whose fixture is the tool's own `--json` answer on this tree — a parameter defaulting to empty is exactly the shape that keeps unit cases green while the live mode still dumps the class in the remainder. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019RfFHiRCSs3JXLK4cwcfox
os-steve
marked this pull request as ready for review
September 4, 2026 04:57
os-steve
enabled auto-merge
September 4, 2026 04:57
Uh oh!
There was an error while loading. Please reload this page.
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.
Fixes#15115
runReconciliationinscripts/pm/dispatch-gates.mjsclassifies a command therunner RECORDED that is not in the derived runnable set. It had three outcomes,
two of which are "explained, not a mistake": a CI-measured-only family, and a
pending-changeset family. The value-bearing class — an invocation whose argv
takes a value from the workflow, added by PR #15114 and subtracted from
--commandsby the second subtraction incommandsFor— had no such bucket, soa recorded one landed in
extra.Reproduced at the merge base, before any edit
Merge base
4283b72a. Record = the 15 commands--commandsderives for achangeset path, plus the live
pr-automation.ymlinvocationnode scripts/check-empty-changeset.mjs --base "$MERGE_BASE":That caption is the defect in one sentence: this run DID derive that family and
then classified it out of the union on purpose, so "named by nothing this run
derived" is the one thing that is false about it. No reason is attached, and the
runner is left to guess whether they typed something wrong.
The bucket
runReconciliationtakesnotRunnableCommands, defaulting to an empty set soevery existing caller's verdict is byte-identical.
ciOnlyCommandsand beforependingCommands, becausethe file already groups those two: they are the two subtractions
commandsFormakes from the runnable union, in that order, while the pending families are a
different fact (a path that did not exist at derivation time).
ciOnlykeepsfirst precedence, matching
commandsFor, so one command can never produce twocounts for one omission.
--rancall site bynotRunnableCommandSet(matchedRows, alwaysRunsRows)— the SAME expressioncommandsForsubtracts with, off thesame rows — so the union and the reconciliation cannot drift about which
invocations are withheld.
recon.okstill readsunrun.lengthonly.--commandsoutput, theclassifier, the derivation keys and every live key are untouched.
Rendered on its own labelled line, in the shape the two beside it use. Same
record, same card, on this branch:
The remainder heading is gone entirely and the verdict is unmoved.
Self-test — 7 new cases, 1353 total
Unit, beside the existing
explainedcase (whose fixture now carries a fourthrecorded entry, the live value-bearing spelling):
explainedNotRunnableand isNOT in
extra;extra— thebucket explains its class and nothing else, which is the half that keeps this
from deleting the remainder rather than shrinking it;
(
explainedCiOnly1,explainedPending1,extra0);oktrue,unrun0;the two neighbouring lines still present and the remainder heading absent.
End to end, a real CLI run (three cases), because every unit case above stays
green if the
--rancall site never PASSES the set — a parameter defaulting toempty is exactly the shape that keeps its own tests green while the live mode
still dumps the class in the remainder. Its fixture is the tool's own
--jsonanswer on this tree rather than a spelling typed into the test, so it cannot
outlive a change to the renderer that produces the real invocation.
Gates — all green, run at head
5fb6e3a7Re-derived from the real change set with
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands(no paths) after the commit; the20 families match the dispatch list exactly, nothing added. Each exit code was
captured by redirecting first, never after a pipe; every line below is the
gate's own verdict line.
check-ci-filter-parity.mjsOK: all 143 declared cross-package glob(s) (99 unique) are covered by core or crosspkg, every crosspkg entry still covers one, and the test job's if: still names both filters.check-closing-keyword-parity.mjscheck-closing-keyword-parity: OK (3 parsers agree on all 9 keywords and both measured separators; sweep found 5 file(s) carrying the grammar across 8245 tracked file(s), all registered).check-closing-keyword-parity.mjs --self-test✓ 24 assertions, 5 mutations of the shipped parsers each driven to red.check-comment-mask-corpus.mjs✓ comment-mask corpus sweep: 5858 files, 0 disagree, 0 unparseable, 49.0s (comparator self-test: 12 cases pass).check-self-test-wired.mjs✓ every one of the 166 script(s) CI runs that ship a --self-test has that self-test run by CI.check-self-test-wired.mjs --self-test4 live ledger row(s) verified ... 7 declared batteries, 50 cases registered, every battery at or above its pinned floor.check-whole-set-label-write.mjs✓ 0 violations — 258 file(s) over 3 root(s) · 160 uses: pin(s) over 18 distinct action(s) judged · 0 allowlist entr(ies)check-whole-set-label-write.mjs --self-test✓ all cases pass (24 fixture trees + 5 refusals + 1 allowlist hatch)pnpm check:agent-test-spelling✓ 0 violations — 438 file(s) · 5916 bare -- token(s) · 1408 launcher-rooted run(s) · 9 separator(s) JUDGEDpnpm check:bash32-floor✓ self-test: 153 cases pass./✓ 26 tracked shell file(s) ... name no bash 4+ constructpnpm check:cli-command-ids✓ 324 command-id literal(s) across 114 file(s) outside packages/cli all resolve to a real command pathpnpm check:cross-package-test-inputsOK: 26 package(s) read outside themselves, all declared, and turbo.json hashes every declared glob.pnpm check:declared-population-live✓ 198 of 249 famil(ies) declare a path population, and every one of them reaches this tree's 8245 tracked file(s).pnpm check:entry-guard✓ 207 scripts/ file(s) — every entry guard goes through invoked-as.mjs; 153 export bindings, 153 of them inert on importpnpm check:nul-bytescheck-nul-bytes: OK (scanned 8238 text file(s) ... no raw ASCII control bytes).pnpm check:parse-guard✓ 206 scripts/ file(s) — every TypeScript parse goes through ts-parse.mjs.pnpm check:pm-dispatch-gates✓ dispatch-gates self-test: 1353 cases pass.pnpm check:pnpm-filter-targets✓ 142/181 --filter occurrence(s) across 33 file(s) resolve against 79 workspace package(s)pnpm check:refd-timer-probeOK 5853 source file(s) swept; the process-global timer probe is read in packages/qa/refd-timer-testkit/src/index.ts and nowhere else.pnpm check:watch-hint-literal✓ 48 declaration(s) across 4 rostered name(s) ... no unrostered spelling of the idiom in the tree.bare-root-worklist.mjs --self-test(not in the derivation; asserted green because a parallel flight edits that file)OK self-test: 54 live row(s), 46 unreachable as spelled, 46 recorded verdict(s) — none stale, none missing, none contradicted.Repo-wide ESLint, not narrowed:
pnpm lint(eslint . --no-inline-config) throughthe shared verify lock —
os-verify-lock: VERDICT command-exit 0 · held the lock 66s.The
dispatch-gates --self-testalso ran through the lock:VERDICT command-exit 0 · held the lock 354s. Both wall-clock figures are shared-box seconds, as the lock'sown verdict line states.
NOT MEASURED, in its own words:
check-test-completenessis itself one of thisdiff's value-bearing families — its argv takes
$RUNNER_TEMPfrom the workflow,so it is outside
--commandsand has no local run. Same forcheck-shard-attestation.mjs --emit ...and the--union-intospelling ofcheck-cross-package-test-inputs(the barepnpm check:cross-package-test-inputsspelling of that family IS in the table above and ran green).
Nothing is published from any package (
scripts/pm/**, no.md), soskip-changesetis applied.Generated by Claude Code