@cloverleaf/reference-impl 0.3.1 → 0.4.1

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 (40) hide show
  1. package/.claude-plugin/plugin.json +18 -0
  2. package/VERSION +1 -1
  3. package/config/affected-routes.json +6 -8
  4. package/config/qa-rules.json +3 -13
  5. package/config/ui-paths.json +6 -1
  6. package/config/ui-review.json +18 -0
  7. package/dist/affected-routes.mjs +1 -1
  8. package/dist/axe-dedupe.mjs +42 -0
  9. package/dist/cli.mjs +32 -1
  10. package/dist/feedback.mjs +1 -1
  11. package/dist/plugin-path.mjs +19 -0
  12. package/dist/qa-report.mjs +65 -0
  13. package/dist/qa-rules.mjs +1 -1
  14. package/dist/route-slug.mjs +23 -0
  15. package/dist/ui-paths.mjs +1 -1
  16. package/dist/ui-review-config.mjs +41 -0
  17. package/dist/visual-diff.mjs +62 -0
  18. package/install.sh +30 -44
  19. package/lib/affected-routes.ts +1 -1
  20. package/lib/axe-dedupe.ts +64 -0
  21. package/lib/cli.ts +32 -1
  22. package/lib/feedback.ts +8 -1
  23. package/lib/plugin-path.ts +21 -0
  24. package/lib/qa-report.ts +77 -0
  25. package/lib/qa-rules.ts +1 -1
  26. package/lib/route-slug.ts +21 -0
  27. package/lib/ui-paths.ts +1 -1
  28. package/lib/ui-review-config.ts +62 -0
  29. package/lib/visual-diff.ts +97 -0
  30. package/package.json +8 -3
  31. package/prompts/qa.md +21 -0
  32. package/prompts/ui-reviewer.md +90 -39
  33. package/skills/{cloverleaf-document.md → cloverleaf-document/SKILL.md} +2 -2
  34. package/skills/{cloverleaf-implement.md → cloverleaf-implement/SKILL.md} +3 -3
  35. package/skills/{cloverleaf-merge.md → cloverleaf-merge/SKILL.md} +26 -5
  36. package/skills/{cloverleaf-new-task.md → cloverleaf-new-task/SKILL.md} +20 -3
  37. package/skills/{cloverleaf-qa.md → cloverleaf-qa/SKILL.md} +26 -11
  38. package/skills/{cloverleaf-review.md → cloverleaf-review/SKILL.md} +18 -8
  39. package/skills/{cloverleaf-ui-review.md → cloverleaf-ui-review/SKILL.md} +37 -20
  40. /package/skills/{cloverleaf-run.md → cloverleaf-run/SKILL.md} +0 -0
@@ -21,7 +21,7 @@ description: Run the Documenter agent on a task in the `implementing` state (ful
21
21
 
22
22
  2. Load the task:
23
23
  ```
24
- ~/.claude/plugins/cloverleaf/bin/cloverleaf-cli load-task <repo_root> <TASK-ID>
24
+ cloverleaf-cli load-task <repo_root> <TASK-ID>
25
25
  ```
26
26
  Verify `status === "implementing"`. Verify `risk_class === "high"`. If either check fails, report and stop.
27
27
 
@@ -36,7 +36,7 @@ description: Run the Documenter agent on a task in the `implementing` state (ful
36
36
  5. Dispatch the Documenter subagent via the Task tool:
37
37
  - `subagent_type`: `general-purpose`
38
38
  - `model`: `sonnet`
39
- - Prompt: contents of `~/.claude/plugins/cloverleaf/prompts/documenter.md` with substitutions:
39
+ - Prompt: contents of `$(cloverleaf-cli plugin-root)/prompts/documenter.md` with substitutions:
40
40
  - `{{task}}` → full task JSON (pretty-printed)
41
41
  - `{{diff}}` → diff output
42
42
  - `{{branch}}` → `cloverleaf/<TASK-ID>`
@@ -13,20 +13,20 @@ The user has invoked this skill with a TASK-ID (e.g., `DEMO-001`).
13
13
 
14
14
  2. Load the task:
15
15
  ```
16
- ~/.claude/plugins/cloverleaf/bin/cloverleaf-cli load-task <repo_root> <TASK-ID>
16
+ cloverleaf-cli load-task <repo_root> <TASK-ID>
17
17
  ```
18
18
  Parse the JSON. Verify `status === "pending"` OR `status === "implementing"` (the second case is a re-run after a Reviewer bounce). If neither, report the current status and ask the user to use the correct command for that state.
19
19
 
20
20
  3. Load any outstanding feedback:
21
21
  ```
22
- ~/.claude/plugins/cloverleaf/bin/cloverleaf-cli latest-feedback <repo_root> <TASK-ID>
22
+ cloverleaf-cli latest-feedback <repo_root> <TASK-ID>
23
23
  ```
24
24
  Capture the output. If present and the latest verdict is `bounce`, pass it into the subagent.
25
25
 
26
26
  4. Dispatch the Implementer subagent via the Task tool:
27
27
  - `subagent_type`: `general-purpose`
28
28
  - `model`: `sonnet`
29
- - Prompt: the contents of `~/.claude/plugins/cloverleaf/prompts/implementer.md`, with placeholders substituted:
29
+ - Prompt: the contents of `$(cloverleaf-cli plugin-root)/prompts/implementer.md`, with placeholders substituted:
30
30
  - `{{task}}` → the full task JSON (pretty-printed)
31
31
  - `{{feedback}}` → the feedback JSON if present, else the literal string `null`
32
32
  - `{{repo_root}}` → absolute path to the current repo
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: cloverleaf-merge
3
- description: Human gate for merging a Cloverleaf task. Branches on state — from `automated-gates` (fast lane) via `human_merge`, or from `final-gate` (full pipeline) via `final_approval_gate`. Requires explicit user confirmation. Usage — /cloverleaf-merge <TASK-ID>.
3
+ description: Human gate for merging a Cloverleaf task. Branches on state — from `automated-gates` (fast lane) via `human_merge`, or from `final-gate` (full pipeline) via `final_approval_gate`. For full-pipeline tasks, performs a real `git merge --no-ff` of the feature branch into main before advancing state. Requires explicit user confirmation. Usage — /cloverleaf-merge <TASK-ID>.
4
4
  ---
5
5
 
6
6
  # Cloverleaf — merge
@@ -53,18 +53,39 @@ description: Human gate for merging a Cloverleaf task. Branches on state — fro
53
53
 
54
54
  3B.3. On explicit `y`:
55
55
  - `cloverleaf-cli emit-gate-decision <repo_root> <TASK-ID> final_approval_gate approve human`
56
- - `cloverleaf-cli advance-status <repo_root> <TASK-ID> merged human final_approval_gate full_pipeline`
57
- - Commit: `git add .cloverleaf/ && git commit -m "cloverleaf: <TASK-ID> merged (full pipeline)"`.
56
+ - Verify we are on main with a clean working tree:
57
+ ```bash
58
+ cd <repo_root>
59
+ git checkout main
60
+ git status
61
+ # must be clean
62
+ ```
63
+ If not clean, stop and report.
64
+ - Perform the real merge — brings the feature branch's Implementer commit, ui-review baseline commit, and any feedback commits into main:
65
+ ```bash
66
+ git merge --no-ff cloverleaf/${TASK_ID} -m "cloverleaf: ${TASK_ID} merged (full pipeline)"
67
+ ```
68
+ If git reports conflicts: abort and escalate.
69
+ ```bash
70
+ git merge --abort
71
+ cloverleaf-cli advance-status <repo_root> ${TASK_ID} escalated agent
72
+ ```
73
+ Exit with a human-readable error explaining the conflict.
74
+ - Advance task status on main (commits `.cloverleaf/tasks/${TASK_ID}.json` + event):
75
+ ```bash
76
+ cloverleaf-cli advance-status <repo_root> ${TASK_ID} merged agent
77
+ ```
58
78
 
59
79
  ### 4. Common: report
60
80
 
61
81
  Report:
62
- - "✓ Merged `<TASK-ID>`. Branch `cloverleaf/<TASK-ID>` is ready for you to push and open a PR."
63
- - "Suggested: `git push origin cloverleaf/<TASK-ID>` then open a PR against `main`."
82
+ - "✓ Merged `<TASK-ID>`. Branch `cloverleaf/<TASK-ID>` has been merged into main."
83
+ - "Suggested: `git push origin main` to push the merge commit."
64
84
 
65
85
  ## Rules
66
86
 
67
87
  - Only proceed on explicit `y`, `Y`, `yes`, `YES`. Anything else: abort without state change.
68
88
  - The skill does NOT push the branch or open a PR.
69
89
  - Fast lane and full pipeline use distinct gates — the state machine records which path was taken.
90
+ - Full-pipeline merges perform a real `git merge --no-ff` before advancing state — the feature branch's code, baselines, and feedback commits all land on main.
70
91
  - If the user declines, no state change and no commit.
@@ -11,13 +11,13 @@ The user has invoked this skill with a brief. Your job: turn the brief into a st
11
11
 
12
12
  1. Determine the active project. Run:
13
13
  ```
14
- ~/.claude/plugins/cloverleaf/bin/cloverleaf-cli infer-project <repo_root>
14
+ cloverleaf-cli infer-project <repo_root>
15
15
  ```
16
16
  where `<repo_root>` is the current working directory. On failure (no projects, or multiple projects), report the error and ask the user to specify `--project=<id>` or to create a project config first.
17
17
 
18
18
  2. Allocate the next task ID:
19
19
  ```
20
- ~/.claude/plugins/cloverleaf/bin/cloverleaf-cli next-task-id <repo_root> --project=<project>
20
+ cloverleaf-cli next-task-id <repo_root> --project=<project>
21
21
  ```
22
22
  Capture the output (e.g., `DEMO-002`).
23
23
 
@@ -45,7 +45,19 @@ The user has invoked this skill with a brief. Your job: turn the brief into a st
45
45
 
46
46
  6. Commit: `git add .cloverleaf/tasks/<allocated-id>.json && git commit -m "cloverleaf: task <allocated-id>"`.
47
47
 
48
- 7. Report:
48
+ 7. **v0.4 scaffolding:** Ensure baseline and run directories are set up:
49
+ ```bash
50
+ # v0.4 scaffolding additions — baselines tracked, runs ephemeral
51
+ mkdir -p <repo_root>/.cloverleaf/baselines
52
+ mkdir -p <repo_root>/.cloverleaf/runs
53
+
54
+ # Ensure .gitignore excludes runs/ (baselines ARE tracked, only runs is ephemeral)
55
+ if ! grep -qE '^\.cloverleaf/runs/?$' <repo_root>/.gitignore 2>/dev/null; then
56
+ echo '.cloverleaf/runs/' >> <repo_root>/.gitignore
57
+ fi
58
+ ```
59
+
60
+ 8. Report:
49
61
  - "Created `<allocated-id>` at `.cloverleaf/tasks/<allocated-id>.json`."
50
62
  - Show the generated acceptance criteria.
51
63
  - Suggest: "Review and edit the task if needed, then run `/cloverleaf-run <allocated-id>`."
@@ -62,3 +74,8 @@ The user has invoked this skill with a brief. Your job: turn the brief into a st
62
74
  - After writing the task, report the chosen risk_class and how it was determined, e.g.:
63
75
  > "Risk class: `high` → full pipeline (matched keyword `component` in acceptance criterion). Override with `--risk=low` if desired."
64
76
  - Users can manually edit `risk_class` in the task JSON before running `/cloverleaf-run`.
77
+
78
+ ## v0.4 artifacts
79
+
80
+ - `.cloverleaf/baselines/` is **tracked** in git; baseline PNGs travel with code.
81
+ - `.cloverleaf/runs/` is **gitignored**; each task's run artifacts (diffs, candidate screenshots, QA reports) are ephemeral.
@@ -7,7 +7,11 @@ description: Run the QA agent on a task in the `qa` state (full pipeline only).
7
7
 
8
8
  ## Steps
9
9
 
10
- 0. Ensure you are on `main`. If not, `git checkout main`. If main has uncommitted changes, stop and report.
10
+ 0. Pre-flight: ensure you are on `main` and clean stale feedback temp files from previous runs (prevents /tmp leakage between tasks). If not on main, `git checkout main`. If main has uncommitted changes, stop and report.
11
+
12
+ ```bash
13
+ rm -f /tmp/cloverleaf-fb-r.json /tmp/cloverleaf-fb-u.json /tmp/cloverleaf-fb-q.json
14
+ ```
11
15
 
12
16
  1. Capture the TASK-ID argument.
13
17
 
@@ -19,30 +23,35 @@ description: Run the QA agent on a task in the `qa` state (full pipeline only).
19
23
 
20
24
  3. Confirm feature branch exists: `git rev-parse --verify cloverleaf/<TASK-ID>`.
21
25
 
22
- 4. Load QA rules JSON:
26
+ 4. Ensure required directories exist:
27
+ ```bash
28
+ mkdir -p <repo_root>/.cloverleaf/runs/<TASK-ID>/qa
29
+ ```
30
+
31
+ 5. Load QA rules JSON:
23
32
  ```bash
24
33
  # Consumer override takes precedence over the package default.
25
34
  if [ -f "<repo_root>/.cloverleaf/config/qa-rules.json" ]; then
26
35
  cat "<repo_root>/.cloverleaf/config/qa-rules.json"
27
36
  else
28
- cat ~/.claude/plugins/cloverleaf/config/qa-rules.json
37
+ cat $(cloverleaf-cli plugin-root)/config/qa-rules.json
29
38
  fi
30
39
  ```
31
40
  Capture for the subagent as `qa_rules`.
32
41
 
33
- 5. Compute diff:
42
+ 6. Compute diff:
34
43
  ```bash
35
44
  git diff main..cloverleaf/<TASK-ID>
36
45
  ```
37
46
 
38
- 6. Dispatch the QA subagent via the Task tool:
47
+ 7. Dispatch the QA subagent via the Task tool:
39
48
  - `subagent_type`: `general-purpose`
40
49
  - `model`: `sonnet`
41
- - Prompt: contents of `~/.claude/plugins/cloverleaf/prompts/qa.md` with substitutions for `{{task}}`, `{{diff}}`, `{{branch}}`, `{{base_branch}}`, `{{repo_root}}`, `{{qa_rules}}` (the JSON loaded in step 4).
50
+ - Prompt: contents of `$(cloverleaf-cli plugin-root)/prompts/qa.md` with substitutions for `{{task}}`, `{{diff}}`, `{{branch}}`, `{{base_branch}}`, `{{repo_root}}`, `{{qa_rules}}` (the JSON loaded in step 5).
42
51
 
43
- 7. Parse response: expect `{"verdict": "pass"|"bounce"|"escalate", "summary", "findings", "results"}`.
52
+ 8. Parse response: expect `{"verdict": "pass"|"bounce"|"escalate", "summary", "findings", "results"}`.
44
53
 
45
- 8. Branch on verdict:
54
+ 9. Branch on verdict:
46
55
 
47
56
  **Pass:**
48
57
  ```
@@ -54,9 +63,15 @@ description: Run the QA agent on a task in the `qa` state (full pipeline only).
54
63
  **Bounce:**
55
64
  1. Write feedback envelope: `echo '<json>' > /tmp/cloverleaf-fb-q.json`
56
65
  2. `cloverleaf-cli write-feedback <repo_root> <TASK-ID> /tmp/cloverleaf-fb-q.json --prefix=q`
57
- 3. `cloverleaf-cli advance-status <repo_root> <TASK-ID> implementing agent --path=full_pipeline`
58
- 4. Commit: `git add .cloverleaf/ && git commit -m "cloverleaf: <TASK-ID> qa bounced → implementing"`.
59
- 5. Report: "✗ QA bounced. `<failed>/<total>` tests failed. State → implementing. Next: `/cloverleaf-implement <TASK-ID>`."
66
+ 3. Commit the persisted feedback file (was missing pre-v0.4.1 bug #3):
67
+ ```bash
68
+ cd <repo_root>
69
+ git add .cloverleaf/feedback/
70
+ git commit -m "cloverleaf: <TASK-ID> qa feedback"
71
+ ```
72
+ 4. `cloverleaf-cli advance-status <repo_root> <TASK-ID> implementing agent --path=full_pipeline`
73
+ 5. Commit: `git add .cloverleaf/ && git commit -m "cloverleaf: <TASK-ID> qa bounced → implementing"`.
74
+ 6. Report: "✗ QA bounced. `<failed>/<total>` tests failed. State → implementing. Next: `/cloverleaf-implement <TASK-ID>`."
60
75
 
61
76
  **Escalate:**
62
77
  1. `cloverleaf-cli advance-status <repo_root> <TASK-ID> escalated agent`
@@ -7,7 +7,7 @@ description: Run the Reviewer agent on a task in the `review` state. Emits a fee
7
7
 
8
8
  ## Steps
9
9
 
10
- 0. Ensure you are on `main`. State is authoritative on main. Run:
10
+ 0. Pre-flight: ensure you are on `main` and clean stale feedback temp files from previous runs (prevents /tmp leakage between tasks):
11
11
 
12
12
  ```bash
13
13
  cd <repo_root>
@@ -17,11 +17,15 @@ description: Run the Reviewer agent on a task in the `review` state. Emits a fee
17
17
 
18
18
  If main has uncommitted changes, stop and report — the user must clean up first.
19
19
 
20
+ ```bash
21
+ rm -f /tmp/cloverleaf-fb-r.json /tmp/cloverleaf-fb-u.json /tmp/cloverleaf-fb-q.json
22
+ ```
23
+
20
24
  1. Capture the TASK-ID argument.
21
25
 
22
26
  2. Load the task:
23
27
  ```
24
- ~/.claude/plugins/cloverleaf/bin/cloverleaf-cli load-task <repo_root> <TASK-ID>
28
+ cloverleaf-cli load-task <repo_root> <TASK-ID>
25
29
  ```
26
30
  Verify `status === "review"`. If not, report the current status and stop.
27
31
 
@@ -36,7 +40,7 @@ description: Run the Reviewer agent on a task in the `review` state. Emits a fee
36
40
  5. Dispatch the Reviewer subagent via the Task tool:
37
41
  - `subagent_type`: `general-purpose`
38
42
  - `model`: `sonnet`
39
- - Prompt: contents of `~/.claude/plugins/cloverleaf/prompts/reviewer.md` with substitutions for `{{task}}`, `{{branch}}`, `{{base_branch}}`, `{{repo_root}}`, `{{diff}}`.
43
+ - Prompt: contents of `$(cloverleaf-cli plugin-root)/prompts/reviewer.md` with substitutions for `{{task}}`, `{{branch}}`, `{{base_branch}}`, `{{repo_root}}`, `{{diff}}`.
40
44
 
41
45
  6. Parse the subagent's response. Expect a feedback envelope JSON of the form `{"verdict": "pass"|"bounce", "summary": "...", "findings": [...]}`. Validate shape: verdict must be `pass` or `bounce`; if `bounce`, findings must have at least one entry with `severity` (one of `blocker|error|warning|info`) and `message`.
42
46
 
@@ -50,11 +54,17 @@ description: Run the Reviewer agent on a task in the `review` state. Emits a fee
50
54
  Report: "✓ Review passed. State → automated-gates. Next: `/cloverleaf-merge <TASK-ID>`."
51
55
 
52
56
  **Bounce:**
53
- 1. Write the feedback envelope to a temp file: `echo '<envelope-json>' > /tmp/cloverleaf-fb.json`.
54
- 2. `cloverleaf-cli write-feedback <repo_root> <TASK-ID> /tmp/cloverleaf-fb.json` — captures the path like `.cloverleaf/feedback/<TASK-ID>-r<N>.json`.
55
- 3. `cloverleaf-cli advance-status <repo_root> <TASK-ID> implementing agent`loops back.
56
- 4. Commit: `git add .cloverleaf/ && git commit -m "cloverleaf: <TASK-ID> review bounced → implementing"`.
57
- 5. Report: "✗ Review bounced. Findings: <summarize findings by severity>. State → implementing. Next: `/cloverleaf-implement <TASK-ID>`."
57
+ 1. Write the feedback envelope to a temp file: `echo '<envelope-json>' > /tmp/cloverleaf-fb-r.json`.
58
+ 2. `cloverleaf-cli write-feedback <repo_root> <TASK-ID> /tmp/cloverleaf-fb-r.json` — captures the path like `.cloverleaf/feedback/<TASK-ID>-r<N>.json`.
59
+ 3. Commit the persisted feedback file (was missing pre-v0.4.1 bug #3):
60
+ ```bash
61
+ cd <repo_root>
62
+ git add .cloverleaf/feedback/
63
+ git commit -m "cloverleaf: <TASK-ID> review feedback"
64
+ ```
65
+ 4. `cloverleaf-cli advance-status <repo_root> <TASK-ID> implementing agent` — loops back.
66
+ 5. Commit: `git add .cloverleaf/ && git commit -m "cloverleaf: <TASK-ID> review bounced → implementing"`.
67
+ 6. Report: "✗ Review bounced. Findings: <summarize findings by severity>. State → implementing. Next: `/cloverleaf-implement <TASK-ID>`."
58
68
 
59
69
  ## Rules
60
70
 
@@ -7,7 +7,7 @@ description: Run the UI Reviewer agent on a task in the `ui-review` state (full
7
7
 
8
8
  ## Steps
9
9
 
10
- 0. Ensure you are on `main`. State is authoritative on main. Run:
10
+ 0. Pre-flight: ensure you are on `main` and clean stale feedback temp files from previous runs (prevents /tmp leakage between tasks):
11
11
 
12
12
  ```bash
13
13
  cd <repo_root>
@@ -17,22 +17,32 @@ description: Run the UI Reviewer agent on a task in the `ui-review` state (full
17
17
 
18
18
  If main has uncommitted changes, stop and report.
19
19
 
20
+ ```bash
21
+ rm -f /tmp/cloverleaf-fb-r.json /tmp/cloverleaf-fb-u.json /tmp/cloverleaf-fb-q.json
22
+ ```
23
+
20
24
  1. Capture the TASK-ID argument.
21
25
 
22
26
  2. Load the task:
23
27
  ```
24
- ~/.claude/plugins/cloverleaf/bin/cloverleaf-cli load-task <repo_root> <TASK-ID>
28
+ cloverleaf-cli load-task <repo_root> <TASK-ID>
25
29
  ```
26
30
  Verify `status === "ui-review"`. If not, report and stop.
27
31
 
28
32
  3. Confirm feature branch exists: `git rev-parse --verify cloverleaf/<TASK-ID>`. If missing, report and stop.
29
33
 
30
- 4. Compute affected routes:
34
+ 4. Ensure required directories exist:
35
+ ```bash
36
+ mkdir -p <repo_root>/.cloverleaf/baselines
37
+ mkdir -p <repo_root>/.cloverleaf/runs/<TASK-ID>/ui-review
38
+ ```
39
+
40
+ 5. Compute affected routes:
31
41
  ```bash
32
- AFFECTED=$(~/.claude/plugins/cloverleaf/bin/cloverleaf-cli affected-routes <repo_root> <TASK-ID>)
42
+ AFFECTED=$(cloverleaf-cli affected-routes <repo_root> <TASK-ID>)
33
43
  ```
34
44
 
35
- 5. **Empty-set early-exit.** If `AFFECTED` is `[]`, skip the subagent entirely:
45
+ 6. **Empty-set early-exit.** If `AFFECTED` is `[]`, skip the subagent entirely:
36
46
  ```bash
37
47
  cloverleaf-cli advance-status <repo_root> <TASK-ID> qa agent '' full_pipeline
38
48
  cd <repo_root>
@@ -42,28 +52,29 @@ description: Run the UI Reviewer agent on a task in the `ui-review` state (full
42
52
  Report: "✓ UI Review skipped (no renderable routes affected). State → qa. Next: `/cloverleaf-qa <TASK-ID>`."
43
53
  Stop here.
44
54
 
45
- 6. Allocate a free preview port:
55
+ 7. Allocate a free preview port:
46
56
  ```bash
47
57
  PREVIEW_PORT=$(node -e "const net=require('net');const s=net.createServer();s.listen(0,()=>{console.log(s.address().port);s.close()})")
48
58
  ```
49
59
 
50
- 7. Compute diff:
60
+ 8. Compute diff:
51
61
  ```bash
52
62
  git diff main..cloverleaf/<TASK-ID>
53
63
  ```
54
64
 
55
- 8. **Browser cache env var.** Before the Task-tool dispatch, ensure `PLAYWRIGHT_BROWSERS_PATH=~/.cache/ms-playwright` is exported so the subagent inherits it. This keeps Playwright from re-downloading ~300 MB of browser binaries inside the worktree.
65
+ 9. **Browser cache env var.** Before the Task-tool dispatch, ensure `PLAYWRIGHT_BROWSERS_PATH=~/.cache/ms-playwright` is exported so the subagent inherits it. This keeps Playwright from re-downloading ~300 MB of browser binaries inside the worktree.
56
66
 
57
- 9. Dispatch the UI Reviewer subagent via the Task tool:
58
- - `subagent_type`: `general-purpose`
59
- - `model`: `sonnet`
60
- - Prompt: contents of `~/.claude/plugins/cloverleaf/prompts/ui-reviewer.md` with substitutions:
61
- - `{{task}}`, `{{diff}}`, `{{branch}}`, `{{base_branch}}`, `{{repo_root}}`, `{{preview_port}}`
62
- - `{{affected_routes}}` → the value of `$AFFECTED` (verbatim — may be `"all"`, a JSON array, or `[]` but step 5 handled `[]` already)
67
+ 10. Dispatch the UI Reviewer subagent via the Task tool:
68
+ - `subagent_type`: `general-purpose`
69
+ - `model`: `sonnet`
70
+ - Prompt: contents of `$(cloverleaf-cli plugin-root)/prompts/ui-reviewer.md` with substitutions:
71
+ - `{{task}}`, `{{diff}}`, `{{branch}}`, `{{base_branch}}`, `{{repo_root}}`, `{{preview_port}}`
72
+ - `{{affected_routes}}` → the value of `$AFFECTED` (verbatim — may be `"all"`, a JSON array, or `[]` but step 6 handled `[]` already)
73
+ - `{{ui_review_config}}` → JSON-stringified result of `cloverleaf-cli ui-review-config <repo_root>` (used by the subagent to scope viewport sizes, thresholds, and axe rule overrides)
63
74
 
64
- 10. Parse the subagent's response. Expect `{"verdict": "pass"|"bounce"|"escalate", "summary": "...", "findings": [...]}`.
75
+ 11. Parse the subagent's response. Expect `{"verdict": "pass"|"bounce"|"escalate", "summary": "...", "findings": [...]}`.
65
76
 
66
- 11. Branch on verdict:
77
+ 12. Branch on verdict:
67
78
 
68
79
  **Pass:**
69
80
  ```
@@ -75,9 +86,15 @@ description: Run the UI Reviewer agent on a task in the `ui-review` state (full
75
86
  **Bounce:**
76
87
  1. Write feedback: `echo '<envelope-json>' > /tmp/cloverleaf-fb-u.json`
77
88
  2. `cloverleaf-cli write-feedback <repo_root> <TASK-ID> /tmp/cloverleaf-fb-u.json --prefix=u`
78
- 3. `cloverleaf-cli advance-status <repo_root> <TASK-ID> implementing agent '' full_pipeline`
79
- 4. Commit: `git add .cloverleaf/ && git commit -m "cloverleaf: <TASK-ID> ui-review bounced → implementing"`.
80
- 5. Report: "✗ UI Review bounced. Findings: <summary by severity>. State → implementing. Next: `/cloverleaf-implement <TASK-ID>`."
89
+ 3. Commit the persisted feedback file (was missing pre-v0.4.1 bug #3):
90
+ ```bash
91
+ cd <repo_root>
92
+ git add .cloverleaf/feedback/
93
+ git commit -m "cloverleaf: <TASK-ID> ui-review feedback"
94
+ ```
95
+ 4. `cloverleaf-cli advance-status <repo_root> <TASK-ID> implementing agent '' full_pipeline`
96
+ 5. Commit: `git add .cloverleaf/ && git commit -m "cloverleaf: <TASK-ID> ui-review bounced → implementing"`.
97
+ 6. Report: "✗ UI Review bounced. Findings: <summary by severity>. State → implementing. Next: `/cloverleaf-implement <TASK-ID>`."
81
98
 
82
99
  **Escalate:**
83
100
  1. `cloverleaf-cli advance-status <repo_root> <TASK-ID> escalated agent`
@@ -89,5 +106,5 @@ description: Run the UI Reviewer agent on a task in the `ui-review` state (full
89
106
  - Never push.
90
107
  - Do not modify source code — UI Reviewer is read-only.
91
108
  - Always teardown preview server + worktree on error.
92
- - Empty-set early-exit (step 5) skips the browser entirely — no Playwright invocation, no worktree.
109
+ - Empty-set early-exit (step 6) skips the browser entirely — no Playwright invocation, no worktree.
93
110
  - On illegal state transition, report and stop without partial commits.