Finding
--require-source-files is the repository's file-set floor: it walks scripts/, src/
and tests/tools/ on disk and fails when a file there was never measured, because the
percentage gates are ratios and a ratio cannot see a file it never weighed.
It catches only one of the two ways a source file can leave every ratio.
A file nothing imports is recorded nowhere, so missingSourceFiles finds it and fails
the gate. But a file that was executed and whose V8 record could not be attributed
back to the text on disk is dropped by collect() into unmapped
(tests/tools/coverage-report.mjs:572-577), and report() is built from the merged map
alone — so it leaves the src files numerator and denominator together. The gate passes
over it too, because main() folds unmapped into the measured set:
// tests/tools/coverage-report.mjs:689
const missing = options.requireSourceFiles
? missingSourceFiles([...merged.keys(), ...unmapped])
: [];
That fold is deliberate and correct for the question missingSourceFiles asks — the
rationale is argued at tests/coverage-report-source-files.test.mjs:139-151, and
counting an unmappable component as missing would make every one of them a permanent
failure. The gap is that nothing else asks the other question. The only trace left is
the informational "Not reported" notice, which no gate scores.
Measured, not asserted
At 593b9fe, node v26.10.0, TZ=UTC, locally. tryRemapJsx was made to decline one
file, simulating the drift described below, and the full gate
(npm run test:unit:coverage:check, all five thresholds plus --require-source-files)
was run:
EXIT=0
src files 100.00 | 99.96 | 8999/8999 lines | 2560/2561 regions (was 9157/9157, 2595/2596)
Not reported (10):
...
src/components/CaseStudies/index.js
158 lines and 35 regions of a real component left the denominator, the file was not
listed under "Never measured", and every gate stayed green.
Why this is reachable, not hypothetical
tryRemapJsx rebuilds the loader's output and compares its length against the
recorded text before trusting the offsets
(tests/tools/coverage-report.mjs:509-511). Any change to swc's output or to
tests/tools/jsx-hooks.mjs — a dependency bump is enough — turns a mapped component into
an unmapped one with the suite still green. The 19 JSX-bearing modules under src/ all
depend on that comparison holding. tests/coverage-report-collect.test.mjs:295 already
pins that a JSX file which cannot be transpiled becomes unmapped; what is missing is any
gate that reacts to it.
Recommendation
Add a second, separate condition to --require-source-files for recorded-but-unmappable
files, leaving missingSourceFiles semantics untouched so its documented exemption (and
its test) stand. Report the two diagnoses together rather than letting the first
short-circuit the second.
With the fix, the same simulation exits 1:
1 source file(s) were recorded but could not be mapped onto the text on disk, so they
enter no ratio below; --require-source-files requires every file under scripts/ and
src/ and tests/tools/ to be measurable.
src/components/CaseStudies/index.js
and the unmodified gate still exits 0 at src files 100.00 | 99.96 | 9157/9157 lines | 2595/2596 regions, with the nine data modules still merely listed.
Coordination
The fix touches tests/tools/coverage-report.mjs, which open PR #1207 also edits. The
two are disjoint at hunk level: #1207 adds the --check-harness* threshold family
(parseArgs, report(), and main() at the report(merged) destructure and the
threshold block below), while this change sits in the --require-source-files failure
block between them and adds no flag and no package.json line.
Priority
- Impact: medium (the instrument every other coverage gate reads can stop measuring a
whole module without any gate noticing; no user-facing effect)
- Effort: low (one helper, one condition, one test file)
🐝 Hive Agent: quality | Instance: hosted-available-lke648397-260827-5n31 | SHA: 593b9fe
— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88
Finding
--require-source-filesis the repository's file-set floor: it walksscripts/,src/and
tests/tools/on disk and fails when a file there was never measured, because thepercentage gates are ratios and a ratio cannot see a file it never weighed.
It catches only one of the two ways a source file can leave every ratio.
A file nothing imports is recorded nowhere, so
missingSourceFilesfinds it and failsthe gate. But a file that was executed and whose V8 record could not be attributed
back to the text on disk is dropped by
collect()intounmapped(
tests/tools/coverage-report.mjs:572-577), andreport()is built from the merged mapalone — so it leaves the
src filesnumerator and denominator together. The gate passesover it too, because
main()foldsunmappedinto the measured set:That fold is deliberate and correct for the question
missingSourceFilesasks — therationale is argued at
tests/coverage-report-source-files.test.mjs:139-151, andcounting an unmappable component as missing would make every one of them a permanent
failure. The gap is that nothing else asks the other question. The only trace left is
the informational "Not reported" notice, which no gate scores.
Measured, not asserted
At
593b9fe, node v26.10.0,TZ=UTC, locally.tryRemapJsxwas made to decline onefile, simulating the drift described below, and the full gate
(
npm run test:unit:coverage:check, all five thresholds plus--require-source-files)was run:
158 lines and 35 regions of a real component left the denominator, the file was not
listed under "Never measured", and every gate stayed green.
Why this is reachable, not hypothetical
tryRemapJsxrebuilds the loader's output and compares its length against therecorded text before trusting the offsets
(
tests/tools/coverage-report.mjs:509-511). Any change to swc's output or totests/tools/jsx-hooks.mjs— a dependency bump is enough — turns a mapped component intoan unmapped one with the suite still green. The 19 JSX-bearing modules under
src/alldepend on that comparison holding.
tests/coverage-report-collect.test.mjs:295alreadypins that a JSX file which cannot be transpiled becomes unmapped; what is missing is any
gate that reacts to it.
Recommendation
Add a second, separate condition to
--require-source-filesfor recorded-but-unmappablefiles, leaving
missingSourceFilessemantics untouched so its documented exemption (andits test) stand. Report the two diagnoses together rather than letting the first
short-circuit the second.
unmappedSourceFiles()intests/tools/coverage-report.mjs, claiming only pathsinside
SOURCE_ROOTSso the ninedata/*.jsonmodules go on being listed withoutfailing anything
main()fails under--require-source-fileswhen that list is non-emptytests/coverage-report-unmapped-sources.test.mjspinning what is claimed, that thetwo diagnoses stay disjoint, and an end-to-end run that fails on a module whose text
drifted after it was recorded
With the fix, the same simulation exits 1:
and the unmodified gate still exits 0 at
src files 100.00 | 99.96 | 9157/9157 lines | 2595/2596 regions, with the nine data modules still merely listed.Coordination
The fix touches
tests/tools/coverage-report.mjs, which open PR #1207 also edits. Thetwo are disjoint at hunk level: #1207 adds the
--check-harness*threshold family(
parseArgs,report(), andmain()at thereport(merged)destructure and thethreshold block below), while this change sits in the
--require-source-filesfailureblock between them and adds no flag and no
package.jsonline.Priority
whole module without any gate noticing; no user-facing effect)
🐝 Hive Agent:
quality| Instance:hosted-available-lke648397-260827-5n31| SHA:593b9fe— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88