@cloverleaf/reference-impl 0.12.0 → 0.13.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: cloverleaf-run
3
- description: End-to-end orchestrator. Reads task.risk_class to dispatch fast lane (implement → reviewmerge) or full pipeline (implement document review [ui-review?] qa → final-merge). Per-agent bounce counters (max 3 each). Usage — /cloverleaf-run <TASK-ID>.
3
+ description: End-to-end orchestrator. Drives every task through one universal delivery council — implement → documentingcouncil final-gate/implementing/escalated. The lane is a risk_class profile selector (delivery-fast / delivery-full); security, UI, and QA are council members. Usage — /cloverleaf-run <TASK-ID>.
4
4
  ---
5
5
 
6
6
  # Cloverleaf — run (orchestrator)
@@ -11,128 +11,71 @@ description: End-to-end orchestrator. Reads task.risk_class to dispatch fast lan
11
11
 
12
12
  Do NOT `git checkout main` from a walker worktree — main is held by the primary repo. To compare against main, use `git diff main..HEAD` or `git show main:<path>`. Sub-skills run from the worktree's current branch and stay on it; the walker (in the primary repo) does the final merge to main itself after all tasks reach final-gate.
13
13
 
14
- ## Per-agent bounce budget
14
+ ## Bounce budget
15
15
 
16
- ```
17
- MAX_REVIEWER_BOUNCES = 3
18
- MAX_UI_REVIEWER_BOUNCES = 3
19
- MAX_QA_BOUNCES = 3
20
- MAX_SECURITY_BOUNCES = 3
21
- ```
16
+ The delivery council owns the loop. `council_bounces` (max 3) counts council bounces back to the Implementer; `plan_review_bounces` (max 3) counts decisive plan-review bounces. On either cap, escalate (section 6). Security, UI, and QA are **council members**, not separate gates — there is no per-agent counter.
22
17
 
23
18
  These counters live in-session (not persisted). Rerunning `/cloverleaf-run` resets.
24
19
 
25
- ## Security gate (both lanes)
26
-
27
- Run this immediately after the task reaches `automated-gates` (Reviewer passed) and BEFORE the lane's next move (fast lane: merge; full pipeline: detect-ui-paths). Initialize `security_bounces = 0` at orchestrator start (alongside the other bounce counters).
28
-
29
- ```bash
30
- cloverleaf-cli classify-security <repo_root> <TASK-ID> --branch cloverleaf/<TASK-ID>
31
- ```
32
-
33
- Parse the JSON. If `classify-security` exits non-zero or emits unparseable output, do NOT silently skip security review (fail-open is unsafe for a security gate). Warn to the user and treat the task as `effective: "high"` — i.e. proceed into security-review anyway (fail toward more scrutiny). If `/cloverleaf-security-review` then cannot run either (e.g. branch/tooling broken), surface the failure and stop rather than merging unreviewed.
34
-
35
- If `effective == "low"` → skip the gate, proceed with the lane.
36
-
37
- If `effective == "high"`:
38
- - If `declared == "low"` (under-classification: `diff_detected` true), you may proactively run `classify-security` to confirm, but the writeback to `security_class: "high"` is now mechanical — the CLI handles it automatically when `advance-status` moves the task to `security-review`. No manual scripting of the writeback is required.
39
- - `cloverleaf-cli advance-status <repo_root> <TASK-ID> security-review agent`; commit.
40
- - Inline `/cloverleaf-security-review <TASK-ID>` steps. Reload the task:
41
- - `status == "automated-gates"` → security review passed; proceed with the lane.
42
- - `status == "implementing"` → bounced. `security_bounces += 1`. If `security_bounces >= MAX_SECURITY_BOUNCES`, escalate (section 6). Else re-enter the implement→review loop (fast lane section 4 / full pipeline section 5.1), which re-runs the security gate on its next pass.
43
- - `status == "escalated"` → the security reviewer found a blocker; stop and surface to the user (a human must review `.cloverleaf/feedback/`). This is the security reviewer's own escalation, distinct from a bounce-budget exhaustion.
44
-
45
- ### Refusal and recover
46
-
47
- In v0.8.1, `advance-status` from `automated-gates` to any post-gate state (`ui-review`, `qa`, `merged`) may exit with **exit code 2** when the task is high-security and has no pass verdict recorded (`security_review_verdict` is absent or not `"pass"`). This is a **security-gate refusal** — the CLI is enforcing that high-security tasks must pass security review before proceeding.
48
-
49
- Recovery sequence:
50
- 1. Advance the task to `security-review` first: `cloverleaf-cli advance-status <repo_root> <TASK-ID> security-review agent`; commit.
51
- 2. Run `/cloverleaf-security-review <TASK-ID>` to execute the security review.
52
- 3. Retry the original `advance-status` call. If the review passed, the CLI will now allow the transition.
53
-
54
20
  ## Steps
55
21
 
56
- 1. Capture TASK-ID.
57
-
58
- 2. Load task: `cloverleaf-cli load-task <repo_root> <TASK-ID>`. Verify `status === "pending"`. If not, report and stop.
59
-
60
- 3. **Council gate detection (opt-in).** Run `cloverleaf-cli council-plan <repo_root> <TASK-ID> task.review` and parse the JSON plan. If `plan.source === "consumer"` **and** `plan.profile !== null`, the project has opted into a configured review council — drive the review phase via **section 7 (Council review path)** instead of the hardcoded reviewer/security/ui/qa steps in sections 4/5. Otherwise (`source: "default"`, or no `task.review` binding) proceed exactly as today:
61
- - `task.risk_class === "low"` → section 4 (Fast Lane)
62
- - `task.risk_class === "high"` → section 5 (Full Pipeline)
63
-
64
- When the council path is active it still uses the Implementer (and, for the full pipeline, the Documenter) to produce the branch; only the review→merge portion is council-driven.
65
-
66
- ### 4. Fast Lane
67
-
68
- Initialize `reviewer_bounces = 0`, `security_bounces = 0`.
22
+ 1. Capture TASK-ID. Initialize `council_bounces = 0`, `plan_review_bounces = 0`.
69
23
 
70
- Loop:
71
- a. Inline `/cloverleaf-implement <TASK-ID>` steps.
72
- b. Inline `/cloverleaf-review <TASK-ID>` steps.
73
- c. Reload task. If `status === "automated-gates"`: pass! Break loop.
74
- d. If `status === "implementing"`: Reviewer bounced. `reviewer_bounces += 1`. If `reviewer_bounces >= MAX_REVIEWER_BOUNCES`, escalate (section 6). Else continue loop.
75
- e. Else: unexpected state. Report and stop.
24
+ 2. Load task: `cloverleaf-cli load-task <repo_root> <TASK-ID>`. Verify `status === "pending"`. If not, report and stop. **Preflight:** `load-task` does not schema-validate. Before dispatching any agent, confirm the task document is schema-valid: `context.rfc` is present, and `risk_class` / `security_class` are `low` or `high`. An invalid task otherwise clears every precondition and fails at its first real transition — after the Implementer has already produced a branch and commits.
76
25
 
77
- After loop (status `automated-gates`): run the **Security gate (both lanes)** (above). Then inline `/cloverleaf-merge <TASK-ID>`.
26
+ If any `advance-status` later fails with `orphan event written to … but task save failed`, the event file it names records a transition that did not happen: delete that file before retrying, or the retry will number the next event around it.
78
27
 
79
- ### 5. Full Pipeline
28
+ 3. **Tactical plan (+ optional decisive plan-review).**
29
+ a. `cloverleaf-cli council-plan <repo_root> <TASK-ID> task.plan_review`. **A decisive `task.plan_review` is not currently wired — do not bind one.** `/cloverleaf-implement <TASK-ID>` always completes both advances (`pending → tactical-plan → implementing`) in a single dispatch and stops at `implementing`; there is no point at which a plan-review verdict can be applied. If a consumer's `.cloverleaf/config/council.json` bound `plan.mode === "decisive"` for this gate anyway, §3b's `cloverleaf-cli apply-council-verdict <repo_root> <TASK-ID> task.plan_review '<verdict>'` would fail — it requires the task to still be at `tactical-plan`, and by the time `/cloverleaf-implement` returns it is already at `implementing`. The shipped default binds no profile to `task.plan_review` (`plan.profile` is always `null` here), so this limitation does not affect the packaged pipeline; it is tracked as a follow-up, not built in this fix. Otherwise (no decisive plan-review bound — the shipped default) simply inline `/cloverleaf-implement <TASK-ID>`, which walks `pending → tactical-plan → implementing` and stops at `implementing`.
30
+ b. **Reserved — not reachable today.** Applying a decisive `task.plan_review` verdict requires the task to still be at `tactical-plan`, and 3a never leaves it there under the current `/cloverleaf-implement`, so skip 3b unconditionally and continue to 3c. The bullets below record the intended reload logic for when a real stop-at-`tactical-plan` mode exists:
31
+ - `implementing` (pass) → continue to 3c.
32
+ - `pending` (bounce) → `plan_review_bounces += 1`; if `>= 3` escalate (section 6); else return to 3a.
33
+ - `escalated` → stop and surface.
34
+ c. Finish the Implementer (task at `implementing`), then reach `documenting` for **every** `risk_class`:
35
+ - `risk_class: "high"` → run `/cloverleaf-document <TASK-ID>` (the Documenter adds doc commits and advances `implementing → documenting`).
36
+ - `risk_class: "low"` (no docs) → the **runner** advances the state itself: `cloverleaf-cli advance-status <repo_root> <TASK-ID> documenting agent`, then commit (`git add .cloverleaf/ && (git diff --cached --quiet || git commit -m "cloverleaf: <TASK-ID> → documenting")`).
80
37
 
81
- Initialize `reviewer_bounces = 0`, `ui_reviewer_bounces = 0`, `qa_bounces = 0`, `security_bounces = 0`.
38
+ Either way the task reaches `documenting` before §4a advances `documenting council`.
82
39
 
83
- 5.1. **Implementer → Documenter → Reviewer loop:**
40
+ 4. **Delivery council.**
41
+ a. Enter the phase: `cloverleaf-cli advance-status <repo_root> <TASK-ID> council agent`. Commit. (Council entry classifies security — a sensitive diff upgrades `security_class` to `high` so the blocking security member runs.)
42
+ b. `cloverleaf-cli council-plan <repo_root> <TASK-ID> task.review`. The plan always carries a profile: the shipped default binds `task.review` to `delivery-fast` (`risk_class: low`) / `delivery-full` (`risk_class: high`); a consumer `.cloverleaf/config/council.json` overrides.
43
+ c. Run the council members (section 7.2), reach the verdict (7.3 chair / 7.4 deterministic), and — **before** applying it — run the **baselines-hold check (section 4.1)**. Then, once cleared, `cloverleaf-cli apply-council-verdict <repo_root> <TASK-ID> task.review '<verdict>'`. Commit the remainder: `git add .cloverleaf/ && (git diff --cached --quiet || git commit -m "cloverleaf: <TASK-ID> council review (<verdict>)")`.
84
44
 
85
- Loop:
86
- a. Inline `/cloverleaf-implement <TASK-ID>` steps.
87
- b. Inline `/cloverleaf-document <TASK-ID>` steps.
88
- c. Inline `/cloverleaf-review <TASK-ID>` steps.
89
- d. Reload task. If `status === "automated-gates"`: pass! Exit this loop.
90
- e. If `status === "implementing"`: Reviewer bounced. `reviewer_bounces += 1`. If `reviewer_bounces >= MAX_REVIEWER_BOUNCES`, escalate. Else continue loop.
91
- f. Else: unexpected. Report and stop.
45
+ ### 4.1 Baselines hold (before applying a council pass)
92
46
 
93
- **Security gate.** Run the **Security gate (both lanes)** (above) now, before UI-path detection. Then continue to 5.2.
94
-
95
- 5.2. **UI-path detection and conditional UI Review:**
47
+ The collapse removed the old `ui-review qa` hold that `baselines_pending` guarded; the hold moves to **council pass**. After the members run (the `ui` member captures baselines and, on new/resized baselines, sets `baselines_pending=true` via `write-ui-review-state` — that mechanism is unchanged), and **before** applying a council `pass` that would advance `council → final-gate`, read the ui-review state:
96
48
 
97
49
  ```bash
98
- cloverleaf-cli detect-ui-paths <repo_root> <TASK-ID>
50
+ cloverleaf-cli read-ui-review-state <repo_root> <TASK-ID>
99
51
  ```
100
52
 
101
- If output is `true`:
102
- - Advance: `cloverleaf-cli advance-status <repo_root> <TASK-ID> ui-review agent --path=full_pipeline`. Commit.
103
- - UI-review loop:
104
- a. Inline `/cloverleaf-ui-review <TASK-ID>` steps.
105
- b. Reload task. If `status === "qa"`: pass! Exit UI-review loop.
106
- c. If `status === "implementing"`: UI Reviewer bounced. `ui_reviewer_bounces += 1`. If `>= MAX_UI_REVIEWER_BOUNCES`, escalate. Else return to section 5.1 (Implementer re-runs, which then re-documents, re-reviews).
107
- d. Else: unexpected. Report and stop.
108
-
109
- If output is `false`: skip UI review. Advance: `cloverleaf-cli advance-status <repo_root> <TASK-ID> qa agent --path=full_pipeline`. Commit.
110
-
111
- 5.3. **QA loop:**
53
+ - If the council verdict is `pass` **and** `baselines_pending` is `true`: do **NOT** apply the verdict. Surface to the human: "⏸ `<TASK-ID>` — new visual baselines need approval. Inspect the captured baseline images, then run `/cloverleaf-approve-baselines <TASK-ID>` (which clears `baselines_pending`) and re-run `/cloverleaf-run <TASK-ID>` — the `ui` member now passes and the council pass applies." Stop here (leave the task at `council`); the re-run re-dispatches the council with `baselines_pending=false`.
54
+ - Otherwise (`baselines_pending` is `false`, or the verdict is `bounce` / `escalate`): proceed to apply the verdict (step 4c). This is a runner **convention** — no FSM change, exactly as the old `ui-review qa` hold was a convention. `/cloverleaf-approve-baselines` and the `write-baseline` guard are unchanged.
112
55
 
113
- Loop:
114
- a. Inline `/cloverleaf-qa <TASK-ID>` steps.
115
- b. Reload task. If `status === "final-gate"`: pass! Exit loop.
116
- c. If `status === "implementing"`: QA bounced. `qa_bounces += 1`. If `qa_bounces >= MAX_QA_BOUNCES`, escalate. Else return to section 5.1.
117
- d. Else: unexpected. Report and stop.
118
-
119
- 5.4. **Final merge:** First run the **Advisory `final_gate` council** (§7.6) if a consumer has bound `task.final_gate`. Inline `/cloverleaf-merge <TASK-ID>` steps (branches to full-pipeline gate per state).
56
+ 5. **Branch on the task's new status** (reload with `load-task`):
57
+ - `final-gate` (pass) → run the advisory `final_gate` council (section 7.6) if bound, then inline `/cloverleaf-merge <TASK-ID>`.
58
+ - `implementing` (bounce) `council_bounces += 1`. If `>= 3`, escalate (section 6). Else return to 3c (re-implement; the batched council feedback is in `.cloverleaf/feedback/`).
59
+ - `escalated` stop and surface (`.cloverleaf/feedback/` + `.cloverleaf/runs/<TASK-ID>/council/task.review.json`).
120
60
 
121
61
  ### 6. Escalation
122
62
 
123
63
  - `cloverleaf-cli advance-status <repo_root> <TASK-ID> escalated agent`
124
64
  - Commit: `git add .cloverleaf/ && git commit -m "cloverleaf: <TASK-ID> escalated (bounce budget exhausted)"`.
125
- - Report: "✗ Escalated `<TASK-ID>`. Review `.cloverleaf/feedback/` and either refine the task or take over manually. Counters: reviewer=<N>, ui_reviewer=<N>, qa=<N>, security=<N>."
65
+ - Report: "✗ Escalated `<TASK-ID>`. Review `.cloverleaf/feedback/` and either refine the task or take over manually. Counters: council_bounces=<N>, plan_review_bounces=<N>."
126
66
 
127
- ### 7. Council review path (opt-in; active when council-plan source is "consumer")
67
+ ## 7. Delivery council mechanics
128
68
 
129
- Initialize `council_bounces = 0`.
69
+ The council member-dispatch, verdict, and apply steps referenced by steps 3b / 4c / 5.
130
70
 
131
- 7.1 **Produce the branch.** Run the Implementer (`/cloverleaf-implement <TASK-ID>` steps); for `risk_class: "high"` also run the Documenter (`/cloverleaf-document <TASK-ID>` steps). The task reaches `review`.
71
+ 7.2 **Run the council members (verdict-only).** Re-run `cloverleaf-cli council-plan <repo_root> <TASK-ID> task.review` to get `plan.rounds`, `plan.aggregation`, `plan.on_round_bounce`, and (for a chair profile) `plan.chair`. For each round **in order**: dispatch **all active members in the round concurrently** — issue their Task-tool calls **in a single message** so the harness runs them in parallel — and capture each member's `{verdict, summary, findings}` envelope. Do **not** advance state (the task stays at `council` until you apply the verdict at step 4c). Rounds still run in sequence; only members *within* a round are concurrent. (Built-in members resolve to the shipped `reviewer`/`security-reviewer`/`ui-reviewer`/`qa` prompts by their `promptPath`; a custom role resolves to `.cloverleaf/prompts/<file>.md`.)
132
72
 
133
- 7.2 **Run the council members (verdict-only).** Re-run `cloverleaf-cli council-plan <repo_root> <TASK-ID> task.review` to get `plan.rounds`, `plan.aggregation`, `plan.on_round_bounce`, and (for a chair profile) `plan.chair`. For each round **in order**: dispatch **all active members in the round concurrently** issue their Task-tool calls **in a single message** so the harness runs them in parallel — and capture each member's `{verdict, summary, findings}` envelope. Do **not** advance state. Rounds still run in sequence; only members *within* a round are concurrent. (Built-in members resolve to the shipped `reviewer`/`security-reviewer`/`ui-reviewer`/`qa` prompts; a custom role resolves to `.cloverleaf/prompts/<file>.md`.)
73
+ **Dispatch conventions:** invoke the Task tool in foreground (default never `run_in_background`); do not poll with foreground `sleep`. Substitute the five base tokens, plus every entry in that member's `substitutions` map from the plan:
74
+ - `{{task}}`, `{{branch}}` (`cloverleaf/<TASK-ID>`), `{{base_branch}}` (`main`), `{{repo_root}}`, `{{diff}}` (`git diff main..cloverleaf/<TASK-ID> -- ':(exclude).cloverleaf/'`) — the five base tokens, always present.
75
+ - `{{<key>}}` for every key in `substitutions`: `council-plan` resolves each member's extra tokens beyond the five base ones (e.g. `test_rules` for `reviewer`, `qa_rules` for `qa`, `affected_routes` / `ui_review_config` / `taskId` for `ui`; `security`'s map is empty — its prompt needs no extra tokens).
76
+ - **`{{preview_port}}` — the one exception.** `ui-reviewer.md` declares it, but it is deliberately NOT in the plan's `substitutions`: planning must stay side-effect free and cannot allocate a port without one. When dispatching the `ui` member, the runner must allocate a free port itself and substitute `{{preview_port}}` before dispatch — the same way the standalone `cloverleaf-ui-review` skill does: `PREVIEW_PORT=$(node -e "const net=require('net');const s=net.createServer();s.listen(0,()=>{console.log(s.address().port);s.close()})")`.
134
77
 
135
- **Dispatch conventions:** invoke the Task tool in foreground (default never `run_in_background`); do not poll with foreground `sleep`. Substitute `{{task}}`, `{{branch}}` (`cloverleaf/<TASK-ID>`), `{{base_branch}}` (`main`), `{{repo_root}}`, `{{diff}}` (`git diff main..cloverleaf/<TASK-ID> -- ':(exclude).cloverleaf/'`).
78
+ Never dispatch a member with an unresolved `{{…}}` token. The three bullets above are the complete set of substitution sources: the five base tokens, every key in that member's `substitutions`, and — for `ui` only `{{preview_port}}`. Apply all three, then scan the filled prompt text; if any `{{}}` remains, stop and report rather than letting the member improvise. (Nothing should: `tests/council.test.ts` pins every built-in prompt's declared tokens against exactly those three sources, so a leftover means the prompt and `MEMBER_TOKENS` have drifted.)
136
79
 
137
80
  Persist each member's envelope: `echo '<envelope>' > /tmp/clv-council-<member>.json && cloverleaf-cli write-feedback <repo_root> <TASK-ID> /tmp/clv-council-<member>.json --prefix=<prefix>`, where `<prefix>` is `r`/`s`/`u`/`q` for the built-ins and the **member id** for a custom role. Collect a members array `[{ "member": "<id>", "verdict": "<pass|bounce|escalate>", "blocking": <plan member blocking>, "weight": <plan member weight> }]`.
138
81
 
@@ -145,28 +88,24 @@ Initialize `council_bounces = 0`.
145
88
  - Otherwise (a blocking member bounced; no member escalated) **dispatch the chair.** Build enriched inputs `[{ "member", "verdict", "blocking", "weight", "envelope": <the member's /tmp/clv-council-<member>.json object> }]`; run `context=$(cloverleaf-cli chair-context '<enriched-inputs-json>')`. Dispatch the chair prompt at `plan.chair.promptPath` as a **read-only** foreground subagent, substituting `{{task}}`, `{{repo_root}}`, and `{{member_verdicts}}` = `$context`; capture its `{verdict, rationale, forward}` output. Then run `cloverleaf-cli chair-verdict '<chair-raw-json>' '<members-json>'` and capture the council verdict JSON.
146
89
  - **Else (deterministic):** map `plan.aggregation` to the CLI rule (a string passes through; `{ "quorum": k }` → `quorum:k`) and run `cloverleaf-cli aggregate-verdicts '<members-json>' <rule>`; capture the council verdict JSON.
147
90
 
148
- 7.4 **Apply.** Run `cloverleaf-cli apply-council-verdict <repo_root> <TASK-ID> task.review '<council-verdict-json>'`. The FSM walk may self-commit some transitions (e.g. `security_class → high`, the rework verdict-reset), so the wrap-up commit can find nothing staged — that is expected. Commit the remainder: `git add .cloverleaf/ && (git diff --cached --quiet || git commit -m "cloverleaf: <TASK-ID> council review (<verdict>)")`.
149
-
150
- 7.5 **Branch on the task's new status (reload with `load-task`):**
151
- - `automated-gates` (fast lane pass) or `final-gate` (full pipeline pass) → proceed to the merge: inline `/cloverleaf-merge <TASK-ID>`.
152
- - `implementing` (bounce) → `council_bounces += 1`. If `council_bounces >= 3`, escalate (section 6). Else return to 7.1.
153
- - `escalated` → stop and surface to the user (review `.cloverleaf/feedback/` and `.cloverleaf/runs/<TASK-ID>/council/task.review.json`).
91
+ 7.4 **Apply.** After the baselines-hold check (section 4.1) clears, run `cloverleaf-cli apply-council-verdict <repo_root> <TASK-ID> task.review '<council-verdict-json>'`. The FSM walk may self-commit some transitions (e.g. `security_class → high`, the rework verdict-reset), so the wrap-up commit can find nothing staged — that is expected. Commit the remainder: `git add .cloverleaf/ && (git diff --cached --quiet || git commit -m "cloverleaf: <TASK-ID> council review (<verdict>)")`. The verdict drives the FSM: `pass` → `council → final-gate`; `bounce` → `council → implementing`; `escalate` → `council → escalated` (branch per step 5).
154
92
 
155
93
  On a chair **bounce**, the result artifact's `forward` array names the members whose feedback the Implementer should prioritize; the chair `rationale` frames them. The council result artifact at `.cloverleaf/runs/<TASK-ID>/council/task.review.json` records per-member verdicts, the aggregate (or chair) verdict, `forward` (for a chair bounce), and the security basis (incl. an omitted or out-voted `security` member). On any member-dispatch failure or unparseable envelope, stop and report — never treat a failed member as a pass.
156
94
 
157
- ### 7.6 Advisory `final_gate` council (opt-in; full pipeline only)
95
+ ### 7.6 Advisory `final_gate` council (opt-in)
158
96
 
159
- `final-gate` is reached only in the full pipeline and is already the human merge pause. Before inlining `/cloverleaf-merge <TASK-ID>` at a full-pipeline final gate (both here at 7.5 and at §5.4), check for an advisory council:
97
+ `final-gate` is the human merge pause. Before inlining `/cloverleaf-merge <TASK-ID>` at the final gate (step 5), check for an advisory council:
160
98
 
161
99
  1. `cloverleaf-cli council-plan <repo_root> <TASK-ID> task.final_gate`.
162
100
  2. If `plan.source !== "consumer"` or `plan.profile === null`, skip — proceed to the plain human merge (today's behavior).
163
101
  3. Otherwise dispatch `plan.rounds` per §7.2 (parallel within a round), reviewing `{{diff}}` = `git diff main..cloverleaf/<TASK-ID> -- ':(exclude).cloverleaf/'`, and reach a verdict per §7.3 (chair) or §7.4-style `aggregate-verdicts` (deterministic). Then `cloverleaf-cli apply-council-verdict <repo_root> <TASK-ID> task.final_gate '<council-verdict-json>'`. This **posts** the advisory result to `.cloverleaf/runs/<TASK-ID>/council/task.final_gate.json` + a feedback envelope and **drives no transition** (the task stays at `final-gate`). Commit: `git add .cloverleaf/ && (git diff --cached --quiet || git commit -m "cloverleaf: <TASK-ID> advisory final_gate council (<verdict>)")`.
164
102
  4. Surface the council verdict + rationale to the human at the merge confirmation. The human still drives `/cloverleaf-merge` (merge) or reject; the advisory council never merges.
165
103
 
166
- The **fast lane's** `human_merge` (`automated-gates → merged`) is not a council gate. `task.plan_review` (advisory, at `tactical-plan`) is supported at the CLI/library level (`council-plan task.plan_review`, `apply-council-verdict task.plan_review`) for a consumer with a human checkpoint at `tactical-plan`; it is not auto-inserted into this autonomous runner.
104
+ `task.plan_review` (decisive, at `tactical-plan`) is **not currently wired** (see §3a/§3b); `task.final_gate` is advisory-only and post-only.
167
105
 
168
106
  ## Rules
169
107
 
170
- - Each agent has its own 3-bounce budget. Bounces from different agents do NOT share counters.
171
- - On any sub-skill error or escalation, orchestrator stops with clear message.
108
+ - The delivery council owns the bounce loop: `council_bounces` (max 3) and `plan_review_bounces` (max 3). There is no per-agent counter security, UI, and QA are members.
109
+ - On any sub-skill error or escalation, the orchestrator stops with a clear message.
172
110
  - Human merge gate is NOT skipped; confirmation is still required at merge time.
111
+ - The baselines-hold is a convention: a council `pass` is held at `baselines_pending` until `/cloverleaf-approve-baselines <TASK-ID>` clears it and the council is re-run.
@@ -162,7 +162,7 @@ description: Autonomous DAG walker for Cloverleaf Plans. Given a PLAN-ID in stat
162
162
 
163
163
  - **`tool_decision_required`** → let the walker policy decide (auto-approve per rules, defer to user for anything not covered).
164
164
 
165
- - **`turn_completed [DONE]`** → the session has finished its current turn with a `[DONE]` terminal token. If the on-disk task status is `final-gate` or `automated-gates`, push onto the final-gate queue. Otherwise continue monitoring.
165
+ - **`turn_completed [DONE]`** → the session has finished its current turn with a `[DONE]` terminal token. If the on-disk task status is `final-gate`, push onto the final-gate queue. Otherwise continue monitoring.
166
166
 
167
167
  - **`turn_completed [NEEDS-INPUT]`** → the session is paused waiting for a user reply. Surface the assistant's last message to the driver and send the user's response via `mcp__claw-drive__send_turn`.
168
168
 
@@ -179,7 +179,7 @@ description: Autonomous DAG walker for Cloverleaf Plans. Given a PLAN-ID in stat
179
179
  ```
180
180
  This covers transient API errors (e.g. HTTP 503, `API Error: 503`) and the `temporarily unavailable` service message without requiring a Session A nudge from the human.
181
181
 
182
- e. **Drain the final-gate queue serially and merge on main.** Session B does NOT invoke `/cloverleaf-merge` — it stops at automated-gates (fast lane) or final-gate (full pipeline) and reports. The walker performs the merge on main in the primary repo. For each queued task:
182
+ e. **Drain the final-gate queue serially and merge on main.** Session B does NOT invoke `/cloverleaf-merge` — it stops at final-gate and reports. The walker performs the merge on main in the primary repo. For each queued task:
183
183
 
184
184
  **Scope check (BEFORE the y/N prompt).** Run `cloverleaf-cli check-scope` and capture its output and exit code:
185
185
 
@@ -204,10 +204,10 @@ description: Autonomous DAG walker for Cloverleaf Plans. Given a PLAN-ID in stat
204
204
 
205
205
  1. Print a full summary to the driver:
206
206
  ```
207
- ⏵ <TASK-ID> ready to merge (<fast lane | full pipeline>)
207
+ ⏵ <TASK-ID> ready to merge
208
208
  Reviewer: <summary>
209
209
  UI Reviewer: <summary or "skipped">
210
- QA: <summary or "n/a for fast lane">
210
+ QA: <summary or "skipped">
211
211
  Session <session_id>, worktree <worktree_path>
212
212
 
213
213
  Confirm merge? (y/N, or ask a question)
@@ -224,7 +224,7 @@ description: Autonomous DAG walker for Cloverleaf Plans. Given a PLAN-ID in stat
224
224
  echo "$CHANGED_FILES" | xargs grep -l -E '^(<{7}|={7}|>{7})' 2>/dev/null
225
225
  # Do NOT proceed; mark task escalated and surface to user
226
226
  else
227
- git -C <repo_root> merge --no-ff cloverleaf/<TASK-ID> -m "cloverleaf: <TASK-ID> merged (<fast_lane | full_pipeline>)"
227
+ git -C <repo_root> merge --no-ff cloverleaf/<TASK-ID> -m "cloverleaf: <TASK-ID> merged"
228
228
  fi
229
229
  ```
230
230
 
@@ -232,12 +232,8 @@ description: Autonomous DAG walker for Cloverleaf Plans. Given a PLAN-ID in stat
232
232
 
233
233
  After a **successful** `git merge --no-ff`, advance state and commit:
234
234
  ```bash
235
- # Fast lane:
236
- cloverleaf-cli emit-gate-decision <repo_root> <TASK-ID> human_merge approve human
237
- cloverleaf-cli advance-status <repo_root> <TASK-ID> merged human human_merge fast_lane
238
- # Full pipeline (task is already at final-gate):
239
235
  cloverleaf-cli emit-gate-decision <repo_root> <TASK-ID> final_approval_gate approve human
240
- cloverleaf-cli advance-status <repo_root> <TASK-ID> merged human final_approval_gate full_pipeline
236
+ cloverleaf-cli advance-status <repo_root> <TASK-ID> merged human final_approval_gate
241
237
  ```
242
238
  ```bash
243
239
  git -C <repo_root> add .cloverleaf/ && git -C <repo_root> commit -m "cloverleaf: <TASK-ID> merged"
@@ -350,32 +346,29 @@ stay on the worktree's current branch (`cloverleaf/<TASK-ID>`).
350
346
 
351
347
  Plan: invoke `/cloverleaf-run <TASK-ID>`.
352
348
 
353
- **DO NOT invoke `/cloverleaf-merge`**. Fast lane stops after `/cloverleaf-review`
354
- lands the task at `automated-gates`. Full pipeline stops after QA/UI-Review
355
- lands the task at `final-gate`. Report status + summaries at that point and
356
- exit cleanly. The walker runs in the primary repo on `main` and performs the
357
- real `git merge --no-ff` itself after human approval — the worktree's main
358
- branch can't be checked out concurrently, which is why the walker owns the
359
- merge. If `/cloverleaf-run` would normally invoke `/cloverleaf-merge`
360
- internally (fast-lane orchestrator), interrupt before that step and exit.
361
-
362
- All four v0.5.2+v0.5.3+v0.5.4+v0.5.5 dogfood fixes are in place:
363
- - /cloverleaf-merge actor: human final_approval_gate full_pipeline.
349
+ **DO NOT invoke `/cloverleaf-merge`**. Delivery lands the task at `final-gate`; do NOT invoke `/cloverleaf-merge`; report status + summaries at that point and exit cleanly. The walker runs in the primary repo on `main` and performs the real `git merge --no-ff` itself after human approval — the worktree's main branch can't be checked out concurrently, which is why the walker owns the merge.
350
+
351
+ All v0.5.2+v0.5.3+v0.5.4+v0.5.5 dogfood fixes are in place:
352
+ - /cloverleaf-merge actor: human final_approval_gate.
364
353
  - cloverleaf-cli prep-worktree is idempotent.
365
354
  - Documenter runs `git status --porcelain` and stages every modified doc.
366
355
  - cloverleaf-ui-review uses /cloverleaf-approve-baselines (fully-qualified).
367
356
 
368
- Expected: zero interventions until you reach automated-gates / final-gate,
369
- then exit.
357
+ Expected: zero interventions until you reach final-gate, then exit.
370
358
 
371
359
  Do not push. Do not publish. Report merge + state commit SHAs on completion.
372
360
  ```
373
361
 
374
362
  ## Walker policy
375
363
 
376
- The walker spawns each Session B with a conservative auto-approve policy (Read/Glob/Grep, git-read, cloverleaf-cli, npm/npx/node, common compound scripts, prep-worktree, mkdir -p, etc.) and an auto-reject list covering sudo, `rm -rf /`, git push, npm publish, destructive disk ops. Anything else escalates to the walker for human-in-the-loop handling.
364
+ The walker spawns each Session B with a conservative policy resolving every tool call to one of four outcomes:
365
+
366
+ - **auto-approve** — Read/Glob/Grep, git reads (including `git -C <path> …`), `npm`/`npx`, `node <script>`, `cloverleaf-cli` anywhere in a compound script, and the usual `set -e` / `cd` / `export` / `source` prefixes.
367
+ - **auto-defer** — pauses for a human: `sudo`/`su`, and anything that runs code the command regex cannot inspect (`node -e`/`-p`, `python -c`, `perl -e`, `sh -c`, `eval`), plus `chmod -R 777`, `chown -R`, `truncate`, `systemctl stop`.
368
+ - **auto-reject** — recursive `rm`, `git push`, `git reset --hard`, `npm publish`, `curl … | bash`, disk-destructive ops (`dd if=`, `mkfs`, `shred`, `fdisk`), writes to real block devices, and writes to claw-drive's own policy file or `.claw-drive/` runtime state.
369
+ - **escalate** — everything else goes to the walker for human-in-the-loop handling.
377
370
 
378
- The concrete policy JSON is the same one used during the CLV-16..CLV-20 dogfood runs; see `.cloverleaf/claw-drive-policy.json` in the repo for the starting template.
371
+ The concrete policy is `.cloverleaf/claw-drive-policy.json` in this repo a starting template, not a guarantee; tune it for your own project. It tracks claw-drive's shipped starter with a few deliberate divergences, each recorded in the file's own `_comment`. After editing it, run `node .cloverleaf/policy-check.mjs`, which asserts the decision for every command in `.cloverleaf/policy-probes.tsv` and exits non-zero on a regression.
379
372
 
380
373
  ## Rules
381
374
 
@@ -395,4 +388,4 @@ The concrete policy JSON is the same one used during the CLV-16..CLV-20 dogfood
395
388
 
396
389
  **RFC-direct task participation in RFC auto-advance.** Tasks with no `parent` field but with `context.rfc` set (created via `/cloverleaf-new-task --rfc=<RFC-ID>`) are *first-class* participants in the `can_auto_advance_rfc` check. They block the advance when in-flight; they count toward delivery when merged. See `cloverleaf-cli rfc-tasks <repo_root> <RFC-ID>` for the categorized view this dispatch reads from, or `reference-impl/README.md` § "Plans vs RFC-direct tasks" for the user-facing pattern docs.
397
390
 
398
- **Security-review escalations.** When a task's effective `security_class` is high, `/cloverleaf-run` routes it through `security-review` off the automated-gates hub. A `blocker` finding (e.g. a leaked credential) advances the task to `escalated`, which surfaces through the walker's existing escalation path — expect and surface these like any other escalation; do not auto-retry a security blocker.
391
+ **Security-review escalations.** When a task's effective `security_class` is high, `/cloverleaf-run` routes it through `security-review` as a council member. A `blocker` finding (e.g. a leaked credential) advances the task to `escalated`, which surfaces through the walker's existing escalation path — expect and surface these like any other escalation; do not auto-retry a security blocker.
@@ -1,9 +1,18 @@
1
1
  ---
2
2
  name: cloverleaf-security-review
3
- description: Run the Security Reviewer agent on a task in the `security-review` state. Hybrid two-pass (deterministic secret scan + LLM vulnerability judgment); emits a feedback envelope; advances to automated-gates (pass), implementing (bounce), or escalated (blocker). Usage — /cloverleaf-security-review <TASK-ID>.
3
+ description: Run the Security Reviewer council member on a task's feature branch as a standalone one-off. Hybrid two-pass (deterministic secret scan + LLM vulnerability judgment). Emit-only — it records the `security_review_verdict`, writes a feedback envelope, and reports the verdict (pass/bounce/escalate) for the delivery council or a human to apply. It does NOT advance the task FSM. Usage — /cloverleaf-security-review <TASK-ID>.
4
4
  ---
5
5
 
6
- # Cloverleaf — security review
6
+ # Cloverleaf — security review (emit-only council member)
7
+
8
+ The delivery states `security-review`/`automated-gates` no longer exist — the `@cloverleaf/standard` task FSM
9
+ collapsed them into a single `council` phase (Council Slice 4). The Security Reviewer is now a **council member**
10
+ that the runner (`/cloverleaf-run`) dispatches; its blocking verdict gates the aggregated council result. A single
11
+ member cannot drive the multi-member council to merge, so this standalone skill is **emit-only**: it runs the two
12
+ passes against the task's branch, records the `security_review_verdict`, emits the feedback envelope, and reports
13
+ the verdict. **It does not advance the FSM** — the council or a human applies the aggregated verdict via
14
+ `apply-council-verdict` (which is what advances `council → final-gate`/`implementing`/`escalated` and records the
15
+ authoritative security backstop for high-security tasks).
7
16
 
8
17
  ## Steps
9
18
 
@@ -14,7 +23,7 @@ description: Run the Security Reviewer agent on a task in the `security-review`
14
23
 
15
24
  1. Capture the TASK-ID argument.
16
25
 
17
- 2. Load the task: `cloverleaf-cli load-task <repo_root> <TASK-ID>`. Verify `status === "security-review"`. If not, report the current status and stop.
26
+ 2. Load the task: `cloverleaf-cli load-task <repo_root> <TASK-ID>`. Light guard only: confirm the task exists and is not terminal (`merged`/`rejected`/`escalated`). Do NOT hard-require any particular state — this skill reviews the branch, not a specific FSM state. If the task is terminal, report the current status and stop.
18
27
 
19
28
  3. Confirm the branch `cloverleaf/<TASK-ID>` exists: `git rev-parse --verify cloverleaf/<TASK-ID>`. If missing, report the discrepancy and stop. Compute the diff for the subagent (do NOT check out): `git diff main..cloverleaf/<TASK-ID>`.
20
29
 
@@ -38,43 +47,39 @@ description: Run the Security Reviewer agent on a task in the `security-review`
38
47
  - else any `error` or `warning` → `verdict: "bounce"`
39
48
  - else (only `info`, or none) → `verdict: "pass"`
40
49
 
41
- 7. **Branch on verdict:**
50
+ 7. **Emit the verdict + envelope (no FSM advance).**
51
+
52
+ Record the member's `security_review_verdict` on the task (a live field the council's `council → final-gate` backstop reads for high-security tasks), then emit the merged feedback envelope. **Never call `advance-status`** — the council/human applies the aggregated verdict.
42
53
 
43
54
  **Pass:**
44
55
  ```bash
45
56
  cloverleaf-cli set-task-field <repo_root> <TASK-ID> security_review_verdict pass
46
57
  git -C <repo_root> add .cloverleaf/ && git -C <repo_root> commit -m "cloverleaf: <TASK-ID> security_review_verdict → pass"
47
- cloverleaf-cli advance-status <repo_root> <TASK-ID> automated-gates agent
48
- git -C <repo_root> add .cloverleaf/ && git -C <repo_root> commit -m "cloverleaf: <TASK-ID> security review passed → automated-gates"
49
58
  ```
50
- Report: "✓ Security review passed. State automated-gates."
59
+ Report: "✓ Security Reviewer verdict: **pass**. Recorded `security_review_verdict=pass`. This is one council member's verdict — the delivery council (`/cloverleaf-run <TASK-ID>`) or a human applies the aggregated verdict (`apply-council-verdict`); this skill does not advance the FSM."
51
60
 
52
61
  **Bounce:**
53
62
  ```bash
54
63
  echo '<merged-envelope-json>' > /tmp/cloverleaf-fb-s.json
55
- cloverleaf-cli write-feedback <repo_root> <TASK-ID> /tmp/cloverleaf-fb-s.json
64
+ cloverleaf-cli write-feedback <repo_root> <TASK-ID> /tmp/cloverleaf-fb-s.json --prefix=s
56
65
  git -C <repo_root> add .cloverleaf/feedback/ && git -C <repo_root> commit -m "cloverleaf: <TASK-ID> security review feedback"
57
66
  cloverleaf-cli set-task-field <repo_root> <TASK-ID> security_review_verdict bounce
58
67
  git -C <repo_root> add .cloverleaf/ && git -C <repo_root> commit -m "cloverleaf: <TASK-ID> security_review_verdict → bounce"
59
- cloverleaf-cli advance-status <repo_root> <TASK-ID> implementing agent
60
- git -C <repo_root> add .cloverleaf/ && git -C <repo_root> commit -m "cloverleaf: <TASK-ID> security review bounced → implementing"
61
68
  ```
62
- Report: "✗ Security review bounced. Findings: <summarize by severity>. State implementing."
69
+ Report: "✗ Security Reviewer verdict: **bounce**. Findings: <summarize by severity>. Feedback emitted to `.cloverleaf/feedback/<TASK-ID>-s<N>.json`. The delivery council or a human applies the verdict (a council bounce loops the task back to `implementing`); this skill does not advance the FSM."
63
70
 
64
71
  **Escalate (blocker found):**
65
72
  ```bash
66
73
  echo '<merged-envelope-json>' > /tmp/cloverleaf-fb-s.json
67
- cloverleaf-cli write-feedback <repo_root> <TASK-ID> /tmp/cloverleaf-fb-s.json
74
+ cloverleaf-cli write-feedback <repo_root> <TASK-ID> /tmp/cloverleaf-fb-s.json --prefix=s
68
75
  git -C <repo_root> add .cloverleaf/feedback/ && git -C <repo_root> commit -m "cloverleaf: <TASK-ID> security review feedback"
69
76
  cloverleaf-cli set-task-field <repo_root> <TASK-ID> security_review_verdict escalate
70
77
  git -C <repo_root> add .cloverleaf/ && git -C <repo_root> commit -m "cloverleaf: <TASK-ID> security_review_verdict → escalate"
71
- cloverleaf-cli advance-status <repo_root> <TASK-ID> escalated agent
72
- git -C <repo_root> add .cloverleaf/ && git -C <repo_root> commit -m "cloverleaf: <TASK-ID> security review escalated (blocker finding)"
73
78
  ```
74
- Report: "⚠ Security review found a BLOCKER. State escalated. A human must review `.cloverleaf/feedback/` before this can proceed."
79
+ Report: "⚠ Security Reviewer verdict: **escalate** — a BLOCKER was found. Recorded `security_review_verdict=escalate` and emitted feedback to `.cloverleaf/feedback/<TASK-ID>-s<N>.json`. A human MUST review `.cloverleaf/feedback/` before this can proceed. The council or a human applies the verdict (a council escalate is un-lowerable → `escalated`); this skill does not advance the FSM."
75
80
 
76
81
  ## Rules
77
82
 
78
83
  - Never push. Read-only on source — the security reviewer does not modify code.
79
- - A `blocker` (e.g. a leaked credential) ALWAYS escalates to a human; never let the bounce loop silently "fix" it.
80
- - On illegal state transition, report and stop without partial commits.
84
+ - A `blocker` (e.g. a leaked credential) ALWAYS yields an `escalate` verdict; never let a bounce loop silently "fix" it. The council/human enforces the terminal escalation.
85
+ - Emit-only: never call `advance-status`. This is one council member's verdict; the council/human applies it.