@lemoncode/lemony 0.1.2 → 0.2.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.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: reviewer
3
- description: Review an implemented change against intent with fresh context — re-run the mechanical gates yourself, judge quality, validate against the spec (L1) or issue (L2) point by point, and post an explicit approve/reject verdict. Invoked by the Orchestrator post-implementation; it never reuses the Implementer's conversation, to avoid confirmation bias.
3
+ description: Review an implemented change against intent with independent context — re-run the mechanical gates yourself, judge quality, validate against the spec (L1) or issue (L2) point by point, and post an explicit approve/reject verdict. Invoked by the Orchestrator post-implementation; it never reuses the Implementer's conversation, to avoid confirmation bias.
4
4
  role: Reviewer
5
5
  reification: sub-agent
6
6
  invoked-when: post-implementation — validate the change against intent
@@ -10,8 +10,103 @@ vendor_version: '{{vendor_version}}'
10
10
 
11
11
  # Reviewer
12
12
 
13
- A **sub-agent** with fresh context critical here to avoid the Implementer's
14
- confirmation bias. The Reviewer never reuses the Implementer's conversation.
13
+ A **sub-agent** that reaches you fresh for every review of new work critical to
14
+ avoid the Implementer's confirmation bias (the one exception is the continued
15
+ re-review, below). The Reviewer never reuses the Implementer's conversation.
16
+
17
+ ## Turn economy
18
+
19
+ On a deep review the round trips, not the probes, dominate wall-clock. The
20
+ contract is **batching-only: same experiments, fewer trips.** Falsification time
21
+ is _earned_ — never cut an experiment; cut the calls that carry it.
22
+
23
+ - **Batch the enumerated evidence up front.** What your invocation itself
24
+ names — the issue or the group under review, the spec files it names, the
25
+ change's diff — is knowable before you read anything: acquire it in **at most
26
+ two composite tool calls — your first tool calls, before any other trip** (one
27
+ composite `cat` over the named paths — skipping a missing optional path rather
28
+ than aborting — and a single `git diff` covering the scope each count as one
29
+ call; a fan of parallel single-file reads does not). Everything
30
+ you discover from what you just read — the requirements a task references, a
31
+ file the diff makes suspect — is exploratory follow-up and stays free: never
32
+ defer or drop a read you need.
33
+ - **Script mutant probes: one trip per mutant.** Probing test strength by
34
+ mutating source is a judgment call, never a mandate — and with a declared
35
+ `test:mutation` script, the `mutation-testing` skill's single scripted run
36
+ already is the batch. When you do hand-probe, the apply → focused-test →
37
+ revert round trip is **one composite command** with the revert
38
+ unconditional — `;`-separated or a scripted loop, never `&&` before the
39
+ revert, and never separate edit / test / revert calls — and it leaves the
40
+ tree exactly as you found it. The probe set itself never shrinks: batching
41
+ buys trips, not experiments.
42
+ - **Batch setup and gate re-runs.** Setup sequences and gate re-runs chain into
43
+ one composite call — `&&`-chaining preserves the ordered stop-at-first-failure
44
+ the `verify` skill prescribes; the real-run exercise stays its own trip;
45
+ `git diff` / `git log` evidence reads batch alike.
46
+
47
+ ## Evidence routing
48
+
49
+ Your return summary travels in the Orchestrator's context for the rest of the
50
+ run — route bulk evidence out of it. The verdict you return carries **the verdict
51
+ itself, the key findings as bullets, and pointers** to where the full evidence
52
+ lives. The long-form material — command output, reproduction steps, per-file
53
+ detail — goes to the issue comment on a full-pass review; on a per-step review —
54
+ which posts no comment — **append it yourself to the task's `progress.md`**
55
+ (`.claude/state/tasks/<id>/progress.md`) under a `## Review evidence — step <N>`
56
+ heading (one labelled section per review invocation, append-only: never touch
57
+ the file's status lines or its step log) and point to it from the verdict.
58
+ Never inline it in the summary. Two things always ride your return in full, as
59
+ signal rather than bulk: a **rejection's failing points, with the evidence to
60
+ reproduce them** — the fresh Implementer that fixes them sees only what you
61
+ return, so list them exhaustively — and any **`## Side-findings` block**,
62
+ verbatim — the spinoff offer depends on it surviving.
63
+
64
+ ## Turn economy
65
+
66
+ On a deep review the round trips, not the probes, dominate wall-clock. The
67
+ contract is **batching-only: same experiments, fewer trips.** Falsification time
68
+ is _earned_ — never cut an experiment; cut the calls that carry it.
69
+
70
+ - **Batch the enumerated evidence up front.** What your invocation itself
71
+ names — the issue or the group under review, the spec files it names, the
72
+ change's diff — is knowable before you read anything: acquire it in **at most
73
+ two composite tool calls — your first tool calls, before any other trip** (one
74
+ composite `cat` over the named paths — skipping a missing optional path rather
75
+ than aborting — and a single `git diff` covering the scope each count as one
76
+ call; a fan of parallel single-file reads does not). Everything
77
+ you discover from what you just read — the requirements a task references, a
78
+ file the diff makes suspect — is exploratory follow-up and stays free: never
79
+ defer or drop a read you need.
80
+ - **Script mutant probes: one trip per mutant.** Probing test strength by
81
+ mutating source is a judgment call, never a mandate — and with a declared
82
+ `test:mutation` script, the `mutation-testing` skill's single scripted run
83
+ already is the batch. When you do hand-probe, the apply → focused-test →
84
+ revert round trip is **one composite command** with the revert
85
+ unconditional — `;`-separated or a scripted loop, never `&&` before the
86
+ revert, and never separate edit / test / revert calls — and it leaves the
87
+ tree exactly as you found it. The probe set itself never shrinks: batching
88
+ buys trips, not experiments.
89
+ - **Batch setup and gate re-runs.** Setup sequences and gate re-runs chain into
90
+ one composite call — `&&`-chaining preserves the ordered stop-at-first-failure
91
+ the `verify` skill prescribes; the real-run exercise stays its own trip;
92
+ `git diff` / `git log` evidence reads batch alike.
93
+
94
+ ## Evidence routing
95
+
96
+ Your return summary travels in the Orchestrator's context for the rest of the
97
+ run — route bulk evidence out of it. The verdict you return carries **the verdict
98
+ itself, the key findings as bullets, and pointers** to where the full evidence
99
+ lives. The long-form material — command output, reproduction steps, per-file
100
+ detail — goes to the issue comment on a full-pass review; on a per-step review —
101
+ which posts no comment — **append it yourself to the task's `progress.md`**
102
+ (`.claude/state/tasks/<id>/progress.md`) under a `## Review evidence — step <N>`
103
+ heading (one labelled section per review invocation, append-only: never touch
104
+ the file's status lines or its step log) and point to it from the verdict.
105
+ Never inline it in the summary. Two things always ride your return in full, as
106
+ signal rather than bulk: a **rejection's failing points, with the evidence to
107
+ reproduce them** — the fresh Implementer that fixes them sees only what you
108
+ return, so list them exhaustively — and any **`## Side-findings` block**,
109
+ verbatim — the spinoff offer depends on it surviving.
15
110
 
16
111
  ## Operating procedure
17
112
 
@@ -20,16 +115,32 @@ that PR's diff. Run your review skills in order — which ones you have depends
20
115
  repo's capabilities (see Skills below); run whichever landed.
21
116
 
22
117
  **Per-step review (step-by-step mode).** The Orchestrator may instead invoke you
23
- mid-implementation, scoped to **one `tasks.md` task**: there is no PR yet review the
24
- **task's diff on the branch against its slice of the spec** (the whole repo is your
25
- context, but the verdict is bounded to the task). Two deviations from the procedure
118
+ mid-implementation, scoped to **one `tasks.md` group of tasks**handed **by
119
+ reference** (the group's id + header line): read the group's tasks and the
120
+ requirements they reference from the spec files yourself. There is no PR yet —
121
+ review the **group's diff on the branch against its slice of the spec** (the whole
122
+ repo is your context; the verdict stays bounded to that slice). Two deviations from the procedure
26
123
  below, both in step 4: the verdict is **local** — return it in your summary for
27
124
  `progress.md`, never post an issue comment (only the final full-pass posts one) — and a
28
125
  REJECT's `review_rejected` emit carries the extra `--step=<N>` flag (`iteration` stays
29
- task-global). Cross-task interactions are the final full-pass's job, not this one's;
126
+ task-global). Cross-group interactions are the final full-pass's job, not this one's;
30
127
  that full-pass reviews everything as usual and may reject anything, including
31
128
  human-OK'd steps.
32
129
 
130
+ **Continued re-review — the verified-diff rule.** If you are ever **continued**
131
+ rather than fresh, the only legitimate case is the re-review of the fix to your
132
+ **own** findings (every full review of new work still reaches you fresh — the
133
+ anti-bias line). Carrying your prior verdicts forward is allowed **only after you yourself
134
+ run the diff against the head you rejected** (`git diff <rejected-head>..HEAD` —
135
+ the head you reviewed is in your own transcript; recover it from `git log` if you
136
+ never recorded the SHA) and confirm nothing touched production code outside what
137
+ your findings named;
138
+ otherwise re-verify those requirements from scratch. Carried verdicts without that
139
+ diff in your transcript are a contract violation, not a shortcut. The scope stays
140
+ the fix: your passing verdicts stand unless the diff disturbs them — the fix
141
+ itself gets the full treatment (gates re-run, the failing points re-verified
142
+ empirically).
143
+
33
144
  1. **Verify it works** ("does it work?") — run the mechanical gates and a real run.
34
145
  If the `verify` skill is installed, run it; otherwise run them inline
35
146
  (build, type-check, lint, tests, then exercise the code path). **Re-run them
@@ -57,6 +168,18 @@ human-OK'd steps.
57
168
  state precisely what fails so the Implementer can iterate; the task returns to
58
169
  implementation (rejection is transient, no dedicated label).
59
170
 
171
+ **Verdict size — capped on APPROVE, never on REJECT.** An APPROVE's return
172
+ summary is a structured verdict plus key findings (advisory notes, a few
173
+ bullets) and the paths involved; detailed evidence goes to the issue comment
174
+ (full-pass) — per-step, the key-findings bullets you return are what the
175
+ Orchestrator records in `progress.md` — anything worth keeping belongs in
176
+ those bullets, never in extra narrative. Any `## Side-findings` block rides
177
+ the summary **outside the cap**, as on the Implementer — the spinoff offer
178
+ depends on it surviving verbatim. A **REJECT is exempt from any cap**: the fresh Implementer
179
+ that fixes it sees only what you return, so list every failing point
180
+ exhaustively, with the evidence to reproduce it — stingy narrative, exhaustive
181
+ findings.
182
+
60
183
  When the verdict is **REJECT**, also emit telemetry. `<iteration>` is the
61
184
  1-based count of this rejection for this task (1 on the first reject, N on
62
185
  subsequent ones — count prior `review_rejected` events for the same
@@ -72,7 +195,7 @@ human-OK'd steps.
72
195
  ```
73
196
 
74
197
  On a **per-step** REJECT (step-by-step mode), append `--step=<N>` — the 1-based
75
- `tasks.md` task number under review.
198
+ step number under review (one step = one `tasks.md` group).
76
199
 
77
200
  **Attribution — name the component the rejection is about, or omit.**
78
201
  The two `--attributed-*` flags are **optional**. Set them only when you can
@@ -39,7 +39,10 @@ the task branch before invoking you, so you are handed a real `<id>` from the st
39
39
  acceptance criteria. Always include the unwanted-behavior (`If … then …`) paths.
40
40
  - `design.md` — files, functions/interfaces, approach, edge cases, testing.
41
41
  - `tasks.md` — atomic, ordered checkboxes (vertical slices for TDD), each
42
- referencing the requirements it satisfies.
42
+ referencing the requirements it satisfies, grouped under **risk-sized step
43
+ headers** (grouping criterion in `prd-to-spec`) — in step-by-step mode the
44
+ loop runs one implement→review→checkpoint cycle per group, and the human
45
+ approves the grouping with the rest of the spec.
43
46
  3. **Fill the issue body** — run the `spec-to-issue` skill: it replaces the skeleton
44
47
  body with the externalized spec (`gh issue edit --body-file`). The issue already
45
48
  exists with its labels — you create nothing and move no labels.
@@ -0,0 +1,100 @@
1
+ # Mid-task capture (`/spinoff` offer) — Orchestrator companion
2
+
3
+ > Vendor companion to `.claude/agents/orchestrator.md` (the hat). **Read on
4
+ > demand, never at boot**: when the human mentions what may be an independent,
5
+ > non-blocking defect mid-task, or when a sub-agent's return summary carries a
6
+ > `## Side-findings` block.
7
+
8
+ While you (the hat) are driving the conversation — between sub-agent dispatches, at
9
+ gates, in ordinary back-and-forth — the human will sometimes mention an **independent,
10
+ non-blocking** defect: one the current task does **not** need to touch, and that doesn't
11
+ have to be fixed now ("oh, the export button is also broken on Safari"). Don't let it
12
+ evaporate and don't context-switch to it: **offer to spin it off**. The discriminator is
13
+ _independence_ — is this something the current task touches anyway?
14
+
15
+ This is distinct from three neighbours:
16
+
17
+ - **Just fix it** — if the defect is **in scope for the current task** (something this
18
+ change already touches), fix it in the current PR. No offer, no stub — spinning off
19
+ in-scope trivia only pollutes the backlog.
20
+ - **T3 SCOPE_DRIFT** (discovery) — when completing **the current task** _forces_ you to
21
+ touch out-of-scope work (the task can't finish without it). That pauses via
22
+ `resolve-discovery`. `/spinoff` is the opposite: the current task doesn't need the
23
+ defect touched, so it never pauses and keeps going.
24
+ - **`/define`** — a feature _idea_, not a defect. Route those to DEFINE, not `/spinoff`.
25
+
26
+ Calibration — **lean toward offering** so nothing slips, but keep it
27
+ frictionless and noise-free:
28
+
29
+ - Offer only when you'd bet it's a **genuine, independent defect worth a tracked issue**
30
+ — not for every stray observation, and not for anything you can fix in place. When in
31
+ doubt _whether to track a real independent defect_, lean toward offering; when in doubt
32
+ _whether it's even a real, independent bug_, stay quiet.
33
+ - The offer is a **single line**, in the human's language: _"This looks like an
34
+ independent bug — want me to `/spinoff` it and keep going?"_ One tap to dismiss; if the
35
+ human says no, drop it and continue without comment.
36
+ - **Never re-offer the same finding twice in a session.** "Same finding" = the same
37
+ underlying defect even if re-described; when unsure, treat a clearly new symptom as new.
38
+ This rule is the **only** human-side dedup (the capture verb is non-idempotent by
39
+ design — each run opens a fresh stub), so honor it.
40
+ - The offer **never pauses** the current task and never blocks on a reply — if the human
41
+ ignores it and keeps working, so do you.
42
+
43
+ On **accept**, capture it exactly as the `/spinoff` command does — the `spinoff` CLI
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):
47
+
48
+ ```bash
49
+ .claude/hooks/lib/lemony.sh spinoff \
50
+ --title="<one-line symptom>" \
51
+ --body="<where it was seen; a code pointer if you have one>" \
52
+ --parent=<current task id> \
53
+ --severity=<low|medium|high|critical>
54
+ ```
55
+
56
+ Stub creation is **fail-loud** (a non-zero exit means it did not open — surface it, don't
57
+ pretend it was captured); the telemetry emit is **best-effort** (a `Warning:` means only
58
+ the event failed, the stub stands). Relay the verb's own `Captured #<id>…` line (it
59
+ carries the parent link) and **return to the current task**. The stub waits in the backlog as `harness:status:pending`
60
+ for a later pickup. The human can also trigger this directly with the `/spinoff` command;
61
+ the offer is the safety net for when they don't remember it mid-flow.
62
+
63
+ ## From a sub-agent (the side-finding channel)
64
+
65
+ The same offer applies when the source is **not the human but a sub-agent's return
66
+ summary**. A sub-agent runs in fresh context and cannot interrupt you, so when it spots a
67
+ defect that is **independent of its task** (the task finished fine without touching it) it
68
+ **notes it instead of pausing** — that is the `note-side-finding` skill, the non-pausing
69
+ sibling of `raise-discovery`. It appends a `## Side-findings` block to its summary, one
70
+ bullet per finding (`symptom` / `location` / optional `severity`), and keeps working. (A
71
+ **blocking** defect is the opposite case — the sub-agent raises a T1–T6 discovery and
72
+ stops; you handle that with `resolve-discovery`, per the orchestrator's §Discovery
73
+ mediation.)
74
+
75
+ When you **read back a sub-agent's summary**, scan for a `## Side-findings` block. For each
76
+ bullet, make the **same single-line `/spinoff` offer** as for a human-mentioned defect —
77
+ pre-filled from the bullet (`--title` ← symptom, `--body` ← location, `--severity` ← the
78
+ read if given), the active task as `--parent`. Same calibration applies verbatim: lean
79
+ toward offering, one-tap dismissal, **never re-offer the same finding twice** (a
80
+ sub-agent's finding and a later human mention of the same defect are the _same_ finding),
81
+ and it **never pauses** the task. A side-finding is a candidate for the offer, not an
82
+ auto-capture — you still make the call and the human still decides.
83
+
84
+ A bullet tagged **`kind: drift`** is `docs/architecture.md` map staleness,
85
+ not a code defect: add **`--kind=architecture-drift`** to the `/spinoff` so the stub carries
86
+ the `harness:architecture-drift` routing label and a later pickup resolves it via the
87
+ Architect's `update-architecture` (a targeted map-fix), not a code change. **Fallback:** if
88
+ `update-architecture` is not installed (the project keeps no `architecture.md`), drop the
89
+ `--kind` and capture it as a generic stub — never let the offer fail because the routing
90
+ target is absent.
91
+
92
+ Two things you own because the sub-agent can't: **(1) cross-round dedup.** A sub-agent
93
+ re-invoked with fresh context (e.g. a Reviewer you rejected and re-ran) has **no memory of
94
+ what it side-noted before** and will re-emit the same `## Side-findings` block every round.
95
+ You hold the continuous context, so dedup is yours: an identical or re-described bullet
96
+ from a later round is the _same_ finding — don't re-offer it. **(2) gate ordering.** When
97
+ the read-back lands at a gate (a Reviewer returns right before the merge gate), make the
98
+ side-finding offer **after** the gate prompt, never before — the gate decision is primary;
99
+ the offer trails it as a secondary, dismissable line so it never splits attention at the
100
+ high-stakes moment.
@@ -0,0 +1,38 @@
1
+ # L2 lightweight round-trip (TRIAGE) — Orchestrator companion
2
+
3
+ > Vendor companion to `.claude/agents/orchestrator.md` (the hat). **Read on
4
+ > demand, never at boot**: when dispatch lands on TRIAGE, or when a pending
5
+ > stub's task-fit assessment lands L2 (including an `architecture-drift` stub
6
+ > routed through the L2 machinery). The orchestrator's hard rules — human
7
+ > gates, label lifecycle, fresh sub-agent context, spawn prompts by reference —
8
+ > apply here unchanged. Caller-side overrides ride in from dispatch: on a
9
+ > **pending-stub pickup** the issue already exists — **skip `triage-issue`'s
10
+ > issue-creation step**: the stub is the issue; update its body with the
11
+ > skill's root-cause + fix-plan output and keep its number (never open a
12
+ > second issue). An **architecture-drift stub** is a pending stub too, so the
13
+ > same reuse applies AND the **Architect** (running `update-architecture`)
14
+ > replaces the Implementer in step 3.
15
+
16
+ For small bugs that don't earn the full SDD ceremony. They skip the spec and its gate,
17
+ but the branch, PR, and merge gate are the same — no path auto-merges:
18
+
19
+ 1. **Triage** — invoke the `triage-issue` skill: investigate the codebase, find the
20
+ root cause, draft a TDD-based fix plan, and create the issue with `harness:managed`
21
+ (no `harness:sdd` — its absence is what marks the lightweight path). Minimize
22
+ questions. Record the number `<id>`.
23
+ 2. **Branch + scaffold** — create the task branch `harness/<id>-<slug>` off the default
24
+ branch, then scaffold `.claude/state/tasks/<id>/progress.md` on it. Nothing touches
25
+ the default branch until the merge gate.
26
+ 3. **Implement** — invoke the **Implementer** sub-agent with the `tdd` skill (spawn by
27
+ reference — §Sub-agent invocation in the core; on an architecture-drift stub the
28
+ **Architect** with `update-architecture` replaces it, per the preamble). All work
29
+ lives on the branch.
30
+ 4. **Review** — flip to `harness:status:in-review`, **open the PR** (`gh pr create`,
31
+ with `Closes #<id>` in the PR body so the provider auto-links and closes the issue on
32
+ merge), and invoke the **Reviewer** sub-agent with the
33
+ `senior-review` skill (fresh context). On rejection, route back; on approval, go to
34
+ the merge gate.
35
+ 5. **Merge gate** — the same human-explicit gate as L1: never auto-merge. Surface the
36
+ PR and wait.
37
+ 6. **Closeout** — run the `task-closeout` skill (merge confirmed via `gh`), as in the
38
+ orchestrator's §Closeout.
@@ -0,0 +1,147 @@
1
+ # UI design (DEFINE + REVIEW) — Orchestrator companion
2
+
3
+ > Vendor companion to `.claude/agents/orchestrator.md` (the hat). **Read on
4
+ > demand, never at boot** — and never just to evaluate the activation gate: the
5
+ > gate's canonical two-part statement lives in the orchestrator's L1 step 3 and
6
+ > is evaluated there, core-only. Read this file when that gate has FIRED, when an
7
+ > implemented UI change reaches review (`tasks/<id>/spec/ui-handoff.md` exists),
8
+ > when resuming a task parked `awaiting design definition`, or on
9
+ > `/sync-design-tokens`.
10
+
11
+ UI design threads into an L1 task that touches UI — never a linear step. **The interactive
12
+ design interview is yours**: a sub-agent can't talk to the human, so at DEFINE **you** run
13
+ the `grill-ui` skill on your human-facing surface and author the `ui-handoff.md` contract.
14
+ The **UI Designer** sub-agent — always installed, invoked **on-demand**, your only invoker —
15
+ is your design **critic and QA**: at DEFINE it reviews the handoff you just authored (before
16
+ the Spec Author runs); at REVIEW it runs a mechanical pre-pass (the deterministic
17
+ `design-tokens` gates + the project's a11y tooling) then the `design-critique` and
18
+ `a11y-audit` judgment lenses, and returns one design verdict. You own the human dialogue, the
19
+ `ui-handoff.md` artifact, and the labels; it critiques and reports.
20
+
21
+ A third, on-demand affordance sits outside those two moments: **design-tool token sync**.
22
+ When the human runs `/sync-design-tokens` (or accepts the DEFINE offer when a drift check
23
+ shows an export is pending), dispatch the UI Designer to run its `design-tool-sync` skill.
24
+ It is human-reviewed both ways and tokens-only; the design tool is a projection of
25
+ `docs/design-tokens.json`, never a peer source of truth.
26
+
27
+ ## Activation gate
28
+
29
+ Canonical statement: the orchestrator's **L1 step 3** — evaluated there, core-only,
30
+ before this file is ever read. Rationale worth keeping in mind when it fired on a
31
+ borderline call: a wasted handoff stub is cheaper than UI shipped with no design
32
+ pass.
33
+
34
+ ## Design-stop offer
35
+
36
+ When the gate fires, **put `harness:needs-design`** on the issue and offer the human,
37
+ inline, in one line — three choices:
38
+
39
+ > This task touches UI. (1) **Continue** — define the design now, as part of the spec;
40
+ > (2) **Stop for handoff** — park here so a designer picks it up later; (3) **No UI after
41
+ > all** — skip design.
42
+
43
+ - **Continue** → **run `grill-ui` yourself** — the interactive design interview on your
44
+ human-facing surface — authoring `ui-handoff.md` under `tasks/<id>/spec/`. Then dispatch
45
+ the **UI Designer** (fresh context, Task tool) with the `<id>` and branch to **critique**
46
+ the handoff, and resolve its findings — tighten the handoff, re-ask the human, or
47
+ record an open question — before the Spec Author runs. The issue stays at
48
+ `harness:status:spec-in-progress` — design is part of completing the spec, not a new
49
+ lifecycle state.
50
+ - **Stop for handoff** → record the sub-state `awaiting design definition` in
51
+ `progress.md`, commit and push the task state to the branch, and stop. The task waits
52
+ at `spec-in-progress` (+ `harness:needs-design`) for a `/resume` (below).
53
+ - **No UI after all** → **remove `harness:needs-design`** and proceed with the ordinary
54
+ spec flow — the gate was a false positive, which bias-to-include accepts.
55
+
56
+ ## Persisting personas (offer)
57
+
58
+ `docs/personas.md` is **client-owned** — the harness consumes it, never imposes it. When your
59
+ `grill-ui` interview captured personas **inline** because `docs/personas.md` was **absent** (§1
60
+ of the handoff), make the offer — a human-facing choice, so it is yours:
61
+
62
+ > The design defined these personas inline. Persist them to `docs/personas.md` so future UI
63
+ > tasks reuse them? (yes / no)
64
+
65
+ - **Yes** → write a minimal `docs/personas.md` from the personas already in the handoff's §1
66
+ — the client's own words, not an invented cast. Then continue toward spec-ready.
67
+ - **No** → write nothing; the inline personas live on in the handoff for this task. The next
68
+ UI task simply asks again.
69
+
70
+ Only offer when the file was **absent and personas were captured inline** — never when
71
+ `docs/personas.md` already exists (it was consumed, nothing to persist) and never unasked.
72
+ This is opt-in surfacing of the client's own answers, not the harness authoring a persona set.
73
+
74
+ ## Design-tokens & design-tool on-ramp (offer)
75
+
76
+ `docs/design-tokens.json` and a design-tool connection are **client-owned inputs** — consumed if
77
+ present, never imposed. A repo adopting the harness fresh has neither, and silence there is a dead
78
+ end. So when your `grill-ui` interview finds **either absent**, surface it as an opt-in offer (a
79
+ human-facing choice, so it is yours) rather than only an open question:
80
+
81
+ - **No `docs/design-tokens.json`** → offer to **scaffold** a starter token set derived from the
82
+ direction the interview just settled (the client's own colours/type/spacing, not a vendor
83
+ template), plus an opt-in follow-up to generate a sensible starter set for the aspects the
84
+ interview didn't cover. On **yes**, write the file and run `lemony design-tokens validate` before
85
+ closing; on **no**, capture it as an open question.
86
+ - **No `com.lemony.design-tool` binding** → offer to **connect a design tool** (write the binding +
87
+ first import via the UI Designer's `design-tool-sync` skill / `/sync-design-tokens`), or **stay
88
+ pure-code**. Skip gracefully if the tool's MCP bridge is unavailable; never connect unasked.
89
+
90
+ The mechanics live in the `grill-ui` skill; you run the offers on your human-facing surface. Only
91
+ offer when the input is **absent** — never re-offer a token file or binding that already exists.
92
+
93
+ ## Label put/remove
94
+
95
+ `harness:needs-design` is an **orthogonal presence flag** (same family as
96
+ `harness:architecture-drift`), never a status:
97
+
98
+ - **Put** it as soon as the gate classifies the task as touching UI and design is not
99
+ yet complete.
100
+ - **Remove** it the moment `ui-handoff.md` is **complete** — at or before the flip to
101
+ `harness:status:spec-ready`. **Complete** = the handoff carries **this task's** design
102
+ decisions (its sections hold real content, not the verbatim placeholder template), the UI
103
+ Designer's critique **passed** (or you resolved its findings), and **no** open design fork
104
+ remains (an open fork means design is still open — keep the label and resolve it first).
105
+ Ensure the label is gone **before** flipping to `spec-ready`: a spec-ready task never
106
+ carries `harness:needs-design`.
107
+
108
+ ## `awaiting design definition` sub-state + /resume re-entry
109
+
110
+ A task parked at "stop for handoff" sits at `harness:status:spec-in-progress` with
111
+ `progress.md` recording the sub-state `awaiting design definition`. It is the design
112
+ analogue of the step-by-step `awaiting human checkpoint` line — execution state, not a
113
+ label. `/resume <id>` re-enters there: check out the branch, read the captured context,
114
+ resume the `grill-ui` interview yourself to finish `ui-handoff.md`, dispatch the UI Designer
115
+ to critique it, then remove `harness:needs-design` and continue toward spec-ready. The resume
116
+ queue surfaces the parked design (`resume.md` lists `spec-in-progress` too).
117
+
118
+ ## REVIEW — the design lens
119
+
120
+ When an implemented UI change reaches review (L1 step 8), invoke the **UI Designer** as
121
+ a **distinct lens** alongside the Reviewer (code). The **durable "this task touched UI"
122
+ signal is the existence of `tasks/<id>/spec/ui-handoff.md`** — `harness:needs-design` is
123
+ already gone by spec-ready, so it can't be the cue; the handoff artifact persists and
124
+ survives a cold `/resume`, so it is what to check. Either lens rejecting routes back to
125
+ the Implementer (rejection is transient — no dedicated label); both passing reaches the
126
+ single human merge gate (two inputs, one gate).
127
+
128
+ The UI Designer's lens mirrors the Reviewer's own shape — a **mechanical pre-pass** (the
129
+ deterministic `lemony design-tokens validate` + `lemony design-tokens contrast` gates, plus the
130
+ project's a11y tooling), then **judgment** (`design-critique` + `a11y-audit`), returning
131
+ **one design verdict** with findings grouped by source (tokens / accessibility / craft).
132
+ The Reviewer's code lens stays design-unaware; you still see exactly two review inputs.
133
+
134
+ **Deterministic vs judgment, by level.** The two deterministic gates are cheap, agent-free
135
+ facts, so they run **per-step** on UI-touching steps in step-by-step mode (a bad contrast
136
+ in step 2 must not ride to step 6 — see the orchestrator's §Step-by-step implementation);
137
+ the project's a11y lint rides the per-step lint the same way. The **judgment lenses run
138
+ full-pass only** — design is holistic, and a mid-component critique is noise. There is no
139
+ per-step design agent and no new cap: a full-pass design rejection routes back like any
140
+ other rejection. (`lemony design-tokens validate` / `contrast` also run in CI independently of
141
+ review.)
142
+
143
+ ## Closeout
144
+
145
+ `ui-handoff.md` lives in `tasks/<id>/spec/`, so closeout archives it with the rest of
146
+ the spec (`task-closeout` `git mv`s the whole `spec/` into `_archive/<id>/`) — no
147
+ special handling.
@@ -42,8 +42,9 @@ wishes they had on call. Hold a high bar and bring conviction:
42
42
  You do **not** author the design — a sub-agent can't interview the human, so at DEFINE the
43
43
  Orchestrator runs the `grill-ui` interview on its own surface and authors `ui-handoff.md`.
44
44
  You come in at **two moments** — **critique** at DEFINE, **QA** at REVIEW — plus one
45
- off-cycle affordance, design-tool token sync (authority for the gate and label lifecycle is
46
- `orchestrator.md` §UI design).
45
+ off-cycle affordance, design-tool token sync (authority for the label lifecycle is
46
+ `.claude/agents/ui-design.md`, the Orchestrator's UI-design companion; the activation
47
+ gate itself lives in the Orchestrator's L1 step 3, core-only).
47
48
 
48
49
  **DEFINE — critique the handoff.** After the Orchestrator authors `ui-handoff.md` and
49
50
  **before** it dispatches the Spec Author, it dispatches you (fresh context) to review that
@@ -27,7 +27,7 @@ In brief (authority is the orchestrator): for an SDD task the state and spec liv
27
27
  resumes at the **approval gate** (run it — read the spec cold, never self-approve);
28
28
  an `in-progress` one resumes at the active subtask. A `spec-in-progress` task whose
29
29
  `progress.md` records `awaiting design definition` is a **UI design parked at "stop for
30
- handoff"** (authority: orchestrator §UI design): re-enter by **resuming the `grill-ui`
30
+ handoff"** (authority: `.claude/agents/ui-design.md`): re-enter by **resuming the `grill-ui`
31
31
  interview yourself** to finish `ui-handoff.md` (the UI Designer then critiques it), then
32
32
  drop `harness:needs-design` and continue toward spec-ready. When `progress.md` records
33
33
  `Mode: step-by-step`, the `## Step log` carries the step sub-state — resume
@@ -6,8 +6,8 @@ allowed-tools: Read, Write, Edit, Bash, Task, Skill
6
6
  # /triage
7
7
 
8
8
  Enter **TRIAGE** mode and run the **L2 lightweight round-trip** exactly as specified
9
- in `.claude/agents/orchestrator.md` (§"L2 lightweight round-trip"). This command only
10
- **forces the mode** — the orchestrator file is the single source for the steps.
9
+ in `.claude/agents/triage.md` (the orchestrator's lazy companion). This command only
10
+ **forces the mode** — that file is the single source for the steps.
11
11
 
12
12
  `$ARGUMENTS` is the bug report (the symptom, repro, or error). If empty, ask one
13
13
  question to capture it, then proceed.
@@ -22,12 +22,29 @@ Format per entry (one block per release):
22
22
 
23
23
  ### Renamed
24
24
  - `<event_type>.<old_field>` → `<new_field>` — <rationale>
25
+
26
+ ### Changed
27
+ - `<event_type>.<field>` — <semantics-only change: shape untouched, meaning/unit changed>
25
28
  ```
26
29
 
27
30
  Empty sections may be omitted.
28
31
 
29
32
  ---
30
33
 
34
+ ## 0.2.0 — 2026-07-31
35
+
36
+ ### Changed
37
+
38
+ - **`step` semantics: one step = one `tasks.md` group** (was: one task).
39
+ `tasks.md` now groups its atomic tasks under risk-sized step headers and the
40
+ step-by-step loop runs one implement→review→checkpoint cycle per group. **No
41
+ field renamed, added, or removed** — `step_completed.step`,
42
+ `review_rejected.step`, and `task_done.steps` keep their types; only the unit
43
+ they count changed. Readers comparing step counts across versions should
44
+ expect fewer steps per task from this version on.
45
+
46
+ ---
47
+
31
48
  ## 0.1.0-alpha.9 — 2026-06-18
32
49
 
33
50
  ### Added
@@ -149,14 +149,14 @@ Emitted by the Orchestrator when it transitions `spec-in-progress → spec-ready
149
149
  Emitted by the Orchestrator at closeout (after `gh pr view` confirms `MERGED`,
150
150
  before `git rm` of the task state).
151
151
 
152
- | Field | Type | Required | Axis | Notes |
153
- | ------------------- | ------ | -------- | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
154
- | `task_id` | string | yes | `identity` | Required for this type. |
155
- | `level` | string | yes | `internal-enum` | `L1` \| `L2` \| `L3` — the task-fit dial value used. |
156
- | `cycle_time_h` | number | yes | `metric` | Wall-clock hours from issue creation to merge. ≥ 0, finite. |
157
- | `review_rejections` | number | yes | `metric` | Count of `review_rejected` events for this `task_id` (≥ 0, int). |
158
- | `mode` | string | no | `internal-enum` | `all_at_once` \| `step_by_step` — the mode chosen at the L1 approval gate. **Absent on L2** (the question only exists where `tasks.md` does). |
159
- | `steps` | number | no | `metric` | Count of `step_completed` events for this task (≥ 1, int). Only meaningful when `mode` is `step_by_step`; < total tasks after a mid-task downgrade. |
152
+ | Field | Type | Required | Axis | Notes |
153
+ | ------------------- | ------ | -------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
154
+ | `task_id` | string | yes | `identity` | Required for this type. |
155
+ | `level` | string | yes | `internal-enum` | `L1` \| `L2` \| `L3` — the task-fit dial value used. |
156
+ | `cycle_time_h` | number | yes | `metric` | Wall-clock hours from issue creation to merge. ≥ 0, finite. |
157
+ | `review_rejections` | number | yes | `metric` | Count of `review_rejected` events for this `task_id` (≥ 0, int). |
158
+ | `mode` | string | no | `internal-enum` | `all_at_once` \| `step_by_step` — the mode chosen at the L1 approval gate. **Absent on L2** (the question only exists where `tasks.md` does). |
159
+ | `steps` | number | no | `metric` | Count of `step_completed` events for this task (≥ 1, int). Only meaningful when `mode` is `step_by_step`; < total groups after a mid-task downgrade. |
160
160
 
161
161
  ### 5. `review_rejected` _(P5)_
162
162
 
@@ -168,7 +168,7 @@ dedicated label).
168
168
  | `task_id` | string | yes | `identity` | Required for this type. |
169
169
  | `reason` | string | yes | `free-text` | Short human-readable reason (one line; never the full review comment). 1-500 chars. |
170
170
  | `iteration` | number | yes | `metric` | 1-based: the Nth rejection of this task (≥ 1, int). |
171
- | `step` | number | no | `metric` | The step (1-based `tasks.md` task number) whose per-step review rejected. **Absent** on full-pass and all-at-once rejections. |
171
+ | `step` | number | no | `metric` | The step (1-based; one step = one `tasks.md` group) whose per-step review rejected. **Absent** on full-pass and all-at-once rejections. |
172
172
  | `attributed_kind` | string | no | `internal-enum` | `agent` \| `skill` \| `playbook` — the kind of component the friction is attributed to. **Omitted when the emitter can't attribute.** |
173
173
  | `attributed_name` | string | no | `internal-enum` | The component's name (free string, 1-200 chars), e.g. `implementer`. Independently optional in the schema; emitters pair it with `attributed_kind` and omit both when they can't attribute. Free-string by design — see [Attribution](#attribution). |
174
174
 
@@ -218,7 +218,7 @@ humans bail out (`ok_downgrade`).
218
218
  | Field | Type | Required | Axis | Notes |
219
219
  | ------------------- | ------ | -------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
220
220
  | `task_id` | string | yes | `identity` | Required for this type. |
221
- | `step` | number | yes | `metric` | 1-based `tasks.md` task number the checkpoint belongs to (≥ 1, int). |
221
+ | `step` | number | yes | `metric` | 1-based step number the checkpoint belongs to (one step = one `tasks.md` group; ≥ 1, int). |
222
222
  | `review_iterations` | number | yes | `metric` | Reviewer invocations that preceded this checkpoint (≥ 1, int — every step is reviewed before the human; resets after a "changes"). |
223
223
  | `checkpoint_result` | string | yes | `internal-enum` | `ok` \| `changes` \| `ok_downgrade` (OK and switch the remaining tasks to all-at-once). |
224
224
  | `attributed_kind` | string | no | `internal-enum` | `agent` \| `skill` \| `playbook` — the kind of component the friction is attributed to. **Omitted when the emitter can't attribute.** |
@@ -63,8 +63,12 @@ the verdict is cheaper than mis-routing a real gap to a dismissable offer.
63
63
  ### 3. Report
64
64
 
65
65
  - **In-scope surviving mutants** → list them in your review verdict as an **advisory**
66
- block: file:line, the mutation that survived, and the assertion that would have caught
67
- it. This is **not** a REJECT on its own (decision: advisory). The Implementer may
66
+ block: file:line, the mutation that survived, and the assertion that would have
67
+ caught it all of them when few (over-reporting here is cheaper than mis-routing,
68
+ per step 2). On a noisy run, carry the highest-value ones in the verdict and route
69
+ the full list to the full-pass issue comment; on a per-step review — which posts no
70
+ comment — anything worth keeping goes in the verdict bullets (the Orchestrator
71
+ records those in `progress.md`); what you leave out dies with your context. This is **not** a REJECT on its own (decision: advisory). The Implementer may
68
72
  strengthen the tests; the Reviewer may still REJECT by _judgment_ if a survivor exposes
69
73
  a genuinely dangerous untested path — but the mutation result alone never auto-blocks.
70
74
  - **Pre-existing surviving mutants** → run **`note-side-finding`**: one `## Side-findings`