@cloverleaf/reference-impl 0.7.2 → 0.7.4

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,7 +1,7 @@
1
1
  {
2
2
  "name": "cloverleaf",
3
3
  "description": "Cloverleaf reference implementation — Claude Code skills for task scaffolding and the Delivery pipeline (implementer, documenter, reviewer, UI reviewer with multi-viewport visual diff, QA, merge, release).",
4
- "version": "0.6.5",
4
+ "version": "0.7.4",
5
5
  "author": {
6
6
  "name": "Renato D'Arrigo",
7
7
  "email": "renato.darrigo@gmail.com"
package/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.0
1
+ 0.7.4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloverleaf/reference-impl",
3
- "version": "0.7.2",
3
+ "version": "0.7.4",
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",
@@ -40,6 +40,7 @@
40
40
  "cloverleaf-cli": "./dist/cli.mjs"
41
41
  },
42
42
  "scripts": {
43
+ "pretest": "node scripts/check-standard-prepped.mjs",
43
44
  "test": "tsc --noEmit && vitest run",
44
45
  "test:watch": "vitest",
45
46
  "typecheck": "tsc --noEmit",
@@ -48,7 +49,7 @@
48
49
  "prepublishOnly": "node scripts/check-standard-prepped.mjs && npm test && npm run build"
49
50
  },
50
51
  "dependencies": {
51
- "@cloverleaf/standard": "^0.5.0",
52
+ "@cloverleaf/standard": "^0.6.0",
52
53
  "ajv": "^8.17.1",
53
54
  "ajv-formats": "^3.0.1",
54
55
  "axe-core": "^4.10.0",
@@ -32,13 +32,23 @@ The user has invoked this skill with a brief. Your job: turn the brief into a st
32
32
  "owner": { "kind": "agent", "id": "implementer" },
33
33
  "project": "<project>",
34
34
  "title": "<concise title derived from brief>",
35
- "context": {},
35
+ "context": <see "context.rfc injection" below>,
36
36
  "acceptance_criteria": ["<criterion 1>", "<criterion 2>", "..."],
37
37
  "definition_of_done": ["<terminal statement of completion>"],
38
38
  "risk_class": "low"
39
39
  }
40
40
  ```
41
41
 
42
+ **`context.rfc` injection:**
43
+
44
+ - If the brief includes `--rfc=<RFC-ID>` (e.g. `/cloverleaf-new-task --rfc=CLV-9 "Brief text..."`), read `<repo_root>/.cloverleaf/rfcs/<RFC-ID>.json` and inject the workItemRef shape:
45
+ ```json
46
+ "context": { "rfc": { "project": "<rfc-project-field>", "id": "<RFC-ID>" } }
47
+ ```
48
+ The `project` field comes from the loaded RFC document, NOT the task's own project (a task in project FOO may legitimately reference an RFC in project BAR).
49
+ - If `<repo_root>/.cloverleaf/rfcs/<RFC-ID>.json` does not exist, abort and ask the user to verify the RFC ID. Do not write the task file.
50
+ - If `--rfc=<ID>` is not passed, leave `context` as `{}` — same as pre-v0.7.4 behavior.
51
+
42
52
  Derive 2-5 acceptance criteria from the brief. Each must be verifiable. Derive one or more Definition of Done strings as an array.
43
53
 
44
54
  5. Write the file to `<repo_root>/.cloverleaf/tasks/<allocated-id>.json`.
@@ -65,6 +75,7 @@ The user has invoked this skill with a brief. Your job: turn the brief into a st
65
75
  ## Rules
66
76
 
67
77
  - Do not guess at acceptance criteria. If the brief is too vague (e.g., "make it faster" with no target), ask the user a clarifying question before writing the file.
78
+ - **`--rfc=<ID>` flag:** When the brief includes `--rfc=<RFC-ID>`, the task's `context.rfc` is populated from the on-disk RFC document (see step 4). Use this when scaffolding a standalone task linked to an RFC without a Plan parent — e.g., a hotfix-task pattern off an open RFC, as practiced by claw-crypto's CC-43/44 and CC-045..052. If `--rfc` is omitted, `context` is left empty; the task can be attached to a Plan later via Plan formation, or `context.rfc` can be edited in by hand.
68
79
  - **risk_class inference:** `risk_class` determines the Delivery pipeline (`"low"` → fast lane; `"high"` → full pipeline). Rules:
69
80
  1. If the user passed `--risk=high` or `--risk=low` as a flag on the skill invocation, honor it.
70
81
  2. Otherwise, set `risk_class: "high"` when the brief OR any acceptance criterion matches (case-insensitive) any of these keywords:
@@ -111,11 +111,23 @@ description: Autonomous DAG walker for Cloverleaf Plans. Given a PLAN-ID in stat
111
111
 
112
112
  Record the returned `session_id`, `worktree_path`, and `branch_name` in walk-state with `state: "running"`, `started_at: <now>`, `last_seq: 0`. Persist via `walk-state-write`.
113
113
 
114
- Immediately after `mcp__claw-drive__start_session` returns, attach a Monitor tool stream for the new session:
114
+ Immediately after `mcp__claw-drive__start_session` returns, read the `notification_contract` from the session response and validate it:
115
+
116
+ ```bash
117
+ IDLE_AFTER=$(echo "$START_SESSION_RESPONSE" | jq -r '.notification_contract.idle_after_seconds // 600')
118
+ EXPECTED_TOKENS="DONE NEEDS-INPUT"
119
+ for tok in $EXPECTED_TOKENS; do
120
+ if ! echo "$START_SESSION_RESPONSE" | jq -e ".notification_contract.vocabulary | index(\"$tok\")" > /dev/null 2>&1; then
121
+ echo "WARNING: notification_contract.vocabulary missing expected token '$tok' — vocab drift detected" >&2
122
+ fi
123
+ done
124
+ ```
125
+
126
+ Then attach a Monitor tool stream for the new session:
115
127
 
116
128
  ```
117
129
  Monitor(
118
- watch_command: "claw-drive watch <session_id> --since 0 --idle-after 600",
130
+ watch_command: "claw-drive watch <session_id> --since 0 --idle-after $IDLE_AFTER",
119
131
  persistent: true,
120
132
  timeout_ms: 3600000
121
133
  )
@@ -127,13 +139,13 @@ description: Autonomous DAG walker for Cloverleaf Plans. Given a PLAN-ID in stat
127
139
 
128
140
  ```
129
141
  Monitor(
130
- watch_command: "claw-drive watch <session_id> --since <last_seq> --idle-after 600",
142
+ watch_command: "claw-drive watch <session_id> --since <last_seq> --idle-after $IDLE_AFTER",
131
143
  persistent: true,
132
144
  timeout_ms: 3600000
133
145
  )
134
146
  ```
135
147
 
136
- The `--idle-after 600` flag instructs claw-drive to emit a synthetic `idle` event if a session produces no output for 600 seconds (10 minutes), enabling the walker to detect stalled sessions without polling.
148
+ The `--idle-after $IDLE_AFTER` flag instructs claw-drive to emit a synthetic `idle` event if a session produces no output for `$IDLE_AFTER` seconds, enabling the walker to detect stalled sessions without polling.
137
149
 
138
150
  d. **Handle events.** Dispatch each incoming Monitor event by type:
139
151
 
@@ -268,7 +280,48 @@ description: Autonomous DAG walker for Cloverleaf Plans. Given a PLAN-ID in stat
268
280
  - `awaiting_final_gate: [ ... ]` — user said `n`; re-invoke `/cloverleaf-merge <TASK-ID>` to retry.
269
281
  - `unreachable: [ ... ]` — descendants of escalated tasks.
270
282
 
271
- If every task in the plan's `task_dag.nodes` has `state: "merged"`, print: "✓ Plan `<PLAN-ID>` complete."
283
+ **Plan completion (Standard 0.6.0+).** If every task in the plan's `task_dag.nodes` has `state: "merged"` AND the Plan's on-disk `status` is `"approved"`, advance the Plan to `completed`:
284
+
285
+ ```bash
286
+ cloverleaf-cli advance-plan <repo_root> <PLAN-ID> completed agent
287
+ git -C <repo_root> add .cloverleaf/plans/<PLAN-ID>.json .cloverleaf/events/
288
+ git -C <repo_root> commit -m "cloverleaf: plan <PLAN-ID> completed (all tasks merged)"
289
+ ```
290
+
291
+ This closes the previous state-sync gap where Plans whose tasks were all merged stayed at `status: "approved"` indefinitely. Skip the advance if the Plan is already at `completed` (idempotent re-runs of `/cloverleaf-run-plan` on a fully-merged plan must not error). After the advance, print: "✓ Plan `<PLAN-ID>` completed (status advanced approved → completed)."
292
+
293
+ If not every task is merged (some escalated or awaiting), do NOT advance the Plan. Print the partial-completion report from the bullets above.
294
+
295
+ **RFC auto-advance (Standard 0.6.0+).** Immediately after the Plan-advance commit lands, check whether the parent RFC can also advance to `completed`. Read the just-completed plan's `parent_rfc` (project + id), then scan all sibling plans of that RFC:
296
+
297
+ ```bash
298
+ PARENT_RFC_PROJECT=$(jq -r '.parent_rfc.project' <repo_root>/.cloverleaf/plans/<PLAN-ID>.json)
299
+ PARENT_RFC_ID=$(jq -r '.parent_rfc.id' <repo_root>/.cloverleaf/plans/<PLAN-ID>.json)
300
+ RFC_STATUS=$(jq -r '.status' <repo_root>/.cloverleaf/rfcs/"$PARENT_RFC_ID".json)
301
+
302
+ # Count sibling Plans still in-flight (drafting, gate-pending, or approved)
303
+ INFLIGHT=$(jq -s --arg proj "$PARENT_RFC_PROJECT" --arg id "$PARENT_RFC_ID" \
304
+ '[.[] | select(.parent_rfc.project == $proj and .parent_rfc.id == $id and (.status == "drafting" or .status == "gate-pending" or .status == "approved"))] | length' \
305
+ <repo_root>/.cloverleaf/plans/*.json)
306
+
307
+ # Count sibling Plans in completed (need at least one to advance)
308
+ COMPLETED=$(jq -s --arg proj "$PARENT_RFC_PROJECT" --arg id "$PARENT_RFC_ID" \
309
+ '[.[] | select(.parent_rfc.project == $proj and .parent_rfc.id == $id and .status == "completed")] | length' \
310
+ <repo_root>/.cloverleaf/plans/*.json)
311
+
312
+ if [ "$RFC_STATUS" = "approved" ] && [ "$INFLIGHT" = "0" ] && [ "$COMPLETED" != "0" ]; then
313
+ cloverleaf-cli advance-rfc <repo_root> "$PARENT_RFC_ID" completed agent
314
+ git -C <repo_root> add .cloverleaf/rfcs/"$PARENT_RFC_ID".json .cloverleaf/events/
315
+ git -C <repo_root> commit -m "cloverleaf: rfc $PARENT_RFC_ID completed ($COMPLETED sibling plans completed, 0 in-flight)"
316
+ echo "✓ RFC $PARENT_RFC_ID advanced approved → completed."
317
+ fi
318
+ ```
319
+
320
+ Auto-advance rules in plain language:
321
+ - Skip entirely if the RFC's `status` is not `approved` (already terminal, already abandoned, or somehow still pre-approval — leave it).
322
+ - Skip if any sibling Plan is still in-flight (`drafting`, `gate-pending`, or `approved`) — more work is pending on this RFC.
323
+ - Skip if no sibling Plan is `completed` (all `rejected`) — the RFC's decomposition was uniformly rejected; operator must decide whether to abandon or re-decompose.
324
+ - Otherwise advance the RFC to `completed`. Idempotent: the status guard makes re-runs safe.
272
325
 
273
326
  ## Next steps (release publishing)
274
327
 
@@ -342,3 +395,7 @@ The concrete policy JSON is the same one used during the CLV-16..CLV-20 dogfood
342
395
  - Final-gate drain is serial across tasks — one prompt, one decision.
343
396
  - The walker exits after the loop reports the final status; it does not auto-retry escalated tasks.
344
397
  - Scope-contested merges are escalated, never auto-resolved.
398
+
399
+ ## Notes
400
+
401
+ **Vocab dependency.** The walker reads `notification_contract.vocabulary` from the `start_session` response advisorily — if the expected tokens (`DONE`, `NEEDS-INPUT`) are absent it warns to stderr but continues. The authoritative source of truth for which tokens Session B will emit is the SDK's `--driven-tokens` flag passed when claw-drive spawns the session. A mismatch between the contract and the actual flag signals a version skew between the claw-drive server and the reference-impl skill; upgrade both components together to keep them in sync.