The standalone Coverage (metrics only) job in verify-extended.yml re-ran the entire suite (bun test --coverage test/unit/ test/integration/) as a second job, doubling Extended-Verification runtime on every dispatch with little added value. It was removed in #22 to stop the duplicate work. This issue tracks re-introducing coverage the right way.
Goal
Produce coverage from the integration run that already happens (one run, not two), and emit it per platform so coverage can be compared across Windows/macOS/Linux and x64/arm64.
Why it is not trivial
The integration jobs run tests in a per-file loop (separate bun test invocations) for CHR-boot isolation / sequential boot (avoids parallel-boot contention). bun cannot merge coverage across separate invocations, which is exactly why the old job used a single combined invocation instead.
Proposed design (validated: bun test --coverage --coverage-reporter=lcov --coverage-dir=<dir> works)
- In each integration job’s per-file loop, add
--coverage --coverage-reporter=lcov --coverage-dir=coverage to the existing bun test "$f" call. These flags do not change pass/fail, so the gating result is unaffected.
- After each file, move
coverage/lcov.info to a per-file name (it is overwritten each invocation), e.g. coverage/$(echo "$f" | tr "/." "__").lcov.
- After the loop, merge all
coverage/*.lcov with a small portable bun script (scripts/merge-lcov.ts, no deps) that sums DA:/FNF:/FNH: records and prints line% + function%.
- Append the merged numbers to the job summary and upload
coverage/ as coverage-<platform-label> for cross-platform comparison.
- Guard every coverage step with
if: always() + non-fatal (|| true) so coverage plumbing can never red a gating integration job.
Notes
Follow-up from #22 (review item 3 — “rework the Coverage (metrics only) implementation”).
The standalone Coverage (metrics only) job in
verify-extended.ymlre-ran the entire suite (bun test --coverage test/unit/ test/integration/) as a second job, doubling Extended-Verification runtime on every dispatch with little added value. It was removed in #22 to stop the duplicate work. This issue tracks re-introducing coverage the right way.Goal
Produce coverage from the integration run that already happens (one run, not two), and emit it per platform so coverage can be compared across Windows/macOS/Linux and x64/arm64.
Why it is not trivial
The integration jobs run tests in a per-file loop (separate
bun testinvocations) for CHR-boot isolation / sequential boot (avoids parallel-boot contention).buncannot merge coverage across separate invocations, which is exactly why the old job used a single combined invocation instead.Proposed design (validated:
bun test --coverage --coverage-reporter=lcov --coverage-dir=<dir>works)--coverage --coverage-reporter=lcov --coverage-dir=coverageto the existingbun test "$f"call. These flags do not change pass/fail, so the gating result is unaffected.coverage/lcov.infoto a per-file name (it is overwritten each invocation), e.g.coverage/$(echo "$f" | tr "/." "__").lcov.coverage/*.lcovwith a small portable bun script (scripts/merge-lcov.ts, no deps) that sumsDA:/FNF:/FNH:records and prints line% + function%.coverage/ascoverage-<platform-label>for cross-platform comparison.if: always()+ non-fatal (|| true) so coverage plumbing can never red a gating integration job.Notes
ci.yml(push pipeline already reports unit coverage); this is Extended-Verification-only.Follow-up from #22 (review item 3 — “rework the Coverage (metrics only) implementation”).