@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.
- package/README.md +17 -16
- package/catalog/VERSION +1 -1
- package/catalog/agents/implementer.md +36 -1
- package/catalog/agents/orchestrator.md +206 -83
- package/catalog/agents/reviewer.md +8 -3
- package/catalog/agents/spinoff.md +3 -2
- package/catalog/agents/ui-design.md +3 -1
- package/catalog/agents/ui-designer.md +6 -3
- package/catalog/commands/pause.md +50 -5
- package/catalog/commands/resume.md +13 -2
- package/catalog/commands/spinoff.md +5 -3
- package/catalog/commands/sync-design-tokens.md +6 -2
- package/catalog/harness.config.schema.json +4 -0
- package/catalog/hooks/init.sh +80 -7
- package/catalog/hooks/lib/live-branch.sh +37 -0
- package/catalog/hooks/lib/merge-pr.sh +17 -6
- package/catalog/hooks/lib/playbook-scan.sh +4 -2
- package/catalog/hooks/session-close.sh +26 -7
- package/catalog/schemas/tier2-events-history.md +33 -2
- package/catalog/schemas/tier2-events.md +30 -22
- package/catalog/skills/build-ui/SKILL.md +5 -2
- package/catalog/skills/design-tool-sync/SKILL.md +48 -7
- package/catalog/skills/grill-ui/SKILL.md +4 -1
- package/catalog/skills/grill-ui/ui-handoff-format.md +2 -1
- package/catalog/skills/mutation-testing/SKILL.md +22 -8
- package/catalog/skills/prd-to-spec/SKILL.md +27 -5
- package/catalog/skills/review-pr/SKILL.md +7 -1
- package/catalog/skills/review-pr/reference.md +3 -2
- package/catalog/templates/claude-code/agents.md.tpl +2 -1
- package/catalog/templates/claude-code/harness.config.yml.tpl +12 -3
- package/dist/cli.mjs +2579 -775
- 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
|
|
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
|
-
| `
|
|
146
|
-
| `
|
|
147
|
-
| `
|
|
148
|
-
| `
|
|
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.
|
|
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)
|
|
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
|
|
434
|
-
|
|
435
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
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
|
|
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`
|
|
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
|
|
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** →
|
|
543
|
-
- **Changes** (with feedback) →
|
|
544
|
-
|
|
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** →
|
|
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),
|
|
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. **
|
|
564
|
-
sent back emits more than once, same
|
|
565
|
-
`progress.md` line (step 5)
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
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
|
|
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
|
|
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.**
|
|
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
|
|
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
|
|
728
|
-
|
|
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
|
|
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
|
|
784
|
-
|
|
785
|
-
`
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
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
|
|
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
|
|
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
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
`
|
|
1063
|
-
|
|
1064
|
-
|
|
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
|
|
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.
|
|
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 —
|
|
46
|
-
`--parent`
|
|
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 \
|