crapkit 0.4.1__tar.gz → 0.4.3__tar.gz
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.
- {crapkit-0.4.1 → crapkit-0.4.3}/PKG-INFO +55 -17
- crapkit-0.4.1/src/crapkit.egg-info/PKG-INFO → crapkit-0.4.3/README.md +820 -815
- {crapkit-0.4.1 → crapkit-0.4.3}/pyproject.toml +6 -2
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/__init__.py +1 -1
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/analyze.py +26 -17
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/cli/__init__.py +7 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/cli/admin.py +27 -7
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/cli/claude_hook.py +14 -4
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/cli/parser.py +2 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/cli/queue.py +59 -16
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/cli/ratchet_cmds.py +37 -8
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/cli/reports.py +16 -3
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/cli/scoring.py +61 -8
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/cli/verifying.py +88 -11
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/config.py +102 -10
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/doctor.py +1 -1
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/dup.py +16 -3
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/hook.py +19 -4
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/junitparse.py +53 -3
- crapkit-0.4.3/src/crapkit/keys.py +86 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/lanes.py +30 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/lizardcognitive.py +37 -7
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/mcp_server.py +11 -5
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/override.py +5 -3
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/packet.py +36 -1
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/ratchet.py +76 -18
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/scaffold.py +29 -4
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/store.py +61 -13
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/verify.py +19 -6
- crapkit-0.4.1/README.md → crapkit-0.4.3/src/crapkit.egg-info/PKG-INFO +853 -783
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit.egg-info/SOURCES.txt +1 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit.egg-info/requires.txt +1 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/LICENSE +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/setup.cfg +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/__main__.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/_pygdefer.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/cache.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/churn.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/churn_cache.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/churn_log.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/cli/_shared.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/cli/analyses.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/coupling.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/coverage_istanbul.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/coverage_py.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/covstream.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/diffparse.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/digest.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/discover.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/errors.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/gitio.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/lizardpowershell.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/lizardrust.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/lizardshell.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/merge.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/mutate.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/mutate_pool.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/ratchet_report.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/report.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/sarif.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/sarifio.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/score.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/snapshot.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/uncovered.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/universe.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/watch.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit/worklist.py +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit.egg-info/dependency_links.txt +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit.egg-info/entry_points.txt +0 -0
- {crapkit-0.4.1 → crapkit-0.4.3}/src/crapkit.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: crapkit
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.3
|
|
4
4
|
Summary: Scores every function on complexity times uncovered risk, ranks the worst, and blocks commits that add more.
|
|
5
5
|
Author: Jean-Francois Gagne
|
|
6
6
|
License: MIT
|
|
@@ -28,6 +28,7 @@ Requires-Dist: lizard>=1.24.0
|
|
|
28
28
|
Provides-Extra: dev
|
|
29
29
|
Requires-Dist: pytest>=8; extra == "dev"
|
|
30
30
|
Requires-Dist: pytest-cov>=5; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest-xdist>=3; extra == "dev"
|
|
31
32
|
Dynamic: license-file
|
|
32
33
|
|
|
33
34
|
# crapkit
|
|
@@ -115,7 +116,7 @@ changing crapkit.
|
|
|
115
116
|
|
|
116
117
|
```
|
|
117
118
|
$ crapkit --version
|
|
118
|
-
crapkit 0.4.
|
|
119
|
+
crapkit 0.4.3
|
|
119
120
|
```
|
|
120
121
|
|
|
121
122
|
`python -m crapkit` works identically to the console script and is what to use from a
|
|
@@ -123,6 +124,22 @@ source checkout. Every subcommand accepts `--repo PATH` (default: the current di
|
|
|
123
124
|
so you never have to `cd` into the repo you are scoring. The flag goes after the
|
|
124
125
|
subcommand; [Subcommands](#subcommands) shows both orders.
|
|
125
126
|
|
|
127
|
+
### Upgrading on Windows
|
|
128
|
+
|
|
129
|
+
`uv tool upgrade crapkit`, and `pip install -U` into a tool venv, fail with `os error 32`
|
|
130
|
+
("The process cannot access the file because it is being used by another process") while a
|
|
131
|
+
crapkit MCP server is live: an agent session spawns `crapkit.exe mcp`, which holds the
|
|
132
|
+
launcher, and Windows will not overwrite a running executable. The venv upgrades before
|
|
133
|
+
that copy fails, so `crapkit --version` already reports the new version and the launcher is
|
|
134
|
+
the only stale piece. Quit the agent session and rerun the upgrade, or rename the locked
|
|
135
|
+
exe aside (Windows allows renaming a running one) and copy the new one in; the `.old` file
|
|
136
|
+
goes at the next reboot.
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
mv ~/.local/bin/crapkit.exe ~/.local/bin/crapkit.exe.old
|
|
140
|
+
cp %APPDATA%/uv/tools/crapkit/Scripts/crapkit.exe ~/.local/bin/crapkit.exe
|
|
141
|
+
```
|
|
142
|
+
|
|
126
143
|
## The Claude Code plugin
|
|
127
144
|
|
|
128
145
|
```
|
|
@@ -165,10 +182,16 @@ lane. Nothing about it is provisional: the ceiling still binds and the gate stil
|
|
|
165
182
|
a function over it. Add a coverage lane the day a parser exists and the same scope starts
|
|
166
183
|
joining coverage.
|
|
167
184
|
|
|
185
|
+
`crapkit init` writes that key itself, on every scope whose languages all lack a parser,
|
|
186
|
+
and leaves it off any scope a lane could still measure. So the 60-second start above runs
|
|
187
|
+
unchanged on a Go, Rust or shell repo: `crapkit coverage` scores it with no lane at all,
|
|
188
|
+
and that run is the baseline `worklist`, `next-item`, `ratchet seed` and `verify` read.
|
|
189
|
+
|
|
168
190
|
Three readers are crapkit's own. lizard ships none for shell or PowerShell, so crapkit
|
|
169
191
|
counts their functions itself. Its Rust reader scores a 7-arm `match` as ccn 2 (filed as
|
|
170
192
|
lizard #494), so crapkit counts each non-wildcard arm like a C `case` and retires the
|
|
171
|
-
override the day upstream fixes it.
|
|
193
|
+
override the day upstream fixes it. The cognitive column charges that same block once,
|
|
194
|
+
the way Sonar charges a `switch`.
|
|
172
195
|
|
|
173
196
|
## The gate
|
|
174
197
|
|
|
@@ -178,8 +201,8 @@ different powers:
|
|
|
178
201
|
| Surface | Fires | Power |
|
|
179
202
|
|---|---|---|
|
|
180
203
|
| `crapkit claude-hook` | after an agent's edit lands | **advisory.** Names the breach on stderr. Blocks nothing, because PostToolUse runs after the write |
|
|
181
|
-
| `crapkit rescore FILE --gate` | when you ask | **preview.** The commit gate's verdict on demand, sub-second, before you stage |
|
|
182
|
-
| `crapkit hook-precommit` | `git commit` | **blocks.**
|
|
204
|
+
| `crapkit rescore FILE --gate` | when you ask, after the first coverage run | **preview.** The commit gate's verdict on demand, sub-second, before you stage. With no run behind it, exit 1 and `no snapshot` |
|
|
205
|
+
| `crapkit hook-precommit` | `git commit` | **blocks.** The hook exits 6; git reports 1. Staged blobs only, so it costs the size of the commit and needs no coverage |
|
|
183
206
|
| `crapkit verify` | before you push, and in CI | **the verdict.** Gate, ratchet, new test failures, diff coverage, against the trusted baseline |
|
|
184
207
|
|
|
185
208
|
Both hooks exempt a function the committed ratchet already carries a mark for, so touching
|
|
@@ -239,7 +262,8 @@ crapkit ships a `.pre-commit-hooks.yaml` declaring `id: crapkit-gate`. In your
|
|
|
239
262
|
```yaml
|
|
240
263
|
repos:
|
|
241
264
|
- repo: https://github.com/JeanFrancoisGagne/crapkit
|
|
242
|
-
|
|
265
|
+
# crapkit's release step rewrites this line to the tag it just cut
|
|
266
|
+
rev: v0.4.3
|
|
243
267
|
hooks:
|
|
244
268
|
- id: crapkit-gate
|
|
245
269
|
```
|
|
@@ -275,7 +299,9 @@ crapkit gate: 1 staged function(s) exceed the complexity ceiling of 6:
|
|
|
275
299
|
decompose before committing (coverage cannot save a function above the target).
|
|
276
300
|
```
|
|
277
301
|
|
|
278
|
-
|
|
302
|
+
That commit exited **1**, not 6. Git collapses any failed hook to 1, so 6 is a code you
|
|
303
|
+
only ever see by running the hook yourself: `crapkit hook-precommit` exits 6 on a
|
|
304
|
+
violation and 0 otherwise. The stderr block above is the same either way.
|
|
279
305
|
|
|
280
306
|
`CRAPKIT_OVERRIDE_REASON` is not a bypass. Setting it routes the commit through the full
|
|
281
307
|
three-record audit: an alert line through `alert_command`, a ratchet entry staged into the
|
|
@@ -311,12 +337,12 @@ crapkit: error: argument command: invalid choice: '/path/to/repo' (choose from '
|
|
|
311
337
|
| `doctor [--show-files] [--json] [--tune] [--plugin-root PATH]` | Checks the config still describes the repo: unknown keys (with the accepted spellings), zero-file scopes, tracked source no scope claims, scopes no lane covers, lane cwds and commands that no longer resolve, lizard importable, oversized files. It WARNs on a lane writing its artifact at the repo root, a committed hook under `core.hooksPath` that is not executable in the index, a directory whose functions are all `untested` while its tests exist, and a scope a lane measures with no `[crapkit.scoped_tests]` template behind it, which is the loop's step 4 with nothing to run. `--tune` prints suggested parallelism knobs and writes nothing. `--plugin-root PATH` reads no repo at all: it checks an installed [plugin](plugin/) against this CLI on both version and hook `--protocol`, one line per disagreement and silence when they agree. See [docs/agent-json.md](docs/agent-json.md#doctor---json). |
|
|
312
338
|
| `inventory [--db PATH] [--export PATH] [--json]` | One lizard pass over every in-scope file into a SQLite snapshot run, cached by content hash. `--db` is the only way to point crapkit at a store outside `.crapkit/`, and only this command accepts it. |
|
|
313
339
|
| `coverage [--lane NAME] [--reuse-artifacts] [--reuse-unchanged] [--export PATH] [--sarif PATH] [--github] [--json]` | Runs the lanes, joins branch coverage onto a fresh inventory, writes a scored run. A failed lane is recorded, not fatal: its scopes fall back to `no-lane` and the run is typed `partial`, so it can never serve as a baseline. See [docs/lanes.md](docs/lanes.md). |
|
|
314
|
-
| `verify [--baseline ID \| --base REF \| --baseline-tsv PATH] [--emit-baseline PATH] [--override REASON] [--reuse-artifacts] [--reuse-unchanged] [--sarif PATH] [--github] [--json]` | The full verdict against the trusted baseline: gate on touched functions, ratchet, no new test failures, optional diff-coverage ceiling. The three baseline selectors are mutually exclusive; `--baseline ID` also bypasses the taint rule ([The trusted baseline](#the-trusted-baseline)), and `--baseline-tsv` reads a commit-stamped file so a fresh clone verifies with no store. Findings a dirty tree produced are tagged `dirty` and counted apart. |
|
|
340
|
+
| `verify [--baseline ID \| --base REF \| --baseline-tsv PATH] [--emit-baseline PATH] [--override REASON] [--reuse-artifacts] [--reuse-unchanged] [--no-tighten] [--sarif PATH] [--github] [--json]` | The full verdict against the trusted baseline: gate on touched functions, ratchet, no new test failures, optional diff-coverage ceiling. The three baseline selectors are mutually exclusive; `--baseline ID` also bypasses the taint rule ([The trusted baseline](#the-trusted-baseline)), and `--baseline-tsv` reads a commit-stamped file so a fresh clone verifies with no store. `--no-tighten` passes the verdict without rewriting the ratchet. Findings a dirty tree produced are tagged `dirty` and counted apart. |
|
|
315
341
|
| `worklist [--top N] [--scope NAME] [--batches N] [--json]` | The risk map: every admitted function ranked by `ccn * churn weight`, floored by `worklist_floor`, with hot simple code and anything over its ceiling admitted past that floor. It ranks finished rows and `no-lane` rows too, marked `ok` and `no-lane`, so it never empties; `next-item` carries the stop condition. `--scope NAME` (repeatable) is exact, not a substring. `--batches N` **adds** a `batches[]` view cutting the active list into at most N file-disjoint batches with co-changing files kept together; the normal keys stay. |
|
|
316
342
|
| `next-item [--top N] [--exclude FRAG] [--scope NAME] [--claim]` | The actionable queue as JSON, with churn, budget estimates and uncovered lines. Same run and same admission floor as `worklist`, a different view of it: `no-lane` rows are skipped and counted in `skipped_no_lane`, and what is left is ranked by `crap` descending rather than by risk, so the item it hands out is often not the worklist's first row. `--exclude FRAG` (repeatable) skips items whose path or function name contains FRAG; `--scope NAME` (repeatable) is exact, not a substring. `--claim` holds what it hands out so a second session skips it. `stale` is true when the ranked run's commit is not HEAD, the same field `worklist` carries. Every item carries a `handle`: the bare identifier, or `(anonymous)#N` for a function with no name, which is the name form that survives the edit the item asks for. |
|
|
317
343
|
| `claims [list \| release PATH NAME \| release --all] [--json]` | The open claims, and the way to hand one back without waiting for a verify. `release` takes the bare identifier, the whole long name, or the `handle` the claim was taken under, which is the only one that picks out a single `(anonymous)` claim. |
|
|
318
|
-
| `brief FILE NAME [--batch N] [--json]` | The start-editing packet for one function: its own `source` text, every function in the file, the scored row and the scope ceiling, the ratchet mark and what the gate will bind on, uncovered lines, duplication twins, file churn, coupling partners, the config's notes, and the literal commands for the rest of the loop. Plus `handle`, `remedy` and the same `est_splits` / `est_uncovered_paths` the queue prints, and a `commands.refresh` that writes a run (`refresh_writes_run`) rather than re-reading the stale one. `NAME` takes the bare identifier, the long name `next-item` printed, the function's start line,
|
|
319
|
-
| `explain FILE NAME [--history] [--tests] [--json]` | A function's score across runs plus its mark. `--history` adds the commits that touched it (`git log -L`), each carrying its message `body`, `--tests` the tests that covered it, which needs coverage.py contexts turned on ([recipe](docs/lanes.md#test-attribution-for-explain---tests)). `--json` emits the same content as one `schema` 1 object. |
|
|
344
|
+
| `brief FILE NAME [--batch N] [--json]` | The start-editing packet for one function: its own `source` text, every function in the file, the scored row and the scope ceiling, the ratchet mark and what the gate will bind on, uncovered lines, duplication twins, file churn, coupling partners, the config's notes, and the literal commands for the rest of the loop. Plus `handle`, `remedy` and the same `est_splits` / `est_uncovered_paths` the queue prints, and a `commands.refresh` that writes a run (`refresh_writes_run`) rather than re-reading the stale one. `NAME` takes the bare identifier, the long name `next-item` printed, the function's start line, `(anonymous)#N` for a function printed `(anonymous)` counting the file's anonymous functions from the top, or `NAME#2` for the second of several functions a file gives one name to. `--batch N` drops the positionals and emits `packets[]` instead: the top N of the queue, built from one read of the store. |
|
|
345
|
+
| `explain FILE NAME [--history] [--tests] [--json]` | A function's score across runs plus its mark. `NAME` resolves exact first: a function whose bare identifier or long name is exactly `NAME` wins, and only when nothing matches exactly does it fall back to a prefix match, so `route` explains `route` rather than every `route_*` beside it. `--history` adds the commits that touched it (`git log -L`), each carrying its message `body`, `--tests` the tests that covered it, which needs coverage.py contexts turned on ([recipe](docs/lanes.md#test-attribution-for-explain---tests)). `--json` emits the same content as one `schema` 1 object. |
|
|
320
346
|
| `rescore FILE ... [--gate] [--json]` | Fresh complexity for named files over the latest run's stale coverage, joined by name. Advisory: it writes no run. `--gate` applies the pre-commit hook's policy to the same selection the hook uses (functions the tree changed since HEAD), minus functions a ratchet mark already covers, and exits 6. |
|
|
321
347
|
| `ratchet seed \| prune \| merge \| move \| report [--enforce] [--json]` | The mark lifecycle: seed new debt, prune gone code (a mark whose file git renamed follows it), merge as a git driver, move re-paths marks, report reads burn-down from the file's own git history. See [docs/ratchet.md](docs/ratchet.md). |
|
|
322
348
|
| `runs [list \| prune [--keep N]] [--json]` | Run history, and retention. `list` marks the run `verify` compares against today `baseline`, and prints `verdict=-` for a run that produces no verdict rather than one that failed. See [The trusted baseline](#the-trusted-baseline). `--keep` (default 5) is a floor on the newest trusted runs, not a cap: the digest pair, every passing verify baseline, every run an override names, and the newest non-hook run are kept too. `prune` VACUUMs afterwards. |
|
|
@@ -324,7 +350,7 @@ crapkit: error: argument command: invalid choice: '/path/to/repo' (choose from '
|
|
|
324
350
|
| `trend [--json]` | Totals per trusted run: functions, over-target count, CRAP load, average, per-scope rollup. |
|
|
325
351
|
| `digest [--alert]` | The delta between the two newest runs with identical lane sets. Silent when nothing changed. `--alert` pipes the body to `alert_command` on stdin. Plain lines, never JSON. |
|
|
326
352
|
| `report [--out PATH]` | One self-contained HTML page written to `.crapkit/report.html` (or `--out PATH`, repo-relative), with the path printed on stdout. It renders what `worklist --json` and `trend --json` already answer at their defaults: the ranked worklist capped at `worklist_top`, the per-scope grades off the newest run, the trend series, and a banner naming every stale lane. It measures nothing and opens no network connection. Per-function CRAP and coverage are absent because no repo-wide payload carries them; each row prints the `crapkit explain` call that does. |
|
|
327
|
-
| `duplication [--min-lines N] [--similarity F] [--top N] [--json]` | Near-duplicate functions by normalized line shingles with containment scoring. Defaults: `--min-lines 8`, `--similarity 0.8`, `--top 50`. `--top` truncates the list. |
|
|
353
|
+
| `duplication [--min-lines N] [--similarity F] [--top N] [--json]` | Near-duplicate functions by normalized line shingles with containment scoring. Defaults: `--min-lines 8`, `--similarity 0.8`, `--top 50`. `--top` truncates the list. A function and a function nested inside it never pair: their spans nest, they score 1.0 by construction, and nobody can deduplicate a factory from its own closure. |
|
|
328
354
|
| `coupling [--min-support N] [--min-confidence F] [--top N] [--json]` | File pairs that keep landing in the same commits. Defaults: `--min-support 5` shared commits, `--min-confidence 0.5` max-direction ratio, `--top 50`. Bulk commits never couple pairs, and a young repo returns nothing at the default support. |
|
|
329
355
|
| `mutate [--files F ...] [--max-mutants N] [--json]` | Diff-scoped mutation testing: flips comparisons, boundary shifts, boolean connectives and boolean literals on changed lines, runs `mutation_command` per mutant, lists survivors. `--files` replaces diff scope with the whole file. `--max-mutants` (default 100) caps the run and the cap warning goes to stderr only, so `mutants` in `--json` is the capped count. Shell and PowerShell files are refused by name on stderr rather than mutated: `<` and `>` are redirections there, not comparisons. |
|
|
330
356
|
| `test-scoped FILE ...` | Runs each owning scope's `[crapkit.scoped_tests]` template on the files (quoted, longest-prefix scope wins). A template with no `{files}` runs as written, which is how a scope whose tests live outside its own paths runs its whole suite. Exit code only; a nonzero runner exits 1. |
|
|
@@ -402,7 +428,9 @@ baseline**. `crapkit runs list` marks which one that is today.
|
|
|
402
428
|
never qualifies, and neither does a `partial` run (a lane failed, so some scope fell back
|
|
403
429
|
to `no-lane`) nor a `hook` override record, which carries no scored rows at all. In `runs
|
|
404
430
|
list`, `verdict=-` marks a run that produces no verdict rather than one that failed: only
|
|
405
|
-
`verify` renders a verdict.
|
|
431
|
+
`verify` renders a verdict. Three readers ask this one question and get this one answer:
|
|
432
|
+
the baseline pick here, `ratchet seed` and `prune`, and the tighten damping that compares a
|
|
433
|
+
mark against the same commit's previous run.
|
|
406
434
|
|
|
407
435
|
**What advances it.** Any qualifying run. `coverage` writes one wherever HEAD is, so a
|
|
408
436
|
dashboard cron advances the baseline exactly as CI does. A passing `verify` advances it
|
|
@@ -536,6 +564,11 @@ makes it step 4 of the burn-down loop. Every key is in
|
|
|
536
564
|
|
|
537
565
|
```
|
|
538
566
|
$ crapkit doctor
|
|
567
|
+
ok config keys all recognized
|
|
568
|
+
ok scope 'calc': 1 files
|
|
569
|
+
ok every tracked source file belongs to a scope
|
|
570
|
+
ok 1 lane(s) declared
|
|
571
|
+
ok lizard 1.24.0
|
|
539
572
|
doctor: no problems found
|
|
540
573
|
```
|
|
541
574
|
|
|
@@ -567,11 +600,12 @@ worklist has none.
|
|
|
567
600
|
|
|
568
601
|
```
|
|
569
602
|
$ crapkit next-item
|
|
570
|
-
{"commit": "fae4db93108b4841a00959f9117430679e7250ca", "empty": false, "item": {"authors": 1, "ccn": 14, "ccn_std": 14, "cognitive": 13, "commits": 1, "cov": 0.5, "crap": 38.5, "end": 28, "est_splits": 3, "est_uncovered_paths": 7, "flag": "measured", "function": "classify( score , attempts , late , bonus )", "nesting": 8, "nloc": 22, "path": "calc/grade.py", "remedy": "decompose", "scope": "calc", "start": 7, "target": 6, "uncovered_lines": [9, 11, 15, 17, 19, 24, 25, 26, 27, 28]}, "run_id": 1, "schema": 1, "skipped_no_lane": 0}
|
|
603
|
+
{"commit": "fae4db93108b4841a00959f9117430679e7250ca", "empty": false, "item": {"authors": 1, "ccn": 14, "ccn_std": 14, "cognitive": 13, "commits": 1, "cov": 0.5, "crap": 38.5, "end": 28, "est_splits": 3, "est_uncovered_paths": 7, "flag": "measured", "function": "classify( score , attempts , late , bonus )", "handle": "classify", "nesting": 8, "nloc": 22, "path": "calc/grade.py", "remedy": "decompose", "scope": "calc", "start": 7, "target": 6, "uncovered_lines": [9, 11, 15, 17, 19, 24, 25, 26, 27, 28]}, "run_id": 1, "schema": 1, "skipped_no_lane": 0, "stale": false}
|
|
571
604
|
```
|
|
572
605
|
|
|
573
606
|
`remedy: "decompose"`, `est_splits: 3` (this needs roughly three pieces to fit under 6),
|
|
574
|
-
and `uncovered_lines` naming the ten lines no test walks.
|
|
607
|
+
and `uncovered_lines` naming the ten lines no test walks. `handle` is the name form to
|
|
608
|
+
pass back, and `stale: false` says the run still describes HEAD. Every field is in
|
|
575
609
|
[docs/agent-json.md](docs/agent-json.md).
|
|
576
610
|
|
|
577
611
|
### 5. Seed the ratchet
|
|
@@ -648,17 +682,21 @@ crapkit: lane 'js' FAILED: lane 'js' produced no artifact at .crapkit/cov/js/cov
|
|
|
648
682
|
crapkit: every lane failed: ...
|
|
649
683
|
```
|
|
650
684
|
|
|
651
|
-
|
|
685
|
+
That failure **writes no run**. Every lane failed, so `coverage` exits before it opens a
|
|
686
|
+
store: there is no `.crapkit/crap.sqlite` yet and the run ids below still start at 1.
|
|
687
|
+
|
|
688
|
+
Install the provider, and pin the major yourself. Unpinned, npm resolves the newest
|
|
689
|
+
provider against your older vitest and refuses the tree:
|
|
652
690
|
|
|
653
691
|
```
|
|
654
|
-
npm i -D @vitest/coverage-v8
|
|
692
|
+
npm i -D "@vitest/coverage-v8@<your vitest major>"
|
|
655
693
|
```
|
|
656
694
|
|
|
657
695
|
| Question | Answer |
|
|
658
696
|
|---|---|
|
|
659
697
|
| Which provider? | Either works. `@vitest/coverage-v8` is vitest's default and needs no config. `@vitest/coverage-istanbul` also works and needs `coverage.provider = "istanbul"` in your vitest config. |
|
|
660
698
|
| Which crapkit parser? | Both feed `parser = "istanbul"`. The provider name and the parser name are unrelated: v8 output is remapped to the istanbul JSON schema before it is written. |
|
|
661
|
-
| Which version? |
|
|
699
|
+
| Which version? | The provider's major has to match vitest's. On vitest 2 that is `npm i -D "@vitest/coverage-v8@2"`, on vitest 3 `npm i -D "@vitest/coverage-v8@3"`. Drop the pin and npm answers `ERESOLVE unable to resolve dependency tree`, naming the peer it could not satisfy. |
|
|
662
700
|
|
|
663
701
|
The artifact crapkit wants is `coverage-final.json`, written by vitest's `json` coverage
|
|
664
702
|
reporter, which is on by default. If your vitest config sets `coverage.reporter`
|