testguard-cli 0.16.0 → 0.18.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.
Files changed (67) hide show
  1. package/CHANGELOG.md +70 -0
  2. package/README.md +169 -14
  3. package/package.json +1 -1
  4. package/spec/GATE-SEMANTICS.md +316 -0
  5. package/spec/README.md +27 -2
  6. package/spec/lib/authoring-input.mjs +40 -0
  7. package/spec/lib/origins.mjs +56 -0
  8. package/spec/lib/validate.mjs +123 -1
  9. package/spec/schemas/annotations.schema.json +65 -0
  10. package/spec/schemas/authoring-input.schema.json +67 -0
  11. package/spec/schemas/brief.schema.json +2 -0
  12. package/spec/schemas/claims.schema.json +2 -8
  13. package/spec/schemas/common.schema.json +73 -0
  14. package/spec/schemas/evidence.schema.json +40 -10
  15. package/spec/schemas/status.schema.json +6 -2
  16. package/src/brief/brief.mjs +11 -4
  17. package/src/claims/annotation-placement.mjs +357 -0
  18. package/src/claims/annotations.mjs +61 -2
  19. package/src/cli.mjs +41 -6
  20. package/src/commands/admit.mjs +13 -0
  21. package/src/commands/annotations.mjs +67 -0
  22. package/src/commands/claims.mjs +8 -4
  23. package/src/commands/probe.mjs +50 -7
  24. package/src/commands/replay.mjs +7 -0
  25. package/src/commands/scaffold.mjs +49 -2
  26. package/src/commands/sweep.mjs +7 -0
  27. package/src/evidence/writer.mjs +12 -4
  28. package/src/git.mjs +4 -4
  29. package/src/init/templates/SKILL.md +35 -0
  30. package/src/probe/attribution.mjs +10 -0
  31. package/src/probe/contention.mjs +20 -2
  32. package/src/probe/cost.mjs +6 -1
  33. package/src/probe/inject.mjs +2 -6
  34. package/src/probe/origin-policy.mjs +69 -0
  35. package/src/probe/policy-freshness.mjs +74 -0
  36. package/src/probe/probe.mjs +49 -24
  37. package/src/probe/runners/discovery.mjs +4 -0
  38. package/src/probe/runners/index.mjs +3 -1
  39. package/src/probe/runners/jest.mjs +2 -2
  40. package/src/probe/runners/lifecycle.mjs +58 -0
  41. package/src/probe/runners/node/entry.mjs +11 -0
  42. package/src/probe/runners/node/report.mjs +66 -0
  43. package/src/probe/runners/node/runner.mjs +42 -0
  44. package/src/probe/runners/node-test.mjs +130 -0
  45. package/src/probe/runners/playwright.mjs +6 -2
  46. package/src/probe/runners/python.mjs +10 -4
  47. package/src/probe/runners/shared.mjs +14 -7
  48. package/src/probe/runners/vitest.mjs +3 -3
  49. package/src/probe/universe.mjs +47 -0
  50. package/src/probe/worktree.mjs +3 -1
  51. package/src/render.mjs +17 -1
  52. package/src/replay/replay.mjs +8 -4
  53. package/src/scaffold/admission.mjs +117 -0
  54. package/src/scaffold/append.mjs +41 -0
  55. package/src/scaffold/apply-append.mjs +71 -0
  56. package/src/scaffold/fix-input.mjs +119 -0
  57. package/src/scaffold/fix-paths.mjs +90 -0
  58. package/src/scaffold/intent.mjs +2 -0
  59. package/src/scaffold/open-append.mjs +44 -0
  60. package/src/scaffold/plan-append.mjs +37 -0
  61. package/src/scaffold/plan-intent-input.mjs +38 -0
  62. package/src/scaffold/prepare-append.mjs +46 -0
  63. package/src/scaffold/request.mjs +30 -0
  64. package/src/scaffold/scaffold.mjs +23 -10
  65. package/src/status/status.mjs +34 -9
  66. package/src/sweep/pool.mjs +33 -0
  67. package/src/sweep/sweep.mjs +9 -4
package/CHANGELOG.md CHANGED
@@ -7,6 +7,76 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.18.0] - 2026-10-01
11
+
12
+ Automated weekly release — everything merged since `v0.17.0`.
13
+
14
+ ### Changed
15
+
16
+ - Merge branch 'main' into dependabot/github_actions/all-actions-d5b8684899
17
+ - feat: native Node probes with measured startup savings (#192)
18
+ - chore(homebrew): sha256 for v0.17.0 (#191)
19
+ - chore(deps): bump actions/cache
20
+
21
+
22
+ ### Added
23
+
24
+ - Explicit `--runner node-test` support for plain JavaScript projects using
25
+ Node's built-in test framework, with native entry-file discovery, fresh
26
+ process confirmations and bounded structured reports. No runner is installed
27
+ and existing automatic runner selection is unchanged.
28
+
29
+ ## [0.17.0] - 2026-10-01
30
+
31
+ Automated weekly release — everything merged since `v0.16.0`.
32
+
33
+ ### Changed
34
+
35
+ - feat: integrate adoption guidance and machine-safe probing (#189)
36
+ - chore(deps-dev): bump vitest from 5.0.1 to 5.0.2 in the all-npm group (#187)
37
+ - chore(homebrew): sha256 for v0.16.0 (#186)
38
+
39
+
40
+ ### Added
41
+
42
+ - Unannotated scaffold defaults use unfinished `TODO-CLAIM-N` identifiers rather than file/function-shaped claim names. Allocation avoids supplied IDs; explicit IDs/annotations and existing evidence remain unchanged, while sweep pooling preserves distinct candidates.
43
+
44
+ - Read-only `scaffold --from-document <local-text-path>` and `--from-fix <full-commit-ID>` inspection, backed by the closed `authoring-input` report contract. Validation retains historical partition counts and rejects unsafe/private paths, inconsistent identities and optimistic verification labels. Stdout-only output emits no document text or claims; input inspection requires independent intent and is not verification.
45
+
46
+ - Explicit `scaffold <source...> --into <existing-draft.json> --claim <ID>` appends mechanically proposed faults while preserving supplied intent and existing faults. `--json` previews without writes; ordinary scaffold remains compatible. Draft updates use bounded admission, owned locking and private recovery, and refuse stale/unsafe inputs or unconfirmed writes rather than claiming verified coverage.
47
+
48
+ - Sweep keeps equal-basename and repeated-annotation drafts distinct before selection, assigning collision-free pooled claim IDs without changing fault content, metadata or defenders.
49
+
50
+ - New mechanical scaffold drafts declare `inferred` origin and ask for intended observable behavior from a requirement, ADR, bug or incident. CLI/status/skill guidance explains the source handoff without authenticating references or promoting annotations/tests into independent intent. Existing supplied scaffold metadata is preserved.
51
+
52
+ - Explicit `probe --require-origin <kinds>` checks declared origins on complete confirmed current-project probes, rechecks native universe and file bindings, and reports failed/unavailable policy without suppressing survivors through baselines or severity floors. Kinds do not authenticate independence; custom/static universes are unavailable. Offline status audits current declarations without certifying freshness; brief retains labeled recorded-run policy before caps and filtering.
53
+
54
+ - Candidate evidence/status/brief schemas accept a closed optional declared-origin policy result, with unsuppressed fault identities, refusal reasons, consistent states and probe exit codes. This is an audit contract, not authenticated independence.
55
+
56
+ - Claim sources share a closed origin vocabulary across claims and evidence, adding `doc`, `bug`, `incident`, `review` and `inferred`. Status reports current declared origins; evidence and briefs summarize all recorded origins before filtering/caps, separating distinct claims from records and reporting conflicting declarations. Human output labels these as unauthenticated declarations. Labels do not change default gates; origin policy requires explicit selection.
57
+
58
+ - Claims/status missing-source-link advisories identify distinct claim IDs and suggest read-only annotation preview without changing verification state, next action or exit codes; annotation-sourced claims retain their existing drift error.
59
+
60
+ - Explicit `claims --annotate` read-only file-header preview and `--apply` authoring for JavaScript/TypeScript and Python, with claim selection, bounded all-target admission, owned locking, private recoverable originals and truthful partial-failure reporting. Authoring JSON uses a closed `annotations` contract; placement is not verification or authentication of intent.
61
+
62
+ ### Fixed
63
+
64
+ - Clarify that cold probes and changed discovery/configuration can require full verification; unchanged target and defender files alone do not guarantee a cheap CI run.
65
+
66
+ - Status marks evidence stale when a recorded automatic-discovery dependency (including a negative candidate, barrel or resolver config) changes or becomes unavailable. Previously unchanged defender lists could hide this drift. Native test-universe policy freshness remains pending.
67
+
68
+ - Annotation scanning and placement ID admission avoid excessive regex backtracking on long alphanumeric tokens without a hyphen; status advice uses bounded, failure-aware scanning so unrelated source failures cannot prevent its verification decision.
69
+
70
+ - Claim statement, severity, source and producer edits now invalidate cached probe evidence and appear as stale in status. Old kills cannot silently carry an edited requirement or provenance declaration.
71
+
72
+ ### Changed
73
+
74
+ - Reduce repeated self-probe setup with focused defenders for 40 existing fault checks, retaining the complete native integration regressions, all 327 fault recipes, three-run confirmation and existing cost budgets.
75
+ - Bound built-in runner concurrency to one worker by default, with `--workers` overrides, and cap outer regression workers at two (one on a two-core machine).
76
+ - Drain noisy runner stdout, bound diagnostics and report reads, and terminate owned runners before restoring mutations and scratch worktrees on cancellation.
77
+ - Run the project-pinned Playwright CLI directly instead of spawning npm for each confirmation, and reset Python interpreter caches at measurement boundaries.
78
+ - Record actual probe elapsed time and unique fresh runner invocations separately from historical attributed costs; preserve all confirmation and cost gates, and invalidate reuse when native worker policy changes.
79
+
10
80
  ## [0.16.0] - 2026-09-30
11
81
 
12
82
  Automated weekly release — everything merged since `v0.15.1`.
package/README.md CHANGED
@@ -127,9 +127,9 @@ raises coverage. TestGuard admits it because it fails when the claim is false.
127
127
  | npm | `npm i -D testguard-cli` then `npx testguard probe` |
128
128
  | pip | `pip install testguard-cli` then `testguard probe` (needs Node ≥ 20) |
129
129
  | Homebrew | `brew tap raccioly/tap && brew install testguard` |
130
- | GitHub Action | `uses: raccioly/testguard@v0.16.0` — see [`action.yml`](./action.yml) |
130
+ | GitHub Action | `uses: raccioly/testguard@v0.18.0` — see [`action.yml`](./action.yml) |
131
131
  | pre-commit | `repo: https://github.com/raccioly/testguard`, hooks `testguard-claims`, `testguard-probe` |
132
- | GitLab CI | `include: - remote: https://raw.githubusercontent.com/raccioly/testguard/v0.16.0/packaging/gitlab/testguard.gitlab-ci.yml` with `inputs:` — see [`packaging/gitlab/`](./packaging/gitlab/testguard.gitlab-ci.yml) |
132
+ | GitLab CI | `include: - remote: https://raw.githubusercontent.com/raccioly/testguard/v0.18.0/packaging/gitlab/testguard.gitlab-ci.yml` with `inputs:` — see [`packaging/gitlab/`](./packaging/gitlab/testguard.gitlab-ci.yml) |
133
133
 
134
134
  Projects that set `min-release-age` in `.npmrc` cannot see a version published
135
135
  less than that many days ago (`ENOVERSIONS`); install that one with
@@ -142,6 +142,7 @@ npx testguard-cli init # install the agent layer at the git
142
142
  npx testguard-cli status --json # where the project is, and the ONE next action
143
143
  npx testguard-cli claims # what does this project claim, and is each claim probeable?
144
144
  npx testguard-cli claims --check-anchors # fail fast if an exact anchor moved or a replacement no longer parses
145
+ npx testguard-cli claims --annotate --claim AUTH-ADMIN --json # read-only file-header placement preview
145
146
  npx testguard-cli scaffold src/auth.ts # propose faults for a file, as a draft to keep or drop
146
147
  npx testguard-cli probe # try to falsify each claim; report what the tests missed
147
148
  npx testguard-cli admit test/auth.test.ts --claim AUTH-ADMIN # does this test satisfy the two-gate rule?
@@ -158,6 +159,54 @@ unclaimed changes or invalid fault anchors, `2` a precondition failed and
158
159
  nothing was probed, `3` usage.
159
160
  Every command accepts `--json`.
160
161
 
162
+ ### Intent-first drafts
163
+
164
+ Scaffold drafts propose mechanical faults, not intended behavior. New claims
165
+ declare `inferred` origin even with an annotation. Supply the intended observable
166
+ behavior from a requirement, ADR, bug or incident independently of the code:
167
+ inputs, expected outcome and forbidden outcome. Record the supplied source
168
+ kind/ref; when unavailable keep inferred. References are not authenticated or
169
+ fetched, and passing tests do not establish independent intent. Review proposals
170
+ against the supplied intent before adopting and probing; existing `--claim`
171
+ metadata is preserved.
172
+
173
+ ### Optional annotation placement
174
+
175
+ Ordinary `claims` output and status notes identify missing scanned source links
176
+ as advisories. Counts are distinct claim IDs, not faults. They do not change
177
+ verification state, its next action or exit codes; annotation-sourced missing
178
+ IDs still produce the existing claims drift error. Scanned text is a lexical
179
+ link, not authenticated intent or source ownership.
180
+ Status advice uses a bounded scan (10,000 entries, 1,000 files, 64 directory
181
+ levels, 256 KiB per file, 2 MiB total); incomplete scans report unavailable
182
+ advice without concluding an ID is absent. Keep the original `--claims`
183
+ argument for preview when inspecting a custom claims selection.
184
+
185
+ `testguard claims --annotate` previews JavaScript/TypeScript or Python
186
+ file-header links for declared claims; repeat `--claim` or use comma-separated
187
+ IDs to select claims. Add `--apply` only after reviewing the selection to
188
+ explicitly write annotations. Each invocation recomputes its plan: an earlier
189
+ preview is not a saved approval token. No `--out` or unrelated inspection
190
+ switches are accepted with authoring. JSON conforms to the `annotations`
191
+ authoring schema; it contains no source/proposed contents or probe verdicts.
192
+
193
+ This is file-level placement, not symbol ownership or proof of correctness.
194
+ Missing annotations do not disable exact fault-anchor validation, and placement
195
+ does not change claim origins, evidence or baselines. Unsupported, ambiguous or
196
+ unsafe targets block the complete selection. Original/proposed files are capped
197
+ at 2 MiB and the aggregate at 16 MiB. Preserve BOM, shebang, Python encoding
198
+ cookie, newline style and permissions. A preview exits 0 when applicable, 2 when
199
+ refused; apply exits 0 only after verified completion, 2 for refusal/partial
200
+ failure; malformed options exit 3.
201
+
202
+ Apply uses an exclusive owned lock and retains fsynced originals in an owner-only
203
+ recovery directory outside the checkout (the result reports its location).
204
+ External claims files can be previewed but cannot authorize writes. It never
205
+ reclaims an existing lock or automatically rolls back over editor changes.
206
+ This is recoverable, not a cross-file atomic transaction: interruption or
207
+ arbitrary concurrent edits can leave partial content. Compare retained originals
208
+ manually before recovery; inspect ownership before removing a leftover lock.
209
+
161
210
  ## How it works
162
211
 
163
212
  ```bash
@@ -253,7 +302,23 @@ npx testguard-cli admit test/x.test.ts --claim X # is this test green on HEAD
253
302
  version, its own bin script — and only then from an executable on PATH,
254
303
  which the evidence records as `runner.source: "path"`; `npx` is never
255
304
  asked, because its cache answers for packages a project does not have.
256
- Anything else goes through `--runner-cmd`. Each runner is proven against
305
+ **Node's built-in framework** uses explicit `--runner node-test` with plain
306
+ JavaScript test files and default Node collection. It uses the Node executable
307
+ running TestGuard, records `runner.source: "builtin"` and its actual version,
308
+ and installs nothing. Discovery loads test modules with test bodies filtered
309
+ out, so top-level code can run. Custom loaders, `NODE_OPTIONS`, `NODE_PATH`
310
+ and module-mocking configurations are outside this initial adapter's scope.
311
+ `auto` keeps its existing runner order. Each confirmation uses fresh isolated
312
+ processes and the same worker, timeout and confirmation rules.
313
+
314
+ To reproduce the narrow native-runner comparison, run
315
+ `node .github/scripts/benchmark-node-runner.mjs --out /absolute/receipt-dir`
316
+ from this repository after installing its pinned development dependencies.
317
+ It compares 17 identical classifier inputs and four existing faults through
318
+ complete probes, with three confirmations, fresh worker receipts and
319
+ reversed execution order. Results describe that workload and runtime only.
320
+
321
+ Other frameworks go through `--runner-cmd`. Each runner is proven against
257
322
  its own copy of the known-answer fixture.
258
323
 
259
324
  **Python** runs under `pytest` when the project's interpreter can import
@@ -308,9 +373,11 @@ npx testguard-cli admit test/x.test.ts --claim X # is this test green on HEAD
308
373
  `--runner-cmd "<cmd> {files} … {out}"`; if the scratch worktree cannot
309
374
  see your `node_modules`, pass `--node-modules <dir>`.
310
375
  3. **Baseline** freezes every non-passing fingerprint. Later probes suppress
311
- what was already known and exit non-zero only on what is new. Claims whose
312
- source and defenders are unchanged reuse their prior verdict, so a probe
313
- in CI costs only what changed. A baseline frozen from `--include-dirty`
376
+ what was already known and exit non-zero only on what is new. Prior verdicts
377
+ can be reused when their recorded inputs and runner policy still match.
378
+ Cold runs, changed discovery/configuration or `--no-reuse` can require a
379
+ full probe; unchanged target and defender files alone do not guarantee reuse.
380
+ A baseline frozen from `--include-dirty`
314
381
  evidence records the snapshot and points at the *parent* of the commit
315
382
  that will carry your tests; after you commit, a clean `probe` plus
316
383
  `baseline --restamp` moves it to that commit — only when the fingerprints
@@ -494,6 +561,11 @@ proposed 510 faults, probed 10 (cap 10), deferred 350.
494
561
 
495
562
  Three rules make it safe to run on a repository that has never seen this tool:
496
563
 
564
+ Pooled draft IDs are unique even when source files share basenames/functions or
565
+ annotation IDs. Sweep reserves original IDs and suffixes collisions before
566
+ selection, keeping every fault, its metadata and defenders attached to its own
567
+ draft. These are proposal identities, not authenticated claims.
568
+
497
569
  - **It never writes `testguard.claims.json`**, and never will. A claim is a
498
570
  sentence someone is willing to stand behind; a sentence nobody wrote is not
499
571
  one. Its drafts land beside the evidence to keep or drop.
@@ -713,12 +785,12 @@ detected base that does not resolve is a warning for `status` and `brief`
713
785
  # GitHub Actions
714
786
  - uses: actions/checkout@v4
715
787
  with: { fetch-depth: 0 }
716
- - uses: raccioly/testguard@v0.16.0
788
+ - uses: raccioly/testguard@v0.18.0
717
789
  with: { command: gate }
718
790
 
719
791
  # GitLab CI — the component-shaped template: gate + probe, brief as an artifact and, opted in, as a merge-request note
720
792
  include:
721
- - remote: 'https://raw.githubusercontent.com/raccioly/testguard/v0.16.0/packaging/gitlab/testguard.gitlab-ci.yml'
793
+ - remote: 'https://raw.githubusercontent.com/raccioly/testguard/v0.18.0/packaging/gitlab/testguard.gitlab-ci.yml'
722
794
  inputs: { dir: backend, post_note: true } # post_note needs TESTGUARD_GITLAB_TOKEN (api scope); one note, updated in place
723
795
  ```
724
796
 
@@ -968,16 +1040,20 @@ said what they want.
968
1040
 
969
1041
  ### What the probe costs, and why a gate gets slow
970
1042
 
971
- A probe's wall clock is not a function of how many claims you have. Per claim
972
- it is roughly
1043
+ A fresh probe grows with the selected faults, confirmation count and the cost
1044
+ of their defenders. Shared baselines and valid verdict reuse avoid some repeated
1045
+ work. Roughly, the fresh work is
973
1046
 
974
1047
  ```
975
- (baseline runs + faults × --confirm) × the cost of that claim's defender SET
1048
+ fresh baseline runs × defender-set cost
1049
+ + Σ (fault confirmations × that fault's defender-set cost)
1050
+ + survivor diagnostics and setup/discovery work
976
1051
  ```
977
1052
 
978
- so one slow acceptance test, named as a defender by five claims, is paid for
979
- thirty times. The symptom is a gate that takes twenty minutes; the cause is a
980
- single line in the claims file, and nothing in the output used to say which.
1053
+ One slow acceptance test selected by several faults can therefore be executed
1054
+ many times. The symptom can be a gate that takes twenty minutes; the selected
1055
+ defender sets determine how much each fault costs. Historical attributed totals
1056
+ are reported separately from measured fresh elapsed time and runner invocations.
981
1057
 
982
1058
  ```bash
983
1059
  npx testguard-cli claims . --cost # read back from the last probe's evidence
@@ -1031,8 +1107,37 @@ so `scaffold` proposes them for you:
1031
1107
  ```bash
1032
1108
  npx testguard-cli scaffold src/auth.ts # → .testguard/scaffold-auth.json (a draft, never your claims file)
1033
1109
  npx testguard-cli scaffold src/auth.ts --claim AUTH-ADMIN # every proposal under one claim; copies it if it exists
1110
+ npx testguard-cli scaffold src/auth.ts src/session.ts --into draft.json --claim AUTH-ADMIN --json # read-only merged preview
1111
+ npx testguard-cli scaffold src/auth.ts src/session.ts --into draft.json --claim AUTH-ADMIN # explicit recoverable draft update
1112
+ npx testguard-cli scaffold --from-document requirements.md --json # read-only input metadata, no document text
1113
+ npx testguard-cli scaffold --from-fix <full-commit-ID> --json # read-only fixed historical inventory
1034
1114
  ```
1035
1115
 
1116
+ Input inspection uses exactly one `--from-document` or `--from-fix`, with no
1117
+ positional sources or other options except JSON/help/version. Fix IDs must be
1118
+ full lowercase SHA-1/SHA-256 commit IDs with exactly one parent. Plain-text
1119
+ documents are bounded to 2 MiB; local Git inspection is offline and bounded.
1120
+ Both output modes are stdout-only and say verification was not performed.
1121
+ Metadata retains historical exclusions, not private/delegated filenames.
1122
+ Input text and commit subjects are untrusted data, not instructions or an
1123
+ authenticated claim. Supply independent intended behavior, review faults and
1124
+ probe afterward; inspection does not create claims or prove coverage.
1125
+
1126
+ Without a supplied ID or annotation, generated groups use unfinished
1127
+ `TODO-CLAIM-N` placeholders rather than module/function names. Replace them with
1128
+ intent-shaped identities when authoring; mechanical grouping does not establish
1129
+ an invariant boundary. Existing claims/evidence are never automatically renamed.
1130
+
1131
+ `--into` requires an existing disposable draft and exactly one existing claim
1132
+ ID. It preserves supplied intent, metadata and prior faults; multiple source
1133
+ paths append in deterministic order. `--json` is a read-only preview. Without
1134
+ it, the tool keeps private recovery outside the checkout and reports updated
1135
+ or unchanged **unproven** draft status. Review and probe are still required.
1136
+ Canonical claims/evidence/baseline paths, unsafe aliases and conflicting options
1137
+ are refused; partial writes never become success or trigger automatic rollback.
1138
+ Limits: 32 sources, 2 MiB per input/output draft or source, 16 MiB source total,
1139
+ 4096 generated proposals. These limits are not a performance guarantee.
1140
+
1036
1141
  | Shape | What it proposes |
1037
1142
  |---|---|
1038
1143
  | `condition-forced` | `if (<guard>) {` → `if (false) {` — a guard is a `!…` condition or one whose body returns, throws or 4xx-es |
@@ -1105,6 +1210,30 @@ verdicts.
1105
1210
 
1106
1211
  ## Status
1107
1212
 
1213
+ Origin summaries are informational: status counts current declared claim
1214
+ origins even when evidence is stale; probe evidence and briefs count recorded
1215
+ origins across all records before filtering or truncation. Distinct claims and
1216
+ records have separate totals; conflicting recorded kinds or references count
1217
+ as mixed claims. Labels such as `spec`, `bug` or `incident` do not authenticate
1218
+ independence and never waive a failed measurement or change default gates.
1219
+ References remain opaque and are not echoed in these summaries. Older strict
1220
+ readers reject these additive fields; use the matching candidate reader for
1221
+ unreleased formats. The candidate `probe --require-origin spec,adr,bug,incident`
1222
+ option selects declared kinds for a complete confirmed current-project probe.
1223
+ Repeat the option or use comma-separated kinds; partial, provisional, explicit
1224
+ historical and ignore-dirty combinations are refused. Failed policy exits 1
1225
+ even when baseline debt or a severity floor hides ordinary findings; unavailable
1226
+ current bindings exit 2. The command rechecks native runner/configuration
1227
+ membership, current claims, targets, defenders and discovery dependencies before
1228
+ publishing. Custom/static runner universes cannot certify this boundary. This is
1229
+ a declaration check, not authenticated independence or an atomic disk snapshot.
1230
+ Offline status recomputes a current-declaration audit using the recorded eligible
1231
+ selection, always marking native freshness unavailable without launching a
1232
+ runner. It does not implicitly activate a new gate or replace status's next
1233
+ action. Briefs preserve the recorded-run policy before caps and baseline
1234
+ filtering, explicitly not current freshness. A zero-item cap never turns
1235
+ survivors into an all-defended message.
1236
+
1108
1237
  **v0.5.** Eleven commands (`status`, `init`, `claims`, `probe`, `admit`,
1109
1238
  `replay`, `baseline`, `brief`, `gate`, `scaffold`, `sweep`, `mcp`), vitest, jest,
1110
1239
  Playwright and Python (pytest / stdlib unittest) runners, hand-authored faults
@@ -1120,6 +1249,32 @@ the transfer of a calibration between repositories — `replay` measures it now;
1120
1249
  whether it carries to a repository with no history is unproven. Each is
1121
1250
  designed for; none is claimed.
1122
1251
 
1252
+ ### Keeping developer machines responsive
1253
+
1254
+ Built-in probe, sweep, replay and admission runners default to one worker. Use
1255
+ `--workers 2` for a larger Vitest/Jest/Playwright worker ceiling; `--serial` always
1256
+ uses one. Python remains serial. Faults and mixed-runner groups run sequentially.
1257
+ Custom `--runner-cmd` commands, browser subprocesses, native library threads and
1258
+ test-created processes are not an OS resource sandbox. The regression suite also
1259
+ caps outer workers at two, or one when fewer than three CPUs are available
1260
+ in an interactive run; dedicated CI uses at most two because its acceptance tests start nested runners.
1261
+
1262
+ `--budget` bounds each runner invocation; `--command-budget` bounds a complete
1263
+ command cooperatively and refuses partial result publication. Cancellation kills
1264
+ owned runners before restoring mutations and removing scratch worktrees. Already
1265
+ reparented daemons remain outside the portable cleanup guarantee. No runner output
1266
+ limit can count as an assertion failure or detection.
1267
+
1268
+ New probe evidence includes actual elapsed time, unique fresh runner time and
1269
+ setup/discovery/other overhead. `probe --cost` and `claims --cost` display this
1270
+ separately from historical attributed record costs. Existing cost ceilings are
1271
+ unchanged; old evidence does not supply a measured breakdown.
1272
+
1273
+ Playwright confirmations run the same project-resolved CLI used for discovery,
1274
+ avoiding an npm subprocess per run. Python projects whose configuration requires
1275
+ pytest-xdist must support serial execution; an incompatible configuration remains
1276
+ unproven rather than bypassing the worker policy.
1277
+
1123
1278
  ## Licence
1124
1279
 
1125
1280
  MIT.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "testguard-cli",
3
- "version": "0.16.0",
3
+ "version": "0.18.0",
4
4
  "description": "Breaks your code on purpose and reports every promise your tests did not notice breaking. Mutation testing bound to the claims a project makes — vitest, jest, Playwright, pytest and unittest.",
5
5
  "type": "module",
6
6
  "license": "MIT",