Observation-class, measured while fixing #10907. No gate is red — CI invokes both consumers from the repo root. Filed unassigned, no pm:queue.
The shape
scripts/cli-build-prerequisite.mjs is the one shared answer to "is the workspace CLI built?", used by scripts/check-i18n-coverage.mjs and scripts/check-i18n-bundles.mjs. Two of its exported constants are CWD-relative:
exportconstCLI='packages/cli/bin/run.js';exportconstCLI_PKG='packages/cli';
resolveCliCommandFile() reads join(CLI_PKG, 'package.json') off those, so from any cwd but the repo root it ENOENTs and returns an unknown reason rather than a derived path.
Measured residue
#10907 anchored check-i18n-coverage.mjs to a module-derived root. Its off-root run is now correct — same verdict as the root run — but the probe above still cannot pre-check, so the run is preceded by a line that reads like a problem when nothing is wrong:
$ 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 (12 config(s), 602 baselined untranslated string(s), none new).
exit 0
And on an unbuilt tree the deferral costs the diagnosis outright. From the root the reader gets one verdict naming the one cause; from off-root the probe defers, every config reaches the in-loop path instead, and the same single environment fact is reported as twelve failures.
Why it is worth recording
The deferral direction is deliberate and correct — resolveCliCommandFile's docblock argues that a probe which cannot read the declaration must not turn a correctly-built workspace red — so this is not a request to change that. What is worth recording is that the reason it cannot read the declaration is a fixable path bug rather than a genuine unreadable shape, and the fix is the same one #10907 applied one file over: derive a root from import.meta.url and join against it. Because the module is shared, the fix lands on both consumer gates at once, which is also why #10907 deliberately did not take it — its ruled file surface was check-i18n-coverage.mjs alone, and widening it would have moved a second gate's behaviour under a card that had not measured it.
Refs
#10907 (where this was measured; that card anchored the consumer, not this shared module)
Generated by Claude Code
Observation-class, measured while fixing #10907. No gate is red — CI invokes both consumers from the repo root. Filed unassigned, no
pm:queue.The shape
scripts/cli-build-prerequisite.mjsis the one shared answer to "is the workspace CLI built?", used byscripts/check-i18n-coverage.mjsandscripts/check-i18n-bundles.mjs. Two of its exported constants are CWD-relative:resolveCliCommandFile()readsjoin(CLI_PKG, 'package.json')off those, so from any cwd but the repo root it ENOENTs and returns anunknownreason rather than a derived path.Measured residue
#10907 anchored
check-i18n-coverage.mjsto a module-derived root. Its off-root run is now correct — same verdict as the root run — but the probe above still cannot pre-check, so the run is preceded by a line that reads like a problem when nothing is wrong:And on an unbuilt tree the deferral costs the diagnosis outright. From the root the reader gets one verdict naming the one cause; from off-root the probe defers, every config reaches the in-loop path instead, and the same single environment fact is reported as twelve failures.
Why it is worth recording
The deferral direction is deliberate and correct —
resolveCliCommandFile's docblock argues that a probe which cannot read the declaration must not turn a correctly-built workspace red — so this is not a request to change that. What is worth recording is that the reason it cannot read the declaration is a fixable path bug rather than a genuine unreadable shape, and the fix is the same one #10907 applied one file over: derive a root fromimport.meta.urland join against it. Because the module is shared, the fix lands on both consumer gates at once, which is also why #10907 deliberately did not take it — its ruled file surface wascheck-i18n-coverage.mjsalone, and widening it would have moved a second gate's behaviour under a card that had not measured it.Refs
#10907 (where this was measured; that card anchored the consumer, not this shared module)
Generated by Claude Code