@gtrabanco/pi-agentic-workflow 0.36.0 → 4.10.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 (52) hide show
  1. package/dist/config/defaults.js +8 -0
  2. package/dist/config/merge.js +20 -0
  3. package/dist/config/schema.js +103 -1
  4. package/dist/config/types.d.ts +60 -0
  5. package/dist/extension/ci-guard.d.ts +29 -0
  6. package/dist/extension/ci-guard.js +39 -0
  7. package/dist/extension/cost-guard.d.ts +30 -0
  8. package/dist/extension/cost-guard.js +50 -0
  9. package/dist/extension/factory.d.ts +11 -4
  10. package/dist/extension/factory.js +4 -1
  11. package/dist/extension/guard-util.d.ts +26 -0
  12. package/dist/extension/guard-util.js +35 -0
  13. package/dist/extension/history-guard.d.ts +59 -0
  14. package/dist/extension/history-guard.js +132 -0
  15. package/dist/extension/index.js +21 -5
  16. package/dist/extension/merge-guard.d.ts +26 -28
  17. package/dist/extension/merge-guard.js +64 -38
  18. package/package.json +7 -6
  19. package/skills/audit-docs/SKILL.md +1 -1
  20. package/skills/audit-pr/SKILL.md +12 -1
  21. package/skills/discover-repository-state/SKILL.md +1 -1
  22. package/skills/execute-phase/SKILL.md +61 -6
  23. package/skills/fold-findings/SKILL.md +126 -8
  24. package/skills/fold-findings/references/FOLD_PROCESS.md +7 -1
  25. package/skills/init-workspace/SKILL.md +1 -1
  26. package/skills/log-session/SKILL.md +1 -1
  27. package/skills/orchestration-envelope/SKILL.md +1 -1
  28. package/skills/phase-contract/SKILL.md +1 -1
  29. package/skills/pre-execution-review/SKILL.md +1 -1
  30. package/skills/product-audit/SKILL.md +4 -1
  31. package/skills/product-audit/references/AUDIT_DIMENSIONS.md +34 -0
  32. package/skills/product-audit/references/AUDIT_PROCESS.md +5 -1
  33. package/skills/resolve-repository-state/SKILL.md +1 -1
  34. package/skills/review-a11y/SKILL.md +1 -1
  35. package/skills/review-brand/SKILL.md +1 -1
  36. package/skills/review-change/SKILL.md +18 -3
  37. package/skills/review-code/SKILL.md +28 -2
  38. package/skills/review-debt/SKILL.md +8 -2
  39. package/skills/review-design/SKILL.md +1 -1
  40. package/skills/review-implementation/SKILL.md +1 -1
  41. package/skills/review-implementation/references/CLASSIFY.md +25 -0
  42. package/skills/review-perf/SKILL.md +1 -1
  43. package/skills/review-security/SKILL.md +1 -1
  44. package/skills/review-seo/SKILL.md +1 -1
  45. package/skills/review-verify/SKILL.md +19 -2
  46. package/skills/triage-issue/SKILL.md +9 -1
  47. package/skills/triage-issue/references/LABELS.md +22 -0
  48. package/skills/unit-lane/SKILL.md +26 -7
  49. package/skills/unit-lane/references/DESIGN.md +55 -1
  50. package/skills/unit-lane/references/PLAN.md +29 -0
  51. package/skills/verification-contract/SKILL.md +9 -1
  52. package/skills/workflow-status/SKILL.md +1 -1
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: fold-findings
3
3
  user-invocable: true
4
- version: 1.11.0
4
+ version: 4.10.0
5
5
  argument-hint: [finding-id …]
6
6
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
7
7
  license: MIT
@@ -34,6 +34,18 @@ skill fixes each root cause, never relabeling, deferring, or weakening its check
34
34
  ✓ 5. The closing `Folded: n/m · Disputed: k · Blocked: j[ · Replan: r]` tally
35
35
  and outcome-branched `→ Next:` block are printed as the ABSOLUTE last output.
36
36
  Every affected finding ID is named in that block, joined with ` + `.
37
+ ✓ 6. Claim-evidence loop ran: before committing, every claim the repair
38
+ introduces was reproduced with the command and observed output pasted
39
+ into the claim table (`claim | command | output | status`). Loop ran until
40
+ green inside the same turn. (S5)
41
+ ✓ 7. Class escalation checked: ≥ 2 folded rows sharing mechanism+axis
42
+ were escalated to one class-level fix-now finding. (S1)
43
+ ✓ 8. Evidence-bound check: every finding citation was verified — the cited
44
+ file:line exists and the snippet matches the working tree verbatim. (S10)
45
+ ✓ 9. Reviewer anti-invention check: new findings are grounded in
46
+ provably-changed bytes (git-computed) or a mis-run cited check. (S10)
47
+ ✓ 10. Net narration diff ≤ 0 per fold: lines deleted, not moved. (S10)
48
+ ✓ 11. Closure status printed: `closure: complete | open(n)`. (S4)
37
49
  ```
38
50
 
39
51
  Any unchecked box means the turn is not done.
@@ -73,8 +85,22 @@ Per Workflow conventions, read:
73
85
  2. Queue the carrier's open rows — a legacy `folded: no` row, a migrated row of
74
86
  `## Findings` (all of them are open); explicit IDs restrict the queue and leave
75
87
  other rows untouched. Group by root cause, verifier and rollback boundary.
76
- 3. The project's verification gate and forge CLI (use the declared forge).
77
- 4. Whether the branch has an open PR; this decides immediate push after commit.
88
+ 3. **Class escalation (S1).** After grouping: ≥ 2 folded rows sharing
89
+ mechanism+axis ⇒ one class-level fix-now finding whose repair targets the
90
+ *mechanism*, not a repeated instance. The two-cycle cap then means what it
91
+ was built to mean: a class the loop refuses to repair is a planning defect,
92
+ not more folds. Document the escalation as `F<next> (class: <mechanism>,
93
+ replaces F<a> + F<b> + …)` in the ledger.
94
+ 4. **Evidence-bound check (S10, from #218).** Before processing, verify every
95
+ finding's citation: the cited `file:line` exists and the snippet matches the
96
+ working tree verbatim. Wrong-citation and position-drift findings are
97
+ discarded mechanically — `refuted` with evidence, no cycle consumed.
98
+ 5. **Reviewer anti-invention check (S10, from #205).** Any new finding surfaced
99
+ during fold must be grounded in **provably-changed bytes** (git-computed) or
100
+ a **mis-run cited check** (the cited validator's own output contradicts it).
101
+ A finding without changed-bytes grounding is a report-note, never fix-now.
102
+ 6. The project's verification gate and forge CLI (use the declared forge).
103
+ 7. Whether the branch has an open PR; this decides immediate push after commit.
78
104
 
79
105
  ## Progressive loading — fold queue
80
106
 
@@ -87,6 +113,58 @@ code or the ledger:
87
113
  Both are normative and one hop from this file. Missing resource → stop; never
88
114
  infer a classification or fold procedure.
89
115
 
116
+ ## Claim-evidence loop (S5 — mandatory before commit)
117
+
118
+ Before committing the fold fix, run the claim-evidence loop. This is not optional;
119
+ a turn that writes without verifying its own claims is the exact failure class
120
+ that produced unit 79's F49→F50→F51.
121
+
122
+ 1. **Claim ledger.** Enumerate every claim the repair introduces: each new
123
+ figure, cross-reference, "X is now Y"; in code: each behavior the fix
124
+ declares. Write one row per claim.
125
+ 2. **Mandatory reproduction.** Every claim is executed, never asserted:
126
+ re-derive the figure with the command, resolve the reference with grep,
127
+ reproduce the behavior. Paste command + observed output into the claim
128
+ table — never type the expected result by hand.
129
+ 3. **Loop until green.** red → repair → re-run, *inside the same turn*, until
130
+ every claim in the closure set verifies. The repairer's turn does not end
131
+ with unreproduced claims.
132
+ 4. **Admission rule.** If no command can verify the sentence, it is not a
133
+ claim, it is an opinion, and it does not get written. This extends the
134
+ repo's own tests-first rule to documentation artifacts.
135
+
136
+ Output the claim table as:
137
+
138
+ ```
139
+ ## Claim-evidence table
140
+ | claim | command | output | status |
141
+ |---|---|---|---|
142
+ | <claim text> | `<command>` | `<observed output>` | ✓ |```
143
+
144
+ All rows must have `status: ✓`. A `status: ✗` row means the turn is not done
145
+ — repair and re-run the claim.
146
+
147
+ The row shape is published grammar, not convention (`evidence-row@1` in
148
+ `@gtrabanco/agentic-workflow-schema`: `EVIDENCE_ROW_COLUMNS`,
149
+ `EVIDENCE_ROW_VERDICTS`, `validateEvidenceRow`). A row whose claim is empty, whose
150
+ command or output is not a backticked command/observation, or whose verdict is
151
+ outside `✓ | ✗` is a shape violation — prose in the command cell is refused
152
+ exactly like an empty one, because a typed expectation is the defect the shape
153
+ exists to stop.
154
+
155
+ ## Closure status (S4, S11)
156
+
157
+ At the end of the fold, print the closure status:
158
+
159
+ ```
160
+ closure: complete | open(n)
161
+ ```
162
+
163
+ - `complete` — all findings in the queue are resolved (folded, refuted, disputed, or replanned).
164
+ - `open(n)` — n findings remain open (blockers that need user input). Print the count and the blocker IDs.
165
+
166
+ Cycle-count stops being the health metric; closure is the invariant.
167
+
90
168
  ## Report — return exactly this structure (fixed output contract)
91
169
 
92
170
  Per finding, in processing order:
@@ -152,6 +230,10 @@ table: [`FOLD_PROCESS.md`](references/FOLD_PROCESS.md) §Batch classification.
152
230
 
153
231
  ## Guardrails
154
232
 
233
+ - The all-stages no-assumption rule binds fold work — **ask-don't-infer**, owner
234
+ `skills/unit-lane/references/DESIGN.md` (`ask-dont-infer@1`): a repair the
235
+ evidence does not settle is researched and asked about, never assumed.
236
+
155
237
  Scope is the ledger (or explicit ID subset); unlisted discoveries are proposals
156
238
  for user triage. Batch only when one root-cause correction, validator set and
157
239
  rollback boundary own the rows: one commit/push, individual ticks/lines. Split
@@ -193,6 +275,36 @@ every declared grep and fails closed with `sweep-mismatch`, naming
193
275
  `file:line`, the regex and the observed count. A fold that changes such a
194
276
  surface and emits no declaration is a `workflow` finding at review.
195
277
 
278
+ **Re-review skip default inversion (S9, feature 30).** The `RE-REVIEW-OPTIONAL/SKIPPED`
279
+ branch shipped in feature 30 was never exercised once (11 cycles on docs-only
280
+ changes). Fix: for docs-only batches with a green sweep declaration
281
+ (#315's claim kind), **skip becomes the machine-decided default** — re-review
282
+ requires recorded justification. Why safe *now*: the residual risk the default
283
+ hedged (stale survivors) becomes a pre-commit failure once #315's sweep kind
284
+ exists. The decision moves from human inertia (always yes) to machine rule
285
+ (batch class + sweep green ⇒ skip).
286
+
287
+ **Net narration diff ≤ 0 (S10 1).** Each fold must strictly decrease the defect
288
+ surface. Add a computed check: the net narration diff per fold must be ≤ 0 —
289
+ lines deleted, not moved. Measured by `git diff --numstat` over the fold's
290
+ commit. This is the arithmetic that makes #307's "deterministic gates converge"
291
+ possible.
292
+
293
+ **Defect identity: mechanism, not file:line (S4).** Defect identity in the ledger
294
+ moves from `file:line` to the *mechanism* (the site stays as evidence). When
295
+ folding, group by mechanism+axis, not by file:line+axis. The same bug surfacing
296
+ as F49, then F50, then F51 costs a full review cycle each time when grouped by
297
+ file:line; grouped by mechanism, one class escalation fixes all three.
298
+
299
+ **Per-file review state (S10 6, from #218; shipped as S16).** `review-state.json`
300
+ per unit, single writer = `scripts/review-state.mjs`, model passes read-only: each
301
+ file in the affecting-path inventory ends a cycle `reviewed@<sha>` or
302
+ `skipped@<sha>` with a concrete reason; skips auto-invalidate when a later diff
303
+ touches the file; coverage closure `inventory − reviewed − skipped = 0` is a
304
+ mechanical receipt check. Run `node scripts/review-state.mjs check --unit <slug>`
305
+ and paste the block — `closure: complete` exits 0, `closure: open(n)` exits 1 and
306
+ is a blocker, never a note.
307
+
196
308
  ## Portability (agents other than Claude Code)
197
309
 
198
310
  Use explicit fallbacks when a primitive is absent: open named `SKILL.md` files in
@@ -251,8 +363,9 @@ decision to skip.
251
363
  |---|---|---|
252
364
  | freeze-batch (≥ 1 product-owned row) | `PRODUCT-ROUTE` | `/unit-lane <slug>` (feature) or `/unit-lane --fix <n>` (fix) when the router concludes `product` — the lane repairs the half through its `design` step, its `review` step re-judges it; the conclusion printed by `bun scripts/unit-route.mjs <unit>` (node fallback if bun is not installed; discovery step the fold already ran) |
253
365
  | freeze-batch (≥ 1 replan-class row) | `REPLAN-ROUTE` | `/unit-lane <slug>` (feature) or `/unit-lane --fix <n>` (fix) when the router concludes `replan` — user confirms, the lane's `plan` step appends the phases and its `review` step gates, then `/execute-phase` on this unit; on `route: decision` stop and surface the decision to the user — the conclusion printed by `bun scripts/unit-route.mjs <unit>` (node fallback if bun is not installed; discovery step the fold already ran) |
254
- | `all-repair-in-place` + docs-only + no folded row severity `high` + prior consumer skip decision | `RE-REVIEW-SKIPPED` | skip — consumer has explicitly decided to skip the re-review |
255
- | `all-repair-in-place` + docs-only + no folded row severity `high` | `RE-REVIEW-OPTIONAL` | `/review-change` (default, delta mode) — or the consumer's recorded skip decision |
366
+ | `all-repair-in-place` + docs-only + green sweep declaration + no folded row severity `high` | `RE-REVIEW-SKIPPED` | skip — green sweep (#315) + docs-only ⇒ skip is default (S9); re-review requires recorded justification |
367
+ | `all-repair-in-place` + docs-only + no sweep declaration + no folded row severity `high` + prior consumer skip decision | `RE-REVIEW-SKIPPED` | skip — consumer has explicitly decided to skip the re-review |
368
+ | `all-repair-in-place` + docs-only + no sweep declaration + no folded row severity `high` | `RE-REVIEW-OPTIONAL` | `/review-change` (default, delta mode) — or the consumer's recorded skip decision |
256
369
  | empty batch (class `none`) | `RE-REVIEW-OPTIONAL` | `/review-change` by default — safe: the head is unchanged |
257
370
  | anything else (behavioral surface or any folded row `high`) | `RE-REVIEW-REQUIRED (delta)` | `/review-change` — delta mode mandatory default |
258
371
 
@@ -264,7 +377,12 @@ decision to skip.
264
377
  - **Frozen-severity-`high` override.** A folded row whose frozen severity is
265
378
  `high` forces `RE-REVIEW-REQUIRED (delta)` even on a docs-only diff. Frozen
266
379
  fields are never edited to reach a branch.
267
- - **SKIPPED requires prior consumer decision (E-D2).** `RE-REVIEW-SKIPPED`
268
- is printed only by a turn carrying an explicit prior consumer decision to
269
- skip. A turn with no recorded prior consumer decision prints
380
+ - **SKIPPED with sweep (S9).** `RE-REVIEW-SKIPPED` is printed when the batch
381
+ is docs-only + has a green sweep declaration (#315's claim kind), even
382
+ without a prior consumer decision. This is the default inversion: skip is
383
+ the machine-decided default for docs-only + sweep green. Prior consumer
384
+ decision is still accepted (backwards-compatible).
385
+ - **SKIPPED without sweep (E-D2).** `RE-REVIEW-SKIPPED` requires an explicit
386
+ prior consumer decision when the batch is docs-only but has no sweep
387
+ declaration. A turn with no recorded prior consumer decision prints
270
388
  `RE-REVIEW-OPTIONAL` + the re-review default, **never** `RE-REVIEW-SKIPPED`.
@@ -78,7 +78,7 @@ hard-wrapped across several lines, never joined into one prose line.
78
78
  ## REPAIR-RECEIPT — fixed printed block (verbatim copy)
79
79
 
80
80
  Printed after the per-finding table and tally, as part of the ABSOLUTE-last
81
- output together with the branching `→ Next:` block. Six fields, always
81
+ output together with the branching `→ Next:` block. Seven fields, always
82
82
  present:
83
83
 
84
84
  ```text
@@ -87,6 +87,12 @@ present:
87
87
  - Refuted/open: <F-ids joined ` + `, or `none`>
88
88
  - Gate: <command> → exit <n> at head <40-hex sha> · n/a when nothing was folded
89
89
  - Batch class: <all-repair-in-place | frozen (replan present) | frozen (product owner present) | none>
90
+ - Closure: <complete | open(n)> · open names the blocker ids
90
91
  - Fold diff: <shortstat from a real `git diff` run> · none when nothing was folded
91
92
  - Branch: <RE-REVIEW-REQUIRED (delta) | RE-REVIEW-OPTIONAL | RE-REVIEW-SKIPPED | REPLAN-ROUTE | PRODUCT-ROUTE>
92
93
  ```
94
+
95
+ The claim-evidence table the fold prints before this block (§ Claim-evidence
96
+ loop in SKILL.md) is what makes `Closure:` a receipt rather than a claim: a row
97
+ with `status: ✗` means the fold is not closed, and `Closure: complete` is only
98
+ printable once every row reads ✓.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: init-workspace
3
3
  user-invocable: true
4
- version: 4.3.0
4
+ version: 4.10.0
5
5
  argument-hint: <target-dir>
6
6
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
7
7
  license: MIT
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: log-session
3
3
  user-invocable: true
4
- version: 2.3.0
4
+ version: 4.10.0
5
5
  argument-hint: "[note to prepend to the entry]"
6
6
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
7
7
  license: MIT
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: orchestration-envelope
3
3
  user-invocable: false
4
- version: 2.4.0
4
+ version: 4.10.0
5
5
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
6
6
  license: MIT
7
7
  description: >
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: phase-contract
3
3
  user-invocable: false
4
- version: 1.1.0
4
+ version: 4.10.0
5
5
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
6
6
  license: MIT
7
7
  description: >
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: pre-execution-review
3
3
  user-invocable: false
4
- version: 2.8.3
4
+ version: 4.10.0
5
5
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
6
6
  license: MIT
7
7
  description: >
@@ -2,7 +2,7 @@
2
2
  name: product-audit
3
3
  user-invocable: true
4
4
  disable-model-invocation: true
5
- version: 3.4.0
5
+ version: 4.10.0
6
6
  metadata:
7
7
  opencode/autoinvoke: false
8
8
  argument-hint: <path-or-area> (optional — defaults to the whole product)
@@ -159,6 +159,9 @@ security items to track first").
159
159
 
160
160
  ## Guardrails
161
161
 
162
+ - **The all-stages no-assumption rule binds this audit** — **ask-don't-infer**,
163
+ owner `skills/unit-lane/references/DESIGN.md` (`ask-dont-infer@1`); an
164
+ unevidenced expectation is asked, never invented.
162
165
  - **Never auto-fixes, never opens issues, never edits the roadmap.** Output is a
163
166
  report + proposals; **every action is the user's decision.** The one file this
164
167
  skill writes is its own report under `docs/audits/` (plus `mkdir -p
@@ -11,6 +11,9 @@
11
11
  | **SEO** | Indexability, metadata, structured data | web |
12
12
  | **Brand / voice** | User-facing copy vs. the brand guide | surfaces with copy |
13
13
  | **Tech debt** | Accumulated shortcuts, TODO/FIXME, stale abstractions | all |
14
+ | **Residue — duplication** | Duplicate content across code **and skill/docs prose** — a grammar block, checklist, table, contract or paragraph copied where a reference should carry it; the duplication check today diff-scoped in `review-code`, re-swept product-wide (see § Residue sweeps) | all |
15
+ | **Residue — unused code** | Code — and skill prose, same rule — that nothing consumes, classified two ways per the classifier's rule (§ Residue sweeps): delivered-feature-without-consumer → bug finding; orphaned-by-requested-replacement/removal → deletion candidate; the dead-code check today diff-scoped in `review-code`, re-swept product-wide | all |
16
+ | **Residue — documentation** | Obsolete docs (they describe surfaces that no longer exist) and missing docs (a live **consumer-facing** surface with no consumer-facing doc — the document-or-don't-coin residue); composes `audit-docs` and never restates its axes (see § Residue sweeps) | all |
14
17
  | **Process & docs** | Incomplete phases, aging open issues, **solvable known-issues**, doc completeness, missing/optimizable workflow docs, capability-inventory freshness (`docs/CAPABILITIES.md` ↔ code drift) | all |
15
18
  | **Workflow discipline** | The workflow's own rules held: branch/PR discipline, `done · #<pr>` links, phase naming (`P1…`), per-phase docs, commit format, dependency closures, artifact language — **run `audit-docs` checks mechanically** (cite the count from `audit-docs`; never restated in the dimension table); never assume a rule held because it "should". **Scope-export recurrence:** across the most recent units (merged or in-flight), each with a non-empty `## Amendments` descope log or a descope-classified born issue (`audit-pr`'s scope-bleed gate) counts as one scope-exporting unit — **≥ 2 consecutive** such units is a planning-quality finding ("features cut too big for real capacity"), routed to the atomicity/split rules (**#64**), not re-litigated as a per-unit defect | all |
16
19
  | **Roadmap coherence** | Stale/obsolete/superseded features, missing dependencies, gaps & opportunities | all |
@@ -22,3 +25,34 @@ internal review pack (`review-code`, `review-security`, `review-verify`,
22
25
  `review-debt`, `review-design`, `review-a11y`, `review-brand`, `review-perf`,
23
26
  `review-seo`) — installed with the workflow, so an applicable axis can never be
24
27
  "missing". Platform skills the project installed run as optional extras on top.
28
+
29
+ ## Residue sweeps (pass-only-if)
30
+
31
+ The three residue dimensions run product-wide across code **and skill/docs
32
+ prose** — "code" includes prose everywhere in this section (#340). A sampled
33
+ sweep states what it sampled, like every dimension. Findings route through the
34
+ classifier (`review-implementation`, `CLASSIFY.md`) like every other finding.
35
+
36
+ **Duplicate content** — pass only if:
37
+
38
+ - ✓ every duplicated grammar block, checklist, table, contract or paragraph found is either a reference to a single owner or carries its declared reason for the copy
39
+ - ✓ each confirmed duplicate is one finding citing both locations
40
+ - ✓ the same sweep run over the clean fixture twin (below) yields zero findings
41
+
42
+ **Unused code, two ways, never conflated** — pass only if:
43
+
44
+ - ✓ every unconsumed exported/defined symbol (or unreferenced prose block) is classified exactly one way: written as part of a delivered feature that **no functionality invokes** → **bug finding** (the feature was not implemented completely — the unit shipped half of what was asked); orphaned because a requested change **replaced or removed** that feature or part → **deletion candidate** (`fix-now (delete)`, not a bug)
45
+ - ✓ the classification cites what requested the original feature and what replaced it — classifier evidence, never the auditor's impression
46
+ - ✓ after any proposed deletion, **features-preserved-without-it** is verified: every requested feature still works without the removed code or prose — a deletion that breaks a requested feature is a finding, not a cleanup
47
+
48
+ **Obsolete & missing documentation** — pass only if:
49
+
50
+ - ✓ every doc describing a surface that no longer exists is a finding (obsolete), citing the live-tree search that proves the surface gone
51
+ - ✓ every live **consumer-facing** surface with no consumer-facing doc is a finding (missing — the document-or-don't-coin residue); internal-only helpers are not findings
52
+ - ✓ `audit-docs`' own axes were run or their result cited — this sweep adds the residue cases, never restates the coherence checks
53
+
54
+ The seeded fixture (`scripts/product-audit-residue-fixture.mjs <dir>`, written
55
+ on demand outside the repository) carries one seed per residue class — a
56
+ duplicated grammar copy, an exported-but-unconsumed function, a doc naming a
57
+ removed surface, a live surface with no doc — plus a clean twin: the sweeps
58
+ must yield exactly one finding per seed on `seeded/` and zero on `clean/`.
@@ -4,7 +4,11 @@
4
4
  2. **Sweep code & axes** — run the applicable axes across the codebase: compose
5
5
  `review-implementation` plus the internal review pack's applicable passes
6
6
  (each returns its fixed-format table + PASS|FAIL), and any optional installed
7
- extras. Classify findings (severity + closed class set from review-implementation/CLASSIFY.md).
7
+ extras. Run the **residue sweeps** (`AUDIT_DIMENSIONS.md` § Residue sweeps):
8
+ duplicate content, unused code classified two ways, obsolete + missing
9
+ documentation — product-wide, across code and skill/docs prose, with the
10
+ features-preserved-without-it check after every proposed deletion. Classify
11
+ findings (severity + closed class set from review-implementation/CLASSIFY.md).
8
12
 
9
13
  **Evidence-provenance gate (fixed):** applies during every evidence-collecting sweep
10
14
  step (2–5). Each item ends with exactly one fallback; never pick another one mid-audit.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: resolve-repository-state
3
3
  user-invocable: true
4
- version: 1.2.2
4
+ version: 4.10.0
5
5
  argument-hint: <contradiction-id>
6
6
  description: >
7
7
  Resolve an explicit Normalized Repository State contradiction. This is the
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: review-a11y
3
3
  user-invocable: false
4
- version: 1.1.0
4
+ version: 4.10.0
5
5
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
6
6
  license: MIT
7
7
  description: >
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: review-brand
3
3
  user-invocable: false
4
- version: 1.1.0
4
+ version: 4.10.0
5
5
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
6
6
  license: MIT
7
7
  description: >
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: review-change
3
3
  user-invocable: true
4
- version: 3.13.0
4
+ version: 4.10.0
5
5
  argument-hint: <path-or-glob> [--adversarial N] [--synthesize]
6
6
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
7
7
  license: MIT
@@ -95,8 +95,10 @@ survives the attempt, that survival *is* the review outcome. So:
95
95
  or the requirement leaves the user's expectation unclear, surface it as a
96
96
  question in non-technical terms (a technical user asks for an app; a
97
97
  non-technical user asks for “an app to measure my heart rate”) — never as an
98
- assumed intent. This extends ask-don't-infer from acceptance criteria to every
99
- expectation the change is judged against.
98
+ assumed intent. This review applies the all-stages no-assumption rule —
99
+ **ask-don't-infer**, owner `skills/unit-lane/references/DESIGN.md`
100
+ (`ask-dont-infer@1`) — to every expectation the change is judged against;
101
+ the rule is owned there, never restated here.
100
102
  - **Repo-wide hunting is not this review.** Open-ended bug hunting, security
101
103
  research and broken-version investigation *across the repository* belong to
102
104
  `product-audit`, where the sweep is scoped and budgeted; this review stays on
@@ -182,6 +184,19 @@ Architectural invariants rules.
182
184
  Resources are one hop from this file. Fixed reviewer/synthesis/output contracts are
183
185
  literal. Missing required resource → stop; never approximate a review contract.
184
186
 
187
+ ## Reviewer anti-invention rule (S10, from #205)
188
+
189
+ After cycle 1, a *new* finding is admissible only when grounded in:
190
+ 1. **Provably-changed bytes** (git-computed diff between the reviewed state
191
+ and the base), or
192
+ 2. A **mis-run cited check** (the cited validator's own output contradicts it).
193
+
194
+ A finding without changed-bytes grounding is a report-note, never fix-now.
195
+ This is narrower and stronger than the delta-mode "genuinely new" admission:
196
+ it bounds what a reviewer may invent at all, not only where it may re-report.
197
+ The classifier routes `fix-now (delete)` for genuine findings; report-notes
198
+ route to `info` severity and do not block.
199
+
185
200
  ## Portability
186
201
 
187
202
  Keep reviewer contexts isolated. Use [portability](references/PORTABILITY.md) for
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: review-code
3
3
  user-invocable: false
4
- version: 1.3.0
4
+ version: 4.10.0
5
5
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
6
6
  license: MIT
7
7
  description: >
@@ -16,7 +16,9 @@ description: >
16
16
 
17
17
  Composed by `review-change` / `product-audit` within their conversation — on any
18
18
  agent, follow this file inline as the routed step. **Findings only; never edits,
19
- never refactors.**
19
+ never refactors.** Questions an unclear expectation raises obey the all-stages
20
+ no-assumption rule — **ask-don't-infer**, owner
21
+ `skills/unit-lane/references/DESIGN.md` (`ask-dont-infer@1`).
20
22
 
21
23
  ## Scope
22
24
 
@@ -51,6 +53,30 @@ default branch. State the scope at the top of the returned table.
51
53
  `sweep-mismatch`
52
54
  ✓ Edge cases the SPEC's dev scenarios name are actually handled in code, not
53
55
  just in tests
56
+ ✓ **Is deleting the surface the complete fix? (S8)** — before any edit is
57
+ proposed, check: does removing the surface entirely achieve the goal more
58
+ reliably than repairing it? If yes → route `fix-now (delete)`, not
59
+ `fix-now (repair)`. This is the deletion mandate: design and plan produce
60
+ retirements as first-class deliverables.
61
+ ✓ **Unused code routes two ways (#340)** — every unconsumed symbol (or
62
+ unreferenced prose block) is a deletion candidate routed through the
63
+ classifier's two-way rule (`review-implementation`, `CLASSIFY.md`):
64
+ delivered-feature-without-consumer → bug finding; orphaned by a requested
65
+ replacement/removal → `fix-now (delete)`. The row cites what requested the
66
+ feature and what replaced it — the two classes are never conflated
67
+ ✓ **Duplication is a deletion candidate (#340)** — a duplicated block,
68
+ checklist or contract (code or prose) proposes its own deletion, or carries
69
+ the recorded reason the copy must exist; a silent duplicate is a finding
70
+ ✓ **Features-preserved-without-it (#340)** — after any proposed deletion
71
+ (code or skill prose; "code" includes prose), verify every requested
72
+ feature still works without the removed part before merge; a deletion that
73
+ breaks a requested feature is a finding, not a cleanup
74
+ ✓ **Removal-feature cascade (#340)** — a change whose purpose is to remove a
75
+ feature deletes the code **and** its documentation **and** every sibling
76
+ mention the context makes necessary, with one sweep declaration per deleted
77
+ truth (`swept: /<pattern>/<flags> → expected <n> in <glob>`); when the
78
+ cascade's extent is unclear, the reviewer researches, understands and
79
+ contrasts — it does not guess the cascade's extent
54
80
 
55
81
  ## Materiality bar
56
82
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: review-debt
3
3
  user-invocable: false
4
- version: 1.1.0
4
+ version: 4.10.0
5
5
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
6
6
  license: MIT
7
7
  description: >
@@ -36,12 +36,18 @@ workarounds pinned to upstream fixes) into explicit, payable debt items:
36
36
  ✓ Attribute it to the axis already recorded in the table — never re-litigate ownership
37
37
  ✓ Confirm every debt item carries a TRIGGER: the condition under which it must be
38
38
  paid (e.g. "3rd consumer appears", ">100k rows") — a debt item without a
39
- trigger is itself a finding
39
+ trigger is itself a finding. Scheduled deletions carry their trigger as the
40
+ removal condition (S8: review-debt items become *scheduled deletions* whose
41
+ TRIGGER names the removal — executable by a fold batch, not archival prose).
40
42
  ✓ Verify no current-unit debt was mislabeled non-blocking: current-unit work
41
43
  cannot be `postpone`/`tradeoff`/`wontfix` — a table showing one is flagged back
42
44
  to the classifier, never reclassified here
43
45
  ✓ Honor the dead-code exception: staged/planned code cross-checked against the
44
46
  roadmap/SPEC/TASKS is not dead code — mark *verify* when unsure, never assert
47
+ ✓ **Deletion route.** A debt item that proposes removal of a surface carries
48
+ `route: fix-now (delete)`, not `route: fix-now (repair)`. The TRIGGER
49
+ specifies what proves the surface is safe to remove (e.g. "no consumer in
50
+ grep <scope> returns >0").
45
51
 
46
52
  ## Return exactly
47
53
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: review-design
3
3
  user-invocable: false
4
- version: 1.1.0
4
+ version: 4.10.0
5
5
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
6
6
  license: MIT
7
7
  description: >
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: review-implementation
3
3
  user-invocable: false
4
- version: 1.12.0
4
+ version: 4.10.0
5
5
  argument-hint: <path-or-glob>
6
6
  allowed-tools: Read, Grep, Glob, Bash, WebFetch
7
7
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
@@ -142,6 +142,29 @@ depends on whether the final `Hardening & PR` phase has already run:
142
142
 
143
143
  The finding is not folded directly; it is folded by the new phase(s).
144
144
 
145
+ ### Unused code routes two ways, never conflated (#340)
146
+
147
+ An unused-code finding — code, or skill prose under the same rule, that nothing
148
+ consumes — classifies exactly one way, and the two classes never merge.
149
+ *Consumes* means a call site, an import, or the doc that orders the surface to
150
+ exist: a path mention does not consume, and a surface the runtime invokes as the
151
+ tree's entry point is not unconsumed — flagging it would make the sweep find the
152
+ thing it runs on, not the residue it hunts:
153
+
154
+ - **Delivered feature, no consumer** — the code was written as part of a
155
+ delivered feature and **no functionality invokes it**: the feature was not
156
+ implemented completely → **bug finding**. Class `fix-now`; the missing half
157
+ (the consumer or the delivery) is folded — **deletion is not the fix** for
158
+ this class.
159
+ - **Orphaned by a requested change** — the code lost its consumer because a
160
+ requested change **replaced or removed** that feature or part: **marked for
161
+ deletion** → `fix-now (delete)`, not a bug. The deletion is a planned task
162
+ with its negative-capability pin, sweep grep and surviving-reference count
163
+ (the plan step's retirement shape).
164
+
165
+ The row cites what requested the original feature and what replaced it; an
166
+ unused-code row without both citations is not classifiable.
167
+
145
168
  ### Decision table
146
169
 
147
170
  For every finding, give the reasoning columns. Example (generic — your findings,
@@ -152,6 +175,8 @@ your domains):
152
175
  | API token committed in a config file | security | high | fix-now | Credential exposure | Low (move to secret store) | Incident risk | no | fold into phase |
153
176
  | New export endpoint has no failure-mode test | tests | med | fix-now | Untested error path | Low | Regression risk | no | fold into phase |
154
177
  | Fixing this backend bug pulls in an auth redesign | correctness | high | decision-required | Unavoidable product/architecture decision | — | Blocking | no | surface decision, block |
178
+ | Exported helper of a delivered feature that nothing invokes | residue | med | fix-now | The unit shipped half of what was asked — the consumer was never delivered (bug, not cleanup) | Low (deliver the consumer or fold the missing half) | Feature stays incomplete | no | fold into phase |
179
+ | Module orphaned by the unit's own replacement of its feature | residue | med | fix-now (delete) | Superseded part left behind by a requested change | Low (delete + sweep declaration) | Dead weight grows | no | fold deletion task |
155
180
  | Rate limiter reusable across the fleet | architecture | low | proposal | Independent of this unit (D3) | — | — | yes | batch proposal + trigger |
156
181
  | Single-caller wrapper around a stdlib call | overengineering | low | ignore | Indirection with no payoff | — | Negligible | no | note rationale |
157
182
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: review-perf
3
3
  user-invocable: false
4
- version: 1.2.0
4
+ version: 4.10.0
5
5
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
6
6
  license: MIT
7
7
  description: >
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: review-security
3
3
  user-invocable: false
4
- version: 1.1.0
4
+ version: 4.10.0
5
5
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
6
6
  license: MIT
7
7
  description: >
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: review-seo
3
3
  user-invocable: false
4
- version: 1.1.0
4
+ version: 4.10.0
5
5
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
6
6
  license: MIT
7
7
  description: >
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: review-verify
3
3
  user-invocable: false
4
- version: 1.1.0
4
+ version: 4.10.0
5
5
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
6
6
  license: MIT
7
7
  description: >
@@ -18,6 +18,12 @@ Composed by `review-change` / `product-audit` within their conversation — on a
18
18
  agent, follow this file inline as the routed step. **Findings only; never edits,
19
19
  never refactors.**
20
20
 
21
+ **Shift from discoverer to auditor of recorded evidence (S5).** The implementer's
22
+ claim-evidence loop is the primary verification. This review *audits* the
23
+ recorded evidence: re-runs a sample of the recorded commands instead of
24
+ re-deriving the whole change. This is the cost-scaling invariant — reviewers
25
+ dig into code only when evidence is absent or contradicts.
26
+
21
27
  ## Scope
22
28
 
23
29
  The diff or path/glob the caller passes; default the current change vs the
@@ -25,10 +31,21 @@ default branch. State the scope at the top of the returned table.
25
31
 
26
32
  ## Checklist (evaluate EVERY item — none is optional; n/a must be stated)
27
33
 
34
+ ✓ **Evidence audit.** Sample the unit doc's Evidence rows: re-run ≥ 3 of the
35
+ recorded commands and compare observed output against what the implementer
36
+ recorded. Mismatch → finding: "evidence contradicts observation at <file:line>".
37
+ ✓ **Claim-evidence loop verification.** Check the fold's claim table (if
38
+ present): every row has `status: ✓`. Any `✗` row means the implementer's
39
+ turn did not complete its claim-evidence loop.
40
+ ✓ **Unit-route triage currency.** Re-run `bun scripts/unit-route.mjs --triage
41
+ <slug>` and compare the `Steps:` line against the unit doc's Evidence section.
42
+ Mismatch → stale triage.
28
43
  ✓ The project's verification gate ran in THIS review (type-check, tests, build
29
44
  per the project's declared commands) — paste exit status per command
30
45
  ✓ The change's primary claimed behavior was exercised for real (run the
31
- CLI/endpoint/function; paste the actual observed output)
46
+ CLI/endpoint/function; paste the actual observed output) — *in addition to*
47
+ the evidence audit, verify at least one behavioral claim not covered by
48
+ recorded evidence
32
49
  ✓ At least one failure-mode from the SPEC's dev scenarios was reproduced (bad
33
50
  input, missing file, error path) and behaved as specified
34
51
  ✓ New/changed tests actually fail when the implementation is reverted or