Recording only, no severity asserted — routing and ranking are triage's. Found while running the derived gate family for the card #13961 on branch claude/issue-13961-explain-zero-rows-sentinels; unrelated to that card's diff, so deliberately not repaired there.
Measured
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack on a diff whose only PM-ish path is one .changeset/*.md file prints, among 67 matched families:
- node scripts/pm/check-half-states.mjs [half-state-patrol.yml] matched via .changeset/EXAMPLE.md => gate source '.changeset'
That command is the live board sweep, not a gate:
- Its standing caller is
.github/workflows/half-state-patrol.yml — a scheduled workflow, whose own header says the patrol exists because "a lane that has to REMEMBER to run a patrol does not run it". It is not triggered by a PR. lint.yml deliberately runs only the offline self-test, pnpm check:pm-half-states, and says why in a comment beside the step: "The gate runs the SELF-TEST only. The live sweep (node scripts/pm/check-half-states.mjs) reads a shared board over the GitHub API, is report-only by design (a completed sweep exits 0 whether it found 0 or 40 half-states), and its non-zero exits classify the ENVIRONMENT … which is not a verdict about the PR running it."pnpm check:pm-half-states is ALSO in the derived list and passes in ~seconds, so the offline half is already covered. The bare node spelling is a second, different command.
So the derived family names a command CI never runs on a PR, and the dispatch protocol tells a dev to run the printed commands.
Cost, measured on one dev container
Running the derived list top to bottom, node scripts/pm/check-half-states.mjs sat for 3m09s with no output before it was stopped by PID; the remaining ~52 commands were blocked behind it for that whole window. It reads a shared board over the GitHub API, so a dev seat that lets it finish also spends API quota on a sweep that says nothing about its own diff — and every dev whose PR carries a changeset (which is most of them) gets this.
Why it is small
The command cannot redden anything: it is report-only by construction. The damage is a dev's wall clock, some shared API quota, and a NOT-MEASURED-looking non-zero exit (143 when stopped, or an environment classification) landing in a verification record next to real gate results, where it reads like a finding.
Scope NOT established
- ⛔ Whether the repair is (a) an exclusion in
dispatch-gates.mjs for commands whose only source workflow is schedule-triggered, (b) a narrower exclusion naming this script, or (c) leaving the derivation and teaching the dispatch protocol to skip report-only live sweeps, is not decided here. (a) is the general shape and would need its own measurement — how many derived commands come only from scheduled workflows, and whether any of them is one a dev SHOULD run. - ⛔ Whether
half-state-patrol.yml's path list should carry .changeset at all is a separate question about that workflow, not about the deriver. - Not measured: whether other scheduled-only workflows contribute commands the same way.
Related
Filed from the #13961 run (branch claude/issue-13961-explain-zero-rows-sentinels). Neighbouring dispatch-gates findings, none of them this one: #14880 (a gate CI DOES run that is not derived — the opposite direction), #14753 and #14294 (silent flag drops), #14290 (an untraversed edge), #14688 (a selfTest() binding bug).
Generated by Claude Code
Recording only, no severity asserted — routing and ranking are triage's. Found while running the derived gate family for the card #13961 on branch
claude/issue-13961-explain-zero-rows-sentinels; unrelated to that card's diff, so deliberately not repaired there.Measured
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstackon a diff whose only PM-ish path is one.changeset/*.mdfile prints, among 67 matched families:That command is the live board sweep, not a gate:
.github/workflows/half-state-patrol.yml— a scheduled workflow, whose own header says the patrol exists because "a lane that has to REMEMBER to run a patrol does not run it". It is not triggered by a PR.lint.ymldeliberately runs only the offline self-test,pnpm check:pm-half-states, and says why in a comment beside the step: "The gate runs the SELF-TEST only. The live sweep (node scripts/pm/check-half-states.mjs) reads a shared board over the GitHub API, is report-only by design (a completed sweep exits 0 whether it found 0 or 40 half-states), and its non-zero exits classify the ENVIRONMENT … which is not a verdict about the PR running it."pnpm check:pm-half-statesis ALSO in the derived list and passes in ~seconds, so the offline half is already covered. The barenodespelling is a second, different command.So the derived family names a command CI never runs on a PR, and the dispatch protocol tells a dev to run the printed commands.
Cost, measured on one dev container
Running the derived list top to bottom,
node scripts/pm/check-half-states.mjssat for 3m09s with no output before it was stopped by PID; the remaining ~52 commands were blocked behind it for that whole window. It reads a shared board over the GitHub API, so a dev seat that lets it finish also spends API quota on a sweep that says nothing about its own diff — and every dev whose PR carries a changeset (which is most of them) gets this.Why it is small
The command cannot redden anything: it is report-only by construction. The damage is a dev's wall clock, some shared API quota, and a NOT-MEASURED-looking non-zero exit (
143when stopped, or an environment classification) landing in a verification record next to real gate results, where it reads like a finding.Scope NOT established
dispatch-gates.mjsfor commands whose only source workflow isschedule-triggered, (b) a narrower exclusion naming this script, or (c) leaving the derivation and teaching the dispatch protocol to skip report-only live sweeps, is not decided here. (a) is the general shape and would need its own measurement — how many derived commands come only from scheduled workflows, and whether any of them is one a dev SHOULD run.half-state-patrol.yml's path list should carry.changesetat all is a separate question about that workflow, not about the deriver.Related
Filed from the #13961 run (branch
claude/issue-13961-explain-zero-rows-sentinels). Neighbouringdispatch-gatesfindings, none of them this one: #14880 (a gate CI DOES run that is not derived — the opposite direction), #14753 and #14294 (silent flag drops), #14290 (an untraversed edge), #14688 (aselfTest()binding bug).Generated by Claude Code