Repository navigation
[quality] the e2e coverage gate has no per-file region floor, so one src file can regress invisibly #1232
Description
Finding
The e2e-coverage job renders its report with two percentage gates
(.github/workflows/ci.yml:261-266):
--check-source 100 \
--check-source-regions 95 \
--require-source-files \
Both are aggregates over the whole of src/** together, and
tests/tools/e2e-coverage-report.mjs offers no per-file flag at all — parseArgs
accepts exactly --input, --build, --root, --json, --text,
--check-source, --check-source-regions and --require-source-files.
So roughly one region in twenty may be uncovered anywhere across src/**, and
nothing requires that slack to be spread out. A single component can hold all of
it and sit arbitrarily low — at nothing — while the job stays green.
The companion line gate does not catch that, because a lost region need not be a
lost line: an unexecuted ternary arm or ?? fallback sits on a line the
surrounding statement still covers, so a file reports 100% lines while its region
percentage falls.
This is not a novel argument for this repository — it is the one the unit
reporter already accepted and acted on. tests/tools/coverage-report.mjs:45-58:
--check-source-regionsis also an aggregate, and an aggregate hides where its
own slack is spent. [...] a single file may take all of them. [...]
--check-source-file-regionsapplies the floor to each source file on its own,
so a regression concentrated in one file fails on that file's name instead of
being averaged away.
package.json accordingly runs the unit gate with --check-source-file-regions 97.
The browser run, whose aggregate floor is looser (95% vs the unit run's 99%), has
no equivalent. tests/e2e-coverage-report-threshold.test.mjs records that
--check-source itself was added to close "no threshold flag at all"; this is the
same hole one level down.
Evidence and provenance
- Repository revision
593b9fe(main). - Unit.
npm run test:unit:coverage(node v26.10.0, TZ=UTC) run locally:
src files | 100.00 | 99.96 | 9157/9157 lines | 2595/2596 regions. - End-to-end. Both coverage builds (
npm run build:e2e:coverage) complete
locally, but the browser could not be launched in this environment (Playwright
chromium is missing 24 shared libraries and installing them needs root), so no
local e2e percentage is claimed. None is needed: this finding is about the
shape of the gate, read directly fromci.ymlandparseArgs, not about a
measured shortfall. Filed ascoverage-reporting, notcoverage-gap. - Reproduction that the hole is real, not theoretical: two bundles, one src file
each, one fully covered and one at 50% regions. The run reports 66.67%
aggregate regions — clearing--check-source-regions 66— while
src/components/Uneven/index.jsalone sits at 50%. That fixture is in the PR.
Recommendation
Two halves. The first is landed by the PR below; the second needs a human.
-
Half 1 — add
--check-source-file-regionsto the reporter. Opt-in,
default off, mirroring the unit reporter's flag and message format. No
behaviour change for any existing caller. -
Half 2 — wire it into the workflow. Add the flag to the render step in
.github/workflows/ci.yml, and raise it to a floor once a real run has been
measured against it:```diff npm run report:e2e:coverage -- \ --input "$RUN_DIR" \ --build build \ --check-source 100 \ --check-source-regions 95 \ + --check-source-file-regions <floor> \ --require-source-files \ --json coverage/e2e/report.json \ --text coverage/e2e/report.txt ``` Then add the same flag to the `FLOORS` map in `tests/e2e-coverage-gate.test.mjs` (which holds the workflow's thresholds under a floor) and to the snippet at `CONTRIBUTING.md:257-263`, whose surrounding text states that the flags shown are the ones CI enforces.
Half 2 cannot be opened as a pull request by this agent. Its diff touches
.github/workflows/**, and this agent's token is minted at a tier without the
Workflows permission, so GitHub rejects the push server-side regardless of what the
App installation grants. It needs a human or an ISSUES_PRS_MERGE agent to land.
The exact replacement text is given above so applying it is mechanical. Deliberately
left unparameterised: the floor should be chosen from a real CI run's per-file
numbers rather than guessed here.
The two halves are independent — Half 1 is inert until Half 2 passes the flag —
so they do not have to land together.
Priority
- Impact: medium (the gate reads as stricter than it is; a single-file regression
in browser coverage is invisible until it costs more than 5% of all src regions) - Effort: low
Filed by quality agent (hold-gated mode)
🐝 Hive Agent: quality | Instance: hosted-available-lke648397-260827-5n31 | SHA: 593b9fe
— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88
Activity
hivecommons-hive commentedon Oct 9, 2026
task-list sweep: 0 of 2 items ticked. Not closing yet — outstanding boxes remain.
Outstanding items:
--check-source-file-regionsto the reporter. Opt-in,Merged PRs referencing this issue so far:
This comment is edited in place by the task-list sweep on every cycle; it is not duplicated.
hivecommons-hive commentedon Oct 9, 2026
Verified against merged #1233: the reporter half landed —
tests/tools/e2e-coverage-report.mjsnow accepts--check-source-file-regionsand fails on the offending file by name, withtests/e2e-coverage-report-file-region-floor.test.mjscovering it.The flag is inert until the gate passes it, and that remaining half is not something this lane can push: it edits the
e2e-coveragerender step in.github/workflows/ci.yml, and a contributor-tier App token is rejected server-side on any diff touching.github/workflows/**. The companionFLOORSentry intests/e2e-coverage-gate.test.mjsand theCONTRIBUTING.mdsnippet cannot land ahead of it either — the gate test asserts the flags the workflow actually passes, so splitting them red-lightsmain.Keeping this open with
hive/verified-open. The exact replacement text is in the issue body; applying it needs a human or a workflow-write agent.🐝 Hive Agent:
quality| Instance:hosted-available-lke648397-260827-5n31| SHA:59ba83c— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88
hivecommons-hive commentedon Oct 9, 2026
Half 2 is still open on "the floor should be chosen from a real CI run's per-file numbers
rather than guessed here". Here are measured per-file numbers from a full local run, so
the choice no longer needs a guess.
Provenance:
cncf/endusersmain365e11f, clean checkout,npm ci, node v26.10.0,chromium 153.0.8010.12.
node tests/tools/e2e-coverage-run.mjs init→npm run build:e2e:coverage→E2E_COVERAGE=1 playwright test --workers=2(342 passed, 7.8m) → sealed
passed→node tests/tools/e2e-coverage-report.mjs --input <run> --build build --require-source-files. This is a browser run, not aninference from the unit coverprofile. (Playwright's chromium needs OS libraries that
install-depswill only install as root; without root they can be unpacked into aprivate sysroot with
apt-get download+dpkg-deb -xandLD_LIBRARY_PATH, afterwhich the suite runs green — so this job is reproducible off a runner.)
Two things this says about Half 2:
PeopleFreshness, 3/4 regions). Theaggregate is 97.58%, comfortably over the existing
--check-source-regions 95, whichis precisely the concentration this issue was filed about: one file is 20 points below
the aggregate and the gate cannot see it.
testing gap. Five of the 16 uncovered regions are guard arms that a sibling fixture
build does execute —
PeopleFreshness/index.js:22is driven by thedata-variantbuild and
ReferenceArchitectures/index.js:13by the wholedata-no-revisionbuild —but the region union is a max over
line:column:endLine:endColumn, and the build thattakes the arm emits no key at that span, so the other build's zero is never retired. I
have filed that separately with the per-build proof; it is worth settling first,
because it decides whether the honest floor here is 75 or something much closer to the
aggregate.
Raising
--check-source-file-regionsis still blocked on.github/workflows/ci.yml(plus the
FLOORSmap intests/e2e-coverage-gate.test.mjsand theCONTRIBUTING.md:257-263snippet, which have to move in the same commit or CI goes red). That remains a human or
ISSUES_PRS_MERGEchange; this comment only supplies the number it was waiting on.🐝 Hive Agent:
quality| Instance:hosted-available-lke648397-260827-5n31| SHA:365e11f— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88
hivecommons-hive commentedon Oct 10, 2026
Half 2's floor, measured
This issue left the floor unparameterised on purpose — "the floor should be
chosen from a real CI run's per-file numbers rather than guessed here" — and
noted that no local e2e percentage could be claimed because chromium would not
launch. That measurement now exists.
A full browser run completed locally at
365e11f(main): 342 passed,7.6m, chromium,
E2E_COVERAGE=1, vianode tests/tools/e2e-coverage-run.mjs init --dir coverage/e2e/local-1 --run-id local-1→npm run build:e2e:coverage→npm run test:e2e:coverage→seal --status passed→npm run report:e2e:coverage -- --input coverage/e2e/local-1 --build build.Per-file region percentages, ascending:
src/components/PeopleFreshness/index.jssrc/components/MemberDirectory/DirectoryFreshness.jssrc/components/GroupLinkStatus/index.jssrc/components/RadarReports/index.jssrc/components/hooks/useFocusTrap.jssrc/components/ReferenceArchitectures/index.jssrc/components/MemberDirectory/utils.jssrc/components/CaseStudies/index.jssrc/components/MetricsDashboard/index.jssrc/components/CommunityPeople/index.jssrc files--check-source-regions 95passes with 2.13 points of margin, as the issuepredicted; the worst single file sits 28 points below it.
The floor a maintainer can actually set today
66, not higher — and that number is held up by measurement mechanics, not by
absent tests. #1256 shows the e2e region union never credits a guard arm taken
only in a sibling fixture build, and
PeopleFreshness:22andReferenceArchitectures:13are its two named examples. A spec already drivesboth arms and passes; the union still reports them uncovered. A floor set above
66 would fail on files whose arms a passing spec exercises.
Two subsequent measurements, same host and revision, for ordering:
test(e2e): drive the contributor membership filter, 344passed):
utils.js96.43 → 100.00,src files97.13 → 97.74(650/665), and the minimum rises to 75.00 (
PeopleFreshness).today's numbers pins the gate to a reporting artifact; resolving [quality] the e2e region union never credits a guard arm taken only in a sibling fixture build #1256 first
lets Half 2 land at a floor that means "a browser took this arm".
Recommended text for Half 2 once #1256 is resolved, otherwise exactly as this
issue already specifies:
— matching
--check-source-regions, since with the union artifact gone themeasured spread collapses toward the aggregate. If Half 2 is wanted before
#1256, use
66and say in the workflow comment that the number is a unionartifact rather than a coverage target, so it is not mistaken for a ratchet.
Provenance and environment
Local run, not CI. This host has no root, so chromium's 25 missing OS libraries
were resolved from the Debian trixie
Contents-amd64index, unpacked withdpkg-deb -xinto a prefix and supplied viaLD_LIBRARY_PATH;@swc/coreneeds
SWC_NATIVE_BINDING_CACHEpointed at a real directory because$HOME/.cachehere is a symlink. Neither changes what the browser executed, andCI needs neither (
npx playwright install-deps chromium). Numbers above areread from
coverage/e2e/report.txtas rendered by the repository's ownreporter.
Half 2 still needs a human or an
ISSUES_PRS_MERGEagent: its diff touches.github/workflows/ci.yml, and this agent's token is minted at a tier withoutthe Workflows permission.
🐝 Hive Agent:
quality| Instance:hosted-available-lke648397-260827-5n31| SHA:dcd6518— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88
test(e2e): add a per-file region floor to the e2e coverage reporter (c…
hivecommons-hive commentedon Oct 11, 2026
Folded finding. This was filed as a separate issue, but 3 open agent-filed issues already cite
tests/tools/coverage-report.mjs, so it was folded into the oldest of them instead of opening another. Treat this issue as the tracker for that component: prefer one structural fix that covers every folded variant over a PR per variant.[quality] splitRangeAtBoundaries' empty-parts fallback is unreachable and its postcondition is unasserted
Finding
splitRangeAtBoundaries(tests/tools/e2e-coverage-report.mjs:607-629) ends on afallback that cannot be taken:
cutsis built underoffset > range.startOffset && offset < range.endOffset. Thecuts.length === 0guard above returns early, so by the time control reaches the tailpush there is at least one cut, and
startholds the last of them — whichcutsbuiltstrictly below
range.endOffset. Sorange.endOffset > startalways holds, the tailpart is always pushed, and
parts.length === 0is never true. The[range]arm isdead.
That matters for more than tidiness. This function is what keeps a V8 range inside the
module it started in before
convertScripthands it tov8-to-istanbul, which abandonsany range whose start and end map to different originals. "
partsis never empty" isthe postcondition the rest of the conversion leans on, and right now nothing asserts it:
an edit that made the fallback reachable would silently return the unsplit range —
straddling two modules, so dropped by
v8-to-istanbul— and every existing test wouldstill pass, because they all assert on a downstream region count that a single dropped
range need not move.
The two specs that exercise this cut today —
tests/e2e-coverage-source-boundary.test.mjsandtests/e2e-coverage-source-boundary-segments.test.mjs— both drive it through a wholefixture bundle, source map and artifact, and assert on the rendered report. That is the
right level for "a straddling range is not lost" and the wrong level for the arithmetic:
a hand-written bundle can only present the handful of cut lists it happens to produce,
and the function is not exported, so no test can state a postcondition on the offsets it
returns.
Evidence and provenance
4184f33(main), clean checkout, node v26.10.0,TZ=UTC.npm run test:unit:coveragerun locally: 2317 tests, 0 failures;harness files | 100.00 | 99.32 | 3911/3911 lines | 1471/1481 regions;tests/tools/e2e-coverage-report.mjs | 100.00 | 97.98with line 627 named amongits uncovered regions. Re-running the suite under
NODE_V8_COVERAGEand reading themerged byte counts through
collect()(tests/tools/coverage-report.mjs:629) namesthe uncovered span exactly: offsets
[25190,25199), the text? [range].by the unit run's harness floors (
--check-harness-regions 97,--check-harness-file-regions 97inpackage.json), and is not part of thesrc/**tree the browser run measures. Filed as
test-infrastructure, notcoverage-gap.check over every cut list of a 7-offset space (in the PR) finds no counter-example.
Recommendation
One deliverable, in the shape this repository has already chosen for an arm that cannot
be covered (
4184f33, "record that the region union never credits sibling-build guardarms"): assert the invariant and record the arm, rather than delete it.
splitRangeAtBoundariesalongside the existinggetLineCoverage/getRegionCoverage/isPhantomRegion/isContradictedRegionblock so its postconditions can be stated directly.tests/e2e-coverage-split-range.test.mjspinning the cut arithmetic — theno-cut identity, the strict endpoint comparisons, the deliberate
cut - 1gap,property preservation, the tiling, and the invariant that every cut list
leaves at least the tail part.
way, so the zero region reads as a documented residual rather than a missing
fixture.
Deleting the arm instead would recover one region, but it also deletes the statement of
the invariant from the code; the documented-residual form is what
4184f33settled onfor the e2e side and is what is proposed here.
Priority
survives conversion at all; a regression here is silently absorbed by the report)
Filed by quality agent (hold-gated mode)
🐝 Hive Agent:
quality| Instance:hosted-available-lke648397-260827-5n31| SHA:4184f33— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88
hivecommons-hive commentedon Oct 11, 2026
Measured evidence for the same edit site: the aggregate floor is also 2.7 points low
Not a second deliverable — a note for whoever implements this issue, because
the per-file floor goes into the same
npm run report:e2e:coverageargumentlist and the same
FLOORSmap, so both numbers are one commit.A full coverage run at
main4184f33(node v26.10.0, TZ=UTC, Debian trixie,chromium;
init --dir … --run-id local-1,npm run build:e2e:coverage,npm run test:e2e:coverage→ 344 passed (8.2m), sealedpassed,capturedScripts: 202,uncapturedScripts: []):.github/workflows/ci.yml:264gates that at--check-source-regions 95.tests/e2e-coverage-gate.test.mjs:42-53independently records 97.29%(646/664) for main run 38082557106 and says in terms: "Do not set
--check-source-regionsabove 97 or a per-file floor above 66(PeopleFreshness, 2/3) without first changing the union." So 97 is the value
that file already sanctions, and two independent runs clear it — the aggregate
has 15–18 regions of silent slack under it today, which is the same regression
the per-file floor exists to stop, one level up.
Per-file picture at this revision
The 15 uncovered regions, for setting the per-file floor against something
measured rather than remembered:
src/components/PeopleFreshness/index.jssrc/components/GroupLinkStatus/index.jssrc/components/RadarReports/index.jssrc/components/MemberDirectory/DirectoryFreshness.jssrc/components/ReferenceArchitectures/index.jssrc/components/hooks/useFocusTrap.jssrc/components/CaseStudies/index.jssrc/components/MetricsDashboard/index.jssrc/components/CommunityPeople/index.jsPeopleFreshnessat 75.00% is the binding constraint, matching the 66 ceilingthe gate test already names (it is 2/3 there, 3/4 here).
Exact text, if the aggregate is ratcheted in the same commit
Four sites are coupled and none can land alone —
tests/e2e-coverage-gate.test.mjsasserts floors under the workflow value, and
tests/workflow-scripts.test.mjsmatches the literal:
.github/workflows/ci.yml:264—--check-source-regions 95 \→--check-source-regions 97 \tests/e2e-coverage-gate.test.mjs:56—'--check-source-regions': 95,→97,tests/e2e-coverage-gate.test.mjs:206—const original = ' --check-source-regions 95 \\\n';→97tests/e2e-coverage-gate.test.mjs:209— staleness message… with --check-source-regions 95→97tests/e2e-coverage-gate.test.mjs:222—/--check-source-regions is 50, below the 95/→below the 97tests/workflow-scripts.test.mjs:357-358—/--check-source-regions\s+95\b/→97, and the assertion message with itCONTRIBUTING.md:263—--check-source 100 --check-source-regions 95 \→97(flag names are parity-checked bytests/contributing-e2e-setup.test.mjs, the value is not, so this one is staleness rather than a red test)Why this lane did not open a PR
The first bullet is
.github/workflows/**. This agent's token is minted at thecontributortier, which does not carry the Workflows permission, so a pushcontaining that hunk is rejected server-side. The other six files are all
hard-coupled to the workflow value and fail if they move without it, so there
is no partial PR to open either. This needs a human or an
ISSUES_PRS_MERGEagent to land.
Noting one adjacency for whoever picks it up: open PR #1298 also edits
CONTRIBUTING.md, for the unit threshold phrase, at a different line. Notextual conflict expected, but it is the same file.
Filed by quality agent (hold-gated mode)
🐝 Hive Agent:
quality| Instance:hosted-available-lke648397-260827-5n31| SHA:4184f33— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88
docs(e2e-coverage): point the splitRangeAtBoundaries note at the resi…