build(coverage): gate line coverage per assembly; record the 2.0 decisions #20

Merged
james.maes merged 3 commits from build/2.0-coverage-gate-20261110 into release/2.0 2026-11-10 18:13:07 +00:00
Owner

What

First pull request of the 2.0 line (target: release/2.0, not main).

  • build/Verify.ps1 now fails when an assembly is below its minimum in build/minimum-coverage.json.
  • build/Assert-Coverage.ps1 merges the suites' reports line by line, takes a per-assembly minimum, and rejects a measured assembly the file does not list.
  • docs/adr/0003-version-2.md records the 2.0 decisions and supersedes the coverage waiver in ADR-0002.
  • CLAUDE.md, AGENTS.md, CONTRIBUTING.md and coverage.runsettings drop the statements this makes false. The child-process test fixture is no longer measured.

Why

Coverage was collected but never enforced: the gate script existed and had tests, yet nothing called it. The 2.0 quality bar (100% Core, 90% Windows) needs a gate that can only move up from today's numbers.

How it was tested

  • Full build/Verify.ps1 locally on this branch: 197 Core and 377 Windows tests pass, zero build warnings, gate passes at Core 87.19%, Windows 68.91%, CLI 38.26% against minimums of 86 / 68 / 38.
  • build/Assert-Coverage.Tests.ps1 under Pester 5.7.1: 14 passed, including the four original cases unchanged.
  • PSScriptAnalyzer 1.25.0 with the repository settings on the three changed scripts: no findings.
  • check-source-headers.py: 319 tracked files verified.
  • Windows coverage moved between 69.04% and 68.91% across two runs of the same commit, which is why the minimum is 68 and not 69.

Not done here: no installer build, no install, no printing, nothing on main.

Checklist

  • Commits are signed and signed off (git commit -S -s)
  • Zero build warnings; format and lint are clean
  • Tests added or updated; the coverage gate still passes
  • Docs updated for user-visible changes
  • No secrets, credentials, or personal data
  • New dependencies are justified below, or none were added (none)
  • Substantial AI assistance, if any, is noted here: written with Claude Code (Claude Fable 5.2) under the owner's direction of 2026-11-10.

🤖 Generated with Claude Code

## What First pull request of the 2.0 line (target: `release/2.0`, not `main`). - `build/Verify.ps1` now fails when an assembly is below its minimum in `build/minimum-coverage.json`. - `build/Assert-Coverage.ps1` merges the suites' reports line by line, takes a per-assembly minimum, and rejects a measured assembly the file does not list. - `docs/adr/0003-version-2.md` records the 2.0 decisions and supersedes the coverage waiver in ADR-0002. - `CLAUDE.md`, `AGENTS.md`, `CONTRIBUTING.md` and `coverage.runsettings` drop the statements this makes false. The child-process test fixture is no longer measured. ## Why Coverage was collected but never enforced: the gate script existed and had tests, yet nothing called it. The 2.0 quality bar (100% Core, 90% Windows) needs a gate that can only move up from today's numbers. ## How it was tested - Full `build/Verify.ps1` locally on this branch: 197 Core and 377 Windows tests pass, zero build warnings, gate passes at Core 87.19%, Windows 68.91%, CLI 38.26% against minimums of 86 / 68 / 38. - `build/Assert-Coverage.Tests.ps1` under Pester 5.7.1: 14 passed, including the four original cases unchanged. - PSScriptAnalyzer 1.25.0 with the repository settings on the three changed scripts: no findings. - `check-source-headers.py`: 319 tracked files verified. - Windows coverage moved between 69.04% and 68.91% across two runs of the same commit, which is why the minimum is 68 and not 69. Not done here: no installer build, no install, no printing, nothing on `main`. ## Checklist - [x] Commits are signed and signed off (`git commit -S -s`) - [x] Zero build warnings; format and lint are clean - [x] Tests added or updated; the coverage gate still passes - [x] Docs updated for user-visible changes - [x] No secrets, credentials, or personal data - [x] New dependencies are justified below, or none were added (none) - [x] Substantial AI assistance, if any, is noted here: written with Claude Code (Claude Fable 5.2) under the owner's direction of 2026-11-10. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
james.maes added 1 commit 2026-11-10 16:47:52 +00:00
Coverage was collected but nothing failed on it: Assert-Coverage.ps1 existed
and was tested, yet neither Verify.ps1 nor CI called it. Verify.ps1 now runs
it after the tests against build/minimum-coverage.json.

The gate merges the suites' reports line by line, so an assembly that two
suites exercise is measured once on what either reaches, instead of by the
better single report. Each assembly has its own minimum, and a measured
assembly the file does not list fails, so a new one cannot ship ungated. The
minimums start at the measured baseline (Core 86, Windows 68, CLI 38) and only
move up; the release bar is 100 / 90 for Core / Windows. The child-process
test fixture is no longer measured.

ADR-0003 records the 2.0 decisions (several servers, a connection wizard,
view models, a versioned pipe contract, the coverage bar) and supersedes the
coverage waiver in ADR-0002. CLAUDE.md, AGENTS.md and CONTRIBUTING.md drop
the statements this makes false, including the rule that Core.Tests is
hosted-only on the maintainer's PC.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Signed-off-by: James Maes <james@kof22.com>
james.maes added 1 commit 2026-11-10 17:25:19 +00:00
Review of the first commit found no blockers and these gaps, now closed:

- The thresholds file was read leniently: null, "", false and "NaN" became
  a minimum the gate always met, and a repeated name overrode an earlier
  one. It is now parsed strictly: one object of numbers from 0 to 100, each
  name once ignoring case.
- A source file that could not be found under its report's roots was merged
  under its recorded name, which under-counts (Core read 73% instead of 87%
  on a moved tree) with nothing saying the merge was wrong; a file found
  under two roots could over-count. Both now fail with the file named.
- An unreadable or empty report now fails with a message instead of being
  skipped or failing obscurely.
- -ThresholdsPath can no longer be combined with -Packages/-MinimumPercent,
  which were silently ignored.
- The script ends with exit 0, so a caller checking $LASTEXITCODE does not
  read a previous command's exit code.
- Percentages print rounded down, so a value just under the minimum never
  prints as meeting it; paths print as they are on disk.

Tests grow from 14 to 30 and now cover reports with source roots (the path
every real run takes), in-process invocation, split ranges and each rejected
input.

The minimums follow one written rule: measured value rounded down, less one
point, because five timing-dependent lines of the Windows layer are reached
on some runs and not others. That gives 86 / 68 / 37. The docs no longer
claim exception records that are not filed, state the CLI release bar, and
say that changed-line coverage is not yet measured.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Signed-off-by: James Maes <james@kof22.com>
james.maes added 1 commit 2026-11-10 17:40:48 +00:00
The host note said where Core.Tests can be built by describing one
machine's security configuration. A public repository is the wrong place
for that. The note now says only that Core.Tests is built where the owner
allows it, and that a quarantined build means stop and ask.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Signed-off-by: James Maes <james@kof22.com>
james.maes merged commit 1431d8c328 into release/2.0 2026-11-10 18:13:07 +00:00
Sign in to join this conversation.