@bensandee/tooling 0.55.1 → 0.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -162,6 +162,80 @@ Convention and overrides coexist — a repo can use both.
162
162
 
163
163
  Works for both `changesets` and `simple` release strategies, on Forgejo (via API upload) and GitHub (via `gh release upload --clobber`). The asset step in the workflow is gated on the release itself having published/pushed, so failed releases never upload stale artifacts.
164
164
 
165
+ ### Coverage tracking
166
+
167
+ | Command | Description |
168
+ | -------------------------- | --------------------------------------------------------------------------------------------- |
169
+ | `tooling coverage:summary` | Print a labeled per-package summary of the latest run. `--json` for machine-readable form. |
170
+ | `tooling coverage:check` | Compare the latest run against `coverage-baseline.json`; exit non-zero on regression. |
171
+ | `tooling coverage:record` | Append the latest run to a `bst/coverage-metrics` orphan branch (CI: push to default branch). |
172
+ | `tooling coverage:status` | Show recent coverage trend. Read-only — fetches the orphan branch, no checkout. |
173
+
174
+ The feature has two halves: a **CI history** that captures one record per commit on the default branch (visible to anyone with the repo), and a **local ratchet** that the agent (or developer) consults before declaring a task complete.
175
+
176
+ #### How it works
177
+
178
+ `repo:sync` enables coverage tracking automatically when a `vitest.config.ts` is present. The generated `vitest.config.ts` includes the `json-summary` reporter so each `pnpm test:coverage` writes `coverage/coverage-summary.json` alongside the human-readable HTML report. A generated `coverage.yml` workflow runs on push to the default branch and pipes:
179
+
180
+ ```text
181
+ pnpm test:coverage → coverage:summary → coverage:record → coverage:status
182
+ ```
183
+
184
+ so every CI log ends with the trend table for the last 10 records.
185
+
186
+ The history file (`coverage-history.jsonl`) lives on a dedicated `bst/coverage-metrics` orphan branch — never on `main`. This sidesteps branch protection (no privileged token needed beyond `contents: write`) and keeps `git log main` clean. `coverage:record` uses pure git plumbing (`hash-object` → `mktree` → `commit-tree` → `push --force-with-lease`) so the working tree is never touched, and concurrent CI runs are handled safely via compare-and-swap with retry.
187
+
188
+ #### The local ratchet
189
+
190
+ A tracked `coverage-baseline.json` at the repo root captures the four overall totals (lines/statements/branches/functions) plus per-package numbers. `coverage:check` compares the latest run against it and exits non-zero if any total drops more than the configured `tolerancePp` (default 0.1). When all four are flat-or-up, `--update-baseline` rewrites the file so it can be staged with the change.
191
+
192
+ `repo:sync` also inserts a `<!-- @tooling:coverage-rule -->` managed block into `CLAUDE.md` describing the workflow:
193
+
194
+ > Before declaring a task complete that touched files under `packages/*/src/`, run `pnpm test:coverage` then `pnpm exec bst coverage:check`. If any total dropped, add tests until parity is restored — or, if a touched file is genuinely not worth covering, exclude it via `coverage.exclude` in `vitest.config.ts` and explain why in the commit message. If all four are flat-or-up, run `pnpm exec bst coverage:check --update-baseline` and stage `coverage-baseline.json`.
195
+
196
+ Skip the rule for docs-only, config-only, dependency-bump, or test-only changes.
197
+
198
+ #### Bootstrap
199
+
200
+ On a clean default branch, generate the initial baseline:
201
+
202
+ ```bash
203
+ pnpm test:coverage
204
+ pnpm exec bst coverage:check --update-baseline --no-fail-on-missing-baseline
205
+ git add coverage-baseline.json
206
+ ```
207
+
208
+ The first CI run on the default branch creates the orphan `bst/coverage-metrics` branch automatically. From any clone, inspect the trend with:
209
+
210
+ ```bash
211
+ pnpm exec bst coverage:status --limit 20
212
+ ```
213
+
214
+ #### Opt-out
215
+
216
+ Disable the feature entirely:
217
+
218
+ ```json
219
+ { "coverage": false }
220
+ ```
221
+
222
+ Or keep the local ratchet but skip the CI history append:
223
+
224
+ ```json
225
+ { "coverage": { "history": "none" } }
226
+ ```
227
+
228
+ | Override field | Default | Description |
229
+ | -------------------- | ------------------------ | ---------------------------------------------------------------------- |
230
+ | `history` | `"orphan-branch"` | `"none"` disables CI history; the local ratchet still works |
231
+ | `historyBranch` | `"bst/coverage-metrics"` | Override the orphan branch name |
232
+ | `tolerancePp` | `0.1` | Tolerance in percentage points before `coverage:check` flags a drop |
233
+ | `gateOnPullRequests` | `false` | Run coverage on PR builds too (deferred follow-up — currently a no-op) |
234
+
235
+ #### Per-package re-sum
236
+
237
+ The trimmed record's `packages` map is computed by aggregating files whose path starts with `packages/<name>/`, so monorepo packages get their own line/branch percentages without per-package vitest configs. Single-package repos collapse to one entry keyed by the directory basename. Per-package numbers are recorded but **not gated** — only the four overall totals control the ratchet.
238
+
165
239
  ### Docker
166
240
 
167
241
  | Command | Description |