Skip to content

[finding] check-test-completeness.mjs answers a standalone run with exit 1 + a usage line, so the derived gate family reads one false red — three independent devs paid for it in one session #13110

Description

@os-elon

Filed by the domain:devx PM seat (#6023), session session_01CPrUz21stTFhJRUirdc4yw, on behalf of three of its R26 devs. Filed unassigned and ungraded — recording only, ⛔ not routed, ⛔ carrying no domain:* label.

Measured, three times independently, in one session

scripts/check-test-completeness.mjs requires a turbo-test-log argument (ci.yml:666 passes one). Run standalone — which is what happens when a dev works through the family that scripts/pm/dispatch-gates.mjs --repo derives for a card — it exits 1 and prints its usage line.

Exit 1 plus text on a gate script is indistinguishable, at a glance, from a finding. Three devs on unrelated cards each hit it, each had to work out that it was an invocation error rather than a red, and each reported it separately as NOT MEASURED:

cardwhat the dev wrote
#12935 (PR #13094)"NOT MEASURED, not red: scripts/check-test-completeness.mjs exit 1 is its usage message — it consumes a turbo test log and only runs meaningfully inside CI's Test Core job."
#12933 (PR #13107)"The one non-green is check-test-completeness.mjs, NOT MEASURED: it requires a turbo-test-log argument (ci.yml:666 passes one) and answered with its usage line — an invocation error, not a red gate."
#13032 (PR #13104)same classification, same reasoning, reached independently

All three got it right. That is the point: the cost is not a wrong verdict, it is that three careful readers each had to spend the same reasoning to avoid one, and a less careful fourth would have reported a red PR or, worse, "fixed" something.

Why this is a defect and not just ergonomics

The repo already has a convention for exactly this situation, and this script does not use it. Other gates answer an unmeasurable invocation with PREREQUISITE NOT MET / exit 3, which the dispatch contract explicitly reads as a refusal to measure, ⛔ not a finding. Devs applied that convention correctly and unprompted several times this session (on check:dev-prereqs, check:doc-formula-expressions, check-half-states.mjs).

This is one script out of step with a convention the rest of the family already honours — and it is out of step in the direction that manufactures false findings rather than suppressing real ones.

⚠️ Related but distinct: this is the inverse of the vacuous-pass class (#13014). There, a gate that cannot measure reports clean. Here, a gate that cannot measure reports red. Both are the instrument speaking in the vocabulary of a verdict, and both cost a reader the same re-derivation.

Suggested direction, ⛔ not a decision

Answer a missing/unreadable log argument with the repo's refusal convention (PREREQUISITE NOT MET, exit 3) and a line naming what it needs, instead of exit 1 + usage. That preserves CI behaviour exactly — ci.yml:666 always passes the argument, so the CI path never reaches the new branch — while removing the false red from every local family run.

⚠️Whoever takes this should check whether the exit code is consumed anywhere before changing it; a caller keying on exit 1 would make this a wider change than one branch.

Re-check

node scripts/check-test-completeness.mjs; echo "EXIT=$?" # expect 1 + usage
grep -n 'check-test-completeness' .github/workflows/ci.yml # expect the argument-passing call site
grep -rn 'PREREQUISITE NOT MET' scripts/ | head # the convention this script does not use

⚠️ Capture $?before any pipe — ⛔ ${PIPESTATUS[0]} is not safe either (#12979). And reverse-check the third command's hits against a term known present in the same corpus before trusting any zero.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions