$npx -y skills add livlign/claude-skills --skill coverage-reportProduce the latest deterministic C0/C1 coverage report for a .NET service. Use when the user asks for a 'coverage report', 'coverage status', 'what's covered', 'C0 C1 numbers', or wants to check the gate. Runs dotnet-coverage + ReportGenerator (numbers are tool output, never esti
| 1 | # coverage-report |
| 2 | |
| 3 | Numbers come only from the tool. The model never estimates, infers, or rounds coverage. |
| 4 | The model's only role is joining tool output to the manifest's reasons and narrating the |
| 5 | observations section. |
| 6 | |
| 7 | Read `${CLAUDE_PLUGIN_ROOT}/rules/coverage-report.base.md` and the repo's |
| 8 | `.claude/coverage/refs/coverage-manifest.yml` first. |
| 9 | |
| 10 | ## One command, any time |
| 11 | |
| 12 | The whole report is one wrapper — no arguments needed (it auto-detects the `.sln`): |
| 13 | |
| 14 | ``` |
| 15 | ./.claude/coverage/tools/report.sh |
| 16 | ``` |
| 17 | |
| 18 | It collects coverage, joins it against the manifest, and **writes a dated per-run folder |
| 19 | `.claude/coverage/reports/<YYYY-MM-DD>/` containing `REPORT.md`, `REPORT.html`, and |
| 20 | `CANNOT-TEST.md`**, then prints the Markdown and exits non-zero if the ratchet fails (so it |
| 21 | doubles as a local gate). Each run writes its own dated folder rather than overwriting a fixed |
| 22 | path, so prior dates are preserved for comparison; override the date with `REPORT_DATE=YYYY-MM-DD` |
| 23 | to re-emit under a specific day. `CANNOT-TEST.md` is generated from the manifest `cannot_test` |
| 24 | entries (grouped by blocking construct, each row citing target, reason, and unlock), not |
| 25 | hand-written. This is the *identical* join CI runs — the report a developer sees locally is the report on |
| 26 | the PR. When invoked as the `coverage-report` skill, just run it and surface the result; |
| 27 | don't re-derive numbers by hand. |
| 28 | |
| 29 | ## Steps |
| 30 | |
| 31 | 1. **Run the wrapper.** `./.claude/coverage/tools/report.sh` (or, before init has copied it, |
| 32 | `${CLAUDE_PLUGIN_ROOT}/scripts/report.sh`). Pass a solution path or repo-filter only if |
| 33 | auto-detect is wrong. If the tools or solution are missing, report that — never fabricate |
| 34 | numbers. All numbers come from the tool + the deterministic join in `coverage-gate.py`; the |
| 35 | model does not parse XML or compute percentages. |
| 36 | |
| 37 | 2. **Append the one narrated section — Observations.** The script's report is complete and |
| 38 | deterministic (verdict, headline, Do-next, insights, by-bucket). The *only* thing the model |
| 39 | adds is **Observations**: suspected-latent-bug entries surfaced during generation (frozen, |
| 40 | not endorsed). Append them under an `## Observations` heading; add nothing else. |
| 41 | |
| 42 | 3. **At baseline only.** Write the measured Adjusted overall into `baseline.recorded_overall` |
| 43 | (with `basis: in-scope`) so it becomes the ratchet floor. Not on ordinary report runs. |
| 44 | |
| 45 | ## Report shape — the Unit Test Report (produced by `coverage-gate.py`) |
| 46 | |
| 47 | Fixed six-section report card. Header carries commit / branch / date / tooling / verdict; |
| 48 | coverage is two-pass throughout — **Adjusted** (target set, the headline + ratchet basis) and |
| 49 | **Raw** (all instrumented), for C0, C1, and Method. |
| 50 | |
| 51 | ``` |
| 52 | # Unit Test Report — <repo> |
| 53 | <commit · branch · date · tooling · verdict (gate PASS/FAIL · Adjusted C0/C1)> |
| 54 | |
| 55 | ## 1. Test Results total / passed / failed / skipped / flaky / duration (from .trx) |
| 56 | ## 2. Coverage Summary Raw | Adjusted | Baseline | Δ, for C0 / C1 / Method; + the Gate block |
| 57 | (ratchet always; diff-coverage + scope-change guard in PR mode, --base) |
| 58 | ## 3. Coverage by Layer columns: Layer | Raw lines | Raw branches | Testable lines | |
| 59 | Testable branches | C0 | C1 — where C0/C1 cells are "NN% (covered/total)" |
| 60 | over the testable slice (covered counts fold into the cell, no separate |
| 61 | covered columns). Rows are |
| 62 | human LAYER names (Application/Service — TARGET, Infrastructure/Integration, |
| 63 | Presentation/Workers, Models/DTOs, Generated, Non-product) mapped from the |
| 64 | manifest categories — NEVER the raw `excl: <category>` strings (an `excl:` row |
| 65 | showing a coverage % read as "excluded but covered??"). Raw = all code in the |
| 66 | layer; Testable = its unit-testable slice (whole file in the target layer; only |
| 67 | carve-out methods elsewhere); C0/C1 are of the testable slice. Only the target |
| 68 | layer feeds the Adjusted headline. + a per-file table (same columns + the file's |
| 69 | Layer) so a 1631-line infra file reading as 131 testable lines is clear. |
| 70 | ## 4. Risk Hotspots methods with complexity ≥5 and coverage <80%, sorted TARGET-FIRST, with a |
| 71 | "What to do" column + per-bucket guidance (target=unit-test; integration= |
| 72 | integration test/extract carve-out; e2e=E2E/refactor) and a takeaway line |
| 73 | calling out how many are real in- |