@lemoncode/lemony 0.5.0 → 0.6.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 (32) hide show
  1. package/README.md +17 -16
  2. package/catalog/VERSION +1 -1
  3. package/catalog/agents/implementer.md +36 -1
  4. package/catalog/agents/orchestrator.md +206 -83
  5. package/catalog/agents/reviewer.md +8 -3
  6. package/catalog/agents/spinoff.md +3 -2
  7. package/catalog/agents/ui-design.md +3 -1
  8. package/catalog/agents/ui-designer.md +6 -3
  9. package/catalog/commands/pause.md +50 -5
  10. package/catalog/commands/resume.md +13 -2
  11. package/catalog/commands/spinoff.md +5 -3
  12. package/catalog/commands/sync-design-tokens.md +6 -2
  13. package/catalog/harness.config.schema.json +4 -0
  14. package/catalog/hooks/init.sh +80 -7
  15. package/catalog/hooks/lib/live-branch.sh +37 -0
  16. package/catalog/hooks/lib/merge-pr.sh +17 -6
  17. package/catalog/hooks/lib/playbook-scan.sh +4 -2
  18. package/catalog/hooks/session-close.sh +26 -7
  19. package/catalog/schemas/tier2-events-history.md +33 -2
  20. package/catalog/schemas/tier2-events.md +30 -22
  21. package/catalog/skills/build-ui/SKILL.md +5 -2
  22. package/catalog/skills/design-tool-sync/SKILL.md +48 -7
  23. package/catalog/skills/grill-ui/SKILL.md +4 -1
  24. package/catalog/skills/grill-ui/ui-handoff-format.md +2 -1
  25. package/catalog/skills/mutation-testing/SKILL.md +22 -8
  26. package/catalog/skills/prd-to-spec/SKILL.md +27 -5
  27. package/catalog/skills/review-pr/SKILL.md +7 -1
  28. package/catalog/skills/review-pr/reference.md +3 -2
  29. package/catalog/templates/claude-code/agents.md.tpl +2 -1
  30. package/catalog/templates/claude-code/harness.config.yml.tpl +12 -3
  31. package/dist/cli.mjs +2579 -775
  32. package/package.json +11 -10
package/README.md CHANGED
@@ -128,24 +128,25 @@ directly; the Orchestrator and sub-agents do, gated by your repo's capabilities.
128
128
 
129
129
  ## Commands
130
130
 
131
- The CLI ships 13 verbs. Run `lemony <command> --help` (or `-h`) for usage;
131
+ The CLI ships 14 verbs. Run `lemony <command> --help` (or `-h`) for usage;
132
132
  `lemony version` (or `--version` / `-v`) prints the installed version.
133
133
 
134
- | Command | What it does | Key flags |
135
- | --------------- | --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
136
- | `install` | Install into a fresh repo, or reconcile a pre-existing `.claude/`. | `--target=<claude-code>` `--task-storage-repo=<owner/name>` `--on-conflict=<vendor\|client>` |
137
- | `update` | Move the install to the CLI's catalog version (3-way merge). | `--on-conflict=<vendor\|client>` `--dry-run` |
138
- | `repair` | Re-sync at the **pinned** version (restore missing files, never clobber edits). | `--dry-run` |
139
- | `rollback` | Restore a pre-change snapshot (offline). | `--to=<version>` `--list` `--cleanup` `--force` |
140
- | `uninstall` | Remove vendor-managed files (keeps your docs, state, adopted skills). | `--labels` |
141
- | `doctor` | Diagnose the installation (read-only); proposes `repair`. | — |
142
- | `status` | Show installed version, branch drift, and open tasks. | — |
143
- | `emit` | Append a telemetry event to `.claude/state/events.jsonl`. | `<type> [--key=value …]` |
144
- | `discovery` | Reflect a raised/resolved discovery onto its issue (label flip; `pause` also comments). | `<pause\|resume>` `--task-id=<id>` `--tier=<T1..T6>` `--status=<…>` `--note=<text>` |
145
- | `design-tokens` | Validate the design-token file, check WCAG contrast, or sync with a design tool (consume-if-exists). | `<validate\|contrast\|import\|export>` `--scan=<dir>` `--from=<file>` `--apply` `--only=<paths>` |
146
- | `review-ledger` | Validate the Reviewer's evidence-ledger sidecar against the spec, the anchored diff and the declared gates (deterministic, agent-free). | `validate` `--task-id=<id>` `--anchor=<oid>` `--step=<N>` `--full-pass` |
147
- | `spinoff` | Capture a non-blocking defect found mid-task as a pending stub. | `--title=<text>` `--body=<text>` `--parent=<id>` `--severity=<…>` `--kind=<…>` |
148
- | `telemetry` | Inspect or control the local anonymous telemetry. | `status` `show` `flush` `enable` `disable [--purge-local]` |
134
+ | Command | What it does | Key flags |
135
+ | --------------- | --------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
136
+ | `install` | Install into a fresh repo, or reconcile a pre-existing `.claude/`. | `--target=<claude-code>` `--task-storage-repo=<owner/name>` `--on-conflict=<vendor\|client>` |
137
+ | `update` | Move the install to the CLI's catalog version (3-way merge). | `--on-conflict=<vendor\|client>` `--dry-run` |
138
+ | `repair` | Re-sync at the **pinned** version (restore missing files, never clobber edits). | `--dry-run` |
139
+ | `rollback` | Restore a pre-change snapshot (offline). | `--to=<version>` `--list` `--cleanup` `--force` |
140
+ | `uninstall` | Remove vendor-managed files (keeps your docs, state, adopted skills). | `--labels` |
141
+ | `doctor` | Diagnose the installation (read-only); proposes `repair`. | — |
142
+ | `status` | Show installed version, branch drift, and open tasks (`--local`: no network call). | `--local` |
143
+ | `emit` | Append a telemetry event to `.claude/state/events.jsonl`. | `<type> [--key=value …]` |
144
+ | `discovery` | Reflect a raised/resolved discovery onto its issue (label flip; `pause` also comments). | `<pause\|resume>` `--task-id=<id>` `--tier=<T1..T6>` `--status=<…>` `--note=<text>` |
145
+ | `checkpoint` | Resolve a human checkpoint answer: commits, push and the `step_completed` emit in one call (used by the Orchestrator). | `<ok\|changes\|ok_downgrade>` `--task-id=<id>` `--auto-commit=<on\|off>` `--step=<N>` `--review-iterations=<K>` |
146
+ | `design-tokens` | Validate the design-token file, check WCAG contrast, or sync with a design tool (consume-if-exists). | `<validate\|contrast\|import\|export>` `--scan=<dir>` `--from=<file>` `--apply` `--only=<paths>` |
147
+ | `review-ledger` | Validate the Reviewer's evidence-ledger sidecar against the spec, the anchored diff and the declared gates (deterministic, agent-free). | `validate` `--task-id=<id>` `--anchor=<oid>` `--step=<N>` `--full-pass` |
148
+ | `spinoff` | Capture a non-blocking defect found mid-task as a pending stub. | `--title=<text>` `--body=<text>` `--parent=<id>` `--severity=<…>` `--kind=<…>` |
149
+ | `telemetry` | Inspect or control the local anonymous telemetry. | `status` `show` `flush` `enable` `disable [--purge-local]` |
149
150
 
150
151
  The harness keeps a **committed baseline** under `.claude/.harness/baseline/<version>/` — a
151
152
  verbatim copy of every installed vendor file at the pinned version — so `update` is a true
package/catalog/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.0
1
+ 0.6.0
@@ -125,6 +125,31 @@ what you run, only how many calls carry it.
125
125
  a deviation from the spec, or a side-finding is always stated, however long the
126
126
  list.
127
127
 
128
+ ## Hand probes (breaking source on purpose)
129
+
130
+ When you deliberately mutate source to confirm a test catches it — because your
131
+ invocation asks for it, or your own judgment does — the probe is **one shell command
132
+ whose restore is a trap installed before the mutation**, never separate edit / test /
133
+ revert calls:
134
+
135
+ ```bash
136
+ ( trap 'mv -f src/queue.ts.bak src/queue.ts 2>/dev/null' EXIT; \
137
+ trap 'kill $! 2>/dev/null; exit 130' INT TERM HUP; \
138
+ sed -i.bak '128s/>=/>/' src/queue.ts; \
139
+ npx vitest run src/queue.spec.ts & wait $! )
140
+ ```
141
+
142
+ The session can stop at any instant — a human's Esc stops your running command
143
+ with SIGTERM and follows it with a SIGKILL within a second or two. The test runs
144
+ in the background under `wait`, so the signal ends the wait at once and the traps
145
+ restore before the SIGKILL lands (a foreground runner would hold every trap until
146
+ it exits). A mutant stranded between
147
+ the edit and a hand revert survives the session boundary as a deliberately wrong
148
+ line, and under auto-commit OFF nothing tells it apart from work in progress (the
149
+ `mutation-testing` skill carries the same recipe). After the trip, `git status`
150
+ shows the tree exactly as before the probe; a leftover `.bak` means a probe was
151
+ stranded — restore from it before anything else.
152
+
128
153
  ## Staging protocol (auto-commit OFF)
129
154
 
130
155
  Active **only when your invocation says so** — the human chose to review the work
@@ -153,7 +178,17 @@ iteration only knows what this contract and the worktree tell it:
153
178
  - **On a fix iteration** (checkpoint `changes`), the Orchestrator hands you a
154
179
  worktree that may carry the human's own revalidated edits: **stage everything
155
180
  first** (`git add -A` — that snapshot is your safe starting point), then
156
- iterate under this same protocol.
181
+ iterate under this same protocol. When the feedback says the delta
182
+ revalidated **red**, that snapshot is a red starting point, not a green floor:
183
+ a rollback returns to it (the human's edits survive), and your first green
184
+ stage replaces it.
185
+ - **On a resume with unverified work** (the Orchestrator names unstaged files it
186
+ found mid-implementation): the opposite of the fix iteration — **stage none of
187
+ it on sight**. It was never proven green and may be a probe stranded mid-flight.
188
+ Restore any `*.bak` first, read each hunk against the index, then prove each
189
+ piece green (or redo it) before it enters a save-point. When the resume is under
190
+ a `(red human delta)` fix-loop line, the staged index may still be that red
191
+ starting point: run the suite before trusting it as a floor.
157
192
 
158
193
  ## Skills
159
194
 
@@ -352,7 +352,8 @@ One step = one `tasks.md` **group**, 1:1 with the grouping the human approved at
352
352
  spec gate. Tasks inside a group stay atomic — the grouping sets how often review and
353
353
  the human checkpoint run, never how the Implementer works. A `tasks.md` without group
354
354
  headers (a legacy or hand-written spec) runs **one task per group** — the pre-grouping
355
- cadence. Tasks added mid-implementation (a resolved discovery) default to **their own
355
+ cadence. Tasks added mid-implementation (a resolved discovery) take the next free
356
+ `T<n>` — a suffixed `T12b` is reported, not read — and default to **their own
356
357
  group**, appended at the end of the loop — M grows, and already-resolved step numbers
357
358
  never shift; a narrowing (a resolved partition discovery) trims or removes groups from
358
359
  the current one onward and trims a resolved group in place — M may shrink, resolved step
@@ -430,9 +431,11 @@ numbers still never shift. For each group, in order:
430
431
  whenever any problem lives outside the sidecar:
431
432
 
432
433
  - **any spec-side problem** — the verb counts them out loud (`unknown-risk-class`, a
433
- tag or ref list that did not parse, a duplicated group number, an orphan task, an
434
- empty group, a dangling requirement ref, a step with no group, a task still
435
- `[ ]` in a group the loop has passed) → no retry. They
434
+ tag or ref list that did not parse, a task line or group header that did not
435
+ parse, a duplicated group number, a task id on two task lines, an orphan task, an
436
+ empty group, a dangling
437
+ requirement ref, a step with no group, a task still `[ ]` in a group the loop
438
+ has passed) → no retry. They
436
439
  live in `tasks.md` / `requirements.md`, which the Reviewer cannot fix: stop and
437
440
  bring them to the human as an **anticipated checkpoint** (below) with the verb's
438
441
  lines as the content — the spec needs a decision, and the fix routes as a discovery
@@ -440,7 +443,7 @@ numbers still never shift. For each group, in order:
440
443
  the sidecar on disk: green → the checkpoint; a sidecar-side red then follows the
441
444
  one-retry rule below. The human's `ok` on an anticipated checkpoint is their call,
442
445
  as at every gate — what never happens is you relaying a red as an APPROVE.
443
- **`unticked-completed-task` is the one spec-side kind that needs no discovery**:
446
+ **`unticked-completed-task` is one of two spec-side kinds that need no discovery**:
444
447
  the Implementer ticks each task at green, so an unticked task in a passed group
445
448
  is a forgotten mark or work that was never done, and only the human can tell
446
449
  which. Name the task ids in the checkpoint and ask. `ok` = "done, the mark was
@@ -448,7 +451,16 @@ numbers still never shift. For each group, in order:
448
451
  do** (`git add .claude/state/tasks/<id>/spec/tasks.md`) — a mediated edit, staged
449
452
  on arrival like a Spec Author update, so the checkpoint contract's spec check
450
453
  (item 4) never reads it as an unconfirmed human spec edit — then re-run the verb.
451
- Wherever an OK's composite commits state, the staged tick rides its
454
+ The other is a `malformed-task-line` about the **box** (neither `[ ]` nor `[x]`: an
455
+ in-progress `[-]`, a padded `[ ]`; a line not written `- [ ] T<n>` — **no** box,
456
+ a numbered item, inside a quote — is a `shape` defect — maybe a note, not a task —
457
+ and routes as a discovery) — the same done-mark, so ask
458
+ the same question
459
+ and write `- [x]` on `ok`, `- [ ]` otherwise, staged and committed the same way.
460
+ Every later mention of `unticked-completed-task` in this file — the tick commit,
461
+ the `[unticked: …]` suffix, the full-pass path, the one mediated edit that is not
462
+ a discovery — covers this box case too, the `- [ ]` rewrite on `changes` included.
463
+ Wherever an OK's `checkpoint` call commits state, the staged tick rides its
452
464
  `.claude/state` half and needs nothing more: every step OK (both knob states),
453
465
  and auto-commit OFF's deferral-ending checkpoint OK, which its pre-gate full pass
454
466
  feeds. **At the merge-gate presentation nothing else commits state before the
@@ -463,10 +475,10 @@ numbers still never shift. For each group, in order:
463
475
  ```
464
476
 
465
477
  A merged `tasks.md` still reading `[ ]` is exactly the harm the kind exists to
466
- stop. That post-APPROVE state write moves the stale-approve fingerprint the way
467
- the ledger's own write does, and routes as the merge gate's exit-40 rule says
468
- (§Merge gate) — a fresh APPROVE re-records the hashes; `--force` stays the
469
- human's separate, informed call. `changes` = the
478
+ stop. That post-APPROVE state write lives under `.claude/state`, which the
479
+ stale-approve fingerprint leaves out (as it does the ledger's own write), so it
480
+ does not invalidate the APPROVE; a code change riding along in the same push
481
+ still would (§Merge gate, exit 40). `changes` = the
470
482
  task is not done → the normal fix iteration, feedback naming the task. Never tick
471
483
  on your own judgment: the mark is the Implementer's claim, and the verb exists so
472
484
  a missing one is read by a person, not smoothed over by you.
@@ -476,7 +488,7 @@ numbers still never shift. For each group, in order:
476
488
  verb's `[kind] message` lines **verbatim** in the spawn prompt — the delta is the
477
489
  payload (§Sub-agent invocation). This is its own cap of **one retry**, separate from
478
490
  the REJECT cap below: a Reviewer that cannot hit the format must not burn the
479
- Implementer's budget. Set the open step's transient line to
491
+ Implementer's budget. Set the open step's transient tail to
480
492
  `awaiting ledger retry (step N/M, retry 1/1)` (step 5) **before** re-invoking — the
481
493
  retry is spent the moment it is issued, so a session that dies mid-retry resumes
482
494
  knowing it is gone. Validate the second APPROVE the same way; a **second red** →
@@ -510,10 +522,10 @@ numbers still never shift. For each group, in order:
510
522
  3. **Human checkpoint** — first run §Checkpoint contract's **spec check** (item
511
523
  4): the state commit below sweeps `spec/`, so an unconfirmed human spec edit
512
524
  must route as a discovery **before** anything commits it. Then set the open
513
- step's `progress.md` line to
525
+ step's `progress.md` tail to
514
526
  `awaiting human checkpoint (step N/M)` (step 5), then commit the task state and
515
527
  **push the branch, best-effort**, as **one composite invocation** (§Turn economy).
516
- This commit and step 4's OK-side twin are **yours, anchored to your checkpoint
528
+ This commit and step 4's `checkpoint` call are **yours, anchored to your checkpoint
517
529
  turns** — never delegated to a sub-agent's return path (a commit left to a
518
530
  sub-agent may never land, and the checkpoint is then invisible to a cold
519
531
  `/resume`):
@@ -539,9 +551,14 @@ numbers still never shift. For each group, in order:
539
551
  Then present the step **per §Checkpoint contract**: what was built and how to
540
552
  run it, the group's commits and touched files, the anchored group diff, the
541
553
  richer-view offer, and the human-delta check. Three answers:
542
- - **OK** → emit `step_completed` (below), next group.
543
- - **Changes** (with feedback) → fresh Implementer with the feedback → per-step
544
- review again (step 2; the review-iteration count resets) → checkpoint again.
554
+ - **OK** → resolve it with the `checkpoint` verb (step 4), next group.
555
+ - **Changes** (with feedback) → resolve it with the `checkpoint` verb (`changes`,
556
+ step 4) in the turn that records the answer — the one that rewrites the open
557
+ line's tail to `checkpoint: changes → fix-loop iteration K` (step 5) — before
558
+ dispatching anyone (Implementer, Spec Author, or a discovery) →
559
+ fresh Implementer
560
+ with the feedback → per-step review again (step 2; the review-iteration count
561
+ resets) → checkpoint again.
545
562
  Human-requested changes go through review like any other fix — **nothing reaches
546
563
  the human unreviewed**. But first classify the request: if it **contradicts the
547
564
  approved spec** (`requirements.md`/`design.md`), don't rewrite anything silently —
@@ -549,32 +566,43 @@ numbers still never shift. For each group, in order:
549
566
  pause label as usual) so the interpretation is confirmed with the human **before**
550
567
  the Spec Author updates the spec and the loop resumes. In doubt, raise it —
551
568
  mediation confirms cheaply.
552
- - **OK and switch to all-at-once** → emit `step_completed` with
553
- `checkpoint_result=ok_downgrade`, update `progress.md`
569
+ - **OK and switch to all-at-once** → update `progress.md`
554
570
  (`Mode: step-by-step (downgraded to all-at-once at step N)` — the gate choice
555
571
  stays first; the downgrade is a suffix, because `task_done.mode` records the gate
556
- choice), and run the **remaining** tasks as a single Implementer invocation
572
+ choice), resolve it with the `checkpoint` verb (`ok_downgrade`, step 4), and run
573
+ the **remaining** tasks as a single Implementer invocation
557
574
  (all-at-once; the auto-commit knob keeps its recorded setting).
558
575
  Checkpoint OKs already given stand.
559
576
 
560
577
  Aborting needs no protocol: the human interrupts the session; `/resume` picks the
561
578
  step sub-state back up from `progress.md`.
562
579
 
563
- 4. **Telemetry** — every **resolved checkpoint** emits one event (so a step the human
564
- sent back emits more than once, same `--step`); the emit, the step's resolved
565
- `progress.md` line (step 5) and the resolution state commit (on OK, plain or
566
- downgrade: `step(<id>): step <N> checkpoint OK`, carrying the same
567
- `-- .claude/state/tasks/<id>/` pathspec as step 3's twin so other staged
568
- content never rides mislabeled) + best-effort push ride as
569
- **one composite turn** (§Turn economy) — without that commit a cold `/resume`
570
- still reads `awaiting` after the last group. Auto-commit OFF: on OK the
571
- same composite additionally carries the group's **code commit** — the deferral
572
- ends here, so code commit + state commit + push + emit land together (exact
573
- commands, the pathspec split of the mixed index, and the all-at-once no-emit
574
- rule in §Auto-commit OFF); on
575
- `changes` nothing is committed and the deferral continues. `<review-iterations>` is the number
580
+ 4. **Resolution and telemetry** — every **resolved checkpoint** emits one
581
+ `step_completed` (so a step the human sent back emits more than once, same
582
+ `--step`). Write the step's resolved `progress.md` line (step 5) first, then
583
+ resolve the answer with the **`checkpoint` verb** (§Checkpoint contract, item 5)
584
+ in the same turn — the call makes the commits, the push and the emit together,
585
+ emit last:
586
+ - **OK** (plain or `ok_downgrade`): the resolution state commit
587
+ `step(<id>): step <N> checkpoint OK` over the task's state — without it a cold
588
+ `/resume` still reads `awaiting` after the last group; auto-commit OFF: preceded
589
+ by the group's **code commit** `step(<id>): step <N>` (the deferral ends here,
590
+ §Auto-commit OFF); then a best-effort push, then the emit.
591
+ - **`changes`**: no commit; auto-commit OFF: it stages the human delta, and the
592
+ deferral continues; then the emit — **the emit never defers**.
593
+
594
+ An answer that arrives bundled with another request (`ok` + `/pause`, a spinoff)
595
+ still runs the verb before that request runs. A rejected commit (a pre-commit
596
+ hook) stops the verb before the emit: fix the cause and run the same call again —
597
+ what already landed is skipped. An answer given **in this session** whose verb
598
+ call never ran is still resolved, late — never dropped; never back-fill events
599
+ from other sessions or machines: while the work has not moved on — no later
600
+ group started and, for a `changes`, no fix-loop Implementer dispatched — run the
601
+ verb now; once it has (its staging would sweep that work into step N), or when the
602
+ verb refuses because the answer's commits were already made without it, emit
603
+ by hand with that phase's own `--review-iterations`. `<review-iterations>` is the number
576
604
  of Reviewer invocations that preceded this checkpoint (≥ 1; resets after a
577
- "changes"):
605
+ "changes"). The late emit:
578
606
 
579
607
  ```bash
580
608
  .claude/hooks/lib/lemony.sh emit step_completed \
@@ -587,7 +615,8 @@ numbers still never shift. For each group, in order:
587
615
  ```
588
616
 
589
617
  **Attribution — name the component the checkpoint friction is about, or
590
- omit.** The two `--attributed-*` flags are **optional**; they're meaningful when
618
+ omit.** The two `--attributed-*` flags — on the verb, or on a late emit — are
619
+ **optional**; they're meaningful when
591
620
  the checkpoint surfaced friction (`changes`, or repeated `review-iterations`) and
592
621
  you can name what produced it — usually the Implementer; a ledger retry is the
593
622
  Reviewer's own. **Omit both on a clean
@@ -609,7 +638,9 @@ numbers still never shift. For each group, in order:
609
638
  5. **`progress.md` step log** — keep the sub-state explicit so `/resume` can re-enter
610
639
  mid-loop. Under a `## Step log` heading, one line per resolved step; the **open**
611
640
  step's line is transient — update it in place as the loop progresses
612
- (`fix-loop iteration K — in progress` while implementing/reviewing,
641
+ (`fix-loop iteration K — in progress` while implementing/reviewing — auto-commit
642
+ OFF: written in the same turn that stages the human delta, with a
643
+ `(red human delta)` suffix when it revalidated red, §Auto-commit OFF —
613
644
  `awaiting ledger retry (step N/M, retry 1/1)` while the fresh Reviewer redoes a red
614
645
  ledger, `awaiting human checkpoint (step N/M)` while waiting on the human — with
615
646
  the `[unticked: T3, T4]` suffix when the checkpoint is the anticipated one an
@@ -624,9 +655,21 @@ numbers still never shift. For each group, in order:
624
655
  - step 1/6 (anchor a1b2c3d) — review ×1 → checkpoint: OK
625
656
  - step 2/6 (anchor e4f5a6b) — review ×3 (2 rejects: missing error path; flaky spec) → checkpoint: changes → review ×1 → checkpoint: OK
626
657
  - step 3/6 (anchor c7d8e9f) — review ×2 (ledger retry ×1) — ledger: criteria 3/3 (basis: requirements), gates 2/2 (basis: config) → checkpoint: OK
627
- - step 4/6 (anchor f1a2b3c) — awaiting human checkpoint (step 4/6)
658
+ - step 4/6 (anchor f1a2b3c) — review ×1 → awaiting human checkpoint (step 4/6)
628
659
  ```
629
660
 
661
+ A review phase — the Reviewer invocations between two checkpoints — is **one**
662
+ `review ×K (N rejects: …)` segment: K counts that phase's invocations (it resets after
663
+ `changes`, as `--review-iterations` does) and N its **REJECT verdicts**, not findings
664
+ — one REJECT listing two problems is still `1 reject`; list findings freely, only the
665
+ number counts verdicts. Update the open phase's segment in place; never append a
666
+ second segment that repeats a phase already on the line. While the step is open,
667
+ its transient sub-state stays the line's tail after the segments already written
668
+ (`… → checkpoint: changes → fix-loop iteration 1 — in progress`): each new sub-state
669
+ replaces only the tail, and the step's resolution replaces the tail with its outcome.
670
+ The turn that writes a `checkpoint: <answer>` also runs the `checkpoint` verb
671
+ (step 4), `changes` included.
672
+
630
673
  Those transient sub-state strings are exactly what a later `/resume` re-enters
631
674
  on: the awaiting line re-presents the pending checkpoint, the fix-loop line
632
675
  re-enters the implement→review loop at that iteration, and the ledger-retry line
@@ -655,7 +698,7 @@ the step loop the transient line is `awaiting ledger retry (full pass, retry 1/1
655
698
  auto-commit-OFF checkpoint when there is one, otherwise the merge-gate presentation,
656
699
  with the verb's lines as the content. An `unticked-completed-task` there resolves as
657
700
  in step 2's routing bullet — on `ok`, tick and stage the named tasks; at the
658
- auto-commit-OFF checkpoint the OK's composite commits them, at the merge-gate
701
+ auto-commit-OFF checkpoint the OK's `checkpoint` call commits them, at the merge-gate
659
702
  presentation you commit them yourself — then re-run the verb.
660
703
 
661
704
  ## Checkpoint contract (how a human gate presents work)
@@ -686,7 +729,8 @@ contract, not a vibe:
686
729
  natively — it IS uncommitted.
687
730
  3. **What was built and how to run it** — from the Implementer's verification line,
688
731
  as today. Checkpoint narration is the product, never overhead (§Turn economy).
689
- 4. **The human delta — always detected, always revalidated.** Whatever the answer
732
+ 4. **The human delta — always detected, always revalidated.** (Every answer then
733
+ resolves through item 5's call.) Whatever the answer
690
734
  (`ok` or `changes: …`), first detect the human's own edits — in auto-commit
691
735
  OFF, **two checks with distinct routes** (every agent save-point is staged at
692
736
  presentation time, so the staged/unstaged seam is the auto-detect):
@@ -721,21 +765,59 @@ contract, not a vibe:
721
765
  The **spec check runs in both knob states** — in auto-commit ON, run it
722
766
  **before** step 3's `awaiting` state commit, which would otherwise silently
723
767
  commit a pre-existing spec edit before detection. Auto-commit ON's work-delta
724
- detection is simply any uncommitted working-tree change.
768
+ detection is any uncommitted working-tree change outside task state —
769
+ `git status --porcelain -- . ':(exclude).claude/state'` (task state is never a
770
+ human delta here: the spec check above owns the spec, and the rest is yours).
725
771
  The **work delta** then runs the pipeline: present it, confirm it is
726
772
  intended, and **re-run the suite with the delta applied** — the delta never
727
- inherits the group's green. **A red revalidation blocks the OK**: never run
728
- the commit composite on a red suite — re-present the failure and route it as
773
+ inherits the group's green. **A red revalidation blocks the OK**: never resolve
774
+ an OK on a red suite — re-present the failure and route it as
729
775
  `changes` (the human decides: fix it themselves, drop the delta, or hand it
730
776
  to the Implementer). On a green revalidation the delta rides with the group:
731
777
  on OK it lands with
732
778
  the group's work (auto-commit OFF: staged into the group's commit; auto-commit ON:
733
779
  committed as its
734
- own commit — `step(<id>): step <N> human delta` — before the next group); on
780
+ own commit, before you write the resolved line and make item 5's call, with a
781
+ pathspec that keeps task state out of it:
782
+ `git add -A -- . ':(exclude).claude/state' && git commit -m "step(<id>): step <N> human delta" -- . ':(exclude).claude/state'`); on
735
783
  `changes` it stays in the worktree for
736
784
  the fresh Implementer (auto-commit OFF: staged first as the safe starting point —
737
785
  §Auto-commit OFF).
738
786
 
787
+ 5. **Resolve the answer with one call.** Write the resolved `progress.md` line
788
+ first (step-by-step step 5 — the state commit carries it), then, in the same
789
+ turn:
790
+
791
+ ```bash
792
+ .claude/hooks/lib/lemony.sh checkpoint <ok|changes|ok_downgrade> \
793
+ --task-id="<id>" \
794
+ --auto-commit=<on|off> \
795
+ --step=<N> \
796
+ --review-iterations=<count>
797
+ ```
798
+
799
+ `--auto-commit` is the value `progress.md` records; `<count>` is the number of
800
+ Reviewer invocations since the last `changes` (≥ 1). Add
801
+ `--attributed-kind`/`--attributed-name` only when the checkpoint surfaced
802
+ friction you can name (step-by-step step 4, Attribution). The all-at-once gate —
803
+ auto-commit OFF only, a downgraded remainder included — omits `--step` and
804
+ `--review-iterations`: on `ok` it still makes the `task(<id>)` commits, but it
805
+ emits nothing (`step_completed` is step-by-step only). The call makes the
806
+ commits, the best-effort push and the `step_completed` emit together, emit last
807
+ (step-by-step step 4 says what each answer lands). **Never make those commits by
808
+ hand, and never copy them from `git log`**: a checkpoint commit's
809
+ `Lemony-Checkpoint:` trailer is the call that made it. An answer bundled with
810
+ another request (`ok` + `/pause`, a spinoff) runs this call before that request.
811
+ A failed call names the step it stopped at; fix the cause and run the same call
812
+ again. It refuses up front — nothing staged or committed — a repo it cannot
813
+ commit safely (no state for the task id, a detached HEAD, an unfinished merge,
814
+ rebase, cherry-pick or revert, unmerged paths) and, under auto-commit ON, an OK
815
+ that left `progress.md` unchanged (under auto-commit OFF the file is always dirty, so the
816
+ check cannot see a missing line — writing it first is on you): write the resolved
817
+ line first — or, when this answer's commits were
818
+ already made without the call, emit by hand instead (step-by-step step 4's late
819
+ emit).
820
+
739
821
  ## Auto-commit OFF (zero commits + staging save-points)
740
822
 
741
823
  The auto-commit OFF state (chosen at the approval gate — §Implementation mode) moves
@@ -759,6 +841,25 @@ pre-registered exit signals.
759
841
  discovery pause **is** visible cross-machine — its labels and issue comment
760
842
  surface — but the full `discoveries.md` entry stays machine-local until an OK
761
843
  lands it.) Same-machine resume reads the worktree as usual.
844
+ - **A resume mid-implementation treats unstaged work as unverified.** While the
845
+ Implementer is still working a group — `progress.md` is **not** at an
846
+ `awaiting human checkpoint` line — the staged index is the last green
847
+ save-point (under a `(red human delta)` fix-loop line it may still be that
848
+ red starting point: tell the fresh Implementer so — it runs the suite before
849
+ trusting it),
850
+ and whatever a resume finds **unstaged** (outside
851
+ `.claude/state`) — the `/pause` note's `Unverified` line lists it — was never
852
+ proven green, however finished it looks: an interrupted hand probe leaves a
853
+ deliberately wrong line that reads exactly like work in progress. Never stage,
854
+ review, or present it as done on sight. Hand it to the fresh Implementer as
855
+ **unverified work to confirm or redo** — the spawn prompt says so and names the
856
+ files — and it proves each piece green (suite, and for a suspicious hunk the diff
857
+ against the index) before the staging protocol lets it in. A leftover `*.bak`
858
+ beside a source file is a stranded probe: restore from it first. **At an
859
+ `awaiting` checkpoint the rule does not apply**: every agent save-point was
860
+ staged at presentation, so unstaged work there is the **human delta** —
861
+ re-present the checkpoint and route it through the human-delta check (step 4
862
+ of §Checkpoint contract), never to the Implementer as suspect work.
762
863
  - **The gate** runs at end of group (step-by-step) or end of everything
763
864
  (all-at-once — after the Implementer signals done and **before** the
764
865
  `in-review` flip: the PR never opens on uncommitted work). In all-at-once the
@@ -780,43 +881,44 @@ pre-registered exit signals.
780
881
  its third answer, OK-and-downgrade).
781
882
  - **OK ⇒ commit + push, after revalidating.** Re-run the suite over the final
782
883
  worktree (human delta staged in) — the gate's green is fresh, never inherited.
783
- Then the deferral ends as **one composite turn**, splitting the mixed index by
784
- pathspec (`git add -A` staged code and task state together; a bare
785
- `git commit` would swallow both into one commit):
786
-
787
- ```bash
788
- git add -A && \
789
- { git diff --cached --quiet -- . ':(exclude).claude/state' || \
790
- git commit -m "<code-msg>" -- . ':(exclude).claude/state'; } && \
791
- { git diff --cached --quiet -- .claude/state || \
792
- git commit -m "<state-msg>" -- .claude/state; }; \
793
- git push # best-effort — a failure warns, never blocks
794
- ```
795
-
796
- Each commit is **guarded on its half of the index holding changes**, so a
797
- degenerate group no-ops that half instead of short-circuiting the other: a
798
- state-only OK (an audit group whose artifact is progress notes, or a human who
799
- discarded the work in the worktree and answered `ok`) still lands its state
800
- commit — an unguarded `&&` chain would silently drop it while the push still
801
- ran, leaving the resolution nowhere on the branch.
802
-
803
- Step-by-step: `<code-msg>` = `step(<id>): step <N>`, `<state-msg>` =
804
- `step(<id>): step <N> checkpoint OK`, and the `step_completed` emit rides the
805
- same turn (step 4). All-at-once (a downgraded remainder resolves as
806
- all-at-once here too): `<code-msg>` = `task(<id>): implementation`,
807
- `<state-msg>` = `task(<id>): implementation checkpoint OK`, and **nothing is
808
- emitted** —
809
- `step_completed` is step-by-step-only (its `--step` has no meaning here, and
810
- closeout's mode recovery reads any `step_completed` as proof of step-by-step);
811
- the gate resolution reaches telemetry through `task_done` as usual. One commit
812
- per group in v1; all-at-once commits the whole implementation as its single
813
- group.
884
+ Then the deferral ends with the **`checkpoint` verb** (§Checkpoint contract,
885
+ item 5) — also when the OK arrives with `/pause` or a spinoff: run it before
886
+ them (the OK ends the deferral, so `/pause`'s no-commit rule does not reach it).
887
+ It stages the worktree, then splits the mixed index by pathspec into a code
888
+ commit (everything outside `.claude/state`) and a state commit, each **guarded on
889
+ its half holding changes** — a state-only OK (an audit group whose artifact is
890
+ progress notes, or a human who discarded the work in the worktree and answered
891
+ `ok`) still lands its state commit — then pushes best-effort. Step-by-step: the
892
+ commits are `step(<id>): step <N>` and `step(<id>): step <N> checkpoint OK`, and
893
+ the `step_completed` emit follows (step 4). All-at-once (a downgraded remainder
894
+ resolves as all-at-once here too — call without `--step`): the commits are
895
+ `task(<id>): implementation` and `task(<id>): implementation checkpoint OK`, and
896
+ **nothing is emitted** — `step_completed` is step-by-step-only (its `--step` has
897
+ no meaning here, and closeout's mode recovery reads any `step_completed` as proof
898
+ of step-by-step); the gate resolution reaches telemetry through `task_done` as
899
+ usual. One commit per group in v1; all-at-once commits the whole implementation
900
+ as its single group.
814
901
 
815
902
  - **Changes ⇒ the Implementer iterates over the worktree.** Same routing as any
816
903
  rejection (fresh context, ≤3 rejects per step): it first **stages the
817
904
  revalidated human delta** (its suite result rides in the feedback) as its
818
905
  safe starting point, then continues
819
- under the staging protocol. Nothing is committed; the deferral continues.
906
+ under the staging protocol. Nothing is committed and the deferral continues.
907
+ **The `checkpoint` verb (`changes`) stages that delta for you (`git add -A`) —
908
+ run it in the same turn that rewrites the open line's tail to
909
+ `fix-loop iteration K`**, and in step-by-step it emits `changes` there too (step 4;
910
+ all-at-once, a downgraded remainder included, emits nothing — call without
911
+ `--step`): a session that dies
912
+ between the line and the Implementer's own stage-first would otherwise leave
913
+ the human's edits unstaged under a mid-implementation line, where a resume
914
+ reads them as unverified work (the resume rule above). The Implementer's
915
+ stage-first then only picks up task state — a harmless repeat. A delta that
916
+ revalidated **red** (the human handed it to the Implementer to fix) is staged
917
+ the same way — unstaged, the Implementer's first rollback would wipe the
918
+ human's edits — but that floor is **red, not proven green**: write the line as
919
+ `fix-loop iteration K — in progress (red human delta)` and say so in the
920
+ feedback. It is the iteration's red starting point until the Implementer's
921
+ first green stage replaces it.
820
922
  - **Watch-fors — pre-registered failure signatures.** v1 tests in real use whether
821
923
  the three roles of tdd commits (fresh-Implementer memory via the branch,
822
924
  granular save-points, 1:1 per-task history) are missed. If one fires, don't
@@ -930,8 +1032,9 @@ pending checks (`merge.checks_timeout_secs` in `harness.config.yml`, default ~10
930
1032
  For a task PR, always pass `--approve-issue` with the task's issue number — that arms
931
1033
  the **stale-approve guard**: the executor reads the Reviewer's APPROVE record
932
1034
  (`Reviewed-tree` / `Diff-fingerprint`) from that issue and refuses to merge content
933
- that no longer matches what the APPROVE reviewed (a clean update-branch stays valid;
934
- any content change does not):
1035
+ that no longer matches what the APPROVE reviewed (a clean update-branch stays valid,
1036
+ and so does a task-state write under `.claude/state`; any other content change does
1037
+ not):
935
1038
 
936
1039
  ```bash
937
1040
  .claude/hooks/lib/merge-pr.sh <pr> --approve-issue <issue> --squash # merge-strategy flags pass through to `gh pr merge`
@@ -1056,12 +1159,31 @@ the task merge time (`mergedAt` from `gh pr view`). `review_rejections` is the n
1056
1159
  `review_rejected` events recorded for this `task_id` in `events.jsonl` (0 on a
1057
1160
  first-pass approval). `<level>` is `L1` for full-SDD tasks (`harness:sdd`
1058
1161
  label), `L2` for triage tasks (no `harness:sdd`). On **L1**, also pass `--mode` —
1059
- the **gate choice**, always: the first mode named on `progress.md`'s `Mode:` line (a
1060
- `(downgraded …)` suffix doesn't change it; a downgraded task still emits
1061
- `--mode=step_by_step`). If `progress.md` is already archived, recover it from
1062
- `events.jsonl`: ≥ 1 `step_completed` event for this `task_id` means `step_by_step`.
1063
- When the gate choice was step-by-step, also pass `--steps` (the count of
1064
- `step_completed` events for this `task_id`). Omit both on L2:
1162
+ the **gate choice**: the first mode named on `progress.md`'s `Mode:` line, written
1163
+ with underscores (`step-by-step` → `step_by_step`); a `(downgraded …)` suffix
1164
+ doesn't change it, so a downgraded task still emits `--mode=step_by_step`. If
1165
+ `progress.md` is already gone (the closeout PR drops it), read the `Mode:` line
1166
+ from its last committed version:
1167
+
1168
+ ```bash
1169
+ P=.claude/state/tasks/<id>/progress.md
1170
+ git show "$(git log -1 --diff-filter=D --format=%H -- ":/$P")^:$P" | grep -m1 '^Mode:'
1171
+ ```
1172
+
1173
+ Only when that prints no `Mode:` line (git has no such version, or it predates
1174
+ the line), fall back to `events.jsonl`: ≥ 1
1175
+ `step_completed` event for this `task_id` means `step_by_step` — but none on this
1176
+ machine does **not** prove all-at-once (the file is local; the steps may have run
1177
+ elsewhere), so with neither source omit `--mode` rather than guess.
1178
+ When the gate choice was step-by-step, also pass `--steps` and `--checkpoints`,
1179
+ both read from the `step_completed` events whose `task_id` is exactly `<id>`:
1180
+ `--steps` is the number of **distinct** `step` values (a step the human sent back
1181
+ emits again with the same `step` — count it once), `--checkpoints` the number of
1182
+ events. A task whose steps 1–4 each needed one `changes` round has 4 steps and 8
1183
+ checkpoints. On an all-at-once L1 task pass `--mode` only; on L2 omit all three.
1184
+ `events.jsonl` is local to the machine: when this one holds no `step_completed`
1185
+ event for a step-by-step task (its steps ran elsewhere), pass
1186
+ `--mode=step_by_step` without counts — a guessed count is worse than none:
1065
1187
 
1066
1188
  ```bash
1067
1189
  .claude/hooks/lib/lemony.sh emit task_done \
@@ -1070,7 +1192,8 @@ When the gate choice was step-by-step, also pass `--steps` (the count of
1070
1192
  --cycle-time-h=<hours> \
1071
1193
  --review-rejections=<count> \
1072
1194
  --mode=<all_at_once|step_by_step> \
1073
- --steps=<count>
1195
+ --steps=<count> \
1196
+ --checkpoints=<count>
1074
1197
  ```
1075
1198
 
1076
1199
  ## Sub-agent invocation
@@ -227,7 +227,9 @@ What the validator enforces in this version, so you never have to guess:
227
227
  actually ran, declared or not.
228
228
  - **Spec-side problems are reported, never dropped — and they are not yours to fix.** A
229
229
  `[risk: …]` tag outside the vocabulary (`unknown-risk-class`), a tag or a `(R<n>)` ref
230
- list that did not parse, a duplicated group number, a task above the first header, an
230
+ list that did not parse, a task line or group header that did not parse (`[-]`,
231
+ `T12b`, `### Group 3`), a duplicated group number, a task id on two task lines, a task
232
+ above the first header, an
231
233
  empty group, a ref `requirements.md` never declares, a step with no group, a task
232
234
  still `[ ]` in a group the loop has passed (`unticked-completed-task` — the
233
235
  Implementer's done-marker is missing, and whether the work is too is the human's
@@ -361,7 +363,7 @@ empirically).
361
363
  ```bash
362
364
  git fetch -q origin <base>
363
365
  echo "Reviewed-tree: $(git rev-parse 'HEAD^{tree}')"
364
- echo "Diff-fingerprint: $(git -c core.quotePath=true diff --raw --no-abbrev --no-renames --no-color "$(git merge-base FETCH_HEAD HEAD)" HEAD | git hash-object --stdin)"
366
+ echo "Diff-fingerprint: $(git --no-literal-pathspecs -c core.quotePath=true diff --raw --no-abbrev --no-renames --no-color "$(git merge-base FETCH_HEAD HEAD)" HEAD -- ':(top,exclude).claude/state' | git hash-object --stdin)"
365
367
  ```
366
368
 
367
369
  `<base>` is the PR's base branch (the default branch for task PRs; a stacked
@@ -375,7 +377,10 @@ empirically).
375
377
  content-changed verdict). The fingerprint digests the PR's own diff against
376
378
  the merge-base, so a clean update-branch later stays valid, while any
377
379
  content change — including a merge resolution touching a file you
378
- reviewed — invalidates the record and routes the PR back to re-review. A
380
+ reviewed — invalidates the record and routes the PR back to re-review.
381
+ Task state under `.claude/state` is left out of the digest, so your ledger
382
+ and evidence writes after this comment — and the Orchestrator's — never
383
+ invalidate it. A
379
384
  re-review that approves posts a fresh APPROVE with fresh hashes; the
380
385
  latest record wins — which is also why these two marker lines must never
381
386
  be quoted in any later comment (the executor trusts the newest comment
@@ -42,8 +42,9 @@ frictionless and noise-free:
42
42
 
43
43
  On **accept**, capture it exactly as the `/spinoff` command does — the `spinoff` CLI
44
44
  verb via the launcher, with the **current task's id** as the parent (recover it the same
45
- way `/spinoff` does — from the `harness/<id>-…` branch or active task state; omit
46
- `--parent` if there is no active task):
45
+ way `/spinoff` does — the `Active task:` line of
46
+ `.claude/hooks/lib/lemony.sh status --local`; omit `--parent` when it reads `(none)` or
47
+ the command fails):
47
48
 
48
49
  ```bash
49
50
  .claude/hooks/lib/lemony.sh spinoff \