@gtrabanco/pi-agentic-workflow 0.19.1 → 0.21.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtrabanco/pi-agentic-workflow",
3
- "version": "0.19.1",
3
+ "version": "0.21.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",
@@ -58,7 +58,7 @@
58
58
  },
59
59
  "dependencies": {
60
60
  "@gtrabanco/agentic-workflow": "0.2.0",
61
- "@gtrabanco/agentic-workflow-schema": "4.5.0"
61
+ "@gtrabanco/agentic-workflow-schema": "4.6.0"
62
62
  },
63
63
  "devDependencies": {
64
64
  "@types/node": "24.13.3",
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: execute-phase
3
3
  user-invocable: true
4
- version: 5.0.1
4
+ version: 5.1.0
5
5
  argument-hint: <NN-slug> [P<k>|step] [--max-attempts N] [--force]
6
6
  allowed-tools: [Bash, Read, Edit, Write, MultiEdit]
7
7
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
@@ -39,7 +39,8 @@ done:
39
39
  ✓ Unit doc read and step selected (explicit P<k> or first unfinished)
40
40
  ✓ Step executed and committed (one commit per step, conventional format)
41
41
  ✓ Evidence rows updated (command → exit/digest → output → verified-by)
42
- ✓ Progress log updated with a dated `YYYY-MM-DD HH:MM` entry (what, commit, next)
42
+ ✓ Progress log updated with a dated `YYYY-MM-DD HH:MM` entry that names the
43
+ phase id (what, commit, next)
43
44
  ✓ Diff guard passed (on implement steps) — see `diff-guard` in PREFLIGHT.md
44
45
  ✓ → Next: block printed as the absolute last output
45
46
  ```
@@ -139,10 +140,13 @@ After each step: run the project's verification gate (type-check + tests + build
139
140
  ### 7. Whole-unit mode
140
141
 
141
142
  When invoked as `<NN-slug>` with no step: loop all remaining steps, one commit
142
- each. After each step: gates, execute, diff guard (if implement), evidence/
143
- progress update, commit. Skip intermediate review checkpoints; the mandatory end
144
- review covers the full accumulated diff. On gate red at any step: repair that
145
- step (up to `--max-attempts`), then continue the loop. Terminal:
143
+ each. This is an **explicit operator choice only** — the lane's hand-offs
144
+ always name exactly one phase (`<NN-slug> P<k>`), so a bare `<NN-slug>` from a
145
+ lane hand-off is a defect; re-read the hand-off before looping. After each
146
+ step: gates, execute, diff guard (if implement), evidence/progress update,
147
+ commit. Skip intermediate review checkpoints; the mandatory end review covers
148
+ the full accumulated diff. On gate red at any step: repair that step (up to
149
+ `--max-attempts`), then continue the loop. Terminal:
146
150
 
147
151
  ```text
148
152
  UNIT LOOP — <unit> COMPLETE
@@ -195,12 +199,17 @@ These files must be loaded when their topic is active:
195
199
 
196
200
  ## Relationship to other skills
197
201
 
198
- `unit-lane` conducts (triage → steps → doc updates); this executes (one step at a
199
- time or all remaining). `fold-findings` handles review finding repairs. The review
200
- pack axes (`review-implementation`, `review-code`, `review-security`, `review-perf`,
202
+ `unit-lane` conducts (triage → judgment steps → close-out ladder) and hands
203
+ execution off **one phase per turn** (`<NN-slug> P<k>` with the catalog tier);
204
+ this executes the named phase — or, as an explicit operator choice only, all
205
+ remaining steps. The closing hand-off names exactly one phase and the tier
206
+ while phases remain, and resumes the lane after the last one.
207
+ `fold-findings` handles review finding repairs. The review pack axes
208
+ (`review-implementation`, `review-code`, `review-security`, `review-perf`,
201
209
  `review-a11y`, `review-debt`) compose the review step; `workflow-status` routes
202
- here. `triage-issue` feeds issues into the lane. This skill is the **step executor**
203
- a turn invokes to perform one triaged step of a unit under the full gate machinery.
210
+ here. `triage-issue` feeds issues into the lane. This skill is the **step
211
+ executor** a turn invokes to perform one triaged step of a unit under the full
212
+ gate machinery.
204
213
 
205
214
  ## Portability (agents other than Claude Code)
206
215
 
@@ -215,15 +224,30 @@ a turn invokes to perform one triaged step of a unit under the full gate machine
215
224
 
216
225
  ## Done when
217
226
 
218
- - Requested scope is implemented (all remaining steps, one explicit step), gate
219
- is green, unit doc Evidence/Progress are current, and the work is committed.
227
+ - Requested scope is implemented (the named phase, or all remaining steps in an
228
+ explicit operator run), gate is green, unit doc Evidence/Progress are current
229
+ (the Progress entry names the phase id), and the work is committed.
220
230
  - **The closing `→ Next:` block is printed.**
221
231
 
222
232
  ## Closing recommendation
223
233
 
234
+ Exactly one end-state applies — pick by the unit's Tasks section, never print a
235
+ phase id the Tasks section does not define:
236
+
237
+ Phases remain:
238
+
239
+ ```
240
+ → Next: /execute-phase <NN-slug> P<k+1> (tier: <tier>) — one phase per turn; <tier> is the catalog's implement entry
241
+ · whole-unit operator run complete → /review-change (mandatory end review)
242
+ · findings (REVIEW-FAIL) → /fold-findings repairs them; a fresh /review-change follows the fold
243
+ · merge gate after REVIEW-PASS → /audit-pr — the merge gate
244
+ ```
245
+
246
+ The last phase just closed (a lane-run unit):
247
+
224
248
  ```
225
- → Next: /unit-lane <NN-slug> — the conductor continues with the next triaged step
226
- · all steps done → /review-change — the mandatory end review
249
+ → Next: /unit-lane <NN-slug> — resume the conductor for the remaining judgment steps
250
+ · whole-unit operator run complete → /review-change (mandatory end review)
227
251
  · findings (REVIEW-FAIL) → /fold-findings repairs them; a fresh /review-change follows the fold
228
252
  · merge gate after REVIEW-PASS → /audit-pr — the merge gate
229
253
  ```
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: fold-findings
3
3
  user-invocable: true
4
- version: 1.7.0
4
+ version: 1.8.0
5
5
  argument-hint: [finding-id …]
6
6
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
7
7
  license: MIT
@@ -102,9 +102,9 @@ no schema field). Six fields, always present:
102
102
  - Repaired: <F-ids with (VF-<n>) refs, joined ` + `, or `none`>
103
103
  - Refuted/open: <F-ids joined ` + `, or `none`>
104
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>
105
+ - Batch class: <all-repair-in-place | frozen (replan present) | frozen (product owner present) | none>
106
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>
107
+ - Branch: <RE-REVIEW-REQUIRED (delta) | RE-REVIEW-OPTIONAL | RE-REVIEW-SKIPPED | REPLAN-ROUTE | PRODUCT-ROUTE>
108
108
  ```
109
109
 
110
110
  - The `Gate` line carries the actual exit codes observed at the head the gate
@@ -114,9 +114,9 @@ no schema field). Six fields, always present:
114
114
  - The `Fold diff` shortstat comes from a real `git diff` run over the batch's
115
115
  commits.
116
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.
117
+ never reclassifies (`all-repair-in-place`, `frozen (replan present)`,
118
+ `frozen (product owner present)`, or `none` for an empty queue); the
119
+ vocabulary comes from `review-implementation`'s closed class set.
120
120
 
121
121
  **Freeze-batch (replan present).** When the taken queue contains any row whose
122
122
  frozen class is `replan-in-unit` or `decision-required`, nothing folds: no
@@ -129,6 +129,16 @@ and surface the decision to the user, never a planner. `<unit>` is the bare fold
129
129
  `node scripts/unit-route.mjs <unit>` is the discovery step the fold already
130
130
  ran; it is never the recommendation.
131
131
 
132
+ **Freeze-batch (product owner present).** Any taken `fix-now` row whose `Route`
133
+ cell begins `product owner`, `product-owned` or `owned by product` (head-anchored,
134
+ identical to `scripts/unit-route.mjs`'s `PRODUCT_ROUTE` regex,
135
+ per `#293`) freezes the batch too —
136
+ nothing folds, no `folded: yes` flips, no commits: the fold loop repairs source,
137
+ never authority (`pre-execution-review` POLICY §4, `#293`). The receipt records
138
+ the `PRODUCT-ROUTE` branch and the retained row ids; the consumer is the
139
+ router's printed `route: product` lane hand-off. Full condition and hand-off
140
+ table: [`FOLD_PROCESS.md`](references/FOLD_PROCESS.md) §Batch classification.
141
+
132
142
  ## Guardrails
133
143
 
134
144
  Scope is the ledger (or explicit ID subset); unlisted discoveries are proposals
@@ -175,6 +185,7 @@ or touched outside the queue.
175
185
  · any BLOCKED (<F1> + <F2> + …) → supply the listed missing inputs, then re-run /fold-findings
176
186
  · any REPLAN (<F1> + <F2> + …) → /unit-lane <slug> or /unit-lane --fix <n> — the lane re-runs its plan step, appends the phases to the unit's SPEC; its review step gates before /execute-phase on this unit
177
187
  · any DECISION (<F1> + <F2> + …) → stop and surface the decision to the user — a `route: decision` conclusion names no planner, so the unit waits on the user before any plan or code change
188
+ · any PRODUCT (<F1> + <F2> + …) → /unit-lane <slug> or /unit-lane --fix <n> — the lane repairs the half, its review step re-judges it
178
189
  ```
179
190
 
180
191
  Every `· ` sub-bullet is exactly one physical line — never hard-wrapped across
@@ -187,12 +198,13 @@ carry `<slug>` or `<n>` into a live hand-off.
187
198
 
188
199
  ## Closing-block decision branch (choose one, at emission)
189
200
 
190
- The closing block picks exactly one of four outcomes. The **no-decision →
201
+ The closing block picks exactly one of five outcomes. The **no-decision →
191
202
  re-review default** holds whenever the turn carries no recorded prior consumer
192
203
  decision to skip.
193
204
 
194
205
  | Batch state | Branch | `→ Next:` (consumer) |
195
206
  |---|---|---|
207
+ | 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 `node scripts/unit-route.mjs <unit>` (discovery step the fold already ran) |
196
208
  | 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 `node scripts/unit-route.mjs <unit>` (discovery step the fold already ran) |
197
209
  | `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 |
198
210
  | `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 |
@@ -44,6 +44,7 @@
44
44
  | Condition over the taken batch | Batch class | Fold behavior |
45
45
  |---|---|---|
46
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; the consumer is the conclusion printed by `node scripts/unit-route.mjs <unit>` (discovery step the fold already ran), where `<unit>` is the bare folder number or the full slug (both resolve): on `route: replan` the planner command the router printed — `/unit-lane <slug>` (feature) or `/unit-lane --fix <n>` (fix) — the lane 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, never a planner |
47
+ | ≥ 1 row with frozen class `fix-now` whose `Route` cell begins `product owner`, `product-owned` or `owned by product` (head-anchored, identical to `scripts/unit-route.mjs`'s `PRODUCT_ROUTE` regex: `/^(?:product[- ]owner\|product[- ]owned\|owned by product)\b/i`, per `#293`) | `frozen (product owner present)` | **freeze-batch** — nothing folds, no `folded: yes` flips, no commits; the receipt records the PRODUCT-ROUTE and every retained (unfolded) row id; the loop stops; the consumer is the conclusion printed by `node scripts/unit-route.mjs <unit>`: `route: product` and the lane hand-off — `/unit-lane <slug>` (feature) or `/unit-lane --fix <n>` (fix) — the lane repairs the half, its `review` step re-judges it, then `/execute-phase` on this unit |
47
48
  | all taken rows foldable, none replan-class | `all-repair-in-place` | fold as today (group → fix → gate → commit → flip) |
48
49
  | empty queue (zero findings taken) | `none` | receipt only |
49
50
 
@@ -51,8 +52,9 @@
51
52
  class set (`CLASSIFY.md`); the receipt invents no parallel vocabulary.
52
53
 
53
54
  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
55
+ a freeze-batch selects `REPLAN-ROUTE` for a `frozen (replan present)` batch
56
+ and `PRODUCT-ROUTE` for a `frozen (product owner present)` batch; otherwise
57
+ the docs-only file-set test (E-D3) and the frozen-severity-`high` override (E-D2) select
56
58
  `RE-REVIEW-OPTIONAL` vs `RE-REVIEW-REQUIRED (delta)`.
57
59
  8. **Disputes.** Non-reproducible/already-fixed/wrong findings become
58
60
  `DISPUTED <evidence → user decision>`; never edit classification or create an
@@ -82,7 +84,7 @@ present:
82
84
  - Repaired: <F-ids with (VF-<n>) refs, joined ` + `, or `none`>
83
85
  - Refuted/open: <F-ids joined ` + `, or `none`>
84
86
  - Gate: <command> → exit <n> at head <40-hex sha> · n/a when nothing was folded
85
- - Batch class: <all-repair-in-place | frozen (replan present) | none>
87
+ - Batch class: <all-repair-in-place | frozen (replan present) | frozen (product owner present) | none>
86
88
  - Fold diff: <shortstat from a real `git diff` run> · none when nothing was folded
87
- - Branch: <RE-REVIEW-REQUIRED (delta) | RE-REVIEW-OPTIONAL | RE-REVIEW-SKIPPED | REPLAN-ROUTE>
89
+ - Branch: <RE-REVIEW-REQUIRED (delta) | RE-REVIEW-OPTIONAL | RE-REVIEW-SKIPPED | REPLAN-ROUTE | PRODUCT-ROUTE>
88
90
  ```
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: review-change
3
3
  user-invocable: true
4
- version: 3.11.0
4
+ version: 3.12.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
@@ -138,9 +138,10 @@ exact command tokens.
138
138
  fix); the lane re-runs its plan step on this branch, its review step
139
139
  gates, then `/execute-phase <unit>` (yes: list the finding ids; no: omit
140
140
  this line)
141
- · any finding owned by product? → /unit-lane <unit> — the lane's design
142
- step repairs the half, its review step re-judges it (yes: list the ids;
143
- no: omit this line)
141
+ · any finding owned by product? → `node scripts/unit-route.mjs <unit>` prints
142
+ `route: product` + the lane hand-off — `/unit-lane <unit>` for a feature,
143
+ `/unit-lane --fix <n>` for a fix: the lane repairs the half, its review
144
+ step re-judges it (yes: list the ids; no: omit this line)
144
145
  · independent proposals → present to the user; only the user routes them
145
146
  to /triage-issue
146
147
  · adversarial recommendation checklist fired AND this run was
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: review-implementation
3
3
  user-invocable: false
4
- version: 1.10.0
4
+ version: 1.11.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>"
@@ -175,7 +175,7 @@ finding in its `Route` cell.
175
175
  |---|---|---|
176
176
  | `source` | fold locally: `/fold-findings`, then re-run `/review-change` on the changed HEAD | — |
177
177
  | `plan` | run `node scripts/unit-route.mjs <unit>` → `route: replan`; the planning author re-cuts the artifact (SPEC `## Phases`, an obligation row, an acceptance mapping, a ledger) on the same branch with the user's confirmation, then the lane's **`review` step** precedes `execute-phase` | fold it in code and leave the plan describing the old build |
178
- | `product` | `/unit-lane <unit>` repairs the half through its `design` step, its `review` step re-judges it | patch the product claim into agreement in code |
178
+ | `product` | run `node scripts/unit-route.mjs <unit>` → `route: product` → `/unit-lane <slug>` (feature) or `/unit-lane --fix <n>` (fix): the lane repairs the half through its `design` step, its `review` step re-judges it | patch the product claim into agreement in code |
179
179
  | `environment` / `runtime` | the existing retry/`BLOCKED` paths | translate into a PASS, or an issue |
180
180
 
181
181
  - `fix-now` with a `plan` or `product` owner keeps its severity but is **not**
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: triage-issue
3
3
  user-invocable: true
4
- version: 2.10.0
4
+ version: 2.11.0
5
5
  argument-hint: <issue-number> [more issue numbers…] | <audit-id> F<k> [F<j>…] | --prioritize-now <unit> F<k> [F<j>…]
6
6
  author: "Gabriel Trabanco <1969593+gtrabanco@users.noreply.github.com>"
7
7
  license: MIT
@@ -24,6 +24,13 @@ after `/fold-findings` leaves rows unresolved.
24
24
  `decision-required`. Ask the user; do not guess or weaken the finish line.
25
25
  - A finding disproved by current evidence is `disputed`. Preserve the row
26
26
  and show the evidence; do not mark it folded or silently delete it.
27
+ - A `fix-now` finding whose owning stage is `product` — the finding is
28
+ against the product half, not the code — is `product-repair` (#293). Run
29
+ `node scripts/unit-route.mjs <unit>`; its `route: product` line prints the
30
+ lane hand-off (`/unit-lane <unit>` for a feature, `/unit-lane --fix <n>`
31
+ for a fix): the lane repairs the half, its review step re-judges it. Never
32
+ fold it into the current unit — the fold loop repairs source, not
33
+ authority (`pre-execution-review` POLICY §4).
27
34
 
28
35
  4. Never implement the new phases in this triage turn. After a replan, ask the
29
36
  user to continue manually with `/execute-phase <unit> P<n>` (or the fix
@@ -34,7 +41,7 @@ Return exactly one block per finding:
34
41
  ```text
35
42
  REVIEW FINDING <F-k> — <short title>
36
43
  Checked: <commands and evidence>
37
- VERDICT: fix-now | replan-in-unit | decision-required | disputed
44
+ VERDICT: fix-now | replan-in-unit | decision-required | product-repair | disputed
38
45
  Action taken: <current-unit fold/phase | unit-lane | user decision>
39
46
  ```
40
47
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: unit-lane
3
3
  user-invocable: true
4
- version: 1.4.0
4
+ version: 1.5.0
5
5
  argument-hint: <NN-slug | "<idea>"> [--retriage] | --fix <issue-number> | --from-issue <issue-number>
6
6
  description: >
7
7
  One-shot lane conductor for a delivery unit: triage, implement, evidence, and
@@ -85,8 +85,9 @@ re-derives, reorders, or invents steps — it executes only what the catalog say
85
85
 
86
86
  ### 3. Execute triaged steps in order
87
87
 
88
- For each step the triage returned, follow its reference file. Execute **one step
89
- per turn-commit**:
88
+ For each step the triage returned, follow its reference file. Judgment steps
89
+ (research, design, plan, evidence, docs, review) run inline, **one step per
90
+ turn-commit**:
90
91
 
91
92
  1. Read the step's reference — for example:
92
93
  [research](references/RESEARCH.md), [design](references/DESIGN.md),
@@ -100,6 +101,23 @@ per turn-commit**:
100
101
  5. Commit with a conventional commit message.
101
102
  6. For implement steps, run the diff guard (step 4 below).
102
103
 
104
+ Execution steps (implement, tests) **never run inline at the conductor's
105
+ tier** — per-step model routing is reachable only across a turn boundary, so
106
+ execution work hands off one phase per turn:
107
+
108
+ ```
109
+ → Next: /execute-phase <NN-slug> P<k> (tier: <tier>) — run phase P<k>; the lane resumes after the last phase
110
+ · no unfinished phase → continue the close-out ladder (step 6)
111
+ ```
112
+
113
+ `<k>` is the first unfinished phase (the unit doc's Progress log records the
114
+ phases done so far; `bun scripts/unit-route.mjs <NN-slug>` prints it) and
115
+ `<tier>` is the `implement` entry of the triage block's `Tiers:` line. Never
116
+ print the bare whole-unit `/execute-phase <NN-slug>` — whole-unit loop mode
117
+ survives only as an explicit operator choice. When the last phase's turn
118
+ closes, `execute-phase` resumes the lane and the remaining judgment steps
119
+ (evidence, review, docs, release) run here.
120
+
103
121
  ### 4. Diff-size guard (after each implement step)
104
122
 
105
123
  Run `bun scripts/diff-guard.mjs --base <last-reviewed-ref> --unit <NN>`. Paste
@@ -116,12 +134,26 @@ Before every commit:
116
134
  - **Progress log**: `YYYY-MM-DD HH:MM — <what was done> → <commit sha> — next:
117
135
  <what is next>`
118
136
 
119
- ### 6. Close the unit
137
+ ### 6. Close the unit — the close-out ladder
138
+
139
+ When all triaged steps are done, in order:
140
+
141
+ 1. Run the review step (the in-doc `REVIEW-VERDICT` per
142
+ [review](references/REVIEW.md)).
143
+ 2. Resolve every `## Future` row with the user (planned now — registered on
144
+ explicit request only —, kept deferred, or discarded, dated).
145
+ 3. Update the unit doc's status and the index row (release step: branch
146
+ hygiene, PR creation, forge reconciliation).
147
+ 4. **Receipt stage.** The in-doc verdict is not the machine receipt. Verify
148
+ the PR's review receipt (`bun scripts/review-receipt.mjs verify --pr <N>`):
149
+ - **exit 0** (a current `review-change:pass` receipt at the settled head) →
150
+ the closing `→ Next:` recommends `/audit-pr <PR-url>` as the terminal
151
+ stage, with the receipt stated as its precondition.
152
+ - **otherwise** → the closing block is `→ Next: /review-change <NN-slug>`
153
+ (the receipt's sole owner) and `/audit-pr` is not printed — the gate is
154
+ never named before its precondition exists.
120
155
 
121
- When all triaged steps are done, run the review pack axis summary, update the
122
- unit doc's status, resolve every `## Future` row with the user (planned now —
123
- registered on explicit request only —, kept deferred, or discarded, dated),
124
- and print the closing block.
156
+ A turn that ends with an unchecked ladder step is not done.
125
157
 
126
158
  ## Guardrails
127
159
 
@@ -140,16 +172,25 @@ and print the closing block.
140
172
  - Findings never authorize scope growth — record them, route to their owner
141
173
  - Never commit red (test failure) — fix or replan, never silence tests
142
174
  - Never alter a triaged step's order
175
+ - Never run an execution phase inline or print a bare whole-unit
176
+ `/execute-phase` command — one phase per hand-off, tier attached
177
+ - Never print `/audit-pr` before the PR's review receipt verifies current —
178
+ the receipt stage precedes the gate, always
143
179
 
144
180
  ## Relationship to other skills
145
181
 
146
182
  `unit-lane` absorbed the retired fixed-pipeline skills (design-feature,
147
- plan-feature, review-spec, review-plan) into catalog steps. The review pack axes
148
- (`review-implementation`, `review-code`, `review-security`, `review-perf`,
149
- `review-a11y`, `review-debt`) compose the review step; `triage-issue` feeds
150
- issues into the lane; `workflow-status` computes the next lane invocation.
151
- `init-workspace` seeds the unit doc template and catalog conventions into target
152
- projects.
183
+ plan-feature, review-spec, review-plan) into catalog steps. `execute-phase` is
184
+ the lane's executor: the lane conducts (triage, plan, evidence, review,
185
+ close-out) and hands execution off one phase per turn at the phase's tier;
186
+ its closing block names the next single phase and resumes the lane after the
187
+ last one. The review pack axes (`review-implementation`, `review-code`,
188
+ `review-security`, `review-perf`, `review-a11y`, `review-debt`) compose the
189
+ review step; `/review-change` owns the SHA-bound receipt the close-out ladder
190
+ verifies; `/audit-pr` is the terminal merge gate. `triage-issue` feeds issues
191
+ into the lane; `workflow-status` computes the next lane invocation.
192
+ `init-workspace` seeds the unit doc template and catalog conventions into
193
+ target projects.
153
194
 
154
195
  ## Portability (agents other than Claude Code)
155
196
 
@@ -162,17 +203,20 @@ projects.
162
203
 
163
204
  ## Done when
164
205
 
165
- - Every triaged step is executed and committed.
206
+ - Every triaged step is executed and committed — execution phases one
207
+ `/execute-phase <NN-slug> P<k>` turn each, never inline.
166
208
  - The unit doc's Evidence rows, Progress log, and References section are current.
167
- - The diff guard passed for all implement steps.
209
+ - The diff guard passed for all implement steps (or an exception is recorded).
168
210
  - The review step is complete (or skipped per catalog).
211
+ - The close-out ladder ran: receipt verified current, or the closing block
212
+ hands off to `/review-change` before any `/audit-pr` mention.
169
213
  - **The closing `→ Next:` block is printed.**
170
214
 
171
215
  ## Closing recommendation
172
216
 
173
217
  ```
174
- → Next: /unit-lane <NN-slug> — continue to the next triaged step
175
- · all steps done → /review-change (review the accumulated diff)
218
+ → Next: /execute-phase <NN-slug> P<k> (tier: <tier>) — run the next unfinished phase
219
+ · execution done, receipt current (verify --pr <N> exit 0) → /audit-pr <PR-url> — terminal merge gate; the current review-change:pass receipt is its precondition
220
+ · execution done, PR open, receipt missing → /review-change <NN-slug> — post the SHA-bound receipt first
176
221
  · re-triage needed → /unit-lane <NN-slug> --retriage
177
- · finished and merge-ready → /audit-pr (merge gate)
178
222
  ```
@@ -2,42 +2,55 @@
2
2
 
3
3
  ## Purpose
4
4
 
5
- Execute the plan's tasks against the code. One phase per commit. Layer order
6
- respected. Guard enforced.
5
+ Hand the plan's phases to the executor, one phase per turn. The conductor
6
+ never runs an execution phase inline — per-step model routing is reachable
7
+ only across a turn boundary (issue #291 AC3/AC4).
7
8
 
8
9
  ## Inputs
9
10
 
10
11
  - The unit's Tasks section (filled by the plan step)
11
- - The project's architecture doc (layer rules)
12
- - The diff guard baseline from the triage step's reference
12
+ - The triage block's `Tiers:` line (the `implement` entry is the execution tier)
13
+ - The unit's Progress log (which phases are done)
13
14
 
14
15
  ## Fixed output contract
15
16
 
16
- After each phase commit, update the unit doc's **Evidence** section and
17
- **Progress log**:
17
+ At each execution boundary, print exactly one phase hand-off and end the turn:
18
+
19
+ ```
20
+ → Next: /execute-phase <NN-slug> P<k> (tier: <tier>) — run phase P<k>; the lane resumes after the last phase
21
+ · no unfinished phase → continue the close-out ladder
22
+ ```
23
+
24
+ `<k>` = first unfinished phase (lowest `P<n>` bullet the Progress log does not
25
+ record; `bun scripts/unit-route.mjs <NN-slug>` prints it). `<tier>` = the
26
+ `implement` entry of the triage block's `Tiers:` line. Never the bare
27
+ whole-unit command.
28
+
29
+ When the last phase's turn closes, `execute-phase` resumes the lane. Verify
30
+ its work landed in the unit doc before continuing:
18
31
 
19
32
  | AC | What was run | Exit / digest | Output (≤2 lines) | Verified-by |
20
33
  |---|---|---|---|---|
21
- | P1 | <git commit sha> | 0 · <sha> | <result ≤2 lines> | <model> |
34
+ | P1 | <phase validator> | 0 · <sha> | <result ≤2 lines> | <executor model> |
22
35
 
23
36
  ## Checklist (pass only if)
24
37
 
25
- - [ ] Phases executed in P1, P2, … order from the Tasks section
26
- - [ ] One phase per commit (no bundling)
27
- - [ ] Layer order respected (inner layers don't import outer)
28
- - [ ] `git status --porcelain` is empty after each commit
29
- - [ ] Diff guard passed after each phase (see step 4 in SKILL.md)
30
- - [ ] Red run avoided — tests pass before committing, or tests-first red-run
31
- evidence recorded
38
+ - [ ] Every phase handed off as `/execute-phase <NN-slug> P<k> (tier: <tier>)`
39
+ — exactly one phase, never a bare whole-unit command
40
+ - [ ] Phases ran in P1, P2, … order from the Tasks section
41
+ - [ ] Each executor turn recorded its Evidence row and dated Progress entry
42
+ - [ ] Diff guard run at the lane's resume (see step 4 in SKILL.md)
43
+ - [ ] `git status --porcelain` is empty when the lane resumes
32
44
 
33
45
  ## Allowed
34
46
 
35
- - Changes scoped to the phase's acceptance criteria only
36
- - Bug fixes in affected paths that the phase touches
47
+ - Changes scoped to the phase's acceptance criteria only (enforced by the
48
+ executor's own gates)
37
49
  - Documentation updates in the same commit as the code change
38
50
 
39
51
  ## Forbidden
40
52
 
53
+ - Never run an execution phase inline at the conductor's tier
41
54
  - No unrelated refactors in the same commit
42
55
  - No new abstractions or dependencies beyond what the unit doc demands
43
56
  - Never commit red (test failure)
@@ -5,6 +5,18 @@
5
5
  Proportional + materiality review. A finding blocks only when a user-visible
6
6
  outcome the ACs would miss, or a contract violation.
7
7
 
8
+ ## Receipt boundary (issue #291 AC1)
9
+
10
+ The in-doc `REVIEW-VERDICT` is prose evidence, **not** the machine receipt
11
+ `/audit-pr` consumes. The receipt's sole owner is `/review-change`
12
+ (`bun scripts/review-receipt.mjs emit`). At close-out, with the PR open:
13
+
14
+ - `bun scripts/review-receipt.mjs verify --pr <N>` exit 0 → the closing block
15
+ recommends `/audit-pr <PR-url>` as the terminal stage.
16
+ - otherwise → the closing block is `→ Next: /review-change <NN-slug>` and
17
+ `/audit-pr` is never printed first. `n/a: no PR` is not a silent pass — the
18
+ release step opens the PR before close-out, so the hand-off always fires.
19
+
8
20
  ## Inputs
9
21
 
10
22
  - The unit's Evidence section (reviewer re-runs it)
@@ -42,4 +54,6 @@ REVIEW-VERDICT: PASS | FAIL
42
54
  - Never alter the acceptance criteria during review
43
55
  - Never approve without re-running the evidence
44
56
  - Never skip an axis the catalog demands
45
- - Never reuse a finding from a previous cycle without re-evaluating it
57
+ - Never reuse a finding from a previous cycle without re-evaluating it
58
+ - Never treat the in-doc verdict as the merge gate's receipt — the close-out
59
+ ladder verifies `review-receipt.mjs` before any `/audit-pr` mention
@@ -2,7 +2,11 @@
2
2
 
3
3
  ## Purpose
4
4
 
5
- Run and verify the tests the triage determined are applicable.
5
+ Run and verify the tests the triage determined are applicable. Test execution
6
+ rides the executor's phases (each phase's `validator:` runs the project's
7
+ gate); when the tests step is the turn's own boundary, it hands off like
8
+ implement does — one `/execute-phase <NN-slug> P<k> (tier: <tier>)` turn,
9
+ never inline.
6
10
 
7
11
  ## Inputs
8
12