@cloverleaf/reference-impl 0.4.1 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloverleaf/reference-impl",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "description": "Reference implementation of the Cloverleaf methodology as Claude Code skills. Implements the Tight Loop (Implementer + Reviewer).",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -0,0 +1,63 @@
1
+ # Plan Agent
2
+
3
+ **Operation:** breakdown
4
+
5
+ **Repo root:** {{repo_root}}
6
+ **Doc context URI:** {{doc_context_uri}}
7
+
8
+ You are the Plan Agent. Your role is to take an approved RFC and its completed Spikes and produce a Plan artifact: a directed acyclic graph of Tasks plus inline task definitions, plus an optional path-pattern → reviewer-role mapping.
9
+
10
+ ---
11
+
12
+ **RFC:** {{rfc}}
13
+ **Completed spikes:** {{spikes}}
14
+ **Path rules (optional):** {{path_rules}}
15
+
16
+ ## Your task
17
+
18
+ 1. Read the RFC's `problem`, `solution`, `unknowns[]`, `acceptance_criteria[]`, and `out_of_scope[]`.
19
+ 2. Read each completed spike's `findings` and `recommendation` — incorporate them into the breakdown.
20
+ 3. Decompose the work into 3–8 tasks. Each task must:
21
+ - Be independently testable and reviewable.
22
+ - Have a clear `definition_of_done` (measurable, not aspirational).
23
+ - Have explicit `acceptance_criteria` (what "done" looks like from the outside).
24
+ - Carry a `risk_class`: `"low"` for trivial / doc-only tasks (fast-lane Delivery), `"high"` otherwise (full-pipeline Delivery).
25
+ - Start at `status: "pending"`. The full enum is: `pending | tactical-plan | implementing | documenting | review | automated-gates | ui-review | qa | final-gate | merged | rejected | escalated`.
26
+ Note: "pending" is the correct initial value — the string "todo" is invalid and will be rejected by schema validation.
27
+ 4. Build a `task_dag` using the edge-based shape from `dependency-dag.schema.json`:
28
+ - `nodes: Array<{project, id}>` — one workItemRef per task in `tasks[]`.
29
+ - `edges: Array<{from: {project, id}, to: {project, id}}>` — directed edges from prerequisite to dependent. `to` cannot start until `from` completes. Both endpoints must appear in `nodes`. DAG roots are nodes that appear in no edge's `to` field.
30
+ 5. If `path_rules` is non-empty, emit `path_reviewer_map: Array<{pattern, role}>` by mapping the rules' path globs to reviewer roles.
31
+
32
+ ## Emit a Plan JSON conforming to `plan.schema.json`
33
+
34
+ Required top-level fields:
35
+ - `type: "plan"`
36
+ - `id` — supplied by orchestrator (the next available ID in the project's work-item namespace)
37
+ - `project` — supplied by orchestrator
38
+ - `status: "drafting"`
39
+ - `owner` — `{ "kind": "agent", "id": "plan" }`
40
+ - `parent_rfc: { project: <rfc.project>, id: <rfc.id> }`
41
+ - `task_dag` — as described above
42
+ - `tasks` — array of full Task docs conforming to `task.schema.json`
43
+
44
+ ### Critical runtime invariants
45
+ - The set of `tasks[].id` MUST equal the set of workItemRefs in `task_dag.nodes`. No task without a DAG node; no DAG node without a task.
46
+ - `task_dag.edges` MUST form an acyclic graph. Cycles will be rejected by the orchestrator at materialisation time.
47
+ - `additionalProperties: false` on Plan and on each Task — emit ONLY schema-defined fields.
48
+
49
+ ### Important: the Plan has NO `title` field
50
+ Unlike RFC / Spike / Task, the Plan schema does not define a `title` field. Do not add one.
51
+
52
+ ## Task IDs
53
+ - Each task's `id` must follow the project's ID convention (typically `<PROJECT>-<N>`).
54
+ - Task IDs must not collide with any existing `.cloverleaf/{rfcs,spikes,plans,tasks}/` work item. The orchestrator supplies a `next_id_base` hint in its invocation context; allocate task IDs sequentially starting from that base.
55
+ - Example: if `next_id_base` is `CLV-13` and you're emitting 3 tasks, use `CLV-13`, `CLV-14`, `CLV-15` in `tasks[]` and in `task_dag.nodes`.
56
+
57
+ ## Output format
58
+ Write the Plan JSON to stdout, nothing else. No prose, no markdown fences. The orchestrator captures stdout and validates against `plan.schema.json` (and each task via `task.schema.json`). Budget: 3 bounces per invocation.
59
+
60
+ ## General rules
61
+ - **Schema compliance is mandatory.** Each task in `tasks[]` must independently pass `task.schema.json` validation.
62
+ - **No file writes.** Orchestrator persists your output.
63
+ - Gate for Plan approval: `task_batch_gate` (approved by human after `gate-pending`).
@@ -0,0 +1,74 @@
1
+ # Researcher Agent
2
+
3
+ **Operation:** {{operation}} (`draftRfc` or `runSpike`)
4
+
5
+ **Repo root:** {{repo_root}}
6
+ **Doc context URI:** {{doc_context_uri}}
7
+
8
+ You are the Researcher Agent. Your role is to ground ideas in the project's existing AI-facing documentation, then emit either an RFC (when drafting) or Spike findings (when investigating). You do not execute production code changes; you read docs and emit structured JSON.
9
+
10
+ ---
11
+
12
+ ## If operation = draftRfc
13
+
14
+ **Brief:** {{brief}}
15
+
16
+ **Prior RFC (if this is a re-draft after spikes):** {{prior_rfc}}
17
+ **Completed spikes (if any):** {{completed_spikes}}
18
+
19
+ ### Your task
20
+ 1. Read the docs under `{{repo_root}}/{{doc_context_uri}}` that are relevant to the brief.
21
+ 2. If `prior_rfc` is non-empty, read it and the `completed_spikes` — your output may be identical to the prior RFC if no revision is needed, or a revised body if findings warrant change.
22
+ 3. Emit a single JSON document conforming to `rfc.schema.json` (from `@cloverleaf/standard`). Required top-level fields:
23
+ - `type: "rfc"`
24
+ - `id` — supplied by orchestrator via `{{repo_root}}` context; preserve the existing ID if prior_rfc is given, else use the orchestrator's allocated ID
25
+ - `project` — supplied by orchestrator
26
+ - `status: "drafting"`
27
+ - `owner` — object `{ kind: "agent"|"human"|"system", id: string }`; use `{ "kind": "agent", "id": "researcher" }`
28
+ - `title` — short name
29
+ - `problem` — paragraph describing what's wrong or missing
30
+ - `solution` — paragraph describing the proposed approach
31
+ - `unknowns` — **array of strings**, each entry is one uncertainty that should become a Spike (e.g. "What is the webkit install size?"). Empty array if no uncertainties.
32
+ - `acceptance_criteria` — array of strings (minItems: 1), each a measurable condition for RFC approval
33
+ - `out_of_scope` — array of strings; can be empty
34
+
35
+ ### Important schema notes
36
+ - **The RFC does NOT contain a `spikes` field.** Spikes are separate work items created by the orchestrator after reading your `unknowns[]`. Each `unknowns[]` entry becomes a Spike's `question`.
37
+ - `additionalProperties: false` — do not emit extra fields. Optional schema fields: `parent`, `relationships`, `extensions`.
38
+
39
+ ### Output format
40
+ Write the JSON to stdout, nothing else. No prose, no markdown fences, no explanation. The orchestrator captures stdout and validates against the schema. Budget: 3 bounces per invocation.
41
+
42
+ ---
43
+
44
+ ## If operation = runSpike
45
+
46
+ **Spike input:** {{spike}}
47
+
48
+ ### Your task
49
+ 1. Read the spike's `question` and `method` fields.
50
+ 2. `method` is one of:
51
+ - `research` — read documentation, synthesise an answer
52
+ - `prototype` — describe a minimal prototype (you don't build it — the Implementer does in Delivery; spike output describes what to prototype)
53
+ - `benchmark` — describe what to measure and expected comparison axes
54
+ 3. Investigate using `{{repo_root}}/{{doc_context_uri}}` docs plus any read-only code inspection necessary. Do NOT modify files.
55
+ 4. Emit the input spike object with these additions/changes:
56
+ - `status: "completed"`
57
+ - `findings: string` — **a single string** summarising evidence-backed observations. Multi-sentence paragraphs are fine; do NOT emit an array.
58
+ - `recommendation: string` — **a single string** summarising the implication for the RFC / Plan.
59
+
60
+ ### Schema compliance
61
+ - Preserve all existing spike fields (`id, type, owner, project, title, parent_rfc, question, method`).
62
+ - Add `findings` and `recommendation`.
63
+ - Output must conform to `spike.schema.json` (from `@cloverleaf/standard`).
64
+ - `additionalProperties: false` — no extra fields.
65
+
66
+ ### Output format
67
+ Write the updated spike JSON to stdout, nothing else. Budget: 3 bounces per invocation.
68
+
69
+ ---
70
+
71
+ ## General rules
72
+ - **Schema compliance is mandatory.** If your output fails AJV validation, you bounce and try again. Budget: 3 bounces per invocation.
73
+ - **No side-effects on the filesystem.** Don't write files. The orchestrator persists your output.
74
+ - **No tool use beyond reading.** v0.5 limits Researcher to doc-reading; web search and external tools are future work.
@@ -0,0 +1,74 @@
1
+ ---
2
+ name: cloverleaf-breakdown
3
+ description: Invoke the Plan agent (operation=breakdown) to decompose an approved RFC + completed spikes into a Plan with task_dag + inline tasks. Transitions Plan drafting → gate-pending (task_batch_gate). Usage — /cloverleaf-breakdown <RFC-ID>.
4
+ ---
5
+
6
+ # Cloverleaf — Plan breakdown
7
+
8
+ The user has invoked this skill with an RFC-ID (e.g., `CLV-009`).
9
+
10
+ ## Steps
11
+
12
+ 1. Capture `<RFC-ID>` as `$RFC_ID`. If missing, report usage and stop.
13
+
14
+ 2. Load and verify the RFC is in status `approved`:
15
+ ```
16
+ cloverleaf-cli load-rfc <repo_root> <RFC-ID>
17
+ ```
18
+ If `status !== "approved"`, report "RFC must be approved before breakdown" and stop.
19
+
20
+ 3. Collect all completed Spikes for this RFC. For each `.cloverleaf/spikes/*.json`:
21
+ - Parse the JSON.
22
+ - If `parent_rfc.id === $RFC_ID` AND `parent_rfc.project === <rfc.project>` AND `status === "completed"`: include in the SPIKES array.
23
+ - If zero matches, SPIKES is `[]`.
24
+
25
+ 4. Load discovery config:
26
+ ```bash
27
+ CFG=$(cloverleaf-cli discovery-config --repo-root <repo_root>)
28
+ DOC_CTX=$(echo "$CFG" | jq -r .docContextUri)
29
+ PROJECT_ID=$(echo "$CFG" | jq -r .projectId)
30
+ ```
31
+
32
+ 5. Compute the next work-item ID (this is the Plan's ID):
33
+ ```
34
+ PLAN_ID=$(cloverleaf-cli next-work-item-id <repo_root> $PROJECT_ID)
35
+ ```
36
+
37
+ 6. Dispatch the Plan subagent via the Task tool:
38
+ - `subagent_type`: `general-purpose`
39
+ - `model`: `sonnet`
40
+ - Prompt: contents of `$(cloverleaf-cli plugin-root)/prompts/plan.md`, with placeholders:
41
+ - `{{rfc}}` → the full RFC JSON
42
+ - `{{spikes}}` → the SPIKES JSON array
43
+ - `{{doc_context_uri}}` → `$DOC_CTX`
44
+ - `{{repo_root}}` → absolute path to the current repo
45
+ - `{{path_rules}}` → `null` (v0.5 does not auto-populate path_rules; defer to v0.6)
46
+
47
+ In the subagent context, also supply a hint that `next_id_base === $PLAN_ID`, so task IDs in `tasks[]` start at `PLAN_ID + 1`. The Plan agent allocates its own ID as `next_id_base` and task IDs sequentially after.
48
+
49
+ 7. Parse subagent response — expected JSON conforming to `plan.schema.json`. Required fields: `id, type: "plan", status: "drafting", owner, project, parent_rfc, task_dag (edge-based), tasks (inline Task docs, status=pending)`. 3-bounce budget per invocation.
50
+
51
+ 8. Ensure output `plan.id === $PLAN_ID`, `project === $PROJECT_ID`, `parent_rfc === { project: <rfc.project>, id: $RFC_ID }`. If the subagent drifted, override these before save.
52
+
53
+ 9. Save the Plan:
54
+ ```
55
+ cloverleaf-cli save-plan <repo_root> /tmp/plan-$PLAN_ID.json
56
+ ```
57
+
58
+ 10. Transition drafting → gate-pending:
59
+ ```
60
+ cloverleaf-cli advance-plan <repo_root> $PLAN_ID gate-pending agent task_batch_gate
61
+ ```
62
+
63
+ 11. Commit:
64
+ ```bash
65
+ git add .cloverleaf/plans/ .cloverleaf/events/
66
+ git commit -m "cloverleaf: plan $PLAN_ID for RFC $RFC_ID → gate-pending"
67
+ ```
68
+
69
+ 12. Print the Plan ID.
70
+
71
+ ## Notes
72
+
73
+ - Tasks from `plan.tasks[]` are NOT yet materialised on disk. Materialisation happens only after a human approves via `/cloverleaf-gate $PLAN_ID approve`, which transitions the Plan to `approved`, at which point the orchestrator runs `cloverleaf-cli materialise-tasks`.
74
+ - If the RFC has no completed spikes (`unknowns[]` was empty), SPIKES is `[]` and the Plan agent works from the RFC alone.
@@ -0,0 +1,139 @@
1
+ ---
2
+ name: cloverleaf-discover
3
+ description: End-to-end Discovery orchestrator. Drives RFC → (Spikes) → Plan → gates → task materialisation. Blocks on human gate decisions (rfc_strategy_gate, task_batch_gate). On Plan approval, materialises tasks and asks whether to kick off /cloverleaf-run on the first DAG root. Usage — /cloverleaf-discover <brief-file>.
4
+ ---
5
+
6
+ # Cloverleaf — discover (Discovery orchestrator)
7
+
8
+ The user has invoked this skill with a brief file path (e.g., `docs/briefs/cross-browser-ui-review.md`).
9
+
10
+ ## Branch discipline
11
+
12
+ Each sub-skill runs from `main`. Between steps, confirm branch is `main` before proceeding. All sub-skills return the user to `main`.
13
+
14
+ ## Per-agent bounce budget (in-session)
15
+
16
+ - **Researcher and Plan agent bounces are budgeted inside the sub-skills** (`/cloverleaf-draft-rfc`, `/cloverleaf-spike`, `/cloverleaf-breakdown`), each with a 3-bounce per-invocation budget. The orchestrator invokes each sub-skill once per step — if a sub-skill exhausts its budget, it halts, and the orchestrator treats that as a hard halt and dumps state.
17
+ - **Revise loops are budgeted in the orchestrator:**
18
+ ```
19
+ MAX_REVISE_LOOPS = 3
20
+ ```
21
+ Resets on each `/cloverleaf-discover` invocation.
22
+
23
+ ## Steps
24
+
25
+ 1. Capture `<brief-file>` as `$BRIEF_FILE`. Verify file exists:
26
+ ```bash
27
+ [ -f "$BRIEF_FILE" ] || { echo "Brief file not found: $BRIEF_FILE" >&2; exit 1; }
28
+ ```
29
+
30
+ 2. Verify branch is `main`:
31
+ ```bash
32
+ [ "$(git rev-parse --abbrev-ref HEAD)" = "main" ] || { echo "Run /cloverleaf-discover from main" >&2; exit 1; }
33
+ ```
34
+
35
+ 3. **Create the RFC** — inline `/cloverleaf-new-rfc $BRIEF_FILE` steps. Capture the printed RFC ID as `$RFC_ID`.
36
+
37
+ Initialise revise loop counter:
38
+ ```
39
+ revise_loops = 0
40
+ ```
41
+
42
+ 4. **Draft RFC (Researcher draftRfc)** — inline `/cloverleaf-draft-rfc $RFC_ID` steps. Researcher runs with a per-invocation bounce budget (3 bounces inside draft-rfc).
43
+ - On bounce exhaustion (draft-rfc exits non-zero): dump state to `.cloverleaf/runs/$RFC_ID/discover-crash.json` and halt.
44
+ - Reload the RFC. Its new status is either `spike-in-flight` (unknowns non-empty) or `planning` (unknowns empty).
45
+
46
+ 5. **Conditional on RFC status after step 4:**
47
+ - If `planning`: skip the spike loop below; proceed to step 6.
48
+ - If `spike-in-flight`: run every pending spike linked to this RFC:
49
+ ```bash
50
+ for each spike in .cloverleaf/spikes/*.json where parent_rfc.id === $RFC_ID AND status === "pending":
51
+ inline /cloverleaf-spike <SPIKE_ID> steps.
52
+ ```
53
+
54
+ If `/cloverleaf-spike` exits non-zero or leaves the spike in a non-`completed` status after returning, treat that as bounce exhaustion: dump state to `.cloverleaf/runs/$RFC_ID/discover-crash.json` (including the spike ID) and halt. The orchestrator does NOT resume partially-run spike trees — if any spike is unresolved, the whole Discovery halts.
55
+
56
+ After all spikes complete:
57
+
58
+ 1. Transition RFC spike-in-flight → drafting:
59
+ ```
60
+ cloverleaf-cli advance-rfc <repo_root> $RFC_ID drafting agent
61
+ ```
62
+ 2. Re-invoke `/cloverleaf-draft-rfc $RFC_ID` — Researcher sees the completed spikes and may revise the RFC body. draft-rfc itself re-transitions the RFC to `spike-in-flight` (if new unknowns emerge — should not happen the second time since spikes were answered) or `planning` (expected path).
63
+
64
+ Rationale: redundant redraft is cheap; avoids introducing an off-contract "rfc_revision_required" boolean. The human gate at step 6 catches any missed revisions.
65
+
66
+ 6. **Gate: rfc_strategy_gate** — transition RFC to gate-pending:
67
+ ```
68
+ cloverleaf-cli advance-rfc <repo_root> $RFC_ID gate-pending agent rfc_strategy_gate
69
+ ```
70
+
71
+ Prompt human (blocking readline):
72
+ ```
73
+ RFC $RFC_ID at rfc_strategy_gate: approve / reject / revise [reason]? > _
74
+ ```
75
+
76
+ Parse input. On:
77
+ - `approve` → inline `/cloverleaf-gate $RFC_ID approve` steps. Continue to step 7.
78
+ - `reject [reason]` → inline `/cloverleaf-gate $RFC_ID reject [reason]` steps. Exit with summary.
79
+ - `revise [reason]` → inline `/cloverleaf-gate $RFC_ID revise [reason]` steps. `revise_loops += 1`. If `revise_loops >= MAX_REVISE_LOOPS`, dump state and halt. Else loop back to step 4.
80
+
81
+ 7. **Plan breakdown** — inline `/cloverleaf-breakdown $RFC_ID` steps. Per-invocation bounce budget (3 bounces inside breakdown). Capture `$PLAN_ID`. On bounce exhaustion: dump state and halt.
82
+
83
+ 8. **Gate: task_batch_gate** — Plan is already in `gate-pending` (set by breakdown). Prompt:
84
+ ```
85
+ PLN $PLAN_ID at task_batch_gate: approve / reject [reason]? > _
86
+ ```
87
+
88
+ On:
89
+ - `approve` → inline `/cloverleaf-gate $PLAN_ID approve` steps. Continue.
90
+ - `reject [reason]` → inline `/cloverleaf-gate $PLAN_ID reject [reason]` steps. Exit with summary.
91
+
92
+ 9. **Materialise tasks**:
93
+ ```bash
94
+ OUT=$(cloverleaf-cli materialise-tasks <repo_root> $PLAN_ID)
95
+ TASK_IDS=$(echo "$OUT" | jq -r '.task_ids[]')
96
+ ```
97
+
98
+ On materialise-tasks failure (cycle detected, or AJV validation error):
99
+ - The error message from `cloverleaf-cli` identifies the failing task.
100
+ - `materialiseTasksFromPlan` is atomic: the cycle-check and AJV pre-validation run BEFORE any file write, so no task files were created.
101
+ - The Plan remains in `approved` status (the gate was legitimately approved; the materialisation issue is with the Plan's own task DAG, not the gate decision).
102
+ - Dump state to `.cloverleaf/runs/$PLAN_ID/materialise-crash.json` and halt.
103
+ - Operator investigation typically leads to a new `/cloverleaf-breakdown` run to produce a corrected Plan (the rejected path is via the ORIGINAL gate, not a post-approval state correction).
104
+
105
+ 10. **Compute DAG roots**:
106
+ ```bash
107
+ PLAN_JSON=$(cloverleaf-cli load-plan <repo_root> $PLAN_ID)
108
+
109
+ # DAG roots = nodes whose id never appears as `to.id` in any edge.
110
+ # v0.5 picks the FIRST root only; multi-root concurrent Delivery is v0.6.
111
+ FIRST_ROOT=$(echo "$PLAN_JSON" | jq -r '
112
+ (.task_dag.edges | map(.to.id)) as $targets
113
+ | [.task_dag.nodes[] | select(.id as $n | ($targets | index($n)) | not) | .id][0]
114
+ ')
115
+ ```
116
+
117
+ v0.5 simplified rule: pick the FIRST root only (first `nodes[]` entry whose `id` does not appear in any `edges[].to.id`). Defer multi-root walk to v0.6.
118
+
119
+ 11. **Prompt to kick off first root** (blocking readline):
120
+ ```
121
+ N tasks materialised: $TASK_IDS.
122
+ DAG roots: $FIRST_ROOT.
123
+ Run first root via /cloverleaf-run now? [y/N] > _
124
+ ```
125
+
126
+ On `y` or `yes` (case-insensitive): inline `/cloverleaf-run <FIRST_ROOT>` steps. On anything else: exit with summary.
127
+
128
+ 12. **Exit summary**:
129
+ - RFC ID + final status
130
+ - Spike IDs + findings summary (if any)
131
+ - Plan ID + task count
132
+ - Materialised task IDs
133
+ - Whether first root was invoked (and its outcome if so)
134
+
135
+ ## Notes
136
+
137
+ - v0.5 prompts only for the FIRST DAG root. Multi-root concurrent Delivery is v0.6 scope.
138
+ - All bounces and revise loops halt cleanly with a state dump at `.cloverleaf/runs/<RFC_ID>/discover-crash.json`. No partial work is left in an inconsistent state — the gate_decision events and work-item status are always coherent.
139
+ - The readline prompts are compatible with the user's session-bridging tool for automated dogfooding.
@@ -0,0 +1,99 @@
1
+ ---
2
+ name: cloverleaf-draft-rfc
3
+ description: Invoke the Researcher agent (operation=draftRfc) to populate an RFC body from its brief. Emits zero or more Spike work items from the RFC's unknowns[]. Transitions the RFC drafting → spike-in-flight (if unknowns exist) or drafting → planning (if no unknowns). Usage — /cloverleaf-draft-rfc <RFC-ID>.
4
+ ---
5
+
6
+ # Cloverleaf — draft RFC
7
+
8
+ The user has invoked this skill with an RFC-ID (e.g., `CLV-009`).
9
+
10
+ ## Steps
11
+
12
+ 1. Capture `<RFC-ID>` as `$RFC_ID`. If missing, report usage and stop.
13
+
14
+ 2. Load the RFC:
15
+ ```
16
+ cloverleaf-cli load-rfc <repo_root> <RFC-ID>
17
+ ```
18
+ Parse the JSON. Verify `status === "drafting"`. If not, report and stop.
19
+
20
+ 3. Load the discovery config:
21
+ ```bash
22
+ CFG=$(cloverleaf-cli discovery-config --repo-root <repo_root>)
23
+ DOC_CTX=$(echo "$CFG" | jq -r .docContextUri)
24
+ ```
25
+
26
+ 4. Gather re-draft context (optional — used when re-invoked after spikes):
27
+ - `PRIOR_RFC`: the current RFC JSON (for a re-draft, same content)
28
+ - `COMPLETED_SPIKES`: for each spike ref linked to this RFC (via spike's `parent_rfc` field), if `status === "completed"`, include its findings/recommendation. Build a JSON array. If none, use `[]`.
29
+
30
+ Find all spikes for this RFC by scanning `.cloverleaf/spikes/*.json` for files whose `parent_rfc.id === $RFC_ID`. Use jq. If none, the array is empty.
31
+
32
+ 5. Dispatch the Researcher subagent via the Task tool:
33
+ - `subagent_type`: `general-purpose`
34
+ - `model`: `sonnet`
35
+ - Prompt: contents of `$(cloverleaf-cli plugin-root)/prompts/researcher.md`, with placeholders substituted:
36
+ - `{{operation}}` → `draftRfc`
37
+ - `{{brief}}` → the RFC's `problem` field (seeded by `/cloverleaf-new-rfc`)
38
+ - `{{doc_context_uri}}` → `$DOC_CTX`
39
+ - `{{repo_root}}` → absolute path to the current repo
40
+ - `{{prior_rfc}}` → `PRIOR_RFC` JSON (or the literal string `null` for first draft)
41
+ - `{{completed_spikes}}` → `COMPLETED_SPIKES` JSON array (or `[]`)
42
+ - `{{spike}}` → (unused for draftRfc; substitute `null`)
43
+
44
+ 6. Parse subagent's response: expected JSON conforming to `rfc.schema.json`. Required fields: `id`, `type: "rfc"`, `status: "drafting"`, `owner`, `project`, `title`, `problem`, `solution`, `unknowns` (array of strings), `acceptance_criteria`, `out_of_scope`.
45
+
46
+ If output fails schema validation: bounce. Budget: 3 bounces per invocation. On budget exhaustion: report and stop without advancing state.
47
+
48
+ 7. Ensure output `id === $RFC_ID` and `project === <original>`. If the subagent changed them, override back.
49
+
50
+ 8. Save the populated RFC:
51
+ ```bash
52
+ cloverleaf-cli save-rfc <repo_root> /tmp/rfc-draft-$RFC_ID.json
53
+ ```
54
+
55
+ 9. Inspect `rfc.unknowns[]`:
56
+
57
+ **If `unknowns.length > 0`:** create one Spike per unknown:
58
+ ```bash
59
+ for unknown in rfc.unknowns:
60
+ SPIKE_ID=$(cloverleaf-cli next-work-item-id <repo_root> <project>)
61
+ cat > /tmp/spike-$SPIKE_ID.json <<EOF
62
+ {
63
+ "type": "spike",
64
+ "project": "<project>",
65
+ "id": "$SPIKE_ID",
66
+ "status": "pending",
67
+ "owner": { "kind": "agent", "id": "researcher" },
68
+ "title": "<first 80 chars of unknown>",
69
+ "parent_rfc": { "project": "<project>", "id": "$RFC_ID" },
70
+ "question": "<unknown>",
71
+ "method": "research"
72
+ }
73
+ EOF
74
+ cloverleaf-cli save-spike <repo_root> /tmp/spike-$SPIKE_ID.json
75
+ ```
76
+
77
+ Then transition RFC:
78
+ ```
79
+ cloverleaf-cli advance-rfc <repo_root> <RFC-ID> spike-in-flight agent
80
+ ```
81
+
82
+ **If `unknowns.length === 0`:** transition RFC directly to planning:
83
+ ```
84
+ cloverleaf-cli advance-rfc <repo_root> <RFC-ID> planning agent
85
+ ```
86
+
87
+ 10. Clean up temp files. Commit state files under `.cloverleaf/`:
88
+ ```bash
89
+ git add .cloverleaf/rfcs/ .cloverleaf/spikes/ .cloverleaf/events/
90
+ git commit -m "cloverleaf: draft RFC $RFC_ID + spike emission"
91
+ ```
92
+
93
+ 11. Report: RFC body populated; N spikes created (list IDs); RFC status now `spike-in-flight` or `planning`.
94
+
95
+ ## Notes
96
+
97
+ - This skill does NOT prompt for human input. It's a pure agent step.
98
+ - The orchestrator (`/cloverleaf-discover`) invokes this plus manages bounces and gates.
99
+ - For a re-draft after spikes complete, invoke this skill again with the same RFC-ID — it will pick up completed spikes and may revise the RFC body.
@@ -0,0 +1,106 @@
1
+ ---
2
+ name: cloverleaf-gate
3
+ description: Human gate action on an RFC (rfc_strategy_gate) or Plan (task_batch_gate) in status gate-pending. Usage — /cloverleaf-gate <item-id> <approve|reject|revise> [reason]. `revise` is valid only at rfc_strategy_gate (RFC only).
4
+ ---
5
+
6
+ # Cloverleaf — human gate
7
+
8
+ The user has invoked this skill with `<item-id> <action> [reason]`.
9
+
10
+ ## Steps
11
+
12
+ 1. Capture arguments:
13
+ - `$ITEM_ID` = first positional arg
14
+ - `$ACTION` = second positional arg (must be `approve`, `reject`, or `revise`)
15
+ - `$REASON` = remaining args joined with spaces (optional)
16
+
17
+ If `ITEM_ID` or `ACTION` is missing, report usage and stop.
18
+
19
+ 2. Validate action:
20
+ ```bash
21
+ case "$ACTION" in
22
+ approve|reject|revise) ;;
23
+ *) echo "Invalid action: $ACTION. Use approve, reject, or revise." >&2; exit 1 ;;
24
+ esac
25
+ ```
26
+
27
+ 3. Detect work-item type by checking which directory has the JSON file:
28
+ ```bash
29
+ if [ -f "<repo_root>/.cloverleaf/rfcs/$ITEM_ID.json" ]; then
30
+ TYPE=rfc
31
+ GATE=rfc_strategy_gate
32
+ elif [ -f "<repo_root>/.cloverleaf/plans/$ITEM_ID.json" ]; then
33
+ TYPE=plan
34
+ GATE=task_batch_gate
35
+ else
36
+ echo "No RFC or Plan found with ID $ITEM_ID" >&2
37
+ exit 1
38
+ fi
39
+ ```
40
+
41
+ 4. Validate that `revise` is only valid at `rfc_strategy_gate` (i.e., on RFCs — revise is only exclusive to rfc_strategy_gate):
42
+ ```bash
43
+ if [ "$ACTION" = "revise" ] && [ "$TYPE" != "rfc" ]; then
44
+ echo "revise is only valid at rfc_strategy_gate (RFCs). Use reject on Plans." >&2
45
+ exit 2
46
+ fi
47
+ ```
48
+
49
+ 5. Verify the item is in `gate-pending` status:
50
+ ```bash
51
+ STATUS=$(cloverleaf-cli load-$TYPE <repo_root> $ITEM_ID | jq -r .status)
52
+ if [ "$STATUS" != "gate-pending" ]; then
53
+ echo "$TYPE $ITEM_ID is in status '$STATUS', not gate-pending" >&2
54
+ exit 3
55
+ fi
56
+ ```
57
+
58
+ 6. Emit the gate-decision event:
59
+ ```bash
60
+ if [ -n "$REASON" ]; then
61
+ cloverleaf-cli emit-gate-decision <repo_root> $ITEM_ID $GATE $ACTION human --comment="$REASON"
62
+ else
63
+ cloverleaf-cli emit-gate-decision <repo_root> $ITEM_ID $GATE $ACTION human
64
+ fi
65
+ ```
66
+
67
+ 7. Advance the work-item state:
68
+ ```bash
69
+ case "$ACTION" in
70
+ approve)
71
+ cloverleaf-cli advance-$TYPE <repo_root> $ITEM_ID approved human $GATE
72
+ ;;
73
+ reject)
74
+ cloverleaf-cli advance-$TYPE <repo_root> $ITEM_ID rejected human $GATE
75
+ ;;
76
+ revise)
77
+ # RFC-only — validated in step 4
78
+ cloverleaf-cli advance-rfc <repo_root> $ITEM_ID drafting human $GATE
79
+ # Persisting the revise reason as a feedback finding is deferred to v0.6.
80
+ # For now, the reason is surfaced on stdout so the caller can capture it
81
+ # and pass it back via the next /cloverleaf-draft-rfc invocation context.
82
+ if [ -n "$REASON" ]; then
83
+ echo "revise reason: $REASON"
84
+ fi
85
+ ;;
86
+ esac
87
+ ```
88
+
89
+ 8. Commit state files:
90
+ ```bash
91
+ git add .cloverleaf/rfcs/ .cloverleaf/plans/ .cloverleaf/events/
92
+ git commit -m "cloverleaf: gate $ITEM_ID $ACTION ($GATE)"
93
+ ```
94
+
95
+ 9. Print the new status:
96
+ ```bash
97
+ NEW=$(cloverleaf-cli load-$TYPE <repo_root> $ITEM_ID | jq -r .status)
98
+ echo "$ITEM_ID: $STATUS → $NEW"
99
+ ```
100
+
101
+ ## Notes
102
+
103
+ - `revise` (RFC only) returns the RFC to `drafting`. The orchestrator loops back to `/cloverleaf-draft-rfc`.
104
+ - On `reject` of an RFC: terminal (enters rejected state; orchestrator halts).
105
+ - On `reject` of a Plan: plan enters rejected state; it can be re-decomposed via a new `/cloverleaf-breakdown` run (rejected → drafting via agent is a legal transition).
106
+ - `[reason]` text is persisted in the gate_decision event's `comment` field. For `revise`, it's also echoed to stdout so the calling orchestrator can feed it back to the Researcher on re-draft.
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: cloverleaf-new-rfc
3
+ description: Scaffold a new RFC work item from a brief file. Usage — /cloverleaf-new-rfc <brief-file>. Writes `.cloverleaf/rfcs/<ID>.json` with status=drafting and empty body fields (populated by /cloverleaf-draft-rfc). Returns the new RFC ID.
4
+ ---
5
+
6
+ # Cloverleaf — new RFC
7
+
8
+ ## Steps
9
+
10
+ 1. Capture `<brief-file>` (first positional arg). Verify file exists:
11
+
12
+ ```bash
13
+ BRIEF_FILE="$1"
14
+ [ -f "$BRIEF_FILE" ] || { echo "Brief file not found: $BRIEF_FILE" >&2; exit 1; }
15
+ ```
16
+
17
+ 2. Load the discovery config to get `projectId`:
18
+
19
+ ```bash
20
+ CFG=$(cloverleaf-cli discovery-config --repo-root $(pwd))
21
+ PROJECT_ID=$(echo "$CFG" | jq -r .projectId)
22
+ [ -z "$PROJECT_ID" ] && { echo "set projectId in .cloverleaf/config/discovery.json" >&2; exit 2; }
23
+ ```
24
+
25
+ 3. Compute next work-item ID:
26
+
27
+ ```bash
28
+ RFC_ID=$(cloverleaf-cli next-work-item-id $(pwd) "$PROJECT_ID")
29
+ ```
30
+
31
+ 4. Read brief content:
32
+
33
+ ```bash
34
+ BRIEF_CONTENT=$(cat "$BRIEF_FILE")
35
+ ```
36
+
37
+ 5. Build the RFC skeleton JSON. Derive a short title from the brief's first non-empty line (truncate if long). Problem = brief content. All other body fields are seeded with schema-conformant placeholders that `/cloverleaf-draft-rfc` will overwrite.
38
+
39
+ ```bash
40
+ FIRST_LINE=$(head -n 1 "$BRIEF_FILE" | sed 's/^# *//' | cut -c1-120)
41
+ TMPFILE=$(mktemp --suffix=.json)
42
+
43
+ cat > "$TMPFILE" <<EOF
44
+ {
45
+ "type": "rfc",
46
+ "project": "$PROJECT_ID",
47
+ "id": "$RFC_ID",
48
+ "status": "drafting",
49
+ "owner": { "kind": "agent", "id": "researcher" },
50
+ "title": $(echo "$FIRST_LINE" | jq -Rs .),
51
+ "problem": $(echo "$BRIEF_CONTENT" | jq -Rs .),
52
+ "solution": "TBD — to be populated by /cloverleaf-draft-rfc.",
53
+ "unknowns": [],
54
+ "acceptance_criteria": ["RFC body populated by researcher agent"],
55
+ "out_of_scope": []
56
+ }
57
+ EOF
58
+ ```
59
+
60
+ 6. Save via CLI (validates against rfc.schema.json):
61
+
62
+ ```bash
63
+ cloverleaf-cli save-rfc $(pwd) "$TMPFILE"
64
+ rm "$TMPFILE"
65
+ ```
66
+
67
+ 7. Print the new RFC ID to stdout:
68
+
69
+ ```bash
70
+ echo "$RFC_ID"
71
+ ```
72
+
73
+ ## Notes
74
+
75
+ - This skill does NOT invoke the Researcher agent. Use `/cloverleaf-draft-rfc <RFC_ID>` to populate body from the brief + doc grounding.
76
+ - To drive the whole Discovery flow end-to-end, use `/cloverleaf-discover <brief-file>` instead.