Observation-class, measured while reading gate populations for #10840. No gate is red — CI invokes this gate from the repo root, where it behaves correctly. Filed unassigned, no pm:queue.
The shape
scripts/check-i18n-coverage.mjs resolves its example population CWD-relatively, unlike every other scan gate in scripts/, which joins against a REPO_ROOT/ROOT derived from import.meta.url:
constEXAMPLES_DIR='examples';// not join(ROOT, 'examples')functiondiscoverExamples(){if(!existsSync(EXAMPLES_DIR))return[];// <- an empty POPULATION, not an error
...
}BASELINE_PATH is spelled the same way.
Why it matters: the empty scan reports OK
Run from anywhere other than the repo root, the guard returns [] and the gate goes green over a scan of nothing:
$ cd /tmp && node .../scripts/check-i18n-coverage.mjs
check-i18n-coverage: could not read packages/cli/package.json (ENOENT ...) - build prerequisite not pre-checked
check-i18n-coverage: OK (0 config(s), 0 baselined untranslated string(s), none new).
exit 0
OK (0 config(s)) is the #4690 shape this repo refuses elsewhere by name — "zero is a broken scan, not a clean repo". trackedFiles in scripts/pm/dispatch-gates.mjs throws on an empty listing for exactly this reason, and its docblock argues the case. Here the same condition is a silent pass, and the ENOENT line above it is printed as a note rather than a verdict.
Not urgent, and why it is worth recording anyway
CI runs it from the repo root, so nothing is red today and this is not a request to treat it as such. What makes it worth a card is that the failure is invisible in the direction that matters: a green line over a population of zero is indistinguishable from a green line over the real population, so if the invocation ever moves — a new workflow step with a working-directory:, a wrapper script, a dev running it by hand from a package dir — the gate stops checking anything and says so in the same words it uses when it passes.
Direction (not a decision)
Two independent halves, either useful alone:
- Join both constants against a module-derived root, as the sibling gates do —
check-skills-token-ratchet.mjs and check-ratchet-remedy-authority.mjs are the nearest models. - Refuse the empty population rather than returning it, the way
trackedFiles does — so an unreadable input can never look like an empty answer.
Refs
#10840 (where this was found — that card's own subject is a different property of the same constant) · trackedFiles' docblock in scripts/pm/dispatch-gates.mjs for the #4690 argument this is the counter-example to
Generated by Claude Code
Observation-class, measured while reading gate populations for #10840. No gate is red — CI invokes this gate from the repo root, where it behaves correctly. Filed unassigned, no
pm:queue.The shape
scripts/check-i18n-coverage.mjsresolves its example population CWD-relatively, unlike every other scan gate inscripts/, which joins against aREPO_ROOT/ROOTderived fromimport.meta.url:BASELINE_PATHis spelled the same way.Why it matters: the empty scan reports OK
Run from anywhere other than the repo root, the guard returns
[]and the gate goes green over a scan of nothing:OK (0 config(s))is the #4690 shape this repo refuses elsewhere by name — "zero is a broken scan, not a clean repo".trackedFilesinscripts/pm/dispatch-gates.mjsthrows on an empty listing for exactly this reason, and its docblock argues the case. Here the same condition is a silent pass, and the ENOENT line above it is printed as a note rather than a verdict.Not urgent, and why it is worth recording anyway
CI runs it from the repo root, so nothing is red today and this is not a request to treat it as such. What makes it worth a card is that the failure is invisible in the direction that matters: a green line over a population of zero is indistinguishable from a green line over the real population, so if the invocation ever moves — a new workflow step with a
working-directory:, a wrapper script, a dev running it by hand from a package dir — the gate stops checking anything and says so in the same words it uses when it passes.Direction (not a decision)
Two independent halves, either useful alone:
check-skills-token-ratchet.mjsandcheck-ratchet-remedy-authority.mjsare the nearest models.trackedFilesdoes — so an unreadable input can never look like an empty answer.Refs
#10840 (where this was found — that card's own subject is a different property of the same constant) ·
trackedFiles' docblock inscripts/pm/dispatch-gates.mjsfor the #4690 argument this is the counter-example toGenerated by Claude Code