crapkit 0.5.0__tar.gz → 0.5.1__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.
Files changed (75) hide show
  1. {crapkit-0.5.0/src/crapkit.egg-info → crapkit-0.5.1}/PKG-INFO +20 -5
  2. {crapkit-0.5.0 → crapkit-0.5.1}/README.md +19 -4
  3. {crapkit-0.5.0 → crapkit-0.5.1}/pyproject.toml +1 -1
  4. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/__init__.py +1 -1
  5. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/cli/verifying.py +28 -4
  6. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/verify.py +17 -0
  7. {crapkit-0.5.0 → crapkit-0.5.1/src/crapkit.egg-info}/PKG-INFO +20 -5
  8. {crapkit-0.5.0 → crapkit-0.5.1}/LICENSE +0 -0
  9. {crapkit-0.5.0 → crapkit-0.5.1}/setup.cfg +0 -0
  10. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/__main__.py +0 -0
  11. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/_pygdefer.py +0 -0
  12. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/analyze.py +0 -0
  13. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/cache.py +0 -0
  14. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/churn.py +0 -0
  15. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/churn_cache.py +0 -0
  16. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/churn_log.py +0 -0
  17. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/cli/__init__.py +0 -0
  18. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/cli/_shared.py +0 -0
  19. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/cli/admin.py +0 -0
  20. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/cli/analyses.py +0 -0
  21. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/cli/claude_hook.py +0 -0
  22. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/cli/parser.py +0 -0
  23. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/cli/queue.py +0 -0
  24. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/cli/ratchet_cmds.py +0 -0
  25. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/cli/reports.py +0 -0
  26. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/cli/scoring.py +0 -0
  27. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/config.py +0 -0
  28. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/coupling.py +0 -0
  29. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/coupling_cache.py +0 -0
  30. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/coverage_istanbul.py +0 -0
  31. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/coverage_py.py +0 -0
  32. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/covstream.py +0 -0
  33. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/diffparse.py +0 -0
  34. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/digest.py +0 -0
  35. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/discover.py +0 -0
  36. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/doctor.py +0 -0
  37. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/dup.py +0 -0
  38. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/errors.py +0 -0
  39. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/gitio.py +0 -0
  40. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/hook.py +0 -0
  41. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/invocation.py +0 -0
  42. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/junitparse.py +0 -0
  43. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/keys.py +0 -0
  44. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/lanes.py +0 -0
  45. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/lizardcognitive.py +0 -0
  46. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/lizardpowershell.py +0 -0
  47. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/lizardrust.py +0 -0
  48. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/lizardshell.py +0 -0
  49. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/mcp_server.py +0 -0
  50. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/merge.py +0 -0
  51. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/mutate.py +0 -0
  52. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/mutate_pool.py +0 -0
  53. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/override.py +0 -0
  54. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/packet.py +0 -0
  55. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/procs.py +0 -0
  56. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/ratchet.py +0 -0
  57. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/ratchet_report.py +0 -0
  58. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/report.py +0 -0
  59. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/repotext.py +0 -0
  60. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/rootfind.py +0 -0
  61. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/sarif.py +0 -0
  62. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/sarifio.py +0 -0
  63. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/scaffold.py +0 -0
  64. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/score.py +0 -0
  65. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/snapshot.py +0 -0
  66. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/store.py +0 -0
  67. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/uncovered.py +0 -0
  68. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/universe.py +0 -0
  69. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/watch.py +0 -0
  70. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit/worklist.py +0 -0
  71. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit.egg-info/SOURCES.txt +0 -0
  72. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit.egg-info/dependency_links.txt +0 -0
  73. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit.egg-info/entry_points.txt +0 -0
  74. {crapkit-0.5.0 → crapkit-0.5.1}/src/crapkit.egg-info/requires.txt +0 -0
  75. {crapkit-0.5.0 → crapkit-0.5.1}/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.5.0
3
+ Version: 0.5.1
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
@@ -73,6 +73,16 @@ half-executed straight-line function never reads as fully covered.
73
73
  function at ccn 7 with 100% coverage still scores 7 and still fails the gate. The only
74
74
  move that clears it is splitting the function.
75
75
 
76
+ **Why 6 and not 30.** crap4j's conventional threshold of 30 is a CRAP score: it lets an
77
+ untested `ccn 5` through (25 + 5 = 30) and a fully covered `ccn 30` too. crapkit's default
78
+ is a complexity ceiling, because coverage can at best collapse CRAP to `ccn`, and a
79
+ function you cannot cover past `ccn 6` is one you decompose. Set `target = 30` in
80
+ `crapkit.toml` if you want the crap4j number. A repo with existing debt does not need to:
81
+ `ratchet seed` marks today's over-ceiling functions at today's score, the gate then judges
82
+ only the functions a change touches, and marks may only fall, so adoption never starts with
83
+ a wall of red. Next to crap4py, radon, xenon, wily and SonarQube:
84
+ [docs/comparison.md](https://github.com/JeanFrancoisGagne/crapkit/blob/main/docs/comparison.md).
85
+
76
86
  crapkit scores **git-tracked files only**. Source you have not `git add`ed is invisible to
77
87
  it.
78
88
 
@@ -171,7 +181,7 @@ leaves the box
171
181
 
172
182
  ```
173
183
  $ crapkit --version
174
- crapkit 0.5.0
184
+ crapkit 0.5.1
175
185
  ```
176
186
 
177
187
  `python -m crapkit` works identically to the console script and is what to use from a
@@ -415,7 +425,7 @@ crapkit ships a `.pre-commit-hooks.yaml` declaring `id: crapkit-gate`. In your
415
425
  repos:
416
426
  - repo: https://github.com/JeanFrancoisGagne/crapkit
417
427
  # crapkit's release step rewrites this line to the tag it just cut
418
- rev: v0.5.0
428
+ rev: v0.5.1
419
429
  hooks:
420
430
  - id: crapkit-gate
421
431
  ```
@@ -523,7 +533,7 @@ to a workflow, and every input has a default:
523
533
  - uses: actions/checkout@v4
524
534
  with:
525
535
  fetch-depth: 0
526
- - uses: JeanFrancoisGagne/crapkit@v0.5.0
536
+ - uses: JeanFrancoisGagne/crapkit@v0.5.1
527
537
  ```
528
538
 
529
539
  The whole job those four lines sit in:
@@ -543,7 +553,7 @@ jobs:
543
553
  with:
544
554
  python-version: "3.12" # the interpreter the install below lands in
545
555
  - run: pip install -e ".[dev]" # whatever your lanes need to run
546
- - uses: JeanFrancoisGagne/crapkit@v0.5.0
556
+ - uses: JeanFrancoisGagne/crapkit@v0.5.1
547
557
  with:
548
558
  gate: "false"
549
559
  ```
@@ -1285,6 +1295,11 @@ dropped it once `classify` scored under the ceiling, rewriting the tracked
1285
1295
  A verify may also print `warning: N changed line(s) have no coverage` above its verdict;
1286
1296
  that block is advisory unless `diff_uncovered_max` is set
1287
1297
  ([docs/configuration.md](https://github.com/JeanFrancoisGagne/crapkit/blob/main/docs/configuration.md)).
1298
+ It prints `warning: N function(s) over the ceiling carry no ratchet mark` when the tree
1299
+ holds debt `ratchet seed` never signed: the gate judges touched functions only and the
1300
+ ratchet check compares marks only, so coverage loss on such a function would pass unseen.
1301
+ The count is `unmarked_over_target` in `--json`, fires no exit code, and is zero on a repo
1302
+ with no debt.
1288
1303
 
1289
1304
  ## Documentation
1290
1305
 
@@ -34,6 +34,16 @@ half-executed straight-line function never reads as fully covered.
34
34
  function at ccn 7 with 100% coverage still scores 7 and still fails the gate. The only
35
35
  move that clears it is splitting the function.
36
36
 
37
+ **Why 6 and not 30.** crap4j's conventional threshold of 30 is a CRAP score: it lets an
38
+ untested `ccn 5` through (25 + 5 = 30) and a fully covered `ccn 30` too. crapkit's default
39
+ is a complexity ceiling, because coverage can at best collapse CRAP to `ccn`, and a
40
+ function you cannot cover past `ccn 6` is one you decompose. Set `target = 30` in
41
+ `crapkit.toml` if you want the crap4j number. A repo with existing debt does not need to:
42
+ `ratchet seed` marks today's over-ceiling functions at today's score, the gate then judges
43
+ only the functions a change touches, and marks may only fall, so adoption never starts with
44
+ a wall of red. Next to crap4py, radon, xenon, wily and SonarQube:
45
+ [docs/comparison.md](https://github.com/JeanFrancoisGagne/crapkit/blob/main/docs/comparison.md).
46
+
37
47
  crapkit scores **git-tracked files only**. Source you have not `git add`ed is invisible to
38
48
  it.
39
49
 
@@ -132,7 +142,7 @@ leaves the box
132
142
 
133
143
  ```
134
144
  $ crapkit --version
135
- crapkit 0.5.0
145
+ crapkit 0.5.1
136
146
  ```
137
147
 
138
148
  `python -m crapkit` works identically to the console script and is what to use from a
@@ -376,7 +386,7 @@ crapkit ships a `.pre-commit-hooks.yaml` declaring `id: crapkit-gate`. In your
376
386
  repos:
377
387
  - repo: https://github.com/JeanFrancoisGagne/crapkit
378
388
  # crapkit's release step rewrites this line to the tag it just cut
379
- rev: v0.5.0
389
+ rev: v0.5.1
380
390
  hooks:
381
391
  - id: crapkit-gate
382
392
  ```
@@ -484,7 +494,7 @@ to a workflow, and every input has a default:
484
494
  - uses: actions/checkout@v4
485
495
  with:
486
496
  fetch-depth: 0
487
- - uses: JeanFrancoisGagne/crapkit@v0.5.0
497
+ - uses: JeanFrancoisGagne/crapkit@v0.5.1
488
498
  ```
489
499
 
490
500
  The whole job those four lines sit in:
@@ -504,7 +514,7 @@ jobs:
504
514
  with:
505
515
  python-version: "3.12" # the interpreter the install below lands in
506
516
  - run: pip install -e ".[dev]" # whatever your lanes need to run
507
- - uses: JeanFrancoisGagne/crapkit@v0.5.0
517
+ - uses: JeanFrancoisGagne/crapkit@v0.5.1
508
518
  with:
509
519
  gate: "false"
510
520
  ```
@@ -1246,6 +1256,11 @@ dropped it once `classify` scored under the ceiling, rewriting the tracked
1246
1256
  A verify may also print `warning: N changed line(s) have no coverage` above its verdict;
1247
1257
  that block is advisory unless `diff_uncovered_max` is set
1248
1258
  ([docs/configuration.md](https://github.com/JeanFrancoisGagne/crapkit/blob/main/docs/configuration.md)).
1259
+ It prints `warning: N function(s) over the ceiling carry no ratchet mark` when the tree
1260
+ holds debt `ratchet seed` never signed: the gate judges touched functions only and the
1261
+ ratchet check compares marks only, so coverage loss on such a function would pass unseen.
1262
+ The count is `unmarked_over_target` in `--json`, fires no exit code, and is zero on a repo
1263
+ with no debt.
1249
1264
 
1250
1265
  ## Documentation
1251
1266
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "crapkit"
7
- version = "0.5.0"
7
+ version = "0.5.1"
8
8
  description = "Scores every function on complexity times uncovered risk, ranks the worst, and blocks commits that add more."
9
9
  readme = { file = "README.md", content-type = "text/markdown" }
10
10
  license = { text = "MIT" }
@@ -1,2 +1,2 @@
1
1
  """crapkit: deterministic CRAP-score framework."""
2
- __version__ = "0.5.0"
2
+ __version__ = "0.5.1"
@@ -483,9 +483,13 @@ def _verify_attribution(verdict) -> dict:
483
483
 
484
484
 
485
485
  def _verify_result(verdict, overridden, run_id: int, baseline: dict, commit: str, ranges,
486
- uncovered: list, diff_uncovered_max: int | None) -> dict:
486
+ uncovered: list, diff_uncovered_max: int | None,
487
+ unmarked_over_target: int) -> dict:
487
488
  """`diff_uncovered_max` travels with the count it judges: a reader of exit 9
488
- (the Action's comment) can say which ceiling the lines went over."""
489
+ (the Action's comment) can say which ceiling the lines went over.
490
+ `unmarked_over_target` is the standing debt no mark covers (see
491
+ `_warn_standing_debt`); it fires no exit code and is the one number that
492
+ says how much of the tree the ratchet is not holding."""
489
493
  return {
490
494
  "ok": verdict.ok,
491
495
  "run_id": run_id,
@@ -500,10 +504,28 @@ def _verify_result(verdict, overridden, run_id: int, baseline: dict, commit: str
500
504
  "diff_uncovered_count": len(uncovered),
501
505
  "diff_uncovered": [{"path": p, "line": ln} for p, ln in uncovered[:50]],
502
506
  "diff_uncovered_max": diff_uncovered_max,
507
+ "unmarked_over_target": unmarked_over_target,
503
508
  **_verify_attribution(verdict),
504
509
  }
505
510
 
506
511
 
512
+ def _warn_standing_debt(unmarked: list) -> None:
513
+ """One stderr line for the over-ceiling functions no mark covers.
514
+
515
+ The gate never looks at an untouched function and the ratchet check compares
516
+ marks only, so a rise on these (coverage loss included) reaches no finding;
517
+ docs/ratchet.md says "seed once, early" for exactly this, and a header-only
518
+ marks file cannot say whether seed ever ran. stderr, because
519
+ `--json` prints one object on stdout. Silent at zero, which is the state
520
+ of a repo with no debt and of one seeded in full.
521
+ """
522
+ if not unmarked:
523
+ return
524
+ print(f"warning: {len(unmarked)} function(s) over the ceiling carry no ratchet mark, so a "
525
+ f"rise on them (coverage loss included) passes unseen; record them with "
526
+ f"`{_self()} ratchet seed`", file=sys.stderr)
527
+
528
+
507
529
  def _warn_diff_uncovered(uncovered: list) -> None:
508
530
  if not uncovered:
509
531
  return
@@ -576,7 +598,7 @@ def cmd_verify(args: argparse.Namespace) -> int:
576
598
  from ..diffparse import changed_ranges
577
599
  from ..gitio import GitFacts, diff_since
578
600
  from ..uncovered import missing_by_path
579
- from ..verify import diff_uncovered, evaluate
601
+ from ..verify import diff_uncovered, evaluate, unmarked_over_ceiling
580
602
 
581
603
  root = _command_root(args.repo)
582
604
  cfg = _load_repo_config(root)
@@ -616,6 +638,8 @@ def cmd_verify(args: argparse.Namespace) -> int:
616
638
  # the whole cost of the post-commit verify on an unchanged tree.
617
639
  uncovered = diff_uncovered(ranges, missing_by_path(root, cfg)) if ranges else []
618
640
  _warn_diff_uncovered(uncovered)
641
+ unmarked = unmarked_over_ceiling(scored, ratchet, cfg.target, cfg.scope_targets)
642
+ _warn_standing_debt(unmarked)
619
643
  breach = _diff_cover_breach(cfg, uncovered)
620
644
  if breach:
621
645
  verdict = verdict._replace(ok=False) # a breached run never advances the baseline
@@ -629,7 +653,7 @@ def cmd_verify(args: argparse.Namespace) -> int:
629
653
 
630
654
  _report_verify(args.json,
631
655
  {**_verify_result(verdict, overridden, run_id, baseline, commit, ranges,
632
- uncovered, cfg.diff_uncovered_max),
656
+ uncovered, cfg.diff_uncovered_max, len(unmarked)),
633
657
  **_receipt(tool_versions, ratchet_sha256, changes)},
634
658
  verdict, overridden, cfg.ratchet_file)
635
659
  _refuse_override(verdict, args.override)
@@ -206,6 +206,23 @@ def _ratchet_regressions(fresh, ratchet, dirty) -> list[RatchetRegression]:
206
206
  return regressions
207
207
 
208
208
 
209
+ def unmarked_over_ceiling(fresh: list[ScoredRow], ratchet: list[RatchetEntry], target: int,
210
+ scope_targets: dict[str, int] | None = None) -> list[ScoredRow]:
211
+ """Standing debt nothing guards: the worst row per ratchet key that sits over
212
+ its ceiling with no mark under that key, worst first.
213
+
214
+ The gate judges touched functions only and the ratchet check compares marks
215
+ only, so a rise on one of these (coverage loss included) reaches no finding.
216
+ A marked function that rose is a regression already; this is the debt
217
+ `ratchet seed` was never run on.
218
+ """
219
+ marks = _marks_of(ratchet)
220
+ rows = [row for key, row in rows_by_key(fresh).items()
221
+ if row.crap > _ceiling(row, target, scope_targets) and key not in marks]
222
+ rows.sort(key=lambda r: (-r.crap, r.path, r.start))
223
+ return rows
224
+
225
+
209
226
  def evaluate(
210
227
  *,
211
228
  fresh: list[ScoredRow],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: crapkit
3
- Version: 0.5.0
3
+ Version: 0.5.1
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
@@ -73,6 +73,16 @@ half-executed straight-line function never reads as fully covered.
73
73
  function at ccn 7 with 100% coverage still scores 7 and still fails the gate. The only
74
74
  move that clears it is splitting the function.
75
75
 
76
+ **Why 6 and not 30.** crap4j's conventional threshold of 30 is a CRAP score: it lets an
77
+ untested `ccn 5` through (25 + 5 = 30) and a fully covered `ccn 30` too. crapkit's default
78
+ is a complexity ceiling, because coverage can at best collapse CRAP to `ccn`, and a
79
+ function you cannot cover past `ccn 6` is one you decompose. Set `target = 30` in
80
+ `crapkit.toml` if you want the crap4j number. A repo with existing debt does not need to:
81
+ `ratchet seed` marks today's over-ceiling functions at today's score, the gate then judges
82
+ only the functions a change touches, and marks may only fall, so adoption never starts with
83
+ a wall of red. Next to crap4py, radon, xenon, wily and SonarQube:
84
+ [docs/comparison.md](https://github.com/JeanFrancoisGagne/crapkit/blob/main/docs/comparison.md).
85
+
76
86
  crapkit scores **git-tracked files only**. Source you have not `git add`ed is invisible to
77
87
  it.
78
88
 
@@ -171,7 +181,7 @@ leaves the box
171
181
 
172
182
  ```
173
183
  $ crapkit --version
174
- crapkit 0.5.0
184
+ crapkit 0.5.1
175
185
  ```
176
186
 
177
187
  `python -m crapkit` works identically to the console script and is what to use from a
@@ -415,7 +425,7 @@ crapkit ships a `.pre-commit-hooks.yaml` declaring `id: crapkit-gate`. In your
415
425
  repos:
416
426
  - repo: https://github.com/JeanFrancoisGagne/crapkit
417
427
  # crapkit's release step rewrites this line to the tag it just cut
418
- rev: v0.5.0
428
+ rev: v0.5.1
419
429
  hooks:
420
430
  - id: crapkit-gate
421
431
  ```
@@ -523,7 +533,7 @@ to a workflow, and every input has a default:
523
533
  - uses: actions/checkout@v4
524
534
  with:
525
535
  fetch-depth: 0
526
- - uses: JeanFrancoisGagne/crapkit@v0.5.0
536
+ - uses: JeanFrancoisGagne/crapkit@v0.5.1
527
537
  ```
528
538
 
529
539
  The whole job those four lines sit in:
@@ -543,7 +553,7 @@ jobs:
543
553
  with:
544
554
  python-version: "3.12" # the interpreter the install below lands in
545
555
  - run: pip install -e ".[dev]" # whatever your lanes need to run
546
- - uses: JeanFrancoisGagne/crapkit@v0.5.0
556
+ - uses: JeanFrancoisGagne/crapkit@v0.5.1
547
557
  with:
548
558
  gate: "false"
549
559
  ```
@@ -1285,6 +1295,11 @@ dropped it once `classify` scored under the ceiling, rewriting the tracked
1285
1295
  A verify may also print `warning: N changed line(s) have no coverage` above its verdict;
1286
1296
  that block is advisory unless `diff_uncovered_max` is set
1287
1297
  ([docs/configuration.md](https://github.com/JeanFrancoisGagne/crapkit/blob/main/docs/configuration.md)).
1298
+ It prints `warning: N function(s) over the ceiling carry no ratchet mark` when the tree
1299
+ holds debt `ratchet seed` never signed: the gate judges touched functions only and the
1300
+ ratchet check compares marks only, so coverage loss on such a function would pass unseen.
1301
+ The count is `unmarked_over_target` in `--json`, fires no exit code, and is zero on a repo
1302
+ with no debt.
1288
1303
 
1289
1304
  ## Documentation
1290
1305
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes