@gtrabanco/pi-agentic-workflow 0.5.0 → 0.7.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 (28) hide show
  1. package/package.json +1 -1
  2. package/skills/audit-pr/SKILL.md +1 -1
  3. package/skills/audit-pr/references/02_CLOSURE_AND_SCOPE_GATES.md +1 -1
  4. package/skills/design-feature/SKILL.md +1 -1
  5. package/skills/design-feature/references/REPAIR.md +5 -0
  6. package/skills/execute-phase/SKILL.md +1 -1
  7. package/skills/execute-phase/references/PRE_EXECUTION_GATE.md +1 -1
  8. package/skills/fold-findings/SKILL.md +59 -1
  9. package/skills/fold-findings/references/FOLD_POLICY.md +13 -0
  10. package/skills/fold-findings/references/FOLD_PROCESS.md +40 -3
  11. package/skills/plan-feature/SKILL.md +1 -1
  12. package/skills/plan-feature/references/ROUTING.md +7 -2
  13. package/skills/pre-execution-review/SKILL.md +1 -1
  14. package/skills/pre-execution-review/references/LEDGERS.md +6 -0
  15. package/skills/pre-execution-review/references/POLICY.md +28 -0
  16. package/skills/pre-execution-review/references/SNAPSHOT.md +6 -0
  17. package/skills/review-change/SKILL.md +1 -1
  18. package/skills/review-change/references/PERSIST_AND_DECIDE.md +6 -0
  19. package/skills/review-change/references/REVIEW_PROCESS.md +35 -2
  20. package/skills/review-plan/SKILL.md +10 -8
  21. package/skills/review-plan/references/OUTPUT.md +31 -17
  22. package/skills/review-spec/SKILL.md +1 -1
  23. package/skills/review-spec/references/OUTPUT.md +20 -1
  24. package/skills/ship-roadmap/SKILL.md +1 -1
  25. package/skills/ship-roadmap/references/ADVANCE.md +3 -3
  26. package/skills/workflow-status/SKILL.md +1 -1
  27. package/skills/workflow-status/references/PRE_EXECUTION.md +1 -0
  28. package/skills/workflow-status/references/SENSOR_CORE.md +7 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtrabanco/pi-agentic-workflow",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Pi package: canonical agentic-workflow skills, friendly slash commands, and per-command model routing.",
5
5
  "keywords": [
6
6
  "pi-package",
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: audit-pr
3
3
  user-invocable: true
4
- version: 5.0.3
4
+ version: 5.1.0
5
5
  argument-hint: <pr-number> (optional — defaults to the current branch's PR)
6
6
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
7
7
  license: MIT
@@ -95,7 +95,7 @@ verdict:
95
95
  `structural.reasonCode`/`changedPaths` name the drifted dimension), and — for a
96
96
  feature unit — its named `— spec` parent re-derives the same way. Bound artifacts
97
97
  are frozen: new implementation-phase files are allowed, edits to a bound artifact
98
- are not. Stale, missing or wrong-stage lineage → **BLOCKED**,
98
+ are not. Stale, missing, wrong-stage **or impossible-timeline** lineage → **BLOCKED**,
99
99
  `→ Next: /review-plan <unit>` (or `/review-spec <unit>` when the parent is the
100
100
  broken link). A `SPEC-REVIEW-PASS` never satisfies the plan hop, and vice versa.
101
101
  2. **Obligations are closed.** Every row of the unit's obligation ledger is
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: design-feature
3
3
  user-invocable: true
4
- version: 3.2.0
4
+ version: 3.3.0
5
5
  argument-hint: <idea | NN-slug> [<instruction>]
6
6
  author: "Gabriel Trabanco <gtrabanco@users.noreply.github.com>"
7
7
  license: MIT
@@ -65,6 +65,11 @@ further edit, then routes to that owner. More cycles stay allowed when
65
65
  correctness needs them; they never earn a PASS, and an exhausted cycle budget
66
66
  does not downgrade an open finding.
67
67
 
68
+ A repair responding to a persisted verdict is **never** a loop defect (POLICY §4
69
+ scopes every guard to blind re-reviews): a unit whose `progress.md` carries an open
70
+ FAIL/NEEDS-DESIGN receipt is being repaired by definition, so no "already complete"
71
+ answer exists for it and no cycle cap converts its verdict into a dead end.
72
+
68
73
  The spec-stage detail this skill adds: the owning stage of a Product-half miss is
69
74
  `product` unless the evidence proves the plan asked for something the SPEC never
70
75
  said — then it is `plan`, and it leaves this skill for `plan-feature`.
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: execute-phase
3
3
  user-invocable: true
4
- version: 4.3.0
4
+ version: 4.4.0
5
5
  argument-hint: <NN> [P<k>] | --fix <n> [P<k>] | [--max-attempts N] [--force]
6
6
  allowed-tools: [Bash, Read, Edit, Write, MultiEdit]
7
7
  author: "Gabriel Trabanco <gtrabanco@users.noreply.github.com>"
@@ -21,7 +21,7 @@ Actual: <receipt state — what was read, and `structural.changedPaths` +
21
21
  `structural.reasonCode` from the verify run naming which bound file moved>
22
22
 
23
23
  → Next: /review-plan <NN>-<slug> — the plan needs a current independent review
24
- · the review returned NEEDS-DESIGN / a Product-rooted finding → /design-feature <NN>-<slug>
24
+ · the review returned a Product-rooted finding → /design-feature <NN>-<slug>
25
25
  · a bound artifact is genuinely wrong → /plan-feature <NN>-<slug> (re-cut), then re-review
26
26
  · no bypass flag exists for this gate: --force has never covered it and does not now
27
27
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: fold-findings
3
3
  user-invocable: true
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  argument-hint: [finding-id …]
6
6
  author: "Gabriel Trabanco <gtrabanco@users.noreply.github.com>"
7
7
  license: MIT
@@ -92,6 +92,37 @@ Folded: n/m · Disputed: k · Blocked: j · Replan: r
92
92
 
93
93
  Omit `· Replan: r` when `r = 0` (preserves the existing three-field format).
94
94
 
95
+ Then print the REPAIR-RECEIPT as the ABSOLUTE-last output, together with the
96
+ branching `→ Next:` block below. The receipt is immutable once printed; a
97
+ later fold prints a new receipt (append-only output history — no ledger row,
98
+ no schema field). Six fields, always present:
99
+
100
+ ```
101
+ ## REPAIR-RECEIPT
102
+ - Repaired: <F-ids with (VF-<n>) refs, joined ` + `, or `none`>
103
+ - Refuted/open: <F-ids joined ` + `, or `none`>
104
+ - Gate: <command> → exit <n> at head <40-hex sha> · n/a when nothing was folded
105
+ - Batch class: <all-repair-in-place | frozen (replan present) | none>
106
+ - Fold diff: <shortstat from a real `git diff` run> · none when nothing was folded
107
+ - Branch: <RE-REVIEW-REQUIRED (delta) | RE-REVIEW-OPTIONAL | RE-REVIEW-SKIPPED | REPLAN-ROUTE>
108
+ ```
109
+
110
+ - The `Gate` line carries the actual exit codes observed at the head the gate
111
+ ran on — green or red. A **failed gate never silences the receipt**: the
112
+ batch is reported with the observed exit codes and nothing folded (a red gate
113
+ is not a silent gap).
114
+ - The `Fold diff` shortstat comes from a real `git diff` run over the batch's
115
+ commits.
116
+ - The `Batch class` derives from the taken queue's frozen rows only — the fold
117
+ never reclassifies (`all-repair-in-place`, `frozen (replan present)`, or
118
+ `none` for an empty queue); the vocabulary comes from
119
+ `review-implementation`'s closed class set.
120
+
121
+ **Freeze-batch (replan present).** When the taken queue contains any row whose
122
+ frozen class is `replan-in-unit` or `decision-required`, nothing folds: no
123
+ `folded: yes` flips, no commits. The receipt records the `REPLAN-ROUTE` branch
124
+ and every retained (unfolded) row id, and the loop stops to route to planning.
125
+
95
126
  ## Guardrails
96
127
 
97
128
  Scope is the ledger (or explicit ID subset); unlisted discoveries are proposals
@@ -139,3 +170,30 @@ or touched outside the queue.
139
170
 
140
171
  Replace placeholders with every actual affected finding ID before printing; never
141
172
  print `<F2>`, `…`, or a single representative ID in a live hand-off.
173
+
174
+ ## Closing-block decision branch (choose one, at emission)
175
+
176
+ The closing block picks exactly one of four outcomes. The **no-decision →
177
+ re-review default** holds whenever the turn carries no recorded prior consumer
178
+ decision to skip.
179
+
180
+ | Batch state | Branch | `→ Next:` (consumer) |
181
+ |---|---|---|
182
+ | freeze-batch (≥ 1 replan-class row) | `REPLAN-ROUTE` | plan-fix/execute-phase on this unit after the user confirms the replan |
183
+ | `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 |
184
+ | `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 |
185
+ | empty batch (class `none`) | `RE-REVIEW-OPTIONAL` | `/review-change` by default — safe: the head is unchanged |
186
+ | anything else (behavioral surface or any folded row `high`) | `RE-REVIEW-REQUIRED (delta)` | `/review-change` — delta mode mandatory default |
187
+
188
+ **Branch-selection decision inputs.**
189
+
190
+ - **Docs-only test (E-D3).** ``RE-REVIEW-OPTIONAL`` requires every fold-diff
191
+ file to be a Markdown/documentation file; otherwise the batch is behavioral
192
+ (→ `RE-REVIEW-REQUIRED (delta)`).
193
+ - **Frozen-severity-`high` override.** A folded row whose frozen severity is
194
+ `high` forces `RE-REVIEW-REQUIRED (delta)` even on a docs-only diff. Frozen
195
+ fields are never edited to reach a branch.
196
+ - **SKIPPED requires prior consumer decision (E-D2).** `RE-REVIEW-SKIPPED`
197
+ is printed only by a turn carrying an explicit prior consumer decision to
198
+ skip. A turn with no recorded prior consumer decision prints
199
+ `RE-REVIEW-OPTIONAL` + the re-review default, **never** `RE-REVIEW-SKIPPED`.
@@ -48,3 +48,16 @@ Never edit an existing test's expectation to match behaviour: a setup repair may
48
48
  only keep assertions at least as strong and never touch expectations; the
49
49
  test-immutability contract (`verification-contract`) owns the sole amendment
50
50
  path.
51
+
52
+ ## Reproducer handoff (materialize, never re-derive)
53
+
54
+ Before repairing a **behavioral** finding, read the row's `finding-mark@1`
55
+ `recheck` cell (method + reproducer, written by `review-change` at verification
56
+ time) and materialize it as the regression check — the method as written (red
57
+ test first, reproducible command output, or direct read). The fold runner
58
+ **never invents or re-derives** the reproducer; it consumes the cell as the
59
+ allowed materialization.
60
+
61
+ - A `recheck` cell that cannot be materialized as a runnable check yields
62
+ `BLOCKED <missing input>` and names the missing input.
63
+ - Never substitute a weaker re-derived check for the recorded reproducer.
@@ -2,7 +2,9 @@
2
2
 
3
3
  1. **Build the queue.** Take every `folded: no` fix-now row, or the explicit ID
4
4
  subset, in severity/id order. `replan-in-unit` rows emit `REPLAN`; they stay
5
- on the same SPEC/branch/PR and never become issues.
5
+ on the same SPEC/branch/PR and never become issues. **Empty batch:** an
6
+ empty queue (zero findings taken) prints a REPAIR-RECEIPT with batch class `none`
7
+ and nothing folded — a receipt only, no flips, no commits.
6
8
  2. **Form the fewest atomic correction groups.** Findings may share one group
7
9
  only when all boxes pass:
8
10
 
@@ -33,9 +35,44 @@
33
35
  member so no finding disappears inside the batch.
34
36
  6. **Continue groups.** A blocked/disputed group does not prevent independent
35
37
  groups from folding. Leave its rows `no` and emit individual outcomes.
36
- 7. **Disputes.** Non-reproducible/already-fixed/wrong findings become
38
+ **Failed gate:** if the group's gate is red, do not fold the group — the
39
+ receipt records the observed gate exit codes and nothing is folded for it;
40
+ never silence the receipt and never commit red.
41
+ 7. **Batch classification.** The batch class derives from the taken queue's
42
+ frozen rows only, and the fold never reclassifies:
43
+
44
+ | Condition over the taken batch | Batch class | Fold behavior |
45
+ |---|---|---|
46
+ | ≥ 1 row with frozen class `replan-in-unit` or `decision-required` | `frozen (replan present)` | **freeze-batch** — nothing folds, no `folded: yes` flips, no commits; the receipt records the REPLAN-ROUTE and every retained (unfolded) row id; the loop stops and routes to planning |
47
+ | all taken rows foldable, none replan-class | `all-repair-in-place` | fold as today (group → fix → gate → commit → flip) |
48
+ | empty queue (zero findings taken) | `none` | receipt only |
49
+
50
+ The batch-class vocabulary references only `review-implementation`'s closed
51
+ class set (`CLASSIFY.md`); the receipt invents no parallel vocabulary.
52
+
53
+ The emitted branch follows the closing-block decision inputs in the skill:
54
+ a freeze-batch always selects `REPLAN-ROUTE`; otherwise the docs-only
55
+ file-set test (E-D3) and the frozen-severity-`high` override (E-D2) select
56
+ `RE-REVIEW-OPTIONAL` vs `RE-REVIEW-REQUIRED (delta)`.
57
+ 8. **Disputes.** Non-reproducible/already-fixed/wrong findings become
37
58
  `DISPUTED <evidence → user decision>`; never edit classification or create an
38
59
  issue.
39
- 8. **Replan.** If the smallest correct group exceeds a reviewable correction,
60
+ 9. **Replan.** If the smallest correct group exceeds a reviewable correction,
40
61
  emit `REPLAN` with proposed phases appended to the same unit. After user
41
62
  confirmation, `/execute-phase <unit>` completes them and ticks the rows.
63
+
64
+ ## REPAIR-RECEIPT — fixed printed block (verbatim copy)
65
+
66
+ Printed after the per-finding table and tally, as part of the ABSOLUTE-last
67
+ output together with the branching `→ Next:` block. Six fields, always
68
+ present:
69
+
70
+ ```text
71
+ ## REPAIR-RECEIPT
72
+ - Repaired: <F-ids with (VF-<n>) refs, joined ` + `, or `none`>
73
+ - Refuted/open: <F-ids joined ` + `, or `none`>
74
+ - Gate: <command> → exit <n> at head <40-hex sha> · n/a when nothing was folded
75
+ - Batch class: <all-repair-in-place | frozen (replan present) | none>
76
+ - Fold diff: <shortstat from a real `git diff` run> · none when nothing was folded
77
+ - Branch: <RE-REVIEW-REQUIRED (delta) | RE-REVIEW-OPTIONAL | RE-REVIEW-SKIPPED | REPLAN-ROUTE>
78
+ ```
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: plan-feature
3
3
  user-invocable: true
4
- version: 5.0.0
4
+ version: 5.1.0
5
5
  argument-hint: <NN-slug | #N> | --from-issue N | --scaffold <slug> | --next
6
6
  author: "Gabriel Trabanco <gtrabanco@users.noreply.github.com>"
7
7
  license: MIT
@@ -29,10 +29,15 @@ SPEC's `## Design status` marker is the SPEC-local record and the
29
29
  → Next: /execute-phase <NN> <next-phase> — this feature is already being
30
30
  implemented; resume the current phase, don't re-plan it.
31
31
  ```
32
- 4. **Roadmap row status `done`** → **STOP**. Print exactly:
32
+ 4. **Roadmap row status `done`** → **STOP** (replanning stays forbidden — the
33
+ feature is fully built), and: `done` means built + PR open with the human merge
34
+ pending (a lifecycle label, never a gate verdict), so this is **not** "nothing
35
+ pending". Route to the merge gate instead. Print exactly:
33
36
 
34
37
  ```
35
- → Next: nothing — <NN>-<slug> already shipped (roadmap status `done`).
38
+ → Next: /audit-pr <PR> — done means built + PR open, merge pending (a lifecycle label, never a gate verdict)
39
+ · the row's PR is merged → nothing pending, pick the next unit → /plan-feature --next
40
+ · no PR is open → the row is mislabeled or execution stopped → /execute-phase <NN> (never a replan)
36
41
  ```
37
42
  5. **Roadmap row status `idea`, or no row at all** → **STOP**. Print exactly:
38
43
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: pre-execution-review
3
3
  user-invocable: false
4
- version: 2.0.0
4
+ version: 2.2.0
5
5
  author: "Gabriel Trabanco <gtrabanco@users.noreply.github.com>"
6
6
  license: MIT
7
7
  description: >
@@ -194,3 +194,9 @@ counter-evidence in the same report and **never becomes a row**, a fold task,
194
194
  or a re-review trigger. The mark's `confirmed | refuted` value and the
195
195
  `recheck` cell (the method the finding's axis demands) are what let a driver
196
196
  outside the repo consume the verification the review performed.
197
+
198
+ `fold-findings` reads the `recheck` cell to **materialize** the finding's
199
+ reproducer as its regression check — it never re-derives it; a `recheck` cell
200
+ that cannot be materialized yields `BLOCKED <missing input>`. This consumption
201
+ leaves the row shape, the `VF-` exclusions, and the `review-change`
202
+ single-writer rule untouched.
@@ -76,6 +76,13 @@ on a Product- or Plan-rooted finding is invalid even when the candidate changed:
76
76
  the loop repairs source, not authority. Runtime retry and budget mechanics stay
77
77
  outside this policy and can never be translated into a PASS.
78
78
 
79
+ The guards above gate **blind re-reviews** — an identical snapshot with the
80
+ identical question — and never a repair performed in response to a persisted
81
+ verdict: a repair turn whose input is a FAIL/NEEDS-DESIGN receipt produces a new
82
+ snapshot by design, so no cycle cap or anomaly rule may block or end it. The
83
+ anomaly is printed and routed, never a stop, and no cap converts a verdict into a
84
+ dead end.
85
+
79
86
  ### 5. What a cycle can never produce
80
87
 
81
88
  - A verdict from an author turn, a readiness preflight, a roadmap status, or a
@@ -93,6 +100,14 @@ outside this policy and can never be translated into a PASS.
93
100
  an open row with a new name.
94
101
  - Execution authority from a neighbouring stage: a `SPEC-REVIEW-PASS` never unlocks
95
102
  `execute-phase`, and a `PLAN-REVIEW-PASS` never certifies the Product half.
103
+ - A gate answer from a roadmap row's status. Gates read receipts only;
104
+ roadmap rows are labels and never answer a gate. `done` means built + PR open
105
+ with the human merge pending (`docs/features/ROADMAP.md` § Status legend;
106
+ `docs/fix/README.md` § Status legend), so it never satisfies or suppresses a
107
+ pre-execution/verification gate, never retires the obligation to re-derive a
108
+ receipt, and never lets a reviewer or consumer report a unit closed while its
109
+ PR is unmerged. The complement of §5's "no verdict *from* a status" — and the
110
+ same rule read the other way: a status never **suppresses** a gate either.
96
111
 
97
112
  ### 6. Legacy adoption (units planned before this gate existed)
98
113
 
@@ -142,6 +157,19 @@ reports; a printed verdict whose mark is still "for next turn" is not finished.
142
157
  a gate rejection. The mark is what the ownership map designates for that truth
143
158
  class — receipt block, folded row, rejection trace — at the home and column set
144
159
  [`LEDGERS.md`](LEDGERS.md) names. This section opens no second home.
160
+ - **The reviewer is consumer zero.** Write-then-report is mechanical, not prose: in
161
+ the same act as persisting the receipt, the reviewer runs the sensor's own
162
+ `verify --stage <spec|plan> --unit <id> [--dir …]` (the fix unit's recipe; a
163
+ feature plan adds `--parent`) and pastes the sensor's JSON answer beside the
164
+ verdict block *before* the report is printed. A digest-bound receipt requires
165
+ `structural.fresh: true` (and, for a PASS verdict, `current: true`); exit 3
166
+ (`missing-receipt-snapshot`) or a digest-bound `structural.fresh: false` means
167
+ the mark did not land — the reviewer fixes the write and re-runs, and the verdict
168
+ is not emit-able in that turn. A `Snapshot: refused` receipt's
169
+ `missing-receipt-snapshot` answer is its sanctioned form. A verdict block
170
+ printed without the pasted self-check output is a contract defect, and every
171
+ consumer reads a chat-only verdict as `missing-receipt-snapshot` — it does not
172
+ exist to the sensor.
145
173
  - **A gate rejection is typed**, from a closed set of four: `dependency`, `status`,
146
174
  `phase-lint`, `stale-or-missing-receipt`. Each fixed gate block carries its type
147
175
  and names what it read and where the turn goes:
@@ -105,6 +105,12 @@ sensor exists to catch: they carry no bound digest, so they fail as
105
105
  `missing-receipt-snapshot` rather than being interpreted charitably. Nothing here
106
106
  grants a verdict — only a reviewer turn writes the block.
107
107
 
108
+ **The reviewer is consumer zero.** This re-verify recipe, run by the reviewer itself
109
+ in the same act as persisting the receipt (POLICY §8), is the self-check that makes
110
+ write-then-report mechanical: the reviewer runs `verify --stage …` for its own stage
111
+ before it prints the verdict and pastes the sensor's answer beside the block. The
112
+ recipe owner stays this file; §8 owns the rule the recipe serves.
113
+
108
114
  ### Authoring side: rotating the revision
109
115
 
110
116
  The author's `artifactRevisionId` is the field that lets a reviewer prove its own
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: review-change
3
3
  user-invocable: true
4
- version: 3.2.1
4
+ version: 3.4.0
5
5
  argument-hint: <path-or-glob> [--adversarial N] [--synthesize]
6
6
  author: "Gabriel Trabanco <gtrabanco@users.noreply.github.com>"
7
7
  license: MIT
@@ -135,6 +135,12 @@
135
135
  · adversarial recommendation checklist fired AND this run was
136
136
  single-reviewer? → re-run the fold review as /review-change
137
137
  --adversarial N (N per the ladder below) instead of single-reviewer
138
+
139
+ The two-cycle cap scopes the **review→fold loop on source findings** only (a
140
+ finding already on the branch, repaired here). A planning repair routed by a
141
+ `class: plan`/`product` finding is a **verdict response** under
142
+ `pre-execution-review` POLICY §4 — it re-derives plan/Product authority, not
143
+ source — so it is never a loop-defect stop and never counts against this cap.
138
144
  (yes: <which box fired>; no: omit this line)
139
145
  · SPEC drift flagged here AND on a prior unit? → /product-audit (yes: the
140
146
  founding assumptions are probably stale — don't keep patching a
@@ -21,6 +21,37 @@
21
21
  same location. A cycle ≥ 2 that produces any new fix-now row appends the
22
22
  `CONVERGENCE-ANOMALY` block (`pre-execution-review/references/POLICY.md` §4)
23
23
  to the report.
24
+
25
+ **Delta mode (default on a post-fold re-review).** When the preceding fold
26
+ receipt's branch is `RE-REVIEW-REQUIRED (delta)` — or `RE-REVIEW-OPTIONAL`
27
+ acted on with the re-review decision — the review runs **delta mode**:
28
+
29
+ 1. Re-verify every `folded: yes` row at the `file:line` cited in its
30
+ `review-findings.md` row (the existing cycle-≥2 rule above);
31
+ 2. Review the **fold diff only** (`git diff <pre-batch HEAD>..<batch HEAD>`
32
+ over the commits this turn's batch produced);
33
+ 3. Require the **gate green at the reviewed head** and the sibling
34
+ `ACCEPTANCE.md` blob recomputed to an **exact match** — the step-2
35
+ structural precondition, unchanged and still mandatory;
36
+ 4. Append the normal `review-mark@1` `REVIEW-RAN` mark — delta cycles count
37
+ toward the two-cycle cap from the unchanged source (marks + forge
38
+ receipts), never a fresh reset;
39
+ 5. Admit a candidate only when **genuinely new**: a same-`file:line`+axis
40
+ re-report inside the delta scope is admitted only as
41
+ `regression of <id>` or `DISPUTED`, never a plain new row (extending the
42
+ cycle-2 rule to the whole delta scope);
43
+ 6. A clean delta pass posts the normal SHA-bound `REVIEW-PASS`.
44
+
45
+ **Escalation to a full pass.** Either trigger escalates a delta review to a
46
+ full pass, and the escalation **states which trigger fired and the observed
47
+ numbers**:
48
+
49
+ - **Width** — any changed file outside the union of the batch's cited files
50
+ (the folded rows' `file:line`), or any changed line in a cited file more
51
+ than **50 lines** from every cited line in that file (changed-line starts
52
+ read from `git diff --unified=0` hunk headers);
53
+ - **Size** — added+deleted changed lines **> 200**, or changed files
54
+ **> 15** (`git diff --numstat`).
24
55
  2. **Frozen acceptance + SPEC drift check (structural).** Locate sibling
25
56
  `ACCEPTANCE.md`, recompute its blob, and require an exact match with the
26
57
  execution receipt before assessing the candidate. Missing/mismatch is a
@@ -129,8 +160,10 @@
129
160
 
130
161
  The review→fold loop runs at most **two** review→fold cycles per unit, counted
131
162
  unit-level and family-agnostic from the ledger's `REVIEW-RAN` marks and forge
132
- receipts — new finding families do not reset the count. After two cycles without
133
- convergence, the review prints
163
+ receipts — new finding families do not reset the count. **Delta cycles count
164
+ from the same unchanged source** (the `review-mark@1` marks + forge receipts), so
165
+ a delta-scoped re-review does not escape or reset the two-cycle bound. After two
166
+ cycles without convergence, the review prints
134
167
 
135
168
  ```text
136
169
  LOOP CAP REACHED — <unit>
@@ -1,15 +1,16 @@
1
1
  ---
2
2
  name: review-plan
3
3
  user-invocable: true
4
- version: 1.5.0
4
+ version: 1.6.0
5
5
  argument-hint: <NN-slug | fix-N | path/to/SPEC.md> [--adversarial N]
6
6
  author: "Gabriel Trabanco <gtrabanco@users.noreply.github.com>"
7
7
  license: MIT
8
8
  description: >
9
9
  Independent read-only review of a frozen Engineering plan before execution, in a
10
10
  context that did not cut it: feature or fix snapshot, obligation ledger sweep,
11
- phase and validator checks. Returns only PLAN-REVIEW-PASS, PLAN-REVIEW-FAIL, or
12
- NEEDS-DESIGN with a snapshot-bound receipt. Never edits a plan artifact.
11
+ phase and validator checks. Returns only PLAN-REVIEW-PASS or PLAN-REVIEW-FAIL
12
+ with a snapshot-bound receipt (a product-intent gap is PLAN-REVIEW-FAIL with
13
+ `class: product`). Never edits a plan artifact.
13
14
  Triggers: "review-plan", "review the plan", "review the phases".
14
15
  ---
15
16
 
@@ -81,7 +82,7 @@ another `references/` path.
81
82
  |---|---|---|
82
83
  | Roadmap row read, unit kind known (feature or fix) | [checks](references/CHECKS.md) — snapshot construction, falsification, the L1–L6 ledger sweep | [eng-checks](references/ENG-CHECKS.md) and [output](references/OUTPUT.md) |
83
84
  | Snapshot bound and the ledgers swept clean enough to judge the plan | [eng-checks](references/ENG-CHECKS.md) — P1–P12, plus F1–F4 for a fix unit | [output](references/OUTPUT.md) until every check has a result |
84
- | Any check failed, the parent receipt is missing/stale, or a product choice is open | [output](references/OUTPUT.md) for the FAIL / `NEEDS-DESIGN` block and route | — |
85
+ | Any check failed, the parent receipt is missing/stale, or a product choice is open | [output](references/OUTPUT.md) for the FAIL block (product-intent gaps get `class: product`) and route | — |
85
86
  | A prior Plan receipt exists for this unit | [output](references/OUTPUT.md) §Repeats for the no-progress / convergence gate before re-running anything | never blend rows from two snapshots |
86
87
 
87
88
  ## Guardrails
@@ -98,12 +99,13 @@ another `references/` path.
98
99
  candidate `ReviewReceipt` or a staged `VerificationReceipt` answers different
99
100
  questions and never stands in for a Plan review. A missing parent receipt is
100
101
  reported, not repaired by assumption.
101
- - **Three verdicts only.** Exactly `PLAN-REVIEW-PASS | PLAN-REVIEW-FAIL |
102
- NEEDS-DESIGN`. No partial pass, no "approve with caveats", no SPEC verdict, no
103
- generic "approved" verb (PD1).
102
+ - **Two verdicts only.** Exactly `PLAN-REVIEW-PASS | PLAN-REVIEW-FAIL`.
103
+ No partial pass, no "approve with caveats", no SPEC verdict, no generic
104
+ "approved" verb (PD1). The design-verdict token is not a verdict at this stage — a gap
105
+ requiring invented product intent is `PLAN-REVIEW-FAIL` with `class: product`.
104
106
  - **No engineering decisions invented.** Where the right phase cut, validator, or
105
107
  migration depends on a product choice this review cannot make, return
106
- `NEEDS-DESIGN` and route it to the human through `design-feature` — invalidating
108
+ `class: product` and route it to the human through `design-feature` — invalidating
107
109
  downstream Plan evidence is the point.
108
110
  - **No source fixes.** A plan defect that this turn could "just patch" is still a
109
111
  defect: report it and route it. Implementing while reviewing collapses the gate.
@@ -13,7 +13,7 @@ One `PreExecutionReviewReceipt v1`
13
13
 
14
14
  ```text
15
15
  ## Pre-execution review receipt v1 — plan
16
- - Review: <receipt-id> · Snapshot: <64-hex|refused> · Verdict: <plan-review-pass|plan-review-fail|needs-design>
16
+ - Review: <receipt-id> · Snapshot: <64-hex|refused> · Verdict: <plan-review-pass|plan-review-fail>
17
17
  - Unit: <unitId> · Stage: plan · Unit kind: <feature|fix>
18
18
  - Parent SPEC snapshot: <64-hex> · Parent Product receipt: <receipt-id of the current SPEC-REVIEW-PASS>
19
19
  - Source revision: <40-hex> · Artifact revision: <artifactRevisionId>
@@ -52,6 +52,26 @@ verdict, and file one finding row per refused artifact carrying its code verbati
52
52
  checks bind to a snapshot, so with no snapshot none of them ran. `SNAPSHOT.md` owns why
53
53
  a refusal prints no digest and what a consumer then reads this receipt as.
54
54
 
55
+ **Self-check (`verify --stage plan …`, POLICY §8).** In the same act as appending the
56
+ receipt, run the recipe owner's re-verify for this stage and paste the sensor's JSON
57
+ answer beside the verdict block before reporting. A feature plan run names `--parent`
58
+ (the Product digest this plan descended from); a fix unit omits it (it binds none):
59
+
60
+ ```bash
61
+ # feature plan — binds the Product snapshot it descends from
62
+ node scripts/pre-execution-snapshot.mjs verify --stage plan --unit <NN-slug> --dir docs/features/<NN>-<slug> --unit-kind feature --parent <64-hex>
63
+ # fix unit — no Product half exists (D6)
64
+ node scripts/pre-execution-snapshot.mjs verify --stage plan --unit fix-<N> --dir docs/fix/<N> --unit-kind fix
65
+ ```
66
+
67
+ A digest-bound receipt requires `structural.fresh: true` (and, for a PASS verdict,
68
+ `current: true`); `exit 3` (`missing-receipt-snapshot`) or a digest-bound
69
+ `structural.fresh: false` means the mark did not land — fix the write and re-run, the
70
+ verdict is not emit-able in this turn. A `Snapshot: refused` receipt's
71
+ `missing-receipt-snapshot` answer is its sanctioned form. A verdict block printed
72
+ without the pasted self-check output is a contract defect — chat-only is
73
+ `missing-receipt-snapshot` to every consumer.
74
+
55
75
  ### Verdict blocks — return exactly one
56
76
 
57
77
  ```text
@@ -72,20 +92,11 @@ PLAN-REVIEW-FAIL — <NN-slug|fix-N> BLOCKED
72
92
  - Parent state: <current | stale-parent → review-spec first | missing → review-spec first>
73
93
  ```
74
94
 
75
- ```text
76
- NEEDS-DESIGN — <NN-slug|fix-N>
77
- - Snapshot: <digest> · Blocking rows: <Lnn / Pnn / obligation-id>
78
- - Missing choice (product authority only): <one bounded question>
79
- - Recommended default: <the smallest coherent answer>
80
- - Downstream: this Plan receipt and every execution decision bound to the parent
81
- Product half are invalid until the answer lands and the Product half is re-reviewed
82
- ```
83
-
84
- `NEEDS-DESIGN` when the answer requires inventing product intent, scope, role,
85
- authority, or user outcome; `PLAN-REVIEW-FAIL` when the plan is decidable but
86
- incomplete, contradictory, unowned, or unsupported. Never blend them; never emit
87
- a fourth verdict, a generic "approved", or a `SPEC-REVIEW-*` verdict from this
88
- stage.
95
+ `PLAN-REVIEW-FAIL` when the plan is decidable but incomplete, contradictory,
96
+ unowned, or unsupported. A gap that requires **inventing product intent is
97
+ `PLAN-REVIEW-FAIL` with `class: product`** — the design-verdict token is not a
98
+ verdict at this stage: only `review-spec` may emit it. Never emit a generic
99
+ "approved" or a `SPEC-REVIEW-*` verdict from this stage.
89
100
 
90
101
  ### Routes
91
102
 
@@ -104,7 +115,6 @@ not authority.
104
115
  | `PLAN-REVIEW-FAIL`, `class: plan` | `plan-feature` / `plan-fix` (the author) | one root-caused repair batch → new `artifactRevisionId` → re-review of the new snapshot |
105
116
  | `PLAN-REVIEW-FAIL`, `class: product` | `design-feature` | repair the Product half → `review-spec` → the Plan receipt is re-derived (`stale-parent`) |
106
117
  | `PLAN-REVIEW-FAIL`, `class: source\|environment\|runtime` | its owner, later | record the row, keep it `open`, route it. Do not edit the plan to hide it and do not start `execute-phase` on a plan carrying an open material row |
107
- | `NEEDS-DESIGN` | the human, through `design-feature` | dated amendment → new Product revision → `review-spec` → `plan-feature` replan → `/review-plan` again |
108
118
 
109
119
  Repeating this review follows the no-progress and convergence rules in
110
120
  `pre-execution-review/references/POLICY.md` §4 — a repeat needs
@@ -121,6 +131,10 @@ into `review-change → fold-findings`, which repairs source, not plan authority
121
131
  ✓ L1–L6 resolved, and every applicable P/F check resolved to pass / finding / n/a
122
132
  ✓ Obligation ledger swept row by row: none blank, deferred, duplicated, unvalidated
123
133
  ✓ One verdict block returned verbatim from the closed set
134
+ ✓ RUN `verify --stage plan` for this stage in-turn (feature plan names `--parent`;
135
+ fix omits it), JSON pasted beside the block; `structural.fresh: true` (+ `current: true` on PASS) —
136
+ `exit 3`/`structural.fresh: false` means the mark did not land, fix and re-run;
137
+ `exit 4`/`current: false` means a verdict persisted but not a PASS — the verdict itself is the emit result, route per verdict
124
138
  ✓ Receipt appended to progress.md and findings appended to planning-findings.md
125
139
  ✓ `git status --porcelain` shows no change to any reviewed plan artifact
126
140
  ✓ Closing `→ Next:` printed as the absolute last output
@@ -136,7 +150,7 @@ On PASS:
136
150
  · Product half moved after this receipt → the parent went stale: /review-spec <NN>
137
151
  ```
138
152
 
139
- On FAIL or NEEDS-DESIGN, name every finding id once, in order, joined with ` + `:
153
+ On FAIL, name every finding id once, in order, joined with ` + `:
140
154
 
141
155
  ```
142
156
  → Next: /plan-feature <NN-slug> "<instruction>" (or /plan-fix <N> "<instruction>") —
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: review-spec
3
3
  user-invocable: true
4
- version: 1.6.0
4
+ version: 1.7.0
5
5
  argument-hint: <NN-slug | path/to/SPEC.md>
6
6
  author: "Gabriel Trabanco <gtrabanco@users.noreply.github.com>"
7
7
  license: MIT
@@ -42,6 +42,22 @@ verdict, and file one finding row per refused artifact carrying its code verbati
42
42
  checks bind to a snapshot, so with no snapshot none of them ran. `SNAPSHOT.md` owns why
43
43
  a refusal prints no digest and what a consumer then reads this receipt as.
44
44
 
45
+ **Self-check (`verify --stage spec …`, POLICY §8).** In the same act as appending the
46
+ receipt, run the recipe owner's re-verify for this stage and paste the sensor's JSON
47
+ answer beside the verdict block before reporting:
48
+
49
+ ```bash
50
+ node scripts/pre-execution-snapshot.mjs verify --stage spec --unit <NN-slug> --dir docs/features/<NN>-<slug> --unit-kind <feature|fix>
51
+ ```
52
+
53
+ A digest-bound receipt requires `structural.fresh: true` (and, for a PASS verdict,
54
+ `current: true`); `exit 3` (`missing-receipt-snapshot`) or a digest-bound
55
+ `structural.fresh: false` means the mark did not land — fix the write and re-run, the
56
+ verdict is not emit-able in this turn. A `Snapshot: refused` receipt's
57
+ `missing-receipt-snapshot` answer is its sanctioned form. A verdict block printed
58
+ without the pasted self-check output is a contract defect — chat-only is
59
+ `missing-receipt-snapshot` to every consumer.
60
+
45
61
  ### Verdict blocks — return exactly one
46
62
 
47
63
  ```text
@@ -110,7 +126,10 @@ is ever lost between cycles.
110
126
  ✓ Snapshot digest computed from one revision and pasted; no mixed-revision bytes
111
127
  ✓ All 14 Product checks resolved to pass / finding / n/a with a reason
112
128
  ✓ One verdict block returned verbatim from the closed set
113
- ✓ Receipt appended to the unit's progress.md before the report was printed
129
+ ✓ RUN `verify --stage spec` for this stage in-turn, JSON pasted beside the block;
130
+ `structural.fresh: true` (+ `current: true` on PASS) — `exit 3`/`structural.fresh: false` means
131
+ the mark did not land, fix and re-run, verdict not emit-able; `exit 4`/`current: false` means
132
+ a verdict persisted but not a PASS — the verdict itself is the emit result, route per verdict
114
133
  ✓ `git status --porcelain` shows no change to any reviewed artifact
115
134
  ✓ Closing `→ Next:` printed as the absolute last output
116
135
  ```
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: ship-roadmap
3
3
  user-invocable: true
4
- version: 5.1.0
4
+ version: 5.2.0
5
5
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
6
6
  license: MIT
7
7
  argument-hint: "[--fullauto] | --continue [--fullauto]"
@@ -42,9 +42,9 @@
42
42
  - **REVIEW-PLAN** (only between PLAN and EXECUTE) — compose `review-plan` in a
43
43
  clean context at the routed tier over the plan the previous stage just froze.
44
44
  `PLAN-REVIEW-PASS` releases EXECUTE. A FAIL routes by root cause: plan-local
45
- (bad phase cut, blank validator, ledger drift) → one root-caused re-cut by the
46
- planning author and a fresh review; product-rooted or an assumption this record
47
- cannot settle → `NEEDS-DESIGN` → park as in REVIEW-SPEC. A second local cycle
45
+ (bad phase cut, blank validator, ledger drift) → root-caused re-cut by the
46
+ planning author and a review; product-rooted or an assumption this record
47
+ cannot settle → PLAN-REVIEW-FAIL with class: product → design-feature. A second local cycle
48
48
  that changes nothing stops editing and reports `CONVERGENCE-ANOMALY` instead of
49
49
  burning a third budget. **No stage between PLAN and EXECUTE may create a forge
50
50
  issue or defer an obligation to one** — an unmet obligation fails this stage, it
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: workflow-status
3
3
  user-invocable: true
4
- version: 3.1.0
4
+ version: 3.2.0
5
5
  author: "Gabriel Trabanco <gtrabanco@users.noreply.github.com>"
6
6
  license: MIT
7
7
  argument-hint: "[--json-only] [--last-envelope <json|path>]"
@@ -47,6 +47,7 @@ sensor reports a missing gate, never a verdict that no review ever happened.
47
47
  | `self-approved` | the author of the artifact recorded the PASS | that stage's review in a clean context |
48
48
  | `author-readiness` | an authoring readiness result sits where a verdict should be | that stage's review — readiness never licenses execution |
49
49
  | `legacy` | `planned`/`in-progress` unit with no ledgers and no receipt (predates feature 28) | the adoption route below |
50
+ | `impossible-timeline` | `structural.fresh: false`, `structural.reasonCode: impossible-timeline` — digest and revision match by construction; a receipt's own recorded timeline is physically impossible (finish predating source revision's commit date beyond the published skew); a legacy receipt with no parsable Started/finished: line, or a source revision git cannot resolve, stays unflagged (fail-open) | that stage's review — the timeline is self-refuting, not a stale source |
50
51
 
51
52
  A stale receipt re-runs the **review**, not the authoring skill: the artifacts may be
52
53
  exactly right and simply need re-judging in a clean context. A missing verdict block,
@@ -64,14 +64,18 @@ live evidence against a frozen ledger remains a contradiction candidate.
64
64
  command matched to the exact status: `defined` → `/plan-feature <slug>`,
65
65
  `planned` → `/execute-phase <NN>`.
66
66
  - deps unmet (any status ≥ `defined`) → `blocked_units` (unchanged).
67
- 6a. **Sense the pre-execution receipts** for every unit at `defined`, `planned` or
68
- `in-progress` ([pre-execution evidence](PRE_EXECUTION.md)): read the stage's
67
+ 6a. **Sense the pre-execution receipts** for every unit at `defined`, `planned`,
68
+ `in-progress`, **or `done` with a linked PR that is still open (unmerged — merge
69
+ state lives in the forge)** ([pre-execution evidence](PRE_EXECUTION.md)). A
70
+ done-but-unmerged row is a lifecycle label, never merge-ready, so a stale or
71
+ missing receipt there surfaces as a gate blocker; merged units stay excluded
72
+ (the merge itself closes their gates). Read the stage's
69
73
  newest receipt block, re-derive the bound digest with the recipe owner's
70
74
  verify mode (`node scripts/pre-execution-snapshot.mjs verify --stage
71
75
  <spec|plan> --unit <id> [--parent <64-hex>]` — a snapshot digest is a canonical SHA-256, never a
72
76
  git blob id; `structural.reasonCode` names the dimension that drifted), and
73
77
  label the stage `current`/`missing`/`stale`/`wrong-stage`/`substitute`/
74
- `self-approved`/`author-readiness`/`legacy`. The label **overrides step 6's
78
+ `self-approved`/`author-readiness`/`legacy`/`impossible-timeline` (unresolvable revision or unparsable timeline: fail-open → unflagged). The label **overrides step 6's
75
79
  status-only command**: a unit without a current PASS for the stage it is about to
76
80
  enter is demoted out of `startable_now` into a `gate` blocker naming the missing
77
81
  review, and `detail.pre_execution[]` records the row. A roadmap row is never