@lemoncode/lemony 0.2.0 → 0.4.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.
@@ -18,7 +18,7 @@ issue label lifecycle, and runs closeout. The entry-protocol summary lives in
18
18
 
19
19
  ## Companion files (lazy — read on trigger only)
20
20
 
21
- Three procedures live in sibling files, kept out of boot context by design (a fourth
21
+ Four procedures live in sibling files, kept out of boot context by design (a fifth
22
22
  sibling, `.claude/agents/fit-assessment.md`, is a reference doc for the task-fit
23
23
  dial — not a procedure; consult it on a borderline classification). Read the
24
24
  file **when its trigger fires**, then run it as if it were a section here:
@@ -32,6 +32,11 @@ file **when its trigger fires**, then run it as if it were a section here:
32
32
  - **`.claude/agents/spinoff.md`** — mid-task capture (the `/spinoff` offer). Trigger:
33
33
  the human mentions what may be an independent, non-blocking defect, or a sub-agent
34
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.
35
40
 
36
41
  ## Dispatch
37
42
 
@@ -50,9 +55,13 @@ Parse the first prompt's intent (or honor a slash command):
50
55
  nothing to check out: its task PR already merged and its state is archived under
51
56
  `_archive/<id>/`. Its issue is **closed** (the task PR's `Closes #<id>` fired), so it
52
57
  surfaces in the queue only when you list closed issues too (`--state all`) — an
53
- open-only listing misses it. It resumes at closeout **finalize** — confirm the open
54
- `harness/closeout-<id>` record PR merged, then finish the `task-closeout` skill
55
- (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
56
65
  has **no branch and no task state yet**) is the exception: there is nothing to check
57
66
  out. Read the captured context — the **issue title is the always-present symptom**; the
58
67
  body adds a location/pointer and the `Discovered during #<parent>` ref when they exist
@@ -74,7 +83,11 @@ Parse the first prompt's intent (or honor a slash command):
74
83
  the Implementer; closeout's `update-architecture` then re-runs over that diff as a no-op,
75
84
  and there is no spec to archive. **Fallback:** if the project no longer keeps an
76
85
  `architecture.md` (the skill is uninstalled), treat it as a normal `pending` stub —
77
- 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.
78
91
  - **DEFINE** — "define / new task / I have an idea" → the **L1 full-SDD round-trip**
79
92
  below.
80
93
  - **TRIAGE** — "bug / error in / broken / fails when" → the **L2 lightweight
@@ -87,8 +100,8 @@ Parse the first prompt's intent (or honor a slash command):
87
100
  exact same listing `/resume` does with no args. `/resume` (authority: its command
88
101
  file) **owns** the precise `gh` queries; ORIENT does not re-specify them, so it
89
102
  cannot drift. That queue covers the spec-ready and in-progress tasks, the **`/spinoff`
90
- pending stubs** (what a human who never types `/resume` would otherwise forget), and
91
- 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
92
105
  `/triage` (a bug, L2) — and ask which to do. The **start options are unconditional**:
93
106
  when the queue is **empty** (nothing parked), still render the menu with just the
94
107
  start options — that is the "nothing to resume, start something?" case, **not** a
@@ -121,14 +134,25 @@ discardable question; never block on it.
121
134
 
122
135
  This paragraph is the canonical criterion — act on it directly. The fuller L1/L2/L3
123
136
  model, the spec-or-no-spec call between L1 and L2, and worked examples live in the
124
- 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.
125
141
 
126
142
  ## L1 full-SDD round-trip (DEFINE)
127
143
 
128
144
  1. **Grill the idea into a PRD** — run the `grill-with-docs` skill. One question at a
129
145
  time, never auto-decide. Output: a PRD at `docs/prds/<topic>-<date>.md`. The PRD is
130
146
  yours (creator/maintainer); its `Status:` flips to `completed` when the grill
131
- 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.
132
156
  2. **Open the task** — before dispatching anyone, create the tracked task so every
133
157
  sub-agent has an issue to label and a branch to work on:
134
158
  - `gh issue create` with a skeleton body
@@ -137,7 +161,9 @@ sibling `fit-assessment.md`; consult it for a borderline classification.
137
161
  id the task store assigns — the **GitHub issue number** while
138
162
  `task_storage.type: github` — as the task `<id>`.
139
163
  - Create the task branch `harness/<id>-<slug>` off the default branch
140
- (`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
141
167
  work — spec **and** code — lives on this branch; nothing touches the default
142
168
  branch until the human merge gate.
143
169
  3. **Design the UI (if it touches UI)** — before any spec work, evaluate the
@@ -151,7 +177,8 @@ sibling `fit-assessment.md`; consult it for a borderline classification.
151
177
  4. **Dispatch the Spec Author** — invoke the **Spec Author** sub-agent (fresh context,
152
178
  spawn by reference — §Sub-agent invocation) with
153
179
  the PRD path (and the `ui-handoff.md` if one was authored), the issue `<id>`, and the
154
- 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
155
182
  `tasks/<id>/spec/` — no draft holder, the id is real from the start) then `spec-to-issue`
156
183
  (fills the issue **body** from the spec; it creates nothing and moves no labels). It
157
184
  returns a summary.
@@ -176,18 +203,31 @@ sibling `fit-assessment.md`; consult it for a borderline classification.
176
203
  `harness:status:in-progress` and proceed **per the mode chosen at the gate**
177
204
  (§Implementation mode): **all-at-once** invokes the **Implementer** sub-agent (fresh
178
205
  context) once with the `tdd` skill and the branch — it keeps `progress.md` live and
179
- signals done; **step-by-step** runs the per-group loop in §Step-by-step
180
- implementation instead, and rejoins this flow at step 8 after the last group.
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
+ **auto-commit OFF** (the gate's second knob), either mode runs the zero-commit
209
+ protocol — no commit touches the branch before a checkpoint OK (§Auto-commit
210
+ OFF); in all-at-once its single gate runs when the Implementer signals done,
211
+ **before** step 8 — the PR never opens on uncommitted work.
181
212
  8. **Review** — flip to `harness:status:in-review` and **open the PR**
182
213
  (`gh pr create`, `harness/<id>-<slug> → <default>`, with `Closes #<id>` in the PR
183
- 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
184
218
  the **Reviewer** sub-agent (fresh context) with the `senior-review` skill to review
185
219
  that PR. Fresh context is what prevents the Implementer's confirmation bias. **If the
186
220
  task touched UI** — the durable signal is that `tasks/<id>/spec/ui-handoff.md`
187
221
  exists — also invoke the **UI Designer** as a distinct design + a11y lens
188
222
  (REVIEW in `.claude/agents/ui-design.md`). Either lens rejecting routes back to the
189
223
  Implementer (rejection is transient — no dedicated
190
- label); on approval (both lenses), go to the merge gate.
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.
191
231
  9. **Merge gate** — see below. Human-explicit, never auto-merged.
192
232
  10. **Closeout** — see below.
193
233
 
@@ -203,7 +243,27 @@ its branch, read the spec cold, and run this gate before writing any code.
203
243
  1. Present the spec to the human: a short summary plus links to
204
244
  `tasks/<id>/spec/{requirements,design,tasks}.md` and the issue. `tasks.md`
205
245
  carries the **step grouping** the step-by-step loop would follow (risk-sized
206
- headers, one-line rationale each) approving the spec approves the grouping.
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
+
207
267
  2. Wait for an explicit decision:
208
268
  - **Approve** → ask the **implementation mode** in the same interaction
209
269
  (§Implementation mode — the human just read `tasks.md` cold, the best moment to
@@ -259,6 +319,33 @@ applies. The mode is switchable **downward only** (step-by-step → all-at-once,
259
319
  at every checkpoint); there is no upgrade path — all-at-once has no stop where the
260
320
  switch could be offered.
261
321
 
322
+ **The second knob, same interaction — auto-commit.** Alongside the mode, settle
323
+ whether the agent commits automatically as it works, or the human reviews the work
324
+ **uncommitted** before anything lands on the branch. Read
325
+ `implementation.auto_commit` from `harness.config.yml` first (an absent key means
326
+ `human`): `on` / `off` **pin the answer — record it without asking**; `human` (the
327
+ default) asks here, in the same interaction. Ask the **decision, not the mechanism**:
328
+ header **Auto-commit**, question _"Should the agent commit automatically as it
329
+ works?"_, exactly these two options in this order — **OFF first, marked recommended** —
330
+ with these descriptions (short and closed; do not pad them with mode arithmetic or
331
+ your own reading of the trade-off):
332
+
333
+ > **OFF (recommended)** — the agent makes **zero commits**: you review the work
334
+ > uncommitted in the Source Control panel (and can edit it in place); the branch
335
+ > gets its first commit on your OK. Choose this for more control.
336
+ >
337
+ > **ON** — the agent commits and pushes as it works; checkpoints present
338
+ > committed work. Choose this to be interrupted less (in step-by-step it avoids
339
+ > one dirty-tree review per group).
340
+
341
+ Record it next to the mode line (`Auto-commit: off` / `on`) — execution state, like
342
+ the mode. The knob is **L1-only** (it rides this question; L2 always runs the
343
+ commit-as-you-go flow) and orthogonal to the mode: it moves **when the branch first
344
+ receives commits**, never whether review happens. In step-by-step the uncommitted
345
+ gate runs per group; in all-at-once it is **one gate over the entire implementation**
346
+ (its single "group" is the whole `tasks.md`). Auto-commit OFF's mechanics — staging
347
+ save-points, full deferral, watch-fors — live in §Auto-commit OFF.
348
+
262
349
  ## Step-by-step implementation (the per-group loop)
263
350
 
264
351
  One step = one `tasks.md` **group**, 1:1 with the grouping the human approved at the
@@ -267,27 +354,105 @@ the human checkpoint run, never how the Implementer works. A `tasks.md` without
267
354
  headers (a legacy or hand-written spec) runs **one task per group** — the pre-grouping
268
355
  cadence. Tasks added mid-implementation (a resolved discovery) default to **their own
269
356
  group**, appended at the end of the loop — M grows, and already-resolved step numbers
270
- never shift. For each group, in order:
271
-
272
- 1. **Implement the group** invoke the **Implementer** sub-agent (fresh context, as
273
- always) scoped to **this one group**: give it the branch, the task-state paths, and
274
- the group's id + header line in `tasks.md` by reference (§Sub-agent invocation),
275
- it reads the group's tasks from the file itself (`tdd` skill checkbox by checkbox
276
- with small commits, as always). It commits to the branch, logs to
277
- `progress.md`, and signals done. **No PR yet** — the PR opens after the last group,
357
+ never shift; a narrowing (a resolved partition discovery) trims or removes groups from
358
+ the current one onward and trims a resolved group in place — M may shrink, resolved step
359
+ numbers still never shift. For each group, in order:
360
+
361
+ 1. **Implement the group** first **record the group's anchor**: the branch head OID
362
+ at this moment (= the end of the previous approved group; the head at
363
+ implementation start for group 1) goes on the group's step-log line — the
364
+ checkpoint contract diffs against it. Then invoke the **Implementer** sub-agent
365
+ (fresh context, as always) scoped to **this one group**: give it the branch, the
366
+ task-state paths, and the group's id + header line in `tasks.md` — by reference
367
+ (§Sub-agent invocation), it reads the group's tasks from the file itself (`tdd`
368
+ skill — checkbox by checkbox with small commits, as always). It commits to the
369
+ branch (auto-commit OFF: it **stages** instead of committing — point the
370
+ invocation at the staging protocol in `implementer.md`), logs to `progress.md`,
371
+ and signals done. **No PR yet** — the PR opens after the last group,
278
372
  as in all-at-once; the human inspects and runs the **local checkout** (a checkpoint
279
373
  never needs GitHub; the branch is pushed best-effort at each checkpoint — step 3).
280
374
  2. **Per-step review** — invoke the **Reviewer** sub-agent (fresh context) **by
281
375
  reference** (§Sub-agent invocation): the group id + its header line — it reads the
282
376
  group's tasks and requirements itself — scoped to the **group's diff against its
283
- slice of the spec**. The verdict is **local**
377
+ slice of the spec**. **Hand the group's anchor OID (step 1's step-log line) in the
378
+ spawn prompt in both knob states** — the Reviewer self-validates its ledger
379
+ against it (`--anchor`); under auto-commit OFF the prompt additionally says
380
+ `auto-commit is OFF` —
381
+ the diff is then the group's **uncommitted work against the anchor**,
382
+ `git diff <anchor> -- ':(exclude).claude/state'`; worktree == index
383
+ within that scope at review time. The
384
+ verdict is **local**
284
385
  (`progress.md` + session narration) — no issue comment; only the final full-pass
285
386
  posts one. **On a UI-touching step**, also run the deterministic design gates here —
286
387
  `lemony design-tokens validate` + `lemony design-tokens contrast`, agent-free and cheap — and let the
287
388
  project's a11y lint ride the step's lint; a failure is an early-catch REJECT so a bad
288
389
  token pair or hardcoded value can't propagate to a later step. The **judgment** design
289
390
  lenses (`design-critique` / `a11y-audit`) do **not** run per-step — they are full-pass
290
- only (REVIEW in `.claude/agents/ui-design.md`). On REJECT, re-invoke the Implementer (fresh) with the
391
+ only (REVIEW in `.claude/agents/ui-design.md`).
392
+
393
+ **On an APPROVE, validate the evidence ledger before relaying it** — agent-free and
394
+ cheap, like the design gates, and for the same reason: a check an agent performs is a
395
+ check an agent can rationalize away. The Reviewer wrote
396
+ `.claude/state/tasks/<id>/review-ledger/step-<N>.json` (its `## Evidence ledger`
397
+ contract) and self-validated it; you run the same verb:
398
+
399
+ ```bash
400
+ lemony review-ledger validate --task-id=<id> --anchor=<oid> --step=<N>
401
+ ```
402
+
403
+ `<oid>` is the anchor **you** recorded when the group started (step 1's step-log
404
+ line) — never one the Reviewer reports. Trust is by double execution, the
405
+ Diff-fingerprint's own pattern: the Reviewer self-validated with the anchor its
406
+ invocation handed it, and your authoritative run catches a green built on the
407
+ wrong anchor — that red routes like any sidecar-side red below.
408
+
409
+ **In auto-commit ON, run the verb on a clean tree.** The floor's owed set
410
+ reads the diff against the anchor _including uncommitted work_ — correct in
411
+ auto-commit OFF, where the group's work is uncommitted by design, but in
412
+ auto-commit ON an uncommitted tracked
413
+ edit outside `.claude/state` at validation time is a **human delta the Reviewer
414
+ never saw**, and it would red the floor as `unaccounted-file` on a ledger that is
415
+ not wrong. Check `git status --porcelain -- . ':(exclude).claude/state'` first; a
416
+ hit routes through the checkpoint contract's human-delta check **before** you
417
+ validate — never burn the Reviewer retry on unreviewed human content.
418
+
419
+ Green → the APPROVE stands; carry its counts — both halves, `criteria n/m (basis: …)`
420
+ and `gates n/m (basis: …)` — onto the step-log line: the gates basis is the one
421
+ place a green run shows the human whether the project reviews against declared
422
+ gates or the bare real-run floor (`undeclared`).
423
+ Red → **an APPROVE with a red ledger is never relayed**, and a red ledger is not a
424
+ REJECT of the code: the Implementer is not at fault and is **never** re-invoked for
425
+ it. Route on the `[kind]` lines the verb prints — it closes with
426
+ `N spec-side problem(s) … do not retry the Reviewer while any of these stands.`
427
+ whenever any problem lives outside the sidecar:
428
+
429
+ - **any spec-side problem** — the verb counts them out loud (`unknown-risk-class`, a
430
+ tag or ref list that did not parse, a duplicated group number, an orphan task, an
431
+ empty group, a dangling requirement ref, a step with no group) → no retry. They
432
+ live in `tasks.md` / `requirements.md`, which the Reviewer cannot fix: stop and
433
+ bring them to the human as an **anticipated checkpoint** (below) with the verb's
434
+ lines as the content — the spec needs a decision, and the fix routes as a discovery
435
+ (§Discovery mediation). Once the resolution lands in the spec, re-run the verb on
436
+ the sidecar on disk: green → the checkpoint; a sidecar-side red then follows the
437
+ one-retry rule below. The human's `ok` on an anticipated checkpoint is their call,
438
+ as at every gate — what never happens is you relaying a red as an APPROVE.
439
+ - **anything else** (a problem in the sidecar itself) → re-invoke the **Reviewer**
440
+ (fresh, as always) **once**, with the
441
+ verb's `[kind] message` lines **verbatim** in the spawn prompt — the delta is the
442
+ payload (§Sub-agent invocation). This is its own cap of **one retry**, separate from
443
+ the REJECT cap below: a Reviewer that cannot hit the format must not burn the
444
+ Implementer's budget. Set the open step's transient line to
445
+ `awaiting ledger retry (step N/M, retry 1/1)` (step 5) **before** re-invoking — the
446
+ retry is spent the moment it is issued, so a session that dies mid-retry resumes
447
+ knowing it is gone. Validate the second APPROVE the same way; a **second red** →
448
+ anticipated checkpoint with the verb's lines as the content. A `/resume` that lands
449
+ on the `awaiting ledger retry` line re-runs the verb on the sidecar on disk: green →
450
+ step 3's checkpoint; red → the anticipated checkpoint, the retry being spent.
451
+
452
+ A REJECT owes no ledger — do not run the verb on one. A red ledger emits no telemetry
453
+ of its own in this version; the step-log line is its record.
454
+
455
+ On REJECT, re-invoke the Implementer (fresh) with the
291
456
  feedback and re-review — the fix-loop runs until clean, **capped at 3 REJECTs on the
292
457
  same step**:
293
458
  at the cap, stop the loop and bring the disagreement to the human as an
@@ -297,7 +462,15 @@ never shift. For each group, in order:
297
462
  `awaiting human checkpoint (step N/M)` line in `progress.md` — except you present
298
463
  the unresolved disagreement (both positions, the spec slice) instead of a clean
299
464
  step.
300
- 3. **Human checkpoint** — first set the open step's `progress.md` line to
465
+
466
+ In auto-commit OFF, `OK` is also the moment the group's single code commit
467
+ lands, and `changes` sends the fresh Implementer to iterate **over the worktree**
468
+ — both per §Auto-commit OFF.
469
+
470
+ 3. **Human checkpoint** — first run §Checkpoint contract's **spec check** (item
471
+ 4): the state commit below sweeps `spec/`, so an unconfirmed human spec edit
472
+ must route as a discovery **before** anything commits it. Then set the open
473
+ step's `progress.md` line to
301
474
  `awaiting human checkpoint (step N/M)` (step 5), then commit the task state and
302
475
  **push the branch, best-effort**, as **one composite invocation** (§Turn economy).
303
476
  This commit and step 4's OK-side twin are **yours, anchored to your checkpoint
@@ -307,15 +480,25 @@ never shift. For each group, in order:
307
480
 
308
481
  ```bash
309
482
  git add .claude/state/tasks/<id>/ && \
310
- git commit -m "step(<id>): step <N> awaiting checkpoint"; \
483
+ git commit -m "step(<id>): step <N> awaiting checkpoint" \
484
+ -- .claude/state/tasks/<id>/; \
311
485
  git push # best-effort — a failure warns, never blocks
312
486
  ```
313
487
 
488
+ The commit's pathspec keeps it honest: anything else already staged (e.g. a
489
+ human edit staged ahead of the checkpoint) stays staged instead of riding
490
+ mislabeled into the state commit.
491
+
314
492
  A failed push — offline, auth — warns and never blocks; the next push carries
315
493
  it. This long wait is where a session likeliest dies — the push is what lets
316
494
  another machine's `/resume` see the pending checkpoint.
317
- Then present the step: what was built, where to look, how to run it. Three
318
- answers:
495
+ **Auto-commit OFF skips this state commit and push entirely** until the
496
+ OK the branch receives _nothing_, state included (§Auto-commit OFF): update
497
+ the `progress.md` line on disk only, accepting the documented price that the
498
+ pending checkpoint is invisible to a cold `/resume` from another machine.
499
+ Then present the step **per §Checkpoint contract**: what was built and how to
500
+ run it, the group's commits and touched files, the anchored group diff, the
501
+ richer-view offer, and the human-delta check. Three answers:
319
502
  - **OK** → emit `step_completed` (below), next group.
320
503
  - **Changes** (with feedback) → fresh Implementer with the feedback → per-step
321
504
  review again (step 2; the review-iteration count resets) → checkpoint again.
@@ -331,7 +514,8 @@ never shift. For each group, in order:
331
514
  (`Mode: step-by-step (downgraded to all-at-once at step N)` — the gate choice
332
515
  stays first; the downgrade is a suffix, because `task_done.mode` records the gate
333
516
  choice), and run the **remaining** tasks as a single Implementer invocation
334
- (today's mode). Checkpoint OKs already given stand.
517
+ (all-at-once; the auto-commit knob keeps its recorded setting).
518
+ Checkpoint OKs already given stand.
335
519
 
336
520
  Aborting needs no protocol: the human interrupts the session; `/resume` picks the
337
521
  step sub-state back up from `progress.md`.
@@ -339,9 +523,16 @@ never shift. For each group, in order:
339
523
  4. **Telemetry** — every **resolved checkpoint** emits one event (so a step the human
340
524
  sent back emits more than once, same `--step`); the emit, the step's resolved
341
525
  `progress.md` line (step 5) and the resolution state commit (on OK, plain or
342
- downgrade: `step(<id>): step <N> checkpoint OK`) + best-effort push ride as
526
+ downgrade: `step(<id>): step <N> checkpoint OK`, carrying the same
527
+ `-- .claude/state/tasks/<id>/` pathspec as step 3's twin so other staged
528
+ content never rides mislabeled) + best-effort push ride as
343
529
  **one composite turn** (§Turn economy) — without that commit a cold `/resume`
344
- still reads `awaiting` after the last group. `<review-iterations>` is the number
530
+ still reads `awaiting` after the last group. Auto-commit OFF: on OK the
531
+ same composite additionally carries the group's **code commit** — the deferral
532
+ ends here, so code commit + state commit + push + emit land together (exact
533
+ commands, the pathspec split of the mixed index, and the all-at-once no-emit
534
+ rule in §Auto-commit OFF); on
535
+ `changes` nothing is committed and the deferral continues. `<review-iterations>` is the number
345
536
  of Reviewer invocations that preceded this checkpoint (≥ 1; resets after a
346
537
  "changes"):
347
538
 
@@ -358,7 +549,8 @@ never shift. For each group, in order:
358
549
  **Attribution — name the component the checkpoint friction is about, or
359
550
  omit.** The two `--attributed-*` flags are **optional**; they're meaningful when
360
551
  the checkpoint surfaced friction (`changes`, or repeated `review-iterations`) and
361
- you can name what produced it — usually the Implementer. **Omit both on a clean
552
+ you can name what produced it — usually the Implementer; a ledger retry is the
553
+ Reviewer's own. **Omit both on a clean
362
554
  `ok` checkpoint or when you can't confidently attribute** (a wrong guess pollutes
363
555
  the signal). Use the **exact** name from this roster so the data aggregates:
364
556
 
@@ -370,28 +562,35 @@ never shift. For each group, in order:
370
562
  `cli-e2e`, `bash-hooks`)
371
563
 
372
564
  Per-step Reviewer REJECTs also emit `review_rejected` as usual, with the extra
373
- `--step=<N>` flag (the `iteration` count stays task-global, as today).
565
+ `--step=<N>` flag (the `iteration` count stays task-global, as today; an
566
+ all-at-once single-group pass — auto-commit OFF's pre-gate review —
567
+ omits `--step`, per the events schema).
374
568
 
375
569
  5. **`progress.md` step log** — keep the sub-state explicit so `/resume` can re-enter
376
570
  mid-loop. Under a `## Step log` heading, one line per resolved step; the **open**
377
571
  step's line is transient — update it in place as the loop progresses
378
572
  (`fix-loop iteration K — in progress` while implementing/reviewing,
379
- `awaiting human checkpoint (step N/M)` while waiting on the human), then replace it
380
- with the resolved outcome:
573
+ `awaiting ledger retry (step N/M, retry 1/1)` while the fresh Reviewer redoes a red
574
+ ledger, `awaiting human checkpoint (step N/M)` while waiting on the human), then
575
+ replace it with the resolved outcome:
381
576
 
382
577
  ```markdown
383
578
  Mode: step-by-step
384
579
 
385
580
  ## Step log
386
581
 
387
- - step 1/6 — review ×1 → checkpoint: OK
388
- - step 2/6 — review ×3 (2 rejects: missing error path; flaky spec) → checkpoint: changes → review ×1 → checkpoint: OK
389
- - step 3/6 — awaiting human checkpoint (step 3/6)
582
+ - step 1/6 (anchor a1b2c3d) — review ×1 → checkpoint: OK
583
+ - step 2/6 (anchor e4f5a6b) — review ×3 (2 rejects: missing error path; flaky spec) → checkpoint: changes → review ×1 → checkpoint: OK
584
+ - step 3/6 (anchor c7d8e9f) review ×2 (ledger retry ×1) — ledger: criteria 3/3 (basis: requirements), gates 2/2 (basis: config) → checkpoint: OK
585
+ - step 4/6 (anchor f1a2b3c) — awaiting human checkpoint (step 4/6)
390
586
  ```
391
587
 
392
- Those two transient sub-state strings are exactly what a later `/resume` re-enters
588
+ Those transient sub-state strings are exactly what a later `/resume` re-enters
393
589
  on: the awaiting line re-presents the pending checkpoint, the fix-loop line
394
- re-enters the implement→review loop at that iteration.
590
+ re-enters the implement→review loop at that iteration, and the ledger-retry line
591
+ says the single retry is already spent. The `(anchor <oid>)`
592
+ field is the OID step 1 recorded — the checkpoint contract and the per-step
593
+ Reviewer diff against it.
395
594
 
396
595
  After the **last group**, rejoin the normal flow unchanged (L1 step 8): flip to
397
596
  `in-review`, open the PR, and run the **full-pass Reviewer** over everything against
@@ -399,6 +598,192 @@ the spec. The full-pass may reject anything, **including human-OK'd steps** —
399
598
  checkpoint OK means "right direction and it runs", not a review waiver; the full-pass
400
599
  wins, and the human still holds the merge gate to disagree.
401
600
 
601
+ **Every full-pass APPROVE is ledger-validated too** — the step-8 review in either mode,
602
+ auto-commit OFF's single-group pre-gate pass, and a re-APPROVE after the merge gate
603
+ or PR comments sent the PR back to review. The Reviewer writes `full-pass.json` (no step
604
+ number → the union of every group); you run
605
+ `lemony review-ledger validate --task-id=<id> --anchor=<merge-base> --full-pass` —
606
+ the merge-base of the freshly fetched base and the PR head, the Diff-fingerprint's
607
+ own OID (L1 step 8; auto-commit OFF's pre-gate pass instead anchors at the OID
608
+ you recorded when its single group started) — and route a red exactly as
609
+ in step 2 above: one fresh Reviewer retry with the lines verbatim, a second red or any
610
+ spec-side problem to the human, and never an APPROVE relayed on a red ledger. Outside
611
+ the step loop the transient line is `awaiting ledger retry (full pass, retry 1/1)` in
612
+ `progress.md` (no step counter), and "the human" is the gate the pass feeds: the
613
+ auto-commit-OFF checkpoint when there is one, otherwise the merge-gate presentation,
614
+ with the verb's lines as the content.
615
+
616
+ ## Checkpoint contract (how a human gate presents work)
617
+
618
+ Every human checkpoint — per-group in step-by-step, and the single all-at-once gate
619
+ when auto-commit is OFF — presents the same way. "Present the step" is a
620
+ contract, not a vibe:
621
+
622
+ 1. **Anchored scope.** The group's **anchor** — the branch head OID recorded when
623
+ the group started (= the end of the previous approved group; the head at
624
+ implementation start when no group has yet been approved — group 1, or an
625
+ all-at-once run; an all-at-once run that began as a mid-task downgrade anchors
626
+ at the head after the last OK'd group) — bounds exactly what is
627
+ under review. Present the commit list + touched-files table, then the **exact
628
+ group diff**, always excluding task state:
629
+ - auto-commit ON: `git log --oneline <anchor>..HEAD` +
630
+ `git diff --stat <anchor>..HEAD -- ':(exclude).claude/state'`,
631
+ then `git diff <anchor>..HEAD -- ':(exclude).claude/state'`;
632
+ - auto-commit OFF (nothing committed):
633
+ `git diff --stat <anchor> -- ':(exclude).claude/state'`, then
634
+ `git diff <anchor> -- ':(exclude).claude/state'` — staged new files are in
635
+ the index, so they appear.
636
+ 2. **The inline rendered diff is the universal floor.** Probe the environment: when
637
+ a difftool is configured (or an extension like GitLens is present), **offer**
638
+ the richer side-by-side view — an ephemeral config works without touching the
639
+ repo's (`git -c diff.tool=<tool> difftool <range>`). Never assume an extension
640
+ exists. In auto-commit OFF the Source Control panel already shows the work
641
+ natively — it IS uncommitted.
642
+ 3. **What was built and how to run it** — from the Implementer's verification line,
643
+ as today. Checkpoint narration is the product, never overhead (§Turn economy).
644
+ 4. **The human delta — always detected, always revalidated.** Whatever the answer
645
+ (`ok` or `changes: …`), first detect the human's own edits — in auto-commit
646
+ OFF, **two checks with distinct routes** (every agent save-point is staged at
647
+ presentation time, so the staged/unstaged seam is the auto-detect):
648
+ - **Work delta**: the unstaged section outside task state —
649
+ `git diff -- ':(exclude).claude/state'` **plus untracked files outside
650
+ `.claude/state`** (from `git status --porcelain`; `git diff` never shows a
651
+ file the human created). Your own disk-only `progress.md` edits sit
652
+ unstaged under `.claude/state` by design — agent noise, never a human
653
+ delta.
654
+ - **Spec check**: unstaged edits **or untracked files** under the spec —
655
+ `git diff -- .claude/state/tasks/<id>/spec/` plus the untracked (`??`)
656
+ porcelain entries
657
+ under that path (a human-created spec file is untracked and invisible to
658
+ the diff). A hit is **not** a work
659
+ delta: it changes the approved spec, so route it as a **discovery**
660
+ (§Discovery mediation) before the checkpoint resolves. The Spec Author —
661
+ the spec's owner — applies the resolution to the file (restoring it if the
662
+ human's interpretation is rejected), then **re-present this checkpoint**;
663
+ only after that may any commit run, so `git add -A` lands the resolved
664
+ spec, never an unconfirmed unstaged edit. **Mediated changes are staged on
665
+ arrival and never re-raise**: whenever a discovery resolution is applied
666
+ mid-task — the Spec Author's spec update, an Architect artifact — stage it
667
+ immediately (`git add` the touched paths). Resolved artifacts join the
668
+ agent-staged floor, so this check fires only on **unmediated** edits and
669
+ the re-presented checkpoint is clean; an unstaged edit that matches the
670
+ recorded `**Resolution**` in `discoveries.md` is confirmed content — stage
671
+ it, don't re-raise.
672
+
673
+ The **spec check runs in both knob states** — in auto-commit ON, run it
674
+ **before** step 3's `awaiting` state commit, which would otherwise silently
675
+ commit a pre-existing spec edit before detection. Auto-commit ON's work-delta
676
+ detection is simply any uncommitted working-tree change.
677
+ The **work delta** then runs the pipeline: present it, confirm it is
678
+ intended, and **re-run the suite with the delta applied** — the delta never
679
+ inherits the group's green. **A red revalidation blocks the OK**: never run
680
+ the commit composite on a red suite — re-present the failure and route it as
681
+ `changes` (the human decides: fix it themselves, drop the delta, or hand it
682
+ to the Implementer). On a green revalidation the delta rides with the group:
683
+ on OK it lands with
684
+ the group's work (auto-commit OFF: staged into the group's commit; auto-commit ON:
685
+ committed as its
686
+ own commit — `step(<id>): step <N> human delta` — before the next group); on
687
+ `changes` it stays in the worktree for
688
+ the fresh Implementer (auto-commit OFF: staged first as the safe starting point —
689
+ §Auto-commit OFF).
690
+
691
+ ## Auto-commit OFF (zero commits + staging save-points)
692
+
693
+ The auto-commit OFF state (chosen at the approval gate — §Implementation mode) moves
694
+ **when the branch first receives commits**; review, fix-loop routing, and the merge
695
+ gate are unchanged. v1 is deliberately an experiment — the watch-fors below are its
696
+ pre-registered exit signals.
697
+
698
+ - **Zero commits; staging save-points.** The Implementer never commits: it stages
699
+ after every green task (`git add -A`) and **never stages mid-experiment** — the
700
+ staging protocol in `implementer.md`, which the spawn prompt must point at
701
+ explicitly (it inverts the tdd add-early reflex, and a fresh Implementer only
702
+ knows what the contract and the branch tell it). A failed experiment rolls back
703
+ with `git restore . && git clean -fd`: the worktree returns to the last green
704
+ save-point; staged content survives verbatim, including new files.
705
+ - **Everything is deferred** until the human OK: no code commits and **no state
706
+ commits** either — the checkpoint's `awaiting` state commit + push do not run;
707
+ `progress.md` updates on disk only. The documented price, accepted at the
708
+ grill: **no multi-machine durability** during implementation and during the
709
+ checkpoint wait (the flow's longest, where a session likeliest dies) — a cold
710
+ `/resume` from another machine sees nothing pending. (One exception: a
711
+ discovery pause **is** visible cross-machine — its labels and issue comment
712
+ surface — but the full `discoveries.md` entry stays machine-local until an OK
713
+ lands it.) Same-machine resume reads the worktree as usual.
714
+ - **The gate** runs at end of group (step-by-step) or end of everything
715
+ (all-at-once — after the Implementer signals done and **before** the
716
+ `in-review` flip: the PR never opens on uncommitted work). In all-at-once the
717
+ whole implementation is the **single group** and the per-group machinery
718
+ applies to it: the mid-implementation Reviewer runs over the anchored diff
719
+ **before** the gate — nothing reaches the human unreviewed, in either mode —
720
+ and the `changes` fix-loop carries the same 3-reject cap into an anticipated
721
+ checkpoint (whose `step_completed` clause and `step N/M` strings apply only
722
+ in step-by-step — in all-at-once the no-emit rule below wins and the awaiting
723
+ line drops the step counter). Its APPROVE is ledger-validated with `--full-pass`
724
+ and `--anchor=<oid>` — the anchor you recorded when its single group started
725
+ (§Step-by-step implementation, after the last group), never relayed on a red.
726
+ Hand that pre-gate Reviewer the anchor, the words `auto-commit is OFF`, and "the
727
+ whole `tasks.md` as the single group" in place of a group id.
728
+ All agent work is
729
+ staged at presentation time; present per §Checkpoint contract. The human
730
+ inspects the work natively in the Source Control panel and edits/discards
731
+ directly in the worktree; answers are `ok` / `changes: …` (step-by-step keeps
732
+ its third answer, OK-and-downgrade).
733
+ - **OK ⇒ commit + push, after revalidating.** Re-run the suite over the final
734
+ worktree (human delta staged in) — the gate's green is fresh, never inherited.
735
+ Then the deferral ends as **one composite turn**, splitting the mixed index by
736
+ pathspec (`git add -A` staged code and task state together; a bare
737
+ `git commit` would swallow both into one commit):
738
+
739
+ ```bash
740
+ git add -A && \
741
+ { git diff --cached --quiet -- . ':(exclude).claude/state' || \
742
+ git commit -m "<code-msg>" -- . ':(exclude).claude/state'; } && \
743
+ { git diff --cached --quiet -- .claude/state || \
744
+ git commit -m "<state-msg>" -- .claude/state; }; \
745
+ git push # best-effort — a failure warns, never blocks
746
+ ```
747
+
748
+ Each commit is **guarded on its half of the index holding changes**, so a
749
+ degenerate group no-ops that half instead of short-circuiting the other: a
750
+ state-only OK (an audit group whose artifact is progress notes, or a human who
751
+ discarded the work in the worktree and answered `ok`) still lands its state
752
+ commit — an unguarded `&&` chain would silently drop it while the push still
753
+ ran, leaving the resolution nowhere on the branch.
754
+
755
+ Step-by-step: `<code-msg>` = `step(<id>): step <N>`, `<state-msg>` =
756
+ `step(<id>): step <N> checkpoint OK`, and the `step_completed` emit rides the
757
+ same turn (step 4). All-at-once (a downgraded remainder resolves as
758
+ all-at-once here too): `<code-msg>` = `task(<id>): implementation`,
759
+ `<state-msg>` = `task(<id>): implementation checkpoint OK`, and **nothing is
760
+ emitted** —
761
+ `step_completed` is step-by-step-only (its `--step` has no meaning here, and
762
+ closeout's mode recovery reads any `step_completed` as proof of step-by-step);
763
+ the gate resolution reaches telemetry through `task_done` as usual. One commit
764
+ per group in v1; all-at-once commits the whole implementation as its single
765
+ group.
766
+
767
+ - **Changes ⇒ the Implementer iterates over the worktree.** Same routing as any
768
+ rejection (fresh context, ≤3 rejects per step): it first **stages the
769
+ revalidated human delta** (its suite result rides in the feedback) as its
770
+ safe starting point, then continues
771
+ under the staging protocol. Nothing is committed; the deferral continues.
772
+ - **Watch-fors — pre-registered failure signatures.** v1 tests in real use whether
773
+ the three roles of tdd commits (fresh-Implementer memory via the branch,
774
+ granular save-points, 1:1 per-task history) are missed. If one fires, don't
775
+ improvise: **surface it at the checkpoint and record it in `progress.md`** so
776
+ the human can decide the swap to the pre-designed fallback — _deferred push_
777
+ (local tdd commits exactly as today but unpublished; the OK becomes the push:
778
+ commit = internal memory, push = publication). The signatures:
779
+ 1. **Fix-loop memory** — iteration 2 redoes or overwrites iteration 1's work.
780
+ 2. **Save-point residual** — a mid-experiment `git add` silently destroyed the
781
+ save-point (`git status` looks identical; recovery yields nameless blobs),
782
+ or single-level undo proves insufficient (e.g. selectively reverting task
783
+ N−2).
784
+ 3. **PR narrative** — one commit per group cannot reconstruct the per-task
785
+ `step(<id>): step <N>` story.
786
+
402
787
  ## Discovery mediation
403
788
 
404
789
  Any sub-agent (Spec Author, Implementer, Reviewer, Architect) may stop mid-task and
@@ -417,7 +802,11 @@ paused sub-agent with the decision. A discovery can also be raised by **you** (e
417
802
  checkpoint "changes" request that contradicts the spec): the same skill runs, with
418
803
  nothing to re-invoke — the resolution re-enters the loop where it paused. You are the
419
804
  only one who talks to the human and
420
- moves labels — never let a sub-agent self-resolve.
805
+ moves labels — never let a sub-agent self-resolve. An **oversize** discovery — the Spec
806
+ Author or the Implementer finds the scope hides ≥2 independently mergeable units the PRD
807
+ didn't reveal — is a T2 raised and mediated exactly like this; when the human answers
808
+ "partition", read `.claude/agents/partition.md` for the parent/part mechanics (the
809
+ current task keeps the first unit).
421
810
 
422
811
  ## Architect (on-demand)
423
812
 
@@ -466,16 +855,78 @@ action that touches the default branch, so it stays a human decision. Surface it
466
855
  wait:
467
856
 
468
857
  > Reviewed and approved — PR #<pr> is here: <url>.
469
- > (1) merge it yourself, (2) I'll merge it (`gh pr merge`), or
858
+ > (1) merge it yourself, (2) I'll merge it once checks are green (`gh pr merge`), or
470
859
  > (3) run `/review-pr` first for a curated inline pass.
471
860
 
472
- The task stays at `harness:status:in-review` while it waits there is no
473
- "approved-awaiting-merge" rung between review and merge (the `closeout-pending` status is
861
+ A **stacked partition child** reaches this gate only once its PR base is the default
862
+ branch check `baseRefName` first and retarget/merge-in per `.claude/agents/partition.md`;
863
+ never merge a part into a sibling's branch. The task stays at `harness:status:in-review`
864
+ while it waits — there is no "approved-awaiting-merge" rung between review and merge (the `closeout-pending` status is
474
865
  **post**-merge, for a parked closeout record PR — not this gate). When the
475
866
  human merges (in the GitHub UI, by CLI, or by authorizing you to run `gh pr merge`),
476
867
  proceed to closeout. **GitHub is the source of truth for the merge, not this
477
868
  conversation** — closeout confirms it via `gh pr view`.
478
869
 
870
+ ### Executing an authorized merge — the checks precondition
871
+
872
+ "Merge it" is a **conditional authorization**: the agent merges _when it is safe to do
873
+ so_, not an order to execute immediately. The human's yes carries the implicit
874
+ assumption that CI is fine; this contract makes that assumption an explicit
875
+ precondition. Not green ⇒ you never merge on your own — you re-present this gate with
876
+ the real state. (The failure pattern this kills: nobody _decided_ to merge on red — an
877
+ authorization whose background assumption was false got executed without looking.)
878
+
879
+ So never run a bare `gh pr merge`. Execute the merge through the shared executor, which
880
+ verifies the check status the platform reports for the PR and waits — bounded — for
881
+ pending checks (`merge.checks_timeout_secs` in `harness.config.yml`, default ~10 min).
882
+ For a task PR, always pass `--approve-issue` with the task's issue number — that arms
883
+ the **stale-approve guard**: the executor reads the Reviewer's APPROVE record
884
+ (`Reviewed-tree` / `Diff-fingerprint`) from that issue and refuses to merge content
885
+ that no longer matches what the APPROVE reviewed (a clean update-branch stays valid;
886
+ any content change does not):
887
+
888
+ ```bash
889
+ .claude/hooks/lib/merge-pr.sh <pr> --approve-issue <issue> --squash # merge-strategy flags pass through to `gh pr merge`
890
+ ```
891
+
892
+ Act on its exit code:
893
+
894
+ - **0 — merged.** Proceed to closeout.
895
+ - **10 — checks red.** Never merge on red by omission. Re-present the gate with the
896
+ failure: "checks red: <check> fails — merge anyway / wait / want to look at it?".
897
+ Merging on red stays possible, but only as the human's informed decision — on that
898
+ explicit yes, re-run with `--force`.
899
+ - **30 — still pending after the bound.** The authorization never expires silently; it
900
+ expires by asking: "checks still running after <N> min — keep waiting, or leave it
901
+ and I'll tell you when they settle?". "Keep waiting" = re-run the executor (a fresh
902
+ bound, or a longer one via `--timeout-secs <secs>`).
903
+ - **40 — stale approve: the PR content changed after the review.** A push landed in
904
+ the merge-gate window (another dev, a re-invoked implementer) and the diff no longer
905
+ matches what the APPROVE reviewed. Never merge it on the old verdict: route the PR
906
+ back to the Reviewer — the same back-to-review route as the comments path below; a
907
+ fresh APPROVE re-records the hashes — then re-surface this gate. Merging anyway
908
+ stays possible, but only as the human's informed decision — on that explicit yes,
909
+ re-run with `--force` (which skips the checks precondition too: make sure the
910
+ informed yes covers both).
911
+ - **20 — no checks reported (after the grace window).** Never merge alone, whatever the
912
+ cause — repo with no CI, CI outage, path filters: don't try to auto-classify. Ask:
913
+ "I saw no checks available on this PR — merge?". If the human's answer is standing
914
+ ("this repo has no CI — merge without checks"), record it **now** as
915
+ `merge.allow_no_checks: true` in `harness.config.yml` (the executor reads the working
916
+ tree, so no later merge — including this task's closeout — re-asks); the line lands
917
+ on the base with the closeout record PR's commit, never a direct push. For the merge
918
+ at hand, re-run with `--force`.
919
+ - **1 (or any other non-zero)** — not merged, and **not a verdict**: either the check
920
+ status could not be read (`gh`/auth/network failure — the precondition is
921
+ unverifiable, which is _not_ the same as "checks failed") or the merge attempt itself
922
+ was rejected (branch protection wants approval, a conflict, a bad ref). The
923
+ executor's stderr says which — surface that, verbatim, at the gate.
924
+
925
+ The precondition is platform-neutral by design — "the merge executor verifies the check
926
+ status the platform reports for the PR"; `gh` is the GitHub rendering of it. Branch
927
+ protection is the user's belt: the harness executes merges and cannot assume it is
928
+ configured, so the executor carries its own precondition either way.
929
+
479
930
  ### When the human leaves review comments instead of merging
480
931
 
481
932
  The human may respond at this gate not by merging but by **leaving comments on the PR**.
@@ -490,7 +941,14 @@ of an `in-review` task surfaces the open PR's comments and routes here — see
490
941
  route as a Reviewer rejection: re-invoke the Implementer sub-agent (fresh context)
491
942
  with the feedback (transient, no dedicated label). Skip pure acknowledgements or
492
943
  questions that need no code.
493
- 3. **After the fix commit, draft do not auto-post the replies.** Compose a short
944
+ 3. **Route the fixed PR to re-review.** The fix commits are new, unreviewed content
945
+ the Reviewer's standing APPROVE no longer covers them (and the executor's
946
+ stale-approve guard would refuse the merge with exit 40 anyway). Invoke the
947
+ Reviewer on the updated PR (continued re-review of its own findings when the
948
+ comments echo them; fresh otherwise); an approving verdict posts a fresh APPROVE
949
+ with fresh hashes. A reject routes back to step 2 — never draft "done" replies on
950
+ work that hasn't re-passed review.
951
+ 4. **After the re-APPROVE, draft — do not auto-post — the replies.** Compose a short
494
952
  "done ✅" reply threading each addressed comment, then **offer to post them with one
495
953
  confirmation**. Posting a reply inside someone's review thread is outward-facing and
496
954
  notifies the reviewer, so it is a **HITL gate, never automatic**. On approval, post
@@ -499,7 +957,7 @@ of an `in-review` task surfaces the open PR's comments and routes here — see
499
957
  identity it uses for issues, PRs, and merges; there is no separate bot identity). The
500
958
  fix commit is visible on the PR regardless, so declining only skips the
501
959
  acknowledgement, not the fix.
502
- 4. **Re-surface the merge gate** above.
960
+ 5. **Re-surface the merge gate** above.
503
961
 
504
962
  ## Closeout
505
963
 
@@ -508,17 +966,26 @@ GitHub — `gh pr view <pr> --json state,mergedAt` reports `MERGED`, regardless
508
966
  was merged). Closeout **archives, it does not delete, and it records via a dedicated PR**:
509
967
  it raises durable decisions to ADRs, `git mv`s the spec + `discoveries.md`
510
968
  into `.claude/state/tasks/_archive/<id>/`, drops only `progress.md`, and lands the
511
- `history.md` append + the archival on a `harness/closeout-<id>` PR merged with
512
- `gh pr merge` `--auto`. Nothing is pushed direct to the base the closeout record obeys
513
- the same branch isolation as every other change. The skill owns the full mechanics.
514
-
515
- **Closeout splits into two phases** because `--auto` defers to branch protection. If the
516
- closeout PR self-merges (protection is PR + checks only), closeout finalizes in one go. If
517
- protection requires human approval **or auto-merge is disabled repo-wide, which makes
518
- `--auto` error rather than queue** the PR waits: flip the issue to
519
- `harness:status:closeout-pending`, tell the human the record PR is open, and stop. A later
520
- `/resume` of a `closeout-pending` task finalizes once that PR is merged (see Dispatch
521
- RESUME).
969
+ `history.md` append + the archival on a `harness/closeout-<id>` PR self-merged through
970
+ the same checks-precondition executor as the merge gate (`.claude/hooks/lib/merge-pr.sh`
971
+ — **the executor never self-merges on anything but green**; no standing human
972
+ authorization exists on this path, so every not-green outcome takes one of the skill's
973
+ exits self-fix, park, or a human's informed decision never an autonomous merge).
974
+ Nothing is pushed direct to the base the
975
+ closeout record obeys the same branch isolation as every other change. The skill owns
976
+ the full mechanics, including what to do on red, absent, or still-pending checks. A
977
+ task that is a **part of a partition** (its body carries `Part <k> of #<parent>`) also,
978
+ at finalize, ticks its row in the parent's checklist and on the last part — closes the
979
+ parent with a summary comment; the skill's finalize step owns it (mechanics in
980
+ `.claude/agents/partition.md`).
981
+
982
+ **Closeout splits into two phases** because the self-merge only happens on green. If the
983
+ closeout PR's checks pass within the bound (and branch protection asks nothing more),
984
+ closeout finalizes in one go. Otherwise — checks red (and not self-fixable), no checks
985
+ and no standing answer, timeout, or protection requiring human approval — the PR waits:
986
+ flip the issue to `harness:status:closeout-pending`, tell the human the record PR is
987
+ open and why it didn't merge, and stop. A later `/resume` of a `closeout-pending` task
988
+ finalizes once that PR is merged (see Dispatch → RESUME).
522
989
 
523
990
  **Closeout is the Architect's reliable activation point**: before
524
991
  archiving, the skill drives three durable-capture activations, **asymmetric by design** —
@@ -528,7 +995,7 @@ path (the Architect reads the merged diff itself) — no pre-offer, the map
528
995
  tracks reality and the edit is reviewed in the closeout PR), and `playbook-iterate` (HITL
529
996
  offer once per task, for a reusable pattern no `T6` conflict already routed). Closeout
530
997
  never drafts the artifact itself — it lights up the Architect, who owns the criteria
531
- (§Architect on-demand). Each activation no-ops when its skill isn't installed.
998
+ (§Architect). Each activation no-ops when its skill isn't installed.
532
999
 
533
1000
  Before any of this, enforce the discovery invariant: **no `discoveries.md` entry may lack
534
1001
  a resolved `**Resolution**`block, and no`harness:discovery:\*` label may remain.** An