$npx -y skills add livlign/claude-skills --skill coverage-initInitialize the coverage backfill in a .NET repo. Use when setting up dotnet-coverage-kit in a new service for the first time, or when the user says 'init coverage', 'set up coverage backfill', or 'scaffold the coverage manifest'. Detects the repo's architecture and projects, swee
| 1 | # coverage-init |
| 2 | |
| 3 | Run once per repo. Discovers the repo's shape and drafts the per-repo config. It DRAFTS; |
| 4 | a human reviews and corrects before any test generation. Never proceed to generation in |
| 5 | the same turn. |
| 6 | |
| 7 | ## Precondition — run on the latest production branch (master) |
| 8 | |
| 9 | The manifest, the detected structure, and the baseline number must reflect the code that |
| 10 | ships, not an in-flight feature branch. Before doing anything else: |
| 11 | |
| 12 | 1. Confirm the repo is on the production branch (master). If checked out on a feature/topic |
| 13 | branch, **stop** and ask the user to switch — do not init against feature work. |
| 14 | 2. Pull it up to date with the remote (`git fetch` + fast-forward) so the baseline matches |
| 15 | the current tip of master. |
| 16 | 3. Confirm a clean working tree. Uncommitted local changes skew detection and the baseline; |
| 17 | if the tree is dirty, stop and report rather than measuring against unknown edits. |
| 18 | |
| 19 | State the branch and commit you initialized against in the step 11 report, so the eventual |
| 20 | `baseline.ref` is traceable to a real production commit. |
| 21 | |
| 22 | ## Steps |
| 23 | |
| 24 | 1. **Detect SDK-style.** Confirm projects are SDK-style `.csproj` (dotnet-coverage only |
| 25 | supports these). If any target project is a legacy non-SDK `.csproj`, stop and report |
| 26 | it — that project needs coverlet instead and is out of scope for this kit. |
| 27 | |
| 28 | 2. **Inventory projects.** List `.csproj` files and their references. Identify the test |
| 29 | project(s) and what they reference. Identify likely roles (domain, application, |
| 30 | infrastructure, presentation, workers) from project names, references, and folder |
| 31 | layout. Detect whether MediatR is present (handlers vs pipeline behaviors). |
| 32 | |
| 33 | 3. **Derive the TARGET-set hypothesis from the repo's architecture — do NOT apply a fixed |
| 34 | template.** The target is the code whose coverage is counted toward the headline |
| 35 | ("Adjusted") number. This step only forms the *hypothesis* of where target code lives; the |
| 36 | sweep (step 4) classifies the actual files. Based on step 2: |
| 37 | - **Clean / layered** (distinct `*.Domain`, `*.Application` assemblies): candidate target is |
| 38 | those layer assemblies; Infrastructure/Api/Web are informational. |
| 39 | - **Service-oriented / flat** (no layer assemblies; logic in service projects or sub-folders |
| 40 | of an API project): candidate target is the business-logic projects/sub-folders |
| 41 | (e.g. `Account.API/Service/**`), by name + content — do not promote a whole API project if |
| 42 | its logic is confined to a sub-folder. |
| 43 | - **No discernible structure**: `uncategorized`; do not invent layering. |
| 44 | |
| 45 | Everything outside the target is **informational**: still collected and shown, but not |
| 46 | counted toward Adjusted. The report is two-pass — *Raw* (all instrumented code) and |
| 47 | *Adjusted* (target only); the ratchet gates Adjusted. Nothing is hidden. |
| 48 | |
| 49 | 4. **Sweep — classify EVERY source file against the rubric, in parallel (ask first).** |
| 50 | Enumerate all source files: the candidate-target globs from step 3 **and** the rest of the |
| 51 | instrumented production code (so exclusions are evidence-based, not assumed). **Read every |
| 52 | file.** Do not classify by name/folder alone, do not skip small files, do not sample — |
| 53 | small files get misclassified too, and fanning the sweep out removes the cost reason that |
| 54 | ever justified skipping. |
| 55 | |
| 56 | Every file is classified by an **objective signal in the source**, cited at `file:line` |
| 57 | (each rule is a concrete condition — the spec a future static-analysis helper would |
| 58 | automate): |
| 59 | |
| 60 | | Classification | Objective signal that justifies it | |
| 61 | |---|---| |
| 62 | | `dto-no-logic` | only auto-properties / fields; no method body branches (`if`/`switch`/`?:`/loop); cyclomatic complexity ≈ 1. **Not** an AutoMapper `Profile`/mapping-config class (those are `mapper-config`, below) | |
| 63 | | `mapper-config` | an AutoMapper `Profile` or mapping/DI-config class: declarative `CreateMap`/registration only, no branches today. Labeled distinctly from `dto-no-logic` so a future conditional `MapFrom`/`ConvertUsing` is not silently hidden under a "data carrier" label | |
| 64 | | `integration-scope` | depends on a NON-SUBSTITUTABLE infrastructure boundary: a `DbContext` |