Measured 2026-09-05 06:0xZ while deriving the gate family for a scripts/pm/check-half-states.mjs card (PR #15755).
What was measured
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 31 runnable commands for a one-path changeset. Two of them are the same guard:
node scripts/check-partof-closing-keyword.mjs -> exit 2
pnpm check:partof-closing-keyword -> exit 0 (28 cases pass)
The bare form cannot pass anywhere outside a workflow run. Its own refusal says so, in the file's own words:
check:partof-closing-keyword: NOT WIRED — neither PR_BODY nor PR_NUMBER is set, so this run
was handed no pull request and judged nothing. This is a wiring or usage failure, NOT a
verdict: it says nothing about whether any PR body contradicts itself, and no author caused it.
So a dev handed this family runs a command that can only ever be non-zero, and the honest readings of it are "a red gate I must fix" (wrong) or "NOT MEASURED, skip it" (right, but only if the reader knows the difference).
Why the existing safety net does not catch it
dispatch-gates already has the bucket for exactly this class, and on the same run it used it correctly for four other families:
+ 4 famil(ies) matched by path take a VALUE FROM THE WORKFLOW and are NOT above — their argv
carries a variable with no value outside a CI run.
NOT MEASURED — scripts/check-cross-package-test-inputs.mjs --union-into "$RUNNER_TEMP/..."
NOT MEASURED — scripts/check-shard-attestation.mjs --emit --job test --shard ...
NOT MEASURED — scripts/check-test-completeness.mjs "$RUNNER_TEMP/test-core.log" ...
NOT MEASURED — scripts/pm/check-half-states.mjs --format=markdown --provenance="$PROVENANCE"
Each of those is detected because its argv carries a variable. check-partof-closing-keyword.mjs takes its whole input through env: (PR_BODY / PR_NUMBER) and its argv is bare, so the argv-shaped detector cannot see the dependency and files the command as plainly runnable.
The class is not new — #14004 carded the same shape for check-governed-queue-guard ("can only ever exit 1 outside a workflow run") and is no longer open. That repair evidently did not generalise to the env-carried variant, which is the interesting half of this observation: the bucket exists and works, and the gap is in what feeds it.
Shape of a repair (not a decision)
Read the workflow step's env: block alongside its run: argv when deciding whether a derived command takes a value from the workflow. .github/workflows/partof-closing-keyword-guard.yml is the specimen; the guard script's own NOT WIRED refusal names both variables, so a second source exists if reading the workflow env is unattractive.
Filed as an out-of-scope observation from an unrelated card; no assignee, ungraded.
Generated by Claude Code
Measured 2026-09-05 06:0xZ while deriving the gate family for a
scripts/pm/check-half-states.mjscard (PR #15755).What was measured
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 31 runnable commands for a one-path changeset. Two of them are the same guard:The bare form cannot pass anywhere outside a workflow run. Its own refusal says so, in the file's own words:
So a dev handed this family runs a command that can only ever be non-zero, and the honest readings of it are "a red gate I must fix" (wrong) or "NOT MEASURED, skip it" (right, but only if the reader knows the difference).
Why the existing safety net does not catch it
dispatch-gatesalready has the bucket for exactly this class, and on the same run it used it correctly for four other families:Each of those is detected because its argv carries a variable.
check-partof-closing-keyword.mjstakes its whole input throughenv:(PR_BODY/PR_NUMBER) and its argv is bare, so the argv-shaped detector cannot see the dependency and files the command as plainly runnable.The class is not new — #14004 carded the same shape for
check-governed-queue-guard("can only ever exit 1 outside a workflow run") and is no longer open. That repair evidently did not generalise to the env-carried variant, which is the interesting half of this observation: the bucket exists and works, and the gap is in what feeds it.Shape of a repair (not a decision)
Read the workflow step's
env:block alongside itsrun:argv when deciding whether a derived command takes a value from the workflow..github/workflows/partof-closing-keyword-guard.ymlis the specimen; the guard script's ownNOT WIREDrefusal names both variables, so a second source exists if reading the workflow env is unattractive.Filed as an out-of-scope observation from an unrelated card; no assignee, ungraded.
Generated by Claude Code