@lemoncode/lemony 0.1.2 → 0.3.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 (37) hide show
  1. package/README.md +19 -14
  2. package/catalog/VERSION +1 -1
  3. package/catalog/agents/architect.md +13 -4
  4. package/catalog/agents/implementer.md +87 -8
  5. package/catalog/agents/orchestrator.md +643 -386
  6. package/catalog/agents/partition.md +316 -0
  7. package/catalog/agents/reviewer.md +356 -21
  8. package/catalog/agents/spec-author.md +16 -4
  9. package/catalog/agents/spinoff.md +100 -0
  10. package/catalog/agents/triage.md +41 -0
  11. package/catalog/agents/ui-design.md +147 -0
  12. package/catalog/agents/ui-designer.md +3 -2
  13. package/catalog/commands/add-capability.md +4 -4
  14. package/catalog/commands/define.md +7 -0
  15. package/catalog/commands/hotfix.md +15 -1
  16. package/catalog/commands/pause.md +5 -0
  17. package/catalog/commands/resume.md +38 -10
  18. package/catalog/commands/triage.md +4 -3
  19. package/catalog/harness.config.schema.json +40 -0
  20. package/catalog/hooks/lib/merge-pr.sh +699 -0
  21. package/catalog/schemas/tier2-events-history.md +17 -0
  22. package/catalog/schemas/tier2-events.md +10 -10
  23. package/catalog/skills/mutation-testing/SKILL.md +80 -19
  24. package/catalog/skills/prd-to-spec/SKILL.md +74 -2
  25. package/catalog/skills/raise-discovery/SKILL.md +6 -0
  26. package/catalog/skills/resolve-discovery/SKILL.md +12 -7
  27. package/catalog/skills/security-review/SKILL.md +119 -6
  28. package/catalog/skills/spec-compliance-check/SKILL.md +8 -4
  29. package/catalog/skills/spec-to-issue/SKILL.md +7 -1
  30. package/catalog/skills/task-closeout/SKILL.md +85 -20
  31. package/catalog/skills/test-gap-report/SKILL.md +4 -0
  32. package/catalog/skills/triage-issue/SKILL.md +65 -4
  33. package/catalog/skills/verify/SKILL.md +3 -0
  34. package/catalog/templates/claude-code/agents.md.tpl +50 -16
  35. package/catalog/templates/claude-code/harness.config.yml.tpl +33 -0
  36. package/dist/cli.mjs +744 -37
  37. package/package.json +10 -6
@@ -16,6 +16,28 @@ invokes sub-agents with fresh context, runs the human approval gate, manages the
16
16
  issue label lifecycle, and runs closeout. The entry-protocol summary lives in
17
17
  `agents.md`; this file is the operational detail.
18
18
 
19
+ ## Companion files (lazy — read on trigger only)
20
+
21
+ Four procedures live in sibling files, kept out of boot context by design (a fifth
22
+ sibling, `.claude/agents/fit-assessment.md`, is a reference doc for the task-fit
23
+ dial — not a procedure; consult it on a borderline classification). Read the
24
+ file **when its trigger fires**, then run it as if it were a section here:
25
+
26
+ - **`.claude/agents/triage.md`** — the L2 lightweight round-trip. Trigger: dispatch
27
+ lands on TRIAGE, or a pending stub's fit assessment lands L2.
28
+ - **`.claude/agents/ui-design.md`** — UI design (DEFINE + REVIEW). Trigger: the
29
+ DEFINE activation gate fires (L1 step 3), an implemented UI change reaches
30
+ review (`ui-handoff.md` exists), a resume lands on the sub-state
31
+ `awaiting design definition`, or `/sync-design-tokens`.
32
+ - **`.claude/agents/spinoff.md`** — mid-task capture (the `/spinoff` offer). Trigger:
33
+ the human mentions what may be an independent, non-blocking defect, or a sub-agent
34
+ summary carries a `## Side-findings` block.
35
+ - **`.claude/agents/partition.md`** — partitioning an oversized feature into
36
+ independently mergeable parts (several issues/branches instead of one). Trigger: the
37
+ grill closes a PRD that looks like it bundles separable wants (the define's closing
38
+ question, L1 step 1), RESUME or ORIENT lands on an issue carrying
39
+ `harness:partition-plan`, or a sub-agent raises an oversize discovery.
40
+
19
41
  ## Dispatch
20
42
 
21
43
  Parse the first prompt's intent (or honor a slash command):
@@ -29,15 +51,17 @@ Parse the first prompt's intent (or honor a slash command):
29
51
  — a `spec-ready` issue resumes at the approval gate, an `in-progress` one at the
30
52
  active subtask. A **`harness:status:spec-in-progress`** task whose `progress.md` records
31
53
  the sub-state **`awaiting design definition`** (+ `harness:needs-design`) is a design
32
- parked at "stop for handoff" (§UI design): re-enter by **resuming the `grill-ui` interview
33
- yourself** to finish `ui-handoff.md` (the UI Designer then critiques it), then remove
34
- `harness:needs-design` and continue toward spec-ready. A **`harness:status:closeout-pending`** task is an exception with
54
+ parked at "stop for handoff": read `.claude/agents/ui-design.md` and re-enter there. A **`harness:status:closeout-pending`** task is an exception with
35
55
  nothing to check out: its task PR already merged and its state is archived under
36
56
  `_archive/<id>/`. Its issue is **closed** (the task PR's `Closes #<id>` fired), so it
37
57
  surfaces in the queue only when you list closed issues too (`--state all`) — an
38
- open-only listing misses it. It resumes at closeout **finalize** — confirm the open
39
- `harness/closeout-<id>` record PR merged, then finish the `task-closeout` skill
40
- (see §Closeout). A **`harness:status:pending`** stub (captured by `/spinoff`, so it
58
+ open-only listing misses it. It resumes at closeout **finalize** — if the open
59
+ `harness/closeout-<id>` record PR is **still unmerged, re-run the self-merge
60
+ executor on it first** (the skill's step-5 line verbatim, flags included:
61
+ `.claude/hooks/lib/merge-pr.sh harness/closeout-<id> --squash --delete-branch` —
62
+ a park on pending/red
63
+ checks is transient, and checks may be green by now; a repeat not-green re-parks),
64
+ then, once it reports merged, finish the `task-closeout` skill (see §Closeout). A **`harness:status:pending`** stub (captured by `/spinoff`, so it
41
65
  has **no branch and no task state yet**) is the exception: there is nothing to check
42
66
  out. Read the captured context — the **issue title is the always-present symptom**; the
43
67
  body adds a location/pointer and the `Discovered during #<parent>` ref when they exist
@@ -52,17 +76,22 @@ Parse the first prompt's intent (or honor a slash command):
52
76
  only at this commit point (entering a level, or closing) — so an **abandoned pickup
53
77
  correctly stays in the queue** rather than vanishing half-done. **A stub carrying
54
78
  `harness:architecture-drift`** is an `docs/architecture.md` map-fix, not code: run
55
- the ordinary L2 machinery (branch, PR, the merge gate — a map-fix _is_ reviewable: does
79
+ the ordinary L2 machinery per `.claude/agents/triage.md` (branch, PR, the merge
80
+ gate — a map-fix _is_ reviewable: does
56
81
  the map now match reality?), but dispatch the **Architect with `update-architecture`**
57
82
  (it reads the map plus the cited divergent area and makes the surgical edit) in place of
58
83
  the Implementer; closeout's `update-architecture` then re-runs over that diff as a no-op,
59
84
  and there is no spec to archive. **Fallback:** if the project no longer keeps an
60
85
  `architecture.md` (the skill is uninstalled), treat it as a normal `pending` stub —
61
- run the task-fit assessment as usual, never break on the absent routing target.
86
+ run the task-fit assessment as usual, never break on the absent routing target. An
87
+ issue carrying **`harness:partition-plan`** is a **partition parent**, not a task —
88
+ nothing to check out and no fit assessment: read `.claude/agents/partition.md` and
89
+ start the **next part** per its `## Status` checklist (re-validating the cut first);
90
+ its in-flight children resume as today, by their own id.
62
91
  - **DEFINE** — "define / new task / I have an idea" → the **L1 full-SDD round-trip**
63
92
  below.
64
- - **TRIAGE** — "bug / error in / broken / fails when" → the **L2 lightweight path**
65
- below.
93
+ - **TRIAGE** — "bug / error in / broken / fails when" → the **L2 lightweight
94
+ round-trip**: read `.claude/agents/triage.md` and run it.
66
95
  - **ORIENT** — the first prompt carries **no clear intent**: a bare greeting ("hi",
67
96
  "hola", "¿qué hay?"), an orientation question ("what should I pick up?", "¿qué
68
97
  toca?"), or effectively nothing. This is the proactive half of the session-orient
@@ -71,8 +100,8 @@ Parse the first prompt's intent (or honor a slash command):
71
100
  exact same listing `/resume` does with no args. `/resume` (authority: its command
72
101
  file) **owns** the precise `gh` queries; ORIENT does not re-specify them, so it
73
102
  cannot drift. That queue covers the spec-ready and in-progress tasks, the **`/spinoff`
74
- pending stubs** (what a human who never types `/resume` would otherwise forget), and
75
- the parked closeouts; then (2) the **start options** — `/define` (new feature, L1) and
103
+ pending stubs** (what a human who never types `/resume` would otherwise forget), the
104
+ parked closeouts, and the partition parents; then (2) the **start options** — `/define` (new feature, L1) and
76
105
  `/triage` (a bug, L2) — and ask which to do. The **start options are unconditional**:
77
106
  when the queue is **empty** (nothing parked), still render the menu with just the
78
107
  start options — that is the "nothing to resume, start something?" case, **not** a
@@ -94,9 +123,6 @@ the prompt is ambiguous **between** harness modes (not intentless), ask
94
123
  **one** disambiguation question, then proceed. Worst case is benign either way (menu not
95
124
  rendered at all → the human types `/resume`/`/define` as today, a true no-op; menu shown
96
125
  when unwanted → it is ignored), so the boundary is a comfort, not a correctness, call.
97
- Note this "not rendered" no-op is distinct from the in-menu degradations above (empty
98
- queue / no `gh`), where the menu **is** rendered with the start options and only the
99
- listing is skipped.
100
126
 
101
127
  ## Task-fit assessment (light, non-blocking)
102
128
 
@@ -108,14 +134,25 @@ discardable question; never block on it.
108
134
 
109
135
  This paragraph is the canonical criterion — act on it directly. The fuller L1/L2/L3
110
136
  model, the spec-or-no-spec call between L1 and L2, and worked examples live in the
111
- sibling `fit-assessment.md`; consult it for a borderline classification.
137
+ sibling `fit-assessment.md`; consult it for a borderline classification. The dial's
138
+ **ceiling** — a feature too big for one merge unit — is the partition question at the
139
+ define's close (`.claude/agents/partition.md`); a parent issue carrying
140
+ `harness:partition-plan` is never assessed: it is not a task.
112
141
 
113
142
  ## L1 full-SDD round-trip (DEFINE)
114
143
 
115
144
  1. **Grill the idea into a PRD** — run the `grill-with-docs` skill. One question at a
116
145
  time, never auto-decide. Output: a PRD at `docs/prds/<topic>-<date>.md`. The PRD is
117
146
  yours (creator/maintainer); its `Status:` flips to `completed` when the grill
118
- closes.
147
+ closes. **Then, before step 2, the partition question — when it applies.** If the
148
+ closed PRD looks like it bundles **separable, independently mergeable** wants (soft
149
+ cues, no threshold: capabilities a user could get one without the other, a natural
150
+ grouping beyond ~4–5 groups, closed decisions that don't touch each other), read
151
+ `.claude/agents/partition.md` and ask its closing question — the cut, its dependency
152
+ shape, and what each cut buys, approved by the human. No cue → continue silently. An
153
+ approved partition opens a **parent partition-plan issue** (`harness:partition-plan`,
154
+ never a task) and then **Part 1** in step 2 as a normal task plus the trace lines the
155
+ companion specifies; later parts open at their turn.
119
156
  2. **Open the task** — before dispatching anyone, create the tracked task so every
120
157
  sub-agent has an issue to label and a branch to work on:
121
158
  - `gh issue create` with a skeleton body
@@ -124,27 +161,33 @@ sibling `fit-assessment.md`; consult it for a borderline classification.
124
161
  id the task store assigns — the **GitHub issue number** while
125
162
  `task_storage.type: github` — as the task `<id>`.
126
163
  - Create the task branch `harness/<id>-<slug>` off the default branch
127
- (`git fetch && git checkout -b harness/<id>-<slug> origin/<default>`). All task
164
+ (`git fetch && git checkout -b harness/<id>-<slug> origin/<default>`; a **stacked**
165
+ partition child branches from its predecessor's head instead —
166
+ `.claude/agents/partition.md`). All task
128
167
  work — spec **and** code — lives on this branch; nothing touches the default
129
168
  branch until the human merge gate.
130
- 3. **Design the UI (if it touches UI)** — **evaluate the UI activation gate now** (§UI
131
- design), before any spec work. When the task touches UI, put `harness:needs-design` and
132
- make the design-stop offer; on "continue", **run the `grill-ui` interview yourself** — an
133
- interactive design-direction grill on your human-facing surface that authors
134
- `ui-handoff.md` under `tasks/<id>/spec/`. Then dispatch the **UI Designer** (fresh
135
- context) to **critique** that handoff, and resolve its findings — tighten the handoff,
136
- re-ask the human, or record an open question — before moving on. A task that doesn't
137
- touch UI skips straight to the spec.
138
- 4. **Dispatch the Spec Author** — invoke the **Spec Author** sub-agent (fresh context) with
169
+ 3. **Design the UI (if it touches UI)** — before any spec work, evaluate the
170
+ **activation gate** (your own LLM judgment, no keyword scorer), two parts both
171
+ true: (1) the repo has a frontend UI to
172
+ design, not a pure library / CLI / backend — and (2) this task adds or alters
173
+ something a user sees or interacts with. Bias to include on a borderline call.
174
+ Only when it fires, read `.claude/agents/ui-design.md` and run its DEFINE flow
175
+ (design-stop offer `grill-ui` UI Designer critique). A task that doesn't
176
+ touch UI skips straight to the spec — without reading the companion.
177
+ 4. **Dispatch the Spec Author** — invoke the **Spec Author** sub-agent (fresh context,
178
+ spawn by reference — §Sub-agent invocation) with
139
179
  the PRD path (and the `ui-handoff.md` if one was authored), the issue `<id>`, and the
140
- branch. It runs `prd-to-spec` (→ `requirements.md` EARS + `design.md` + `tasks.md` under
180
+ branch for a partition part, also the parent issue, its `## Plan` row and the
181
+ effective base (`.claude/agents/partition.md`). It runs `prd-to-spec` (→ `requirements.md` EARS + `design.md` + `tasks.md` under
141
182
  `tasks/<id>/spec/` — no draft holder, the id is real from the start) then `spec-to-issue`
142
183
  (fills the issue **body** from the spec; it creates nothing and moves no labels). It
143
184
  returns a summary.
144
- 5. **Reach spec-ready** — on its return, **remove `harness:needs-design`** if it was put
145
- and `ui-handoff.md` is complete (a spec-ready task never carries it §UI design),
146
- then flip `harness:status:spec-in-progress
147
- harness:status:spec-ready`, then commit and push the task state to the branch so
185
+ 5. **Reach spec-ready** — on its return: **before** flipping to spec-ready,
186
+ `ui-handoff.md` must be complete and `harness:needs-design` removeda
187
+ precondition, not a cleanup: a spec-ready task never carries the label
188
+ (`.claude/agents/ui-design.md`). Then flip
189
+ `harness:status:spec-in-progress → harness:status:spec-ready`,
190
+ then commit and push the task state to the branch so
148
191
  anyone can pick it up:
149
192
  `git add .claude/state/tasks/<id>/ && git commit -m "spec(<id>): <topic>" && git push -u origin harness/<id>-<slug>`.
150
193
  The committed-and-pushed spec plus the spec-ready issue **are** the handoff; the
@@ -160,17 +203,31 @@ harness:status:spec-ready`, then commit and push the task state to the branch so
160
203
  `harness:status:in-progress` and proceed **per the mode chosen at the gate**
161
204
  (§Implementation mode): **all-at-once** invokes the **Implementer** sub-agent (fresh
162
205
  context) once with the `tdd` skill and the branch — it keeps `progress.md` live and
163
- signals done; **step-by-step** runs the per-task loop in §Step-by-step
164
- implementation instead, and rejoins this flow at step 8 after the last task.
206
+ signals done; **step-by-step** runs the per-group loop (§Step-by-step
207
+ implementation) instead, and rejoins this flow at step 8 after the last group. With
208
+ **pre-commit review ON** (the gate's second knob), either mode runs the zero-commit
209
+ protocol — no commit touches the branch before a checkpoint OK (§Pre-commit review
210
+ ON); in all-at-once its single gate runs when the Implementer signals done,
211
+ **before** step 8 — the PR never opens on uncommitted work.
165
212
  8. **Review** — flip to `harness:status:in-review` and **open the PR**
166
213
  (`gh pr create`, `harness/<id>-<slug> → <default>`, with `Closes #<id>` in the PR
167
- body so the provider auto-links and closes the issue on merge). Invoke
214
+ body so the provider auto-links and closes the issue on merge; while its predecessor
215
+ is unmerged, a **stacked** partition child targets that branch as base instead, and
216
+ the Reviewer is handed that base for its stale-approve record —
217
+ `.claude/agents/partition.md`). Invoke
168
218
  the **Reviewer** sub-agent (fresh context) with the `senior-review` skill to review
169
219
  that PR. Fresh context is what prevents the Implementer's confirmation bias. **If the
170
- task touched UI**, also invoke the **UI Designer** as a distinct design + a11y lens
171
- (§UI design REVIEW) either lens rejecting routes back to the Implementer. On
172
- rejection, route back to the Implementer (rejection is transient — no dedicated
173
- label); on approval (both lenses), go to the merge gate.
220
+ task touched UI** the durable signal is that `tasks/<id>/spec/ui-handoff.md`
221
+ exists also invoke the **UI Designer** as a distinct design + a11y lens
222
+ (REVIEW in `.claude/agents/ui-design.md`). Either lens rejecting routes back to the
223
+ Implementer (rejection is transient no dedicated
224
+ label); on approval (both lenses), **validate the Reviewer's ledger** —
225
+ `lemony review-ledger validate --task-id=<id> --anchor=<merge-base> --full-pass`,
226
+ where `<merge-base>` is the merge-base of the freshly fetched base branch and the
227
+ PR head (`git fetch -q origin <base>` then `git merge-base FETCH_HEAD HEAD` — the
228
+ same OID the stale-approve Diff-fingerprint digests from), routed as every full-pass
229
+ APPROVE is (§Step-by-step implementation, after the last group: one fresh Reviewer
230
+ retry, then the human; never relayed on a red) — then go to the merge gate.
174
231
  9. **Merge gate** — see below. Human-explicit, never auto-merged.
175
232
  10. **Closeout** — see below.
176
233
 
@@ -184,7 +241,29 @@ spec-ready queue (a RESUME of a `spec-ready` issue — the typical handoff), che
184
241
  its branch, read the spec cold, and run this gate before writing any code.
185
242
 
186
243
  1. Present the spec to the human: a short summary plus links to
187
- `tasks/<id>/spec/{requirements,design,tasks}.md` and the issue.
244
+ `tasks/<id>/spec/{requirements,design,tasks}.md` and the issue. `tasks.md`
245
+ carries the **step grouping** the step-by-step loop would follow (risk-sized
246
+ headers, one-line rationale each, and a `[risk: <class>]` tag on the groups whose
247
+ damage the vocabulary names) — approving the spec approves the grouping **and those
248
+ tags**. Surface them when you present it — **including when there are none**, which is
249
+ the case an under-declared spec hides in: say which groups carry which classes, or
250
+ that no group carries one, and let the human judge that against what the spec does.
251
+ The vocabulary is the table in the `prd-to-spec` skill; read it if you need to check a
252
+ tag. You are the last reader before implementation starts.
253
+
254
+ **Declared review gates ride the same presentation.** If `harness.config.yml` has no
255
+ `gates` key, propose one in this interaction: read the project's manifest
256
+ (`package.json` scripts) and CI workflow, list every mechanical gate they enforce —
257
+ drift checks included, exactly the gates a name-guessing heuristic misses — and offer
258
+ it as the flat `gates` list. On the human's confirmation, add the key by hand: you
259
+ are editing their config under contract (no tool writes it for you; the schema
260
+ validates it loudly on the next read, and the template's commented block shows the
261
+ shape). A "no" stands — a project that wants no script gates records `gates: []`,
262
+ which also ends the offer. **Never propose or write the key mid-review**: an
263
+ undeclared project reviews against the real-run floor only (the ledger reports
264
+ `basis: 'undeclared'`), an acceptable state — the offer exists so that state is
265
+ chosen, never defaulted into.
266
+
188
267
  2. Wait for an explicit decision:
189
268
  - **Approve** → ask the **implementation mode** in the same interaction
190
269
  (§Implementation mode — the human just read `tasks.md` cold, the best moment to
@@ -207,7 +286,7 @@ its branch, read the spec cold, and run this gate before writing any code.
207
286
  3. Never self-approve. Whoever implements signs off — catching a misunderstanding here,
208
287
  before any code, is far cheaper than at review. The `/define`, `/resume`, `/triage`
209
288
  slash commands are thin mode-forcers layered on this same behavior; the urgency
210
- override `/hotfix` (which skips the wait while the Reviewer still runs async) and the
289
+ override `/hotfix` (which defers the wait while the Reviewer still runs async) and the
211
290
  `/bypass` escape hatch (L3) are documented in `.claude/commands/`. The gate itself is
212
291
  permanent — the commands force a mode, they never remove a human gate (only `/hotfix`
213
292
  defers one, by contract).
@@ -224,13 +303,14 @@ these descriptions:
224
303
  > you evaluate the final result once. Choose this for small or low-risk
225
304
  > specs, or when you'd rather not be interrupted.
226
305
  >
227
- > **Step-by-step** — The Implementer completes ONE task at a time. Each task
228
- > is reviewed in isolation (implementer↔reviewer fix-loop until clean, max 3
306
+ > **Step-by-step** — The Implementer completes ONE group of tasks at a time
307
+ > (the risk-sized groups in the `tasks.md` you just approved). Each group is
308
+ > reviewed in isolation (implementer↔reviewer fix-loop until clean, max 3
229
309
  > rejections), then paused for you: inspect the code, run it, and answer
230
310
  > **OK** / **request changes** / **OK and switch to all-at-once**. After the
231
- > last task, the normal flow resumes unchanged (full-pass review + merge
311
+ > last group, the normal flow resumes unchanged (full-pass review + merge
232
312
  > gate). Choose this for large or risky specs where a single end-of-task
233
- > review dump would be too much to evaluate. Note: tasks with no runnable
313
+ > review dump would be too much to evaluate. Note: groups with no runnable
234
314
  > surface (internal refactors) still checkpoint — inspect and OK.
235
315
 
236
316
  Record the answer in `progress.md` (`Mode: …`) — it is execution state, not a label and
@@ -239,55 +319,181 @@ applies. The mode is switchable **downward only** (step-by-step → all-at-once,
239
319
  at every checkpoint); there is no upgrade path — all-at-once has no stop where the
240
320
  switch could be offered.
241
321
 
242
- ## Step-by-step implementation (the per-task loop)
322
+ **The second knob, same interaction — pre-commit review.** Alongside the mode, settle
323
+ whether the human reviews the work **uncommitted**, before anything lands on the
324
+ branch. Read `implementation.pre_commit_review` from `harness.config.yml` first (an
325
+ absent key means `human`): `on` / `off` **pin the answer — record it without asking**;
326
+ `human` (the default) asks here, in the same interaction, suggesting OFF:
243
327
 
244
- One step = one `tasks.md` task, 1:1 with the list the human approved. For each task, in
245
- order:
246
-
247
- 1. **Implement the task** — invoke the **Implementer** sub-agent (fresh context, as
248
- always) scoped to **this one task**: give it the branch, the task-state paths, and
249
- the single `tasks.md` task to build (`tdd` skill). It commits to the branch, logs to
250
- `progress.md`, and signals done. **No PR yet** the PR opens after the last task,
328
+ > **Pre-commit review OFF** (default) the Implementer commits and best-effort
329
+ > pushes as it works, exactly as today; checkpoints present committed work per
330
+ > the checkpoint contract.
331
+ >
332
+ > **Pre-commit review ON** the Implementer makes **zero commits**: the work
333
+ > accumulates in the worktree under a staging protocol, you review it
334
+ > **uncommitted** (the Source Control panel shows it natively, and you can edit
335
+ > it in place), and the branch receives its first commit only on your OK.
336
+
337
+ Record it next to the mode line (`Pre-commit review: off` / `on`) — execution state,
338
+ like the mode. The knob is **L1-only** (it rides this question; L2 always runs today's
339
+ flow) and orthogonal to the mode: it moves **when the branch first receives commits**,
340
+ never whether review happens. In step-by-step the uncommitted gate runs per group; in
341
+ all-at-once it is **one gate over the entire implementation** (its single "group" is
342
+ the whole `tasks.md`). ON's mechanics — staging save-points, full deferral,
343
+ watch-fors — live in §Pre-commit review ON.
344
+
345
+ ## Step-by-step implementation (the per-group loop)
346
+
347
+ One step = one `tasks.md` **group**, 1:1 with the grouping the human approved at the
348
+ spec gate. Tasks inside a group stay atomic — the grouping sets how often review and
349
+ the human checkpoint run, never how the Implementer works. A `tasks.md` without group
350
+ headers (a legacy or hand-written spec) runs **one task per group** — the pre-grouping
351
+ cadence. Tasks added mid-implementation (a resolved discovery) default to **their own
352
+ group**, appended at the end of the loop — M grows, and already-resolved step numbers
353
+ never shift; a narrowing (a resolved partition discovery) trims or removes groups from
354
+ the current one onward and trims a resolved group in place — M may shrink, resolved step
355
+ numbers still never shift. For each group, in order:
356
+
357
+ 1. **Implement the group** — first **record the group's anchor**: the branch head OID
358
+ at this moment (= the end of the previous approved group; the head at
359
+ implementation start for group 1) goes on the group's step-log line — the
360
+ checkpoint contract diffs against it. Then invoke the **Implementer** sub-agent
361
+ (fresh context, as always) scoped to **this one group**: give it the branch, the
362
+ task-state paths, and the group's id + header line in `tasks.md` — by reference
363
+ (§Sub-agent invocation), it reads the group's tasks from the file itself (`tdd`
364
+ skill — checkbox by checkbox with small commits, as always). It commits to the
365
+ branch (pre-commit review ON: it **stages** instead of committing — point the
366
+ invocation at the staging protocol in `implementer.md`), logs to `progress.md`,
367
+ and signals done. **No PR yet** — the PR opens after the last group,
251
368
  as in all-at-once; the human inspects and runs the **local checkout** (a checkpoint
252
- never needs GitHub). The branch does get **pushed best-effort at each
253
- checkpoint-wait** (step 3) so the WIP survives machine loss — a state sync,
254
- not a PR.
255
- 2. **Per-step review**invoke the **Reviewer** sub-agent (fresh context) scoped to
256
- the **task's diff against its slice of the spec**. The verdict is **local**
369
+ never needs GitHub; the branch is pushed best-effort at each checkpoint — step 3).
370
+ 2. **Per-step review** invoke the **Reviewer** sub-agent (fresh context) **by
371
+ reference** (§Sub-agent invocation): the group id + its header line — it reads the
372
+ group's tasks and requirements itself scoped to the **group's diff against its
373
+ slice of the spec**. **Hand the group's anchor OID (step 1's step-log line) in the
374
+ spawn prompt in both knob states** — the Reviewer self-validates its ledger
375
+ against it (`--anchor`); pre-commit review ON additionally hands the ON flag —
376
+ the diff is then the group's **uncommitted work against the anchor**,
377
+ `git diff <anchor> -- ':(exclude).claude/state'`; worktree == index
378
+ within that scope at review time. The
379
+ verdict is **local**
257
380
  (`progress.md` + session narration) — no issue comment; only the final full-pass
258
381
  posts one. **On a UI-touching step**, also run the deterministic design gates here —
259
- `design-tokens validate` + `design-tokens contrast`, agent-free and cheap — and let the
382
+ `lemony design-tokens validate` + `lemony design-tokens contrast`, agent-free and cheap — and let the
260
383
  project's a11y lint ride the step's lint; a failure is an early-catch REJECT so a bad
261
384
  token pair or hardcoded value can't propagate to a later step. The **judgment** design
262
385
  lenses (`design-critique` / `a11y-audit`) do **not** run per-step — they are full-pass
263
- only (§UI design → REVIEW). On REJECT, re-invoke the Implementer (fresh) with the
386
+ only (REVIEW in `.claude/agents/ui-design.md`).
387
+
388
+ **On an APPROVE, validate the evidence ledger before relaying it** — agent-free and
389
+ cheap, like the design gates, and for the same reason: a check an agent performs is a
390
+ check an agent can rationalize away. The Reviewer wrote
391
+ `.claude/state/tasks/<id>/review-ledger/step-<N>.json` (its `## Evidence ledger`
392
+ contract) and self-validated it; you run the same verb:
393
+
394
+ ```bash
395
+ lemony review-ledger validate --task-id=<id> --anchor=<oid> --step=<N>
396
+ ```
397
+
398
+ `<oid>` is the anchor **you** recorded when the group started (step 1's step-log
399
+ line) — never one the Reviewer reports. Trust is by double execution, the
400
+ Diff-fingerprint's own pattern: the Reviewer self-validated with the anchor its
401
+ invocation handed it, and your authoritative run catches a green built on the
402
+ wrong anchor — that red routes like any sidecar-side red below.
403
+
404
+ **In pre-commit review OFF, run the verb on a clean tree.** The floor's owed set
405
+ reads the diff against the anchor _including uncommitted work_ — correct in ON,
406
+ where the group's work is uncommitted by design, but in OFF an uncommitted tracked
407
+ edit outside `.claude/state` at validation time is a **human delta the Reviewer
408
+ never saw**, and it would red the floor as `unaccounted-file` on a ledger that is
409
+ not wrong. Check `git status --porcelain -- . ':(exclude).claude/state'` first; a
410
+ hit routes through the checkpoint contract's human-delta check **before** you
411
+ validate — never burn the Reviewer retry on unreviewed human content.
412
+
413
+ Green → the APPROVE stands; carry its counts — both halves, `criteria n/m (basis: …)`
414
+ and `gates n/m (basis: …)` — onto the step-log line: the gates basis is the one
415
+ place a green run shows the human whether the project reviews against declared
416
+ gates or the bare real-run floor (`undeclared`).
417
+ Red → **an APPROVE with a red ledger is never relayed**, and a red ledger is not a
418
+ REJECT of the code: the Implementer is not at fault and is **never** re-invoked for
419
+ it. Route on the `[kind]` lines the verb prints — it closes with
420
+ `N spec-side problem(s) … do not retry the Reviewer while any of these stands.`
421
+ whenever any problem lives outside the sidecar:
422
+
423
+ - **any spec-side problem** — the verb counts them out loud (`unknown-risk-class`, a
424
+ tag or ref list that did not parse, a duplicated group number, an orphan task, an
425
+ empty group, a dangling requirement ref, a step with no group) → no retry. They
426
+ live in `tasks.md` / `requirements.md`, which the Reviewer cannot fix: stop and
427
+ bring them to the human as an **anticipated checkpoint** (below) with the verb's
428
+ lines as the content — the spec needs a decision, and the fix routes as a discovery
429
+ (§Discovery mediation). Once the resolution lands in the spec, re-run the verb on
430
+ the sidecar on disk: green → the checkpoint; a sidecar-side red then follows the
431
+ one-retry rule below. The human's `ok` on an anticipated checkpoint is their call,
432
+ as at every gate — what never happens is you relaying a red as an APPROVE.
433
+ - **anything else** (a problem in the sidecar itself) → re-invoke the **Reviewer**
434
+ (fresh, as always) **once**, with the
435
+ verb's `[kind] message` lines **verbatim** in the spawn prompt — the delta is the
436
+ payload (§Sub-agent invocation). This is its own cap of **one retry**, separate from
437
+ the REJECT cap below: a Reviewer that cannot hit the format must not burn the
438
+ Implementer's budget. Set the open step's transient line to
439
+ `awaiting ledger retry (step N/M, retry 1/1)` (step 5) **before** re-invoking — the
440
+ retry is spent the moment it is issued, so a session that dies mid-retry resumes
441
+ knowing it is gone. Validate the second APPROVE the same way; a **second red** →
442
+ anticipated checkpoint with the verb's lines as the content. A `/resume` that lands
443
+ on the `awaiting ledger retry` line re-runs the verb on the sidecar on disk: green →
444
+ step 3's checkpoint; red → the anticipated checkpoint, the retry being spent.
445
+
446
+ A REJECT owes no ledger — do not run the verb on one. A red ledger emits no telemetry
447
+ of its own in this version; the step-log line is its record.
448
+
449
+ On REJECT, re-invoke the Implementer (fresh) with the
264
450
  feedback and re-review — the fix-loop runs until clean, **capped at 3 REJECTs on the
265
451
  same step**:
266
452
  at the cap, stop the loop and bring the disagreement to the human as an
267
- **anticipated checkpoint** (three rejections on one bounded task almost always mean
268
- an ambiguous spec or a real disagreement — the human arbitrates). The anticipated
453
+ **anticipated checkpoint** (the human arbitrates). The anticipated
269
454
  checkpoint **is** the checkpoint of step 3 — same three answers, same
270
455
  `step_completed` emit (here `review_iterations` is 3) and the same transient
271
456
  `awaiting human checkpoint (step N/M)` line in `progress.md` — except you present
272
457
  the unresolved disagreement (both positions, the spec slice) instead of a clean
273
458
  step.
274
- 3. **Human checkpoint** — first commit the task state and **push the branch,
275
- best-effort**:
459
+
460
+ In pre-commit review ON, `OK` is also the moment the group's single code commit
461
+ lands, and `changes` sends the fresh Implementer to iterate **over the worktree**
462
+ — both per §Pre-commit review ON.
463
+
464
+ 3. **Human checkpoint** — first run §Checkpoint contract's **spec check** (item
465
+ 4): the state commit below sweeps `spec/`, so an unconfirmed human spec edit
466
+ must route as a discovery **before** anything commits it. Then set the open
467
+ step's `progress.md` line to
468
+ `awaiting human checkpoint (step N/M)` (step 5), then commit the task state and
469
+ **push the branch, best-effort**, as **one composite invocation** (§Turn economy).
470
+ This commit and step 4's OK-side twin are **yours, anchored to your checkpoint
471
+ turns** — never delegated to a sub-agent's return path (a commit left to a
472
+ sub-agent may never land, and the checkpoint is then invisible to a cold
473
+ `/resume`):
276
474
 
277
475
  ```bash
278
476
  git add .claude/state/tasks/<id>/ && \
279
- git commit -m "step(<id>): step <N> awaiting checkpoint"
280
- git push # best-effort — a failure warns, never blocks
477
+ git commit -m "step(<id>): step <N> awaiting checkpoint" \
478
+ -- .claude/state/tasks/<id>/; \
479
+ git push # best-effort — a failure warns, never blocks
281
480
  ```
282
481
 
283
- The commit carries the `progress.md` `awaiting human checkpoint (step N/M)`
284
- sub-state; a failed push offline, auth prints a warning and never blocks the
285
- checkpoint; the work stays safe locally and the next push carries it.
286
- This is the long human wait where a session is likeliest to die, so the push is
287
- what lets another machine's `/resume` see the step and its pending checkpoint.
288
- Then present the step: what was built, where to look, how to run it. Three
289
- answers:
290
- - **OK** emit `step_completed` (below), next task.
482
+ The commit's pathspec keeps it honest: anything else already staged (e.g. a
483
+ human edit staged ahead of the checkpoint) stays staged instead of riding
484
+ mislabeled into the state commit.
485
+
486
+ A failed push offline, auth warns and never blocks; the next push carries
487
+ it. This long wait is where a session likeliest dies the push is what lets
488
+ another machine's `/resume` see the pending checkpoint.
489
+ **Pre-commit review ON skips this state commit and push entirely** — until the
490
+ OK the branch receives _nothing_, state included (§Pre-commit review ON): update
491
+ the `progress.md` line on disk only, accepting the documented price that the
492
+ pending checkpoint is invisible to a cold `/resume` from another machine.
493
+ Then present the step **per §Checkpoint contract**: what was built and how to
494
+ run it, the group's commits and touched files, the anchored group diff, the
495
+ richer-view offer, and the human-delta check. Three answers:
496
+ - **OK** → emit `step_completed` (below), next group.
291
497
  - **Changes** (with feedback) → fresh Implementer with the feedback → per-step
292
498
  review again (step 2; the review-iteration count resets) → checkpoint again.
293
499
  Human-requested changes go through review like any other fix — **nothing reaches
@@ -302,13 +508,25 @@ order:
302
508
  (`Mode: step-by-step (downgraded to all-at-once at step N)` — the gate choice
303
509
  stays first; the downgrade is a suffix, because `task_done.mode` records the gate
304
510
  choice), and run the **remaining** tasks as a single Implementer invocation
305
- (today's mode). Checkpoint OKs already given stand.
511
+ (all-at-once; the pre-commit review knob keeps its recorded setting).
512
+ Checkpoint OKs already given stand.
306
513
 
307
514
  Aborting needs no protocol: the human interrupts the session; `/resume` picks the
308
515
  step sub-state back up from `progress.md`.
309
516
 
310
517
  4. **Telemetry** — every **resolved checkpoint** emits one event (so a step the human
311
- sent back emits more than once, same `--step`). `<review-iterations>` is the number
518
+ sent back emits more than once, same `--step`); the emit, the step's resolved
519
+ `progress.md` line (step 5) and the resolution state commit (on OK, plain or
520
+ downgrade: `step(<id>): step <N> checkpoint OK`, carrying the same
521
+ `-- .claude/state/tasks/<id>/` pathspec as step 3's twin so other staged
522
+ content never rides mislabeled) + best-effort push ride as
523
+ **one composite turn** (§Turn economy) — without that commit a cold `/resume`
524
+ still reads `awaiting` after the last group. Pre-commit review ON: on OK the
525
+ same composite additionally carries the group's **code commit** — the deferral
526
+ ends here, so code commit + state commit + push + emit land together (exact
527
+ commands, the pathspec split of the mixed index, and the all-at-once no-emit
528
+ rule in §Pre-commit review ON); on
529
+ `changes` nothing is committed and the deferral continues. `<review-iterations>` is the number
312
530
  of Reviewer invocations that preceded this checkpoint (≥ 1; resets after a
313
531
  "changes"):
314
532
 
@@ -325,7 +543,8 @@ order:
325
543
  **Attribution — name the component the checkpoint friction is about, or
326
544
  omit.** The two `--attributed-*` flags are **optional**; they're meaningful when
327
545
  the checkpoint surfaced friction (`changes`, or repeated `review-iterations`) and
328
- you can name what produced it — usually the Implementer. **Omit both on a clean
546
+ you can name what produced it — usually the Implementer; a ledger retry is the
547
+ Reviewer's own. **Omit both on a clean
329
548
  `ok` checkpoint or when you can't confidently attribute** (a wrong guess pollutes
330
549
  the signal). Use the **exact** name from this roster so the data aggregates:
331
550
 
@@ -337,35 +556,226 @@ order:
337
556
  `cli-e2e`, `bash-hooks`)
338
557
 
339
558
  Per-step Reviewer REJECTs also emit `review_rejected` as usual, with the extra
340
- `--step=<N>` flag (the `iteration` count stays task-global, as today).
559
+ `--step=<N>` flag (the `iteration` count stays task-global, as today; an
560
+ all-at-once single-group pass — pre-commit review ON's pre-gate review —
561
+ omits `--step`, per the events schema).
341
562
 
342
563
  5. **`progress.md` step log** — keep the sub-state explicit so `/resume` can re-enter
343
564
  mid-loop. Under a `## Step log` heading, one line per resolved step; the **open**
344
565
  step's line is transient — update it in place as the loop progresses
345
566
  (`fix-loop iteration K — in progress` while implementing/reviewing,
346
- `awaiting human checkpoint (step N/M)` while waiting on the human), then replace it
347
- with the resolved outcome:
567
+ `awaiting ledger retry (step N/M, retry 1/1)` while the fresh Reviewer redoes a red
568
+ ledger, `awaiting human checkpoint (step N/M)` while waiting on the human), then
569
+ replace it with the resolved outcome:
348
570
 
349
571
  ```markdown
350
572
  Mode: step-by-step
351
573
 
352
574
  ## Step log
353
575
 
354
- - step 1/6 — review ×1 → checkpoint: OK
355
- - step 2/6 — review ×3 (2 rejects: missing error path; flaky spec) → checkpoint: changes → review ×1 → checkpoint: OK
356
- - step 3/6 — awaiting human checkpoint (step 3/6)
576
+ - step 1/6 (anchor a1b2c3d) — review ×1 → checkpoint: OK
577
+ - step 2/6 (anchor e4f5a6b) — review ×3 (2 rejects: missing error path; flaky spec) → checkpoint: changes → review ×1 → checkpoint: OK
578
+ - step 3/6 (anchor c7d8e9f) review ×2 (ledger retry ×1) — ledger: criteria 3/3 (basis: requirements), gates 2/2 (basis: config) → checkpoint: OK
579
+ - step 4/6 (anchor f1a2b3c) — awaiting human checkpoint (step 4/6)
357
580
  ```
358
581
 
359
- Those two transient sub-state strings are exactly what a later `/resume` re-enters
582
+ Those transient sub-state strings are exactly what a later `/resume` re-enters
360
583
  on: the awaiting line re-presents the pending checkpoint, the fix-loop line
361
- re-enters the implement→review loop at that iteration.
584
+ re-enters the implement→review loop at that iteration, and the ledger-retry line
585
+ says the single retry is already spent. The `(anchor <oid>)`
586
+ field is the OID step 1 recorded — the checkpoint contract and the per-step
587
+ Reviewer diff against it.
362
588
 
363
- After the **last task**, rejoin the normal flow unchanged (L1 step 8): flip to
589
+ After the **last group**, rejoin the normal flow unchanged (L1 step 8): flip to
364
590
  `in-review`, open the PR, and run the **full-pass Reviewer** over everything against
365
- the spec. The full-pass may reject anything, **including human-OK'd tasks** — a
591
+ the spec. The full-pass may reject anything, **including human-OK'd steps** — a
366
592
  checkpoint OK means "right direction and it runs", not a review waiver; the full-pass
367
593
  wins, and the human still holds the merge gate to disagree.
368
594
 
595
+ **Every full-pass APPROVE is ledger-validated too** — the step-8 review in either mode,
596
+ pre-commit review ON's single-group pre-gate pass, and a re-APPROVE after the merge gate
597
+ or PR comments sent the PR back to review. The Reviewer writes `full-pass.json` (no step
598
+ number → the union of every group); you run
599
+ `lemony review-ledger validate --task-id=<id> --anchor=<merge-base> --full-pass` —
600
+ the merge-base of the freshly fetched base and the PR head, the Diff-fingerprint's
601
+ own OID (L1 step 8; pre-commit review ON's pre-gate pass instead anchors at the OID
602
+ you recorded when its single group started) — and route a red exactly as
603
+ in step 2 above: one fresh Reviewer retry with the lines verbatim, a second red or any
604
+ spec-side problem to the human, and never an APPROVE relayed on a red ledger. Outside
605
+ the step loop the transient line is `awaiting ledger retry (full pass, retry 1/1)` in
606
+ `progress.md` (no step counter), and "the human" is the gate the pass feeds: the
607
+ pre-commit-ON checkpoint when there is one, otherwise the merge-gate presentation,
608
+ with the verb's lines as the content.
609
+
610
+ ## Checkpoint contract (how a human gate presents work)
611
+
612
+ Every human checkpoint — per-group in step-by-step, and the single all-at-once gate
613
+ when pre-commit review is ON — presents the same way. "Present the step" is a
614
+ contract, not a vibe:
615
+
616
+ 1. **Anchored scope.** The group's **anchor** — the branch head OID recorded when
617
+ the group started (= the end of the previous approved group; the head at
618
+ implementation start when no group has yet been approved — group 1, or an
619
+ all-at-once run; an all-at-once run that began as a mid-task downgrade anchors
620
+ at the head after the last OK'd group) — bounds exactly what is
621
+ under review. Present the commit list + touched-files table, then the **exact
622
+ group diff**, always excluding task state:
623
+ - OFF: `git log --oneline <anchor>..HEAD` +
624
+ `git diff --stat <anchor>..HEAD -- ':(exclude).claude/state'`,
625
+ then `git diff <anchor>..HEAD -- ':(exclude).claude/state'`;
626
+ - ON (nothing committed):
627
+ `git diff --stat <anchor> -- ':(exclude).claude/state'`, then
628
+ `git diff <anchor> -- ':(exclude).claude/state'` — staged new files are in
629
+ the index, so they appear.
630
+ 2. **The inline rendered diff is the universal floor.** Probe the environment: when
631
+ a difftool is configured (or an extension like GitLens is present), **offer**
632
+ the richer side-by-side view — an ephemeral config works without touching the
633
+ repo's (`git -c diff.tool=<tool> difftool <range>`). Never assume an extension
634
+ exists. In ON the Source Control panel already shows the work natively — it IS
635
+ uncommitted.
636
+ 3. **What was built and how to run it** — from the Implementer's verification line,
637
+ as today. Checkpoint narration is the product, never overhead (§Turn economy).
638
+ 4. **The human delta — always detected, always revalidated.** Whatever the answer
639
+ (`ok` or `changes: …`), first detect the human's own edits — in ON, **two
640
+ checks with distinct routes** (every agent save-point is staged at
641
+ presentation time, so the staged/unstaged seam is the auto-detect):
642
+ - **Work delta**: the unstaged section outside task state —
643
+ `git diff -- ':(exclude).claude/state'` **plus untracked files outside
644
+ `.claude/state`** (from `git status --porcelain`; `git diff` never shows a
645
+ file the human created). Your own disk-only `progress.md` edits sit
646
+ unstaged under `.claude/state` by design — agent noise, never a human
647
+ delta.
648
+ - **Spec check**: unstaged edits **or untracked files** under the spec —
649
+ `git diff -- .claude/state/tasks/<id>/spec/` plus the untracked (`??`)
650
+ porcelain entries
651
+ under that path (a human-created spec file is untracked and invisible to
652
+ the diff). A hit is **not** a work
653
+ delta: it changes the approved spec, so route it as a **discovery**
654
+ (§Discovery mediation) before the checkpoint resolves. The Spec Author —
655
+ the spec's owner — applies the resolution to the file (restoring it if the
656
+ human's interpretation is rejected), then **re-present this checkpoint**;
657
+ only after that may any commit run, so `git add -A` lands the resolved
658
+ spec, never an unconfirmed unstaged edit. **Mediated changes are staged on
659
+ arrival and never re-raise**: whenever a discovery resolution is applied
660
+ mid-task — the Spec Author's spec update, an Architect artifact — stage it
661
+ immediately (`git add` the touched paths). Resolved artifacts join the
662
+ agent-staged floor, so this check fires only on **unmediated** edits and
663
+ the re-presented checkpoint is clean; an unstaged edit that matches the
664
+ recorded `**Resolution**` in `discoveries.md` is confirmed content — stage
665
+ it, don't re-raise.
666
+
667
+ The **spec check runs in both knob states** — in OFF, run it **before** step
668
+ 3's `awaiting` state commit, which would otherwise silently commit a
669
+ pre-existing spec edit before detection. OFF's work-delta detection is
670
+ simply any uncommitted working-tree change.
671
+ The **work delta** then runs the pipeline: present it, confirm it is
672
+ intended, and **re-run the suite with the delta applied** — the delta never
673
+ inherits the group's green. **A red revalidation blocks the OK**: never run
674
+ the commit composite on a red suite — re-present the failure and route it as
675
+ `changes` (the human decides: fix it themselves, drop the delta, or hand it
676
+ to the Implementer). On a green revalidation the delta rides with the group:
677
+ on OK it lands with
678
+ the group's work (ON: staged into the group's commit; OFF: committed as its
679
+ own commit — `step(<id>): step <N> human delta` — before the next group); on
680
+ `changes` it stays in the worktree for
681
+ the fresh Implementer (ON: staged first as the safe starting point —
682
+ §Pre-commit review ON).
683
+
684
+ ## Pre-commit review ON (zero commits + staging save-points)
685
+
686
+ The knob's ON state (chosen at the approval gate — §Implementation mode) moves
687
+ **when the branch first receives commits**; review, fix-loop routing, and the merge
688
+ gate are unchanged. v1 is deliberately an experiment — the watch-fors below are its
689
+ pre-registered exit signals.
690
+
691
+ - **Zero commits; staging save-points.** The Implementer never commits: it stages
692
+ after every green task (`git add -A`) and **never stages mid-experiment** — the
693
+ staging protocol in `implementer.md`, which the spawn prompt must point at
694
+ explicitly (it inverts the tdd add-early reflex, and a fresh Implementer only
695
+ knows what the contract and the branch tell it). A failed experiment rolls back
696
+ with `git restore . && git clean -fd`: the worktree returns to the last green
697
+ save-point; staged content survives verbatim, including new files.
698
+ - **Everything is deferred** until the human OK: no code commits and **no state
699
+ commits** either — the checkpoint's `awaiting` state commit + push do not run;
700
+ `progress.md` updates on disk only. The documented price, accepted at the
701
+ grill: **no multi-machine durability** during implementation and during the
702
+ checkpoint wait (the flow's longest, where a session likeliest dies) — a cold
703
+ `/resume` from another machine sees nothing pending. (One exception: a
704
+ discovery pause **is** visible cross-machine — its labels and issue comment
705
+ surface — but the full `discoveries.md` entry stays machine-local until an OK
706
+ lands it.) Same-machine resume reads the worktree as usual.
707
+ - **The gate** runs at end of group (step-by-step) or end of everything
708
+ (all-at-once — after the Implementer signals done and **before** the
709
+ `in-review` flip: the PR never opens on uncommitted work). In all-at-once the
710
+ whole implementation is the **single group** and the per-group machinery
711
+ applies to it: the mid-implementation Reviewer runs over the anchored diff
712
+ **before** the gate — nothing reaches the human unreviewed, in either mode —
713
+ and the `changes` fix-loop carries the same 3-reject cap into an anticipated
714
+ checkpoint (whose `step_completed` clause and `step N/M` strings apply only
715
+ in step-by-step — in all-at-once the no-emit rule below wins and the awaiting
716
+ line drops the step counter). Its APPROVE is ledger-validated with `--full-pass`
717
+ and `--anchor=<oid>` — the anchor you recorded when its single group started
718
+ (§Step-by-step implementation, after the last group), never relayed on a red.
719
+ Hand that pre-gate Reviewer the anchor, the ON
720
+ flag, and "the whole `tasks.md` as the single group" in place of a group id.
721
+ All agent work is
722
+ staged at presentation time; present per §Checkpoint contract. The human
723
+ inspects the work natively in the Source Control panel and edits/discards
724
+ directly in the worktree; answers are `ok` / `changes: …` (step-by-step keeps
725
+ its third answer, OK-and-downgrade).
726
+ - **OK ⇒ commit + push, after revalidating.** Re-run the suite over the final
727
+ worktree (human delta staged in) — the gate's green is fresh, never inherited.
728
+ Then the deferral ends as **one composite turn**, splitting the mixed index by
729
+ pathspec (`git add -A` staged code and task state together; a bare
730
+ `git commit` would swallow both into one commit):
731
+
732
+ ```bash
733
+ git add -A && \
734
+ { git diff --cached --quiet -- . ':(exclude).claude/state' || \
735
+ git commit -m "<code-msg>" -- . ':(exclude).claude/state'; } && \
736
+ { git diff --cached --quiet -- .claude/state || \
737
+ git commit -m "<state-msg>" -- .claude/state; }; \
738
+ git push # best-effort — a failure warns, never blocks
739
+ ```
740
+
741
+ Each commit is **guarded on its half of the index holding changes**, so a
742
+ degenerate group no-ops that half instead of short-circuiting the other: a
743
+ state-only OK (an audit group whose artifact is progress notes, or a human who
744
+ discarded the work in the worktree and answered `ok`) still lands its state
745
+ commit — an unguarded `&&` chain would silently drop it while the push still
746
+ ran, leaving the resolution nowhere on the branch.
747
+
748
+ Step-by-step: `<code-msg>` = `step(<id>): step <N>`, `<state-msg>` =
749
+ `step(<id>): step <N> checkpoint OK`, and the `step_completed` emit rides the
750
+ same turn (step 4). All-at-once (a downgraded remainder resolves as
751
+ all-at-once here too): `<code-msg>` = `task(<id>): implementation`,
752
+ `<state-msg>` = `task(<id>): pre-commit gate OK`, and **nothing is emitted** —
753
+ `step_completed` is step-by-step-only (its `--step` has no meaning here, and
754
+ closeout's mode recovery reads any `step_completed` as proof of step-by-step);
755
+ the gate resolution reaches telemetry through `task_done` as usual. One commit
756
+ per group in v1; all-at-once commits the whole implementation as its single
757
+ group.
758
+
759
+ - **Changes ⇒ the Implementer iterates over the worktree.** Same routing as any
760
+ rejection (fresh context, ≤3 rejects per step): it first **stages the
761
+ revalidated human delta** (its suite result rides in the feedback) as its
762
+ safe starting point, then continues
763
+ under the staging protocol. Nothing is committed; the deferral continues.
764
+ - **Watch-fors — pre-registered failure signatures.** v1 tests in real use whether
765
+ the three roles of tdd commits (fresh-Implementer memory via the branch,
766
+ granular save-points, 1:1 per-task history) are missed. If one fires, don't
767
+ improvise: **surface it at the checkpoint and record it in `progress.md`** so
768
+ the human can decide the swap to the pre-designed fallback — _deferred push_
769
+ (local tdd commits exactly as today but unpublished; the OK becomes the push:
770
+ commit = internal memory, push = publication). The signatures:
771
+ 1. **Fix-loop memory** — iteration 2 redoes or overwrites iteration 1's work.
772
+ 2. **Save-point residual** — a mid-experiment `git add` silently destroyed the
773
+ save-point (`git status` looks identical; recovery yields nameless blobs),
774
+ or single-level undo proves insufficient (e.g. selectively reverting task
775
+ N−2).
776
+ 3. **PR narrative** — one commit per group cannot reconstruct the per-task
777
+ `step(<id>): step <N>` story.
778
+
369
779
  ## Discovery mediation
370
780
 
371
781
  Any sub-agent (Spec Author, Implementer, Reviewer, Architect) may stop mid-task and
@@ -380,103 +790,15 @@ When you get that summary, run the **`resolve-discovery`** skill. It pauses the
380
790
  `paused_from`), has you arbitrate the question with the human, routes the artifact
381
791
  update to its owner (the agent that created it), records the resolution in
382
792
  `discoveries.md`, clears the discovery flag, restores the status, and re-invokes the
383
- paused sub-agent with the decision. You are the only one who talks to the human and
384
- moves labels never let a sub-agent self-resolve.
385
-
386
- ## Mid-task capture (`/spinoff` offer)
387
-
388
- While you (the hat) are driving the conversation between sub-agent dispatches, at
389
- gates, in ordinary back-and-forth the human will sometimes mention an **independent,
390
- non-blocking** defect: one the current task does **not** need to touch, and that doesn't
391
- have to be fixed now ("oh, the export button is also broken on Safari"). Don't let it
392
- evaporate and don't context-switch to it: **offer to spin it off**. The discriminator is
393
- _independence_ — is this something the current task touches anyway?
394
-
395
- This is distinct from three neighbours:
396
-
397
- - **Just fix it** — if the defect is **in scope for the current task** (something this
398
- change already touches), fix it in the current PR. No offer, no stub — spinning off
399
- in-scope trivia only pollutes the backlog.
400
- - **T3 SCOPE_DRIFT** (discovery) — when completing **the current task** _forces_ you to
401
- touch out-of-scope work (the task can't finish without it). That pauses via
402
- `resolve-discovery`. `/spinoff` is the opposite: the current task doesn't need the
403
- defect touched, so it never pauses and keeps going.
404
- - **`/define`** — a feature _idea_, not a defect. Route those to DEFINE, not `/spinoff`.
405
-
406
- Calibration — **lean toward offering** so nothing slips, but keep it
407
- frictionless and noise-free:
408
-
409
- - Offer only when you'd bet it's a **genuine, independent defect worth a tracked issue**
410
- — not for every stray observation, and not for anything you can fix in place. When in
411
- doubt _whether to track a real independent defect_, lean toward offering; when in doubt
412
- _whether it's even a real, independent bug_, stay quiet.
413
- - The offer is a **single line**, in the human's language: _"This looks like an
414
- independent bug — want me to `/spinoff` it and keep going?"_ One tap to dismiss; if the
415
- human says no, drop it and continue without comment.
416
- - **Never re-offer the same finding twice in a session.** "Same finding" = the same
417
- underlying defect even if re-described; when unsure, treat a clearly new symptom as new.
418
- This rule is the **only** human-side dedup (the capture verb is non-idempotent by
419
- design — each run opens a fresh stub), so honor it.
420
- - The offer **never pauses** the current task and never blocks on a reply — if the human
421
- ignores it and keeps working, so do you.
422
-
423
- On **accept**, capture it exactly as the `/spinoff` command does — the `spinoff` CLI
424
- verb via the launcher, with the **current task's id** as the parent (recover it the same
425
- way `/spinoff` does — from the `harness/<id>-…` branch or active task state; omit
426
- `--parent` if there is no active task):
427
-
428
- ```bash
429
- .claude/hooks/lib/lemony.sh spinoff \
430
- --title="<one-line symptom>" \
431
- --body="<where it was seen; a code pointer if you have one>" \
432
- --parent=<current task id> \
433
- --severity=<low|medium|high|critical>
434
- ```
435
-
436
- Stub creation is **fail-loud** (a non-zero exit means it did not open — surface it, don't
437
- pretend it was captured); the telemetry emit is **best-effort** (a `Warning:` means only
438
- the event failed, the stub stands). Relay the verb's own `Captured #<id>…` line (it
439
- carries the parent link) and **return to the current task**. The stub waits in the backlog as `harness:status:pending`
440
- for a later pickup. The human can also trigger this directly with the `/spinoff` command;
441
- the offer is the safety net for when they don't remember it mid-flow.
442
-
443
- ### From a sub-agent (the side-finding channel)
444
-
445
- The same offer applies when the source is **not the human but a sub-agent's return
446
- summary**. A sub-agent runs in fresh context and cannot interrupt you, so when it spots a
447
- defect that is **independent of its task** (the task finished fine without touching it) it
448
- **notes it instead of pausing** — that is the `note-side-finding` skill, the non-pausing
449
- sibling of `raise-discovery`. It appends a `## Side-findings` block to its summary, one
450
- bullet per finding (`symptom` / `location` / optional `severity`), and keeps working. (A
451
- **blocking** defect is the opposite case — the sub-agent raises a T1–T6 discovery and
452
- stops; you handle that with `resolve-discovery`, above.)
453
-
454
- When you **read back a sub-agent's summary**, scan for a `## Side-findings` block. For each
455
- bullet, make the **same single-line `/spinoff` offer** as for a human-mentioned defect —
456
- pre-filled from the bullet (`--title` ← symptom, `--body` ← location, `--severity` ← the
457
- read if given), the active task as `--parent`. Same calibration applies verbatim: lean
458
- toward offering, one-tap dismissal, **never re-offer the same finding twice** (a
459
- sub-agent's finding and a later human mention of the same defect are the _same_ finding),
460
- and it **never pauses** the task. A side-finding is a candidate for the offer, not an
461
- auto-capture — you still make the call and the human still decides.
462
-
463
- A bullet tagged **`kind: drift`** is `docs/architecture.md` map staleness,
464
- not a code defect: add **`--kind=architecture-drift`** to the `/spinoff` so the stub carries
465
- the `harness:architecture-drift` routing label and a later pickup resolves it via the
466
- Architect's `update-architecture` (a targeted map-fix), not a code change. **Fallback:** if
467
- `update-architecture` is not installed (the project keeps no `architecture.md`), drop the
468
- `--kind` and capture it as a generic stub — never let the offer fail because the routing
469
- target is absent.
470
-
471
- Two things you own because the sub-agent can't: **(1) cross-round dedup.** A sub-agent
472
- re-invoked with fresh context (e.g. a Reviewer you rejected and re-ran) has **no memory of
473
- what it side-noted before** and will re-emit the same `## Side-findings` block every round.
474
- You hold the continuous context, so dedup is yours: an identical or re-described bullet
475
- from a later round is the _same_ finding — don't re-offer it. **(2) gate ordering.** When
476
- the read-back lands at a gate (a Reviewer returns right before the merge gate), make the
477
- side-finding offer **after** the gate prompt, never before — the gate decision is primary;
478
- the offer trails it as a secondary, dismissable line so it never splits attention at the
479
- high-stakes moment.
793
+ paused sub-agent with the decision. A discovery can also be raised by **you** (e.g. a
794
+ checkpoint "changes" request that contradicts the spec): the same skill runs, with
795
+ nothing to re-invoke — the resolution re-enters the loop where it paused. You are the
796
+ only one who talks to the human and
797
+ moves labels — never let a sub-agent self-resolve. An **oversize** discovery — the Spec
798
+ Author or the Implementer finds the scope hides ≥2 independently mergeable units the PRD
799
+ didn't reveal is a T2 raised and mediated exactly like this; when the human answers
800
+ "partition", read `.claude/agents/partition.md` for the parent/part mechanics (the
801
+ current task keeps the first unit).
480
802
 
481
803
  ## Architect (on-demand)
482
804
 
@@ -505,184 +827,98 @@ Dispatch it (fresh context, Task tool) when:
505
827
  - **Orientation is needed** — before a decision or spec in a large or unfamiliar
506
828
  codebase, dispatch it with `code-explorer` for a read-only map.
507
829
  - **Closeout — the Architect's reliable activation checkpoint** — the `task-closeout`
508
- skill drives durable capture at the end of every task, in cold blood, where the
509
- discretionary triggers otherwise lose to "unblock the paused sub-agent". Three
510
- activations, **asymmetric by design**: `write-adr` (HITL
511
- offer per resolved discovery — net-new canon, the human curates it), `update-architecture`
512
- (**automatic** dispatch when `docs/architecture.md` exists — the map must _track reality_,
513
- reviewed in the closeout PR diff, no pre-offer), and `playbook-iterate` (HITL offer once
514
- per task catches a reusable pattern no `T6` conflict already routed). Each no-ops when
515
- its skill isn't installed. See §Closeout and `task-closeout`.
516
-
517
- Give it the context (the discovery entry + its resolution, the change, or the request)
518
- and read back its summary. The Architect is **not a gate** — it produces an artifact and
830
+ skill drives three durable-capture activations at the end of every task, in cold
831
+ blood, where the discretionary triggers otherwise lose to "unblock the paused
832
+ sub-agent". The full list and its asymmetry live in §Closeout.
833
+
834
+ Give it the context — the branch when no PR exists yet, the `discoveries.md` entry
835
+ by path with the decision (**in full** pre-record `resolve-discovery` step 3
836
+ its gist once recorded), the change or the human's request as a synthesized delta
837
+ (§Sub-agent invocation) and read back its summary. The Architect is **not a gate** — it produces an artifact and
519
838
  reports; it never moves the status machine. If it reports that the trigger didn't
520
839
  warrant the artifact (an ADR that fails the three tests, a change that isn't
521
840
  architecturally significant, a "playbook" change that's really project-specific), record
522
841
  that and move on — no artifact is forced.
523
842
 
524
- ## UI design (DEFINE + REVIEW)
525
-
526
- UI design threads into an L1 task that touches UI — never a linear step. **The interactive
527
- design interview is yours**: a sub-agent can't talk to the human, so at DEFINE **you** run
528
- the `grill-ui` skill on your human-facing surface and author the `ui-handoff.md` contract.
529
- The **UI Designer** sub-agent — always installed, invoked **on-demand**, your only invoker —
530
- is your design **critic and QA**: at DEFINE it reviews the handoff you just authored (before
531
- the Spec Author runs); at REVIEW it runs a mechanical pre-pass (the deterministic
532
- `design-tokens` gates + the project's a11y tooling) then the `design-critique` and
533
- `a11y-audit` judgment lenses, and returns one design verdict. You own the human dialogue, the
534
- `ui-handoff.md` artifact, and the labels; it critiques and reports.
535
-
536
- A third, on-demand affordance sits outside those two moments: **design-tool token sync**.
537
- When the human runs `/sync-design-tokens` (or accepts the DEFINE offer when a drift check
538
- shows an export is pending), dispatch the UI Designer to run its `design-tool-sync` skill.
539
- It is human-reviewed both ways and tokens-only; the design tool is a projection of
540
- `docs/design-tokens.json`, never a peer source of truth.
541
-
542
- ### Activation gate
543
-
544
- After the grill produces the PRD and the task issue exists, judge — **your own LLM
545
- call**, no runtime keyword scorer — whether this task needs design, as **two parts both
546
- true**:
547
-
548
- 1. **The repo has a frontend** — there is UI to design (a SPA/app surface, components,
549
- styles), not a pure library / CLI / backend.
550
- 2. **This task touches UI** — the change adds or alters something a user sees or
551
- interacts with.
552
-
553
- **Bias to include** on a borderline call: a wasted handoff stub is cheaper than UI
554
- shipped with no design pass. When both hold, the task needs design.
555
-
556
- ### Design-stop offer
557
-
558
- When the gate fires, **put `harness:needs-design`** on the issue and offer the human,
559
- inline, in one line — three choices:
560
-
561
- > This task touches UI. (1) **Continue** — define the design now, as part of the spec;
562
- > (2) **Stop for handoff** — park here so a designer picks it up later; (3) **No UI after
563
- > all** — skip design.
564
-
565
- - **Continue** → **run `grill-ui` yourself** — the interactive design interview on your
566
- human-facing surface — authoring `ui-handoff.md` under `tasks/<id>/spec/`. Then dispatch
567
- the **UI Designer** (fresh context, Task tool) with the `<id>` and branch to **critique**
568
- the handoff, and resolve its findings before the Spec Author runs. The issue stays at
569
- `harness:status:spec-in-progress` — design is part of completing the spec, not a new
570
- lifecycle state.
571
- - **Stop for handoff** → record the sub-state `awaiting design definition` in
572
- `progress.md`, commit and push the task state to the branch, and stop. The task waits
573
- at `spec-in-progress` (+ `harness:needs-design`) for a `/resume` (below).
574
- - **No UI after all** → **remove `harness:needs-design`** and proceed with the ordinary
575
- spec flow — the gate was a false positive, which bias-to-include accepts.
576
-
577
- ### Persisting personas (offer)
578
-
579
- `docs/personas.md` is **client-owned** — the harness consumes it, never imposes it. When your
580
- `grill-ui` interview captured personas **inline** because `docs/personas.md` was **absent** (§1
581
- of the handoff), make the offer — a human-facing choice, so it is yours:
582
-
583
- > The design defined these personas inline. Persist them to `docs/personas.md` so future UI
584
- > tasks reuse them? (yes / no)
585
-
586
- - **Yes** → write a minimal `docs/personas.md` from the personas already in the handoff's §1
587
- — the client's own words, not an invented cast. Then continue toward spec-ready.
588
- - **No** → write nothing; the inline personas live on in the handoff for this task. The next
589
- UI task simply asks again.
590
-
591
- Only offer when the file was **absent and personas were captured inline** — never when
592
- `docs/personas.md` already exists (it was consumed, nothing to persist) and never unasked.
593
- This is opt-in surfacing of the client's own answers, not the harness authoring a persona set.
594
-
595
- ### Design-tokens & design-tool on-ramp (offer)
596
-
597
- `docs/design-tokens.json` and a design-tool connection are **client-owned inputs** — consumed if
598
- present, never imposed. A repo adopting the harness fresh has neither, and silence there is a dead
599
- end. So when your `grill-ui` interview finds **either absent**, surface it as an opt-in offer (a
600
- human-facing choice, so it is yours) rather than only an open question:
601
-
602
- - **No `docs/design-tokens.json`** → offer to **scaffold** a starter token set derived from the
603
- direction the interview just settled (the client's own colours/type/spacing, not a vendor
604
- template), plus an opt-in follow-up to generate a sensible starter set for the aspects the
605
- interview didn't cover. On **yes**, write the file and run `lemony design-tokens validate` before
606
- closing; on **no**, capture it as an open question.
607
- - **No `com.lemony.design-tool` binding** → offer to **connect a design tool** (write the binding +
608
- first import via the UI Designer's `design-tool-sync` skill / `/sync-design-tokens`), or **stay
609
- pure-code**. Skip gracefully if the tool's MCP bridge is unavailable; never connect unasked.
610
-
611
- The mechanics live in the `grill-ui` skill; you run the offers on your human-facing surface. Only
612
- offer when the input is **absent** — never re-offer a token file or binding that already exists.
613
-
614
- ### Label put/remove
615
-
616
- `harness:needs-design` is an **orthogonal presence flag** (same family as
617
- `harness:architecture-drift`), never a status:
618
-
619
- - **Put** it as soon as the gate classifies the task as touching UI and design is not
620
- yet complete.
621
- - **Remove** it the moment `ui-handoff.md` is **complete** — at or before the flip to
622
- `harness:status:spec-ready`. **Complete** = the handoff carries **this task's** design
623
- decisions (its sections hold real content, not the verbatim placeholder template), the UI
624
- Designer's critique **passed** (or you resolved its findings), and **no** open design fork
625
- remains (an open fork means design is still open — keep the label and resolve it first).
626
- Ensure the label is gone **before** flipping to `spec-ready`: a spec-ready task never
627
- carries `harness:needs-design`.
628
-
629
- ### `awaiting design definition` sub-state + /resume re-entry
630
-
631
- A task parked at "stop for handoff" sits at `harness:status:spec-in-progress` with
632
- `progress.md` recording the sub-state `awaiting design definition`. It is the design
633
- analogue of the step-by-step `awaiting human checkpoint` line — execution state, not a
634
- label. `/resume <id>` re-enters there: check out the branch, read the captured context,
635
- resume the `grill-ui` interview yourself to finish `ui-handoff.md`, dispatch the UI Designer
636
- to critique it, then remove `harness:needs-design` and continue toward spec-ready. The resume
637
- queue surfaces the parked design (`resume.md` lists `spec-in-progress` too).
638
-
639
- ### REVIEW — the design lens
640
-
641
- When an implemented UI change reaches review (L1 step 8), invoke the **UI Designer** as
642
- a **distinct lens** alongside the Reviewer (code). The **durable "this task touched UI"
643
- signal is the existence of `tasks/<id>/spec/ui-handoff.md`** — `harness:needs-design` is
644
- already gone by spec-ready, so it can't be the cue; the handoff artifact persists and
645
- survives a cold `/resume`, so it is what to check. Either lens rejecting routes back to
646
- the Implementer (rejection is transient — no dedicated label); both passing reaches the
647
- single human merge gate (two inputs, one gate).
648
-
649
- The UI Designer's lens mirrors the Reviewer's own shape — a **mechanical pre-pass** (the
650
- deterministic `design-tokens validate` + `design-tokens contrast` gates, plus the
651
- project's a11y tooling), then **judgment** (`design-critique` + `a11y-audit`), returning
652
- **one design verdict** with findings grouped by source (tokens / accessibility / craft).
653
- The Reviewer's code lens stays design-unaware; you still see exactly two review inputs.
654
-
655
- **Deterministic vs judgment, by level.** The two deterministic gates are cheap, agent-free
656
- facts, so they run **per-step** on UI-touching steps in step-by-step mode (a bad contrast
657
- in step 2 must not ride to step 6 — see §Step-by-step implementation); the project's a11y
658
- lint rides the per-step lint the same way. The **judgment lenses run full-pass only** —
659
- design is holistic, and a mid-component critique is noise. There is no per-step design
660
- agent and no new cap: a full-pass design rejection routes back like any other rejection.
661
- (`design-tokens validate` / `contrast` also run in CI independently of review.)
662
-
663
- ### Closeout
664
-
665
- `ui-handoff.md` lives in `tasks/<id>/spec/`, so closeout archives it with the rest of
666
- the spec (`task-closeout` `git mv`s the whole `spec/` into `_archive/<id>/`) — no
667
- special handling.
668
-
669
843
  ## Merge gate (`in-review → merged`)
670
844
 
671
845
  When the Reviewer approves, **do not merge automatically.** Merging the PR is the one
672
- action that touches the default branch it may trigger CI and deploys — so it stays a
673
- human decision. Surface it and wait:
846
+ action that touches the default branch, so it stays a human decision. Surface it and
847
+ wait:
674
848
 
675
849
  > Reviewed and approved — PR #<pr> is here: <url>.
676
- > (1) merge it yourself, (2) I'll merge it (`gh pr merge`), or
850
+ > (1) merge it yourself, (2) I'll merge it once checks are green (`gh pr merge`), or
677
851
  > (3) run `/review-pr` first for a curated inline pass.
678
852
 
679
- The task stays at `harness:status:in-review` while it waits there is no
680
- "approved-awaiting-merge" rung between review and merge (the `closeout-pending` status is
853
+ A **stacked partition child** reaches this gate only once its PR base is the default
854
+ branch check `baseRefName` first and retarget/merge-in per `.claude/agents/partition.md`;
855
+ never merge a part into a sibling's branch. The task stays at `harness:status:in-review`
856
+ while it waits — there is no "approved-awaiting-merge" rung between review and merge (the `closeout-pending` status is
681
857
  **post**-merge, for a parked closeout record PR — not this gate). When the
682
858
  human merges (in the GitHub UI, by CLI, or by authorizing you to run `gh pr merge`),
683
859
  proceed to closeout. **GitHub is the source of truth for the merge, not this
684
860
  conversation** — closeout confirms it via `gh pr view`.
685
861
 
862
+ ### Executing an authorized merge — the checks precondition
863
+
864
+ "Merge it" is a **conditional authorization**: the agent merges _when it is safe to do
865
+ so_, not an order to execute immediately. The human's yes carries the implicit
866
+ assumption that CI is fine; this contract makes that assumption an explicit
867
+ precondition. Not green ⇒ you never merge on your own — you re-present this gate with
868
+ the real state. (The failure pattern this kills: nobody _decided_ to merge on red — an
869
+ authorization whose background assumption was false got executed without looking.)
870
+
871
+ So never run a bare `gh pr merge`. Execute the merge through the shared executor, which
872
+ verifies the check status the platform reports for the PR and waits — bounded — for
873
+ pending checks (`merge.checks_timeout_secs` in `harness.config.yml`, default ~10 min).
874
+ For a task PR, always pass `--approve-issue` with the task's issue number — that arms
875
+ the **stale-approve guard**: the executor reads the Reviewer's APPROVE record
876
+ (`Reviewed-tree` / `Diff-fingerprint`) from that issue and refuses to merge content
877
+ that no longer matches what the APPROVE reviewed (a clean update-branch stays valid;
878
+ any content change does not):
879
+
880
+ ```bash
881
+ .claude/hooks/lib/merge-pr.sh <pr> --approve-issue <issue> --squash # merge-strategy flags pass through to `gh pr merge`
882
+ ```
883
+
884
+ Act on its exit code:
885
+
886
+ - **0 — merged.** Proceed to closeout.
887
+ - **10 — checks red.** Never merge on red by omission. Re-present the gate with the
888
+ failure: "checks red: <check> fails — merge anyway / wait / want to look at it?".
889
+ Merging on red stays possible, but only as the human's informed decision — on that
890
+ explicit yes, re-run with `--force`.
891
+ - **30 — still pending after the bound.** The authorization never expires silently; it
892
+ expires by asking: "checks still running after <N> min — keep waiting, or leave it
893
+ and I'll tell you when they settle?". "Keep waiting" = re-run the executor (a fresh
894
+ bound, or a longer one via `--timeout-secs <secs>`).
895
+ - **40 — stale approve: the PR content changed after the review.** A push landed in
896
+ the merge-gate window (another dev, a re-invoked implementer) and the diff no longer
897
+ matches what the APPROVE reviewed. Never merge it on the old verdict: route the PR
898
+ back to the Reviewer — the same back-to-review route as the comments path below; a
899
+ fresh APPROVE re-records the hashes — then re-surface this gate. Merging anyway
900
+ stays possible, but only as the human's informed decision — on that explicit yes,
901
+ re-run with `--force` (which skips the checks precondition too: make sure the
902
+ informed yes covers both).
903
+ - **20 — no checks reported (after the grace window).** Never merge alone, whatever the
904
+ cause — repo with no CI, CI outage, path filters: don't try to auto-classify. Ask:
905
+ "I saw no checks available on this PR — merge?". If the human's answer is standing
906
+ ("this repo has no CI — merge without checks"), record it **now** as
907
+ `merge.allow_no_checks: true` in `harness.config.yml` (the executor reads the working
908
+ tree, so no later merge — including this task's closeout — re-asks); the line lands
909
+ on the base with the closeout record PR's commit, never a direct push. For the merge
910
+ at hand, re-run with `--force`.
911
+ - **1 (or any other non-zero)** — not merged, and **not a verdict**: either the check
912
+ status could not be read (`gh`/auth/network failure — the precondition is
913
+ unverifiable, which is _not_ the same as "checks failed") or the merge attempt itself
914
+ was rejected (branch protection wants approval, a conflict, a bad ref). The
915
+ executor's stderr says which — surface that, verbatim, at the gate.
916
+
917
+ The precondition is platform-neutral by design — "the merge executor verifies the check
918
+ status the platform reports for the PR"; `gh` is the GitHub rendering of it. Branch
919
+ protection is the user's belt: the harness executes merges and cannot assume it is
920
+ configured, so the executor carries its own precondition either way.
921
+
686
922
  ### When the human leaves review comments instead of merging
687
923
 
688
924
  The human may respond at this gate not by merging but by **leaving comments on the PR**.
@@ -697,7 +933,14 @@ of an `in-review` task surfaces the open PR's comments and routes here — see
697
933
  route as a Reviewer rejection: re-invoke the Implementer sub-agent (fresh context)
698
934
  with the feedback (transient, no dedicated label). Skip pure acknowledgements or
699
935
  questions that need no code.
700
- 3. **After the fix commit, draft do not auto-post the replies.** Compose a short
936
+ 3. **Route the fixed PR to re-review.** The fix commits are new, unreviewed content
937
+ the Reviewer's standing APPROVE no longer covers them (and the executor's
938
+ stale-approve guard would refuse the merge with exit 40 anyway). Invoke the
939
+ Reviewer on the updated PR (continued re-review of its own findings when the
940
+ comments echo them; fresh otherwise); an approving verdict posts a fresh APPROVE
941
+ with fresh hashes. A reject routes back to step 2 — never draft "done" replies on
942
+ work that hasn't re-passed review.
943
+ 4. **After the re-APPROVE, draft — do not auto-post — the replies.** Compose a short
701
944
  "done ✅" reply threading each addressed comment, then **offer to post them with one
702
945
  confirmation**. Posting a reply inside someone's review thread is outward-facing and
703
946
  notifies the reviewer, so it is a **HITL gate, never automatic**. On approval, post
@@ -706,7 +949,7 @@ of an `in-review` task surfaces the open PR's comments and routes here — see
706
949
  identity it uses for issues, PRs, and merges; there is no separate bot identity). The
707
950
  fix commit is visible on the PR regardless, so declining only skips the
708
951
  acknowledgement, not the fix.
709
- 4. **Re-surface the merge gate** above.
952
+ 5. **Re-surface the merge gate** above.
710
953
 
711
954
  ## Closeout
712
955
 
@@ -715,26 +958,36 @@ GitHub — `gh pr view <pr> --json state,mergedAt` reports `MERGED`, regardless
715
958
  was merged). Closeout **archives, it does not delete, and it records via a dedicated PR**:
716
959
  it raises durable decisions to ADRs, `git mv`s the spec + `discoveries.md`
717
960
  into `.claude/state/tasks/_archive/<id>/`, drops only `progress.md`, and lands the
718
- `history.md` append + the archival on a `harness/closeout-<id>` PR merged with
719
- `gh pr merge` `--auto`. Nothing is pushed direct to the base the closeout record obeys
720
- the same branch isolation as every other change. The skill owns the full mechanics.
721
-
722
- **Closeout splits into two phases** because `--auto` defers to branch protection. If the
723
- closeout PR self-merges (protection is PR + checks only), closeout finalizes in one go. If
724
- protection requires human approval **or auto-merge is disabled repo-wide, which makes
725
- `--auto` error rather than queue** the PR waits: flip the issue to
726
- `harness:status:closeout-pending`, tell the human the record PR is open, and stop. A later
727
- `/resume` of a `closeout-pending` task finalizes once that PR is merged (see Dispatch
728
- RESUME).
961
+ `history.md` append + the archival on a `harness/closeout-<id>` PR self-merged through
962
+ the same checks-precondition executor as the merge gate (`.claude/hooks/lib/merge-pr.sh`
963
+ — **the executor never self-merges on anything but green**; no standing human
964
+ authorization exists on this path, so every not-green outcome takes one of the skill's
965
+ exits self-fix, park, or a human's informed decision never an autonomous merge).
966
+ Nothing is pushed direct to the base the
967
+ closeout record obeys the same branch isolation as every other change. The skill owns
968
+ the full mechanics, including what to do on red, absent, or still-pending checks. A
969
+ task that is a **part of a partition** (its body carries `Part <k> of #<parent>`) also,
970
+ at finalize, ticks its row in the parent's checklist and on the last part — closes the
971
+ parent with a summary comment; the skill's finalize step owns it (mechanics in
972
+ `.claude/agents/partition.md`).
973
+
974
+ **Closeout splits into two phases** because the self-merge only happens on green. If the
975
+ closeout PR's checks pass within the bound (and branch protection asks nothing more),
976
+ closeout finalizes in one go. Otherwise — checks red (and not self-fixable), no checks
977
+ and no standing answer, timeout, or protection requiring human approval — the PR waits:
978
+ flip the issue to `harness:status:closeout-pending`, tell the human the record PR is
979
+ open and why it didn't merge, and stop. A later `/resume` of a `closeout-pending` task
980
+ finalizes once that PR is merged (see Dispatch → RESUME).
729
981
 
730
982
  **Closeout is the Architect's reliable activation point**: before
731
983
  archiving, the skill drives three durable-capture activations, **asymmetric by design** —
732
984
  `write-adr` (HITL offer per resolved discovery), `update-architecture` (**automatic**
733
- dispatch with the merged diff when `docs/architecture.md` exists no pre-offer, the map
985
+ dispatch when `docs/architecture.md` exists, handing the PR and the `spec/design.md`
986
+ path (the Architect reads the merged diff itself) — no pre-offer, the map
734
987
  tracks reality and the edit is reviewed in the closeout PR), and `playbook-iterate` (HITL
735
988
  offer once per task, for a reusable pattern no `T6` conflict already routed). Closeout
736
989
  never drafts the artifact itself — it lights up the Architect, who owns the criteria
737
- (§Architect on-demand). Each activation no-ops when its skill isn't installed.
990
+ (§Architect). Each activation no-ops when its skill isn't installed.
738
991
 
739
992
  Before any of this, enforce the discovery invariant: **no `discoveries.md` entry may lack
740
993
  a resolved `**Resolution**`block, and no`harness:discovery:\*` label may remain.** An
@@ -767,29 +1020,33 @@ When the gate choice was step-by-step, also pass `--steps` (the count of
767
1020
  ## Sub-agent invocation
768
1021
 
769
1022
  Each sub-agent runs with **fresh context** (a Task-tool invocation), not the hat's
770
- accumulated conversation. Give it the issue link, the relevant task-state paths, and
771
- the skill to run. Read back its returned summary; you own the human dialogue, the
772
- approval gate, and the label lifecycle.
773
-
774
- ## L2 lightweight round-trip (TRIAGE)
775
-
776
- For small bugs that don't earn the full SDD ceremony. They skip the spec and its gate,
777
- but the branch, PR, and merge gate are the same no path auto-merges:
778
-
779
- 1. **Triage** invoke the `triage-issue` skill: investigate the codebase, find the
780
- root cause, draft a TDD-based fix plan, and create the issue with `harness:managed`
781
- (no `harness:sdd` its absence is what marks the lightweight path). Minimize
782
- questions. Record the number `<id>`.
783
- 2. **Branch + scaffold** create the task branch `harness/<id>-<slug>` off the default
784
- branch, then scaffold `.claude/state/tasks/<id>/progress.md` on it. Nothing touches
785
- the default branch until the merge gate.
786
- 3. **Implement** invoke the **Implementer** sub-agent with the `tdd` skill. All work
787
- lives on the branch.
788
- 4. **Review** flip to `harness:status:in-review`, **open the PR** (`gh pr create`,
789
- with `Closes #<id>` in the PR body so the provider auto-links and closes the issue on
790
- merge), and invoke the **Reviewer** sub-agent with the
791
- `senior-review` skill (fresh context). On rejection, route back; on approval, go to
792
- the merge gate.
793
- 5. **Merge gate** the same human-explicit gate as L1: never auto-merge. Surface the
794
- PR and wait.
795
- 6. **Closeout** — run the `task-closeout` skill (merge confirmed via `gh`), as above.
1023
+ accumulated conversation. Read back its returned summary; you own the human dialogue,
1024
+ the approval gate, and the label lifecycle. When a summary carries a
1025
+ `## Side-findings` block, read `.claude/agents/spinoff.md` and run its offer —
1026
+ after any gate prompt the read-back lands on, never before.
1027
+
1028
+ **Spawn prompts go by reference, never by quotation.** The prompt carries the issue
1029
+ link, the relevant task-state and spec **paths**, the skill to run — plus, in
1030
+ step-by-step mode, the group id and its header line and a short **synthesized
1031
+ delta**: only what exists nowhere on disk (reject feedback being addressed, the
1032
+ one-line gist of a **recorded** discovery resolution the full entry lives in
1033
+ `discoveries.md`, reference it; pre-record, `resolve-discovery` step 3 routes the
1034
+ owner with the decision **stated in full** or a human instruction from this
1035
+ conversation). Never paste spec
1036
+ content (`requirements.md` / `design.md` / `tasks.md` text) into the prompt the
1037
+ sub-agent reads those files itself from the paths, always fresher than a quotation.
1038
+ One exception is never trimmed: when the delta **is** the payload (a REJECT's
1039
+ findings), route the reviewer's full findings verbatim. Scope: this rule binds the
1040
+ task loop's role sub-agents; a user-invoked analysis flow (e.g. a PR-review
1041
+ command spawning a stateless analysis agent) follows its own skill's prompt shape.
1042
+
1043
+ ## Turn economy
1044
+
1045
+ Latency is paid **per turn**, not per command: run mechanical sequences whose
1046
+ intermediate output needs no judgment as **one composite invocation**, and batch
1047
+ independent read-only lookups in **one parallel turn**. The step-by-step checkpoint
1048
+ is the canonical case (single chained commit+push; post-resolution, the resolved
1049
+ step line + state commit + emit ride together). Never compact across a judgment point — reading a
1050
+ summary, arbitrating a gate, classifying a discovery each deserve their own turn.
1051
+ Checkpoint **narration** is exempt from all dieting: the gate presentation to the
1052
+ human is the product, never overhead.