cclaw-cli 0.5.1 → 0.5.3

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/README.md CHANGED
@@ -119,7 +119,7 @@ Required repository secret:
119
119
  │ └── <activeRunId>/
120
120
  │ ├── artifacts/ # canonical run artifacts
121
121
  │ ├── run.json
122
- │ └── 00-handoff.md
122
+ │ └── handoff.md
123
123
  └── learnings.jsonl
124
124
  ```
125
125
 
@@ -26,7 +26,7 @@ ${schema.hardGate}
26
26
 
27
27
  ## In / Out
28
28
  - **Reads:** ${readsLine}
29
- - **Writes:** \`.cclaw/artifacts/${schema.artifactFile}\` (canonical run copy: \`.cclaw/runs/<activeRunId>/artifacts/${schema.artifactFile}\`)
29
+ - **Writes:** \`.cclaw/artifacts/${schema.artifactFile}\` (run snapshot under \`.cclaw/runs/<activeRunId>/artifacts/${schema.artifactFile}\` is synchronized by cclaw runtime)
30
30
  - **Next:** \`/cc-next\` (updates flow-state and loads the next stage)
31
31
 
32
32
  ## Context Hydration (mandatory before stage work)
@@ -35,7 +35,7 @@ ${schema.hardGate}
35
35
  3. Load required upstream artifacts for this stage:
36
36
  ${hydrationLines}
37
37
  4. If a canonical run artifact is missing, fallback to the matching file under \`.cclaw/artifacts/\` and record that fallback in the stage artifact.
38
- 5. Write stage output to \`.cclaw/artifacts/${schema.artifactFile}\` and keep canonical run copy aligned at \`.cclaw/runs/<activeRunId>/artifacts/${schema.artifactFile}\`.
38
+ 5. Write stage output to \`.cclaw/artifacts/${schema.artifactFile}\`. Do NOT manually copy into run directories; cclaw sync/runtime keeps run snapshots aligned.
39
39
 
40
40
  ## Gates
41
41
  ${gateIds}
@@ -1,5 +1,22 @@
1
1
  const STAGE_EXAMPLES = {
2
- brainstorm: `### Alternatives comparison
2
+ brainstorm: `### Clarification sequence (Socratic)
3
+
4
+ **Q1 (PURPOSE):** "What decision will this demo help your audience make, and who exactly is that audience?"
5
+ **A1:** "Internal platform team; they should see whether our release flow can be trusted."
6
+
7
+ **Q2 (SCOPE):** "Which outcomes are explicitly OUT of scope for this demo so we avoid accidental expansion?"
8
+ **A2:** "No production rollout automation; only release metadata validation + publish safety checks."
9
+
10
+ **Q3 (BOUNDARIES):** "When release metadata is missing or invalid, what should happen and what should NEVER happen?"
11
+ **A3:** "Must block release with a clear reason; must never auto-publish anyway."
12
+
13
+ **Q4 (ENVIRONMENT):** "Where will this run in practice: local only, CI only, or both? How is it installed and invoked?"
14
+ **A4:** "CI-first in GitHub Actions, but reproducible locally with npm scripts."
15
+
16
+ **Q5 (CONSTRAINTS):** "What constraints are non-negotiable (runtime deps, latency, compatibility, policy)?"
17
+ **A5:** "No new runtime dependencies; checks should stay under 2 minutes; compatible with current workflow."
18
+
19
+ ### Alternatives comparison
3
20
 
4
21
  | Approach | Pros | Cons | Effort | Recommendation |
5
22
  | --- | --- | --- | --- | --- |
@@ -1078,6 +1078,14 @@ export default function cclawPlugin(ctx) {
1078
1078
  payload?.command,
1079
1079
  payload?.tool?.name,
1080
1080
  payload?.tool?.id,
1081
+ payload?.input?.tool,
1082
+ payload?.input?.toolName,
1083
+ payload?.input?.tool_name,
1084
+ payload?.input?.name,
1085
+ payload?.input?.id,
1086
+ payload?.input?.command,
1087
+ payload?.input?.tool?.name,
1088
+ payload?.input?.tool?.id
1081
1089
  ];
1082
1090
  for (const value of candidates) {
1083
1091
  if (typeof value === "string" && value.trim()) return value.trim();
@@ -1085,6 +1093,36 @@ export default function cclawPlugin(ctx) {
1085
1093
  return "unknown";
1086
1094
  }
1087
1095
 
1096
+ function normalizeToolPayload(input, output) {
1097
+ if (typeof output === "undefined") {
1098
+ return input ?? {};
1099
+ }
1100
+ return {
1101
+ input: input ?? {},
1102
+ output: output ?? {}
1103
+ };
1104
+ }
1105
+
1106
+ function resolveEventType(payload) {
1107
+ if (typeof payload === "string") return payload;
1108
+ if (payload && typeof payload === "object") {
1109
+ if (typeof payload.type === "string") return payload.type;
1110
+ if (typeof payload.name === "string") return payload.name;
1111
+ if (payload.event && typeof payload.event === "object") {
1112
+ if (typeof payload.event.type === "string") return payload.event.type;
1113
+ if (typeof payload.event.name === "string") return payload.event.name;
1114
+ }
1115
+ }
1116
+ return "";
1117
+ }
1118
+
1119
+ function resolveEventData(payload) {
1120
+ if (payload && typeof payload === "object" && payload.event && typeof payload.event === "object") {
1121
+ return payload.event;
1122
+ }
1123
+ return payload;
1124
+ }
1125
+
1088
1126
  function appendJsonLine(filePath, value) {
1089
1127
  try {
1090
1128
  appendFileSync(filePath, JSON.stringify(value) + "\\n", "utf8");
@@ -1120,28 +1158,43 @@ export default function cclawPlugin(ctx) {
1120
1158
  }
1121
1159
 
1122
1160
  return {
1123
- event: async (name, data) => {
1124
- if (name === "session.created" || name === "session.resumed" || name === "session.compacted" || name === "session.cleared") {
1161
+ event: async (payload) => {
1162
+ const eventType = resolveEventType(payload);
1163
+ const eventData = resolveEventData(payload);
1164
+ if (eventType === "session.created" || eventType === "session.resumed" || eventType === "session.compacted" || eventType === "session.cleared") {
1125
1165
  emitBootstrap();
1126
1166
  }
1127
- if (name === "session.updated") {
1167
+ if (eventType === "session.updated") {
1128
1168
  // no-op: tracked via activity log
1129
1169
  }
1130
- if (name === "session.idle") {
1170
+ if (eventType === "session.idle") {
1131
1171
  if (!observationEnabled()) return;
1132
1172
  await runHookScript("summarize-observations.sh");
1133
1173
  await runHookScript("stop-checkpoint.sh", { loop_count: 0 });
1134
1174
  }
1135
- if (name === "tool.execute.before") {
1136
- await runHookScript("prompt-guard.sh", data ?? {});
1137
- await runHookScript("workflow-guard.sh", data ?? {});
1138
- recordToolEvent("pre", data);
1175
+ if (eventType === "tool.execute.before") {
1176
+ const toolPayload = normalizeToolPayload(eventData, undefined);
1177
+ await runHookScript("prompt-guard.sh", toolPayload);
1178
+ await runHookScript("workflow-guard.sh", toolPayload);
1179
+ recordToolEvent("pre", toolPayload);
1139
1180
  }
1140
- if (name === "tool.execute.after") {
1141
- await runHookScript("context-monitor.sh", data ?? {});
1142
- recordToolEvent("post", data);
1181
+ if (eventType === "tool.execute.after") {
1182
+ const toolPayload = normalizeToolPayload(eventData, undefined);
1183
+ await runHookScript("context-monitor.sh", toolPayload);
1184
+ recordToolEvent("post", toolPayload);
1143
1185
  }
1144
1186
  },
1187
+ "tool.execute.before": async (input, output) => {
1188
+ const payload = normalizeToolPayload(input, output);
1189
+ await runHookScript("prompt-guard.sh", payload);
1190
+ await runHookScript("workflow-guard.sh", payload);
1191
+ recordToolEvent("pre", payload);
1192
+ },
1193
+ "tool.execute.after": async (input, output) => {
1194
+ const payload = normalizeToolPayload(input, output);
1195
+ await runHookScript("context-monitor.sh", payload);
1196
+ recordToolEvent("post", payload);
1197
+ },
1145
1198
  "experimental.chat.system.transform": (payload) => {
1146
1199
  const bootstrap = buildBootstrap();
1147
1200
  if (typeof payload === "string") {
@@ -47,7 +47,7 @@ Before starting work, ALWAYS:
47
47
  2. **Stages are workflows, not suggestions.** Follow the skill steps in order. Do not skip verification steps.
48
48
  3. **One stage at a time.** Complete the current stage before advancing to the next.
49
49
  4. **Gates must pass.** Every stage has required gates — the agent cannot claim completion without satisfying them.
50
- 5. **Artifacts are mandatory.** Each stage writes to \`.cclaw/artifacts/\` and keeps the active run copy in \`.cclaw/runs/<activeRunId>/artifacts/\` this is the evidence trail.
50
+ 5. **Artifacts are mandatory.** Each stage writes to \`.cclaw/artifacts/\`; cclaw sync/runtime keeps run snapshots in \`.cclaw/runs/<activeRunId>/artifacts/\` aligned as the evidence trail.
51
51
  6. **When in doubt, use \`/cc\`.** If the task is non-trivial and there's no prior artifact, run \`/cc <idea>\` to start brainstorming.
52
52
 
53
53
  ## Stage Quick Reference
@@ -173,10 +173,18 @@ When all required gates are satisfied and the artifact is written:
173
173
 
174
174
  1. **Update \`${RUNTIME_ROOT}/state/flow-state.json\`:**
175
175
  ${stateUpdate}
176
- 2. **Sync artifact** to \`${RUNTIME_ROOT}/runs/<activeRunId>/artifacts/${schema.artifactFile}\`
176
+ - For each passed gate, add an entry to \`guardEvidence\`: \`"<gate_id>": "<artifact path or excerpt proving the gate>"\`. Do NOT leave \`guardEvidence\` empty.
177
+ 2. **Persist artifact** at \`${RUNTIME_ROOT}/artifacts/${schema.artifactFile}\`. Do NOT manually copy into run directories; cclaw sync/runtime keeps \`${RUNTIME_ROOT}/runs/<activeRunId>/artifacts/\` aligned.
177
178
  ${nextAction}
178
179
 
179
180
  **STOP.** Do not load the next stage skill yourself. The user will run \`/cc-next\` when ready (same session or new session).
181
+
182
+ ## Resume Protocol
183
+
184
+ When resuming a stage in a NEW session (artifact exists but gates are not all passed in flow-state):
185
+ 1. Read the existing artifact and check which gates can be verified from artifact evidence.
186
+ 2. For each unverified gate, ask the user to confirm ONE gate at a time. Do NOT batch multiple gate confirmations in a single message.
187
+ 3. Update \`guardEvidence\` for each confirmed gate before proceeding.
180
188
  `;
181
189
  }
182
190
  function stageTransitionAutoAdvanceBlock(schema) {
@@ -279,7 +287,7 @@ function quickStartBlock(stage) {
279
287
 
280
288
  > **Even if you read nothing else, do these 3 things:**
281
289
  > 1. Obey the HARD-GATE below — violating it invalidates the entire stage.
282
- > 2. Complete every checklist step in order and write the artifact to \`.cclaw/artifacts/${schema.artifactFile}\` (canonical run copy: \`.cclaw/runs/<activeRunId>/artifacts/${schema.artifactFile}\`).
290
+ > 2. Complete every checklist step in order and write the artifact to \`.cclaw/artifacts/${schema.artifactFile}\`. Run snapshots in \`.cclaw/runs/<activeRunId>/artifacts/\` are synchronized by cclaw runtime.
283
291
  > 3. Do not claim completion without satisfying gates: ${topGates}${schema.requiredGates.length > 3 ? ` (+${schema.requiredGates.length - 3} more)` : ""}.
284
292
  >
285
293
  > **After this stage:** update \`flow-state.json\` and tell the user to run \`/cc-next\`.
@@ -377,7 +385,7 @@ ${progressiveDisclosureBlock(stage)}
377
385
  ${selfImprovementBlock(stage)}
378
386
  ## Handoff
379
387
  - Next command: \`/cc-next\` (loads whatever stage is current in flow-state)
380
- - Required artifact: \`.cclaw/artifacts/${schema.artifactFile}\` (canonical: \`.cclaw/runs/<activeRunId>/artifacts/${schema.artifactFile}\`)
388
+ - Required artifact: \`.cclaw/artifacts/${schema.artifactFile}\` (run snapshot at \`.cclaw/runs/<activeRunId>/artifacts/${schema.artifactFile}\`, synchronized by cclaw runtime)
381
389
  - Stage stays blocked if any required gate is unsatisfied
382
390
  `;
383
391
  }
@@ -38,8 +38,8 @@ const BRAINSTORM = {
38
38
  checklist: [
39
39
  "Explore project context — check files, docs, recent commits, existing behavior. Summarize what you found (even for seemingly simple projects).",
40
40
  "Assess scope — if the request describes multiple independent subsystems, flag for decomposition before detailed questions.",
41
- "Restate the problem — before any questions, summarize what you understood the user wants and why. Ask the user to confirm or correct your understanding.",
42
- "Ask clarifying questions — one at a time, understand purpose, constraints, success criteria, target users, and edge cases. Continue until you can confidently describe the solution space. Minimum: understand the WHY, WHO, WHAT, and boundary conditions.",
41
+ "Restate the problem — in a SEPARATE message (no questions in this message), summarize what you understood the user wants and why. **STOP and wait** for user to confirm or correct before asking any clarifying questions.",
42
+ "Ask clarifying questions — one at a time, one per message. You MUST cover these categories before proposing approaches: (a) PURPOSE — why this project exists, who it serves; (b) SCOPE — what it must do, what it must NOT do; (c) BOUNDARIES — error handling, edge cases, failure modes; (d) ENVIRONMENT how it runs, deploys, installs; (e) CONSTRAINTS performance, compatibility, dependencies. Skip a category only if the user already provided that info. Do NOT rush — 3 generic questions are never enough for a non-trivial project.",
43
43
  "Propose 2-3 approaches — with real trade-offs (not cosmetic differences) and your explicit recommendation with reasoning. Explain WHY you recommend this option over others.",
44
44
  "Present design — in sections. After each section, explicitly state what you are asking the user to approve: 'Do you approve [specific thing]?' Never ask a bare 'одобряете?/approve?' without context.",
45
45
  "Write design doc — save to `.cclaw/artifacts/01-brainstorm.md`.",
@@ -49,8 +49,8 @@ const BRAINSTORM = {
49
49
  ],
50
50
  interactionProtocol: [
51
51
  "Explore context first (files, docs, existing behavior). Share a brief summary of what you found.",
52
- "Restate the problem in your own words. Ask user to confirm before proceeding to questions.",
53
- "Ask one clarifying question per message. Do NOT combine questions. Continue until you understand purpose, constraints, users, success criteria, and edge cases.",
52
+ "Restate the problem in your own words in a SEPARATE message. Do NOT add any questions to this message. Wait for user to confirm or correct.",
53
+ "Ask clarifying questions — one per message. Cover mandatory categories: PURPOSE, SCOPE, BOUNDARIES, ENVIRONMENT, CONSTRAINTS. Do NOT combine questions. Do NOT propose approaches until all categories are addressed.",
54
54
  "For approach selection: use the Decision Protocol — present labeled options (A/B/C) with REAL trade-offs (not cosmetic) and mark one as (recommended) with clear reasoning. If AskQuestion/AskUserQuestion is available, send exactly ONE question per call, validate fields against runtime schema, and on schema error immediately fall back to plain-text question instead of retrying guessed payloads.",
55
55
  "Every approval question MUST state what exactly is being approved: 'Do you approve [the architecture / the API shape / the dependency choice]?' Never ask a bare 'approve?' or 'looks good?'.",
56
56
  "Get section-by-section approval before finalizing the design direction.",
@@ -59,8 +59,8 @@ const BRAINSTORM = {
59
59
  ],
60
60
  process: [
61
61
  "Explore project context — files, docs, behavior, recent changes. Share findings.",
62
- "Restate the problem — summarize what the user wants and why. Get confirmation.",
63
- "Clarify iteratively — ask questions one at a time until you understand WHY, WHO, WHAT, success criteria, and boundaries.",
62
+ "Restate the problem — summarize what the user wants and why in a SEPARATE message. Wait for confirmation before questions.",
63
+ "Clarify iteratively — ask questions one at a time covering mandatory categories: PURPOSE, SCOPE, BOUNDARIES, ENVIRONMENT, CONSTRAINTS. Do not skip to approaches early.",
64
64
  "Identify whether request should be decomposed into smaller sub-problems.",
65
65
  "Offer 2-3 alternatives with real trade-offs and recommendation with rationale.",
66
66
  "Present design in sections. After each section explicitly name what you ask the user to approve.",
@@ -70,7 +70,11 @@ const BRAINSTORM = {
70
70
  "Handoff to scope stage only after approval is explicit."
71
71
  ],
72
72
  requiredGates: [
73
- { id: "brainstorm_context_explored", description: "Project context and constraints have been reviewed and summarized." },
73
+ { id: "brainstorm_discovery_purpose", description: "Discovery captured WHY this project exists and WHO it serves, with explicit user confirmation." },
74
+ { id: "brainstorm_discovery_scope", description: "Discovery captured explicit in-scope and out-of-scope boundaries before approach selection." },
75
+ { id: "brainstorm_discovery_boundaries", description: "Discovery captured failure modes, edge cases, and error-handling boundaries." },
76
+ { id: "brainstorm_discovery_environment", description: "Discovery captured runtime/install/deployment environment assumptions." },
77
+ { id: "brainstorm_discovery_constraints", description: "Discovery captured constraints (performance, compatibility, dependency limits) before deciding architecture." },
74
78
  { id: "brainstorm_problem_restated", description: "Problem was restated in agent's words and user confirmed the understanding." },
75
79
  { id: "brainstorm_options_compared", description: "At least two alternatives were compared with real trade-offs." },
76
80
  { id: "brainstorm_design_approved", description: "User approved a concrete design direction (with explicit statement of what was approved)." },
@@ -79,6 +83,8 @@ const BRAINSTORM = {
79
83
  ],
80
84
  requiredEvidence: [
81
85
  "Artifact written to `.cclaw/artifacts/01-brainstorm.md`.",
86
+ "Clarification log explicitly records PURPOSE, SCOPE, BOUNDARIES, ENVIRONMENT, and CONSTRAINTS coverage.",
87
+ "Discovery sections include explicit in-scope/out-of-scope boundaries and failure handling boundaries.",
82
88
  "Approved direction captured in artifact.",
83
89
  "Open questions explicitly listed (if any).",
84
90
  "Self-review pass completed with no unresolved issues."
@@ -113,7 +119,8 @@ const BRAINSTORM = {
113
119
  "Invoking implementation skills before writing plans",
114
120
  "Asking bare 'approve?' or 'одобряете?' without stating WHAT is being approved",
115
121
  "Presenting a single summary and asking for blanket approval instead of section-by-section review",
116
- "Rushing through clarification — asking 1-2 generic questions then jumping to design"
122
+ "Rushing through clarification — asking 1-2 generic questions then jumping to design",
123
+ "Batching multiple gate confirmations in one message when resuming a session"
117
124
  ],
118
125
  rationalizations: [
119
126
  { claim: "This is too simple for design.", reality: "Simple tasks fail fast when assumptions are wrong; a short design pass prevents rework." },
@@ -154,8 +161,14 @@ const BRAINSTORM = {
154
161
  traceabilityRule: "Every approved direction must be traceable forward through scope and design. Downstream stages must reference brainstorm decisions."
155
162
  },
156
163
  artifactValidation: [
157
- { section: "Problem Statement", required: true, validationRule: "Must describe the user problem, not the solution. Include WHO and WHY." },
164
+ { section: "Problem Statement", required: true, validationRule: "Must describe the user problem, not the solution. Include WHO and WHY and success signal." },
158
165
  { section: "Known Context", required: true, validationRule: "Files, patterns, constraints discovered during exploration. Evidence that context was actually explored." },
166
+ { section: "Clarification Log", required: true, validationRule: "At least 5 rows covering PURPOSE, SCOPE, BOUNDARIES, ENVIRONMENT, CONSTRAINTS." },
167
+ { section: "Purpose & Beneficiaries", required: true, validationRule: "At least 3 meaningful lines describing why this exists and who benefits." },
168
+ { section: "Scope Boundaries", required: true, validationRule: "At least 2 scope items including explicit out-of-scope boundaries." },
169
+ { section: "Failure Boundaries", required: true, validationRule: "At least 2 failure/edge-case expectations and error visibility behavior." },
170
+ { section: "Runtime Environment", required: true, validationRule: "At least 2 lines describing runtime, install/distribution, and execution environment." },
171
+ { section: "Constraints", required: true, validationRule: "At least 2 concrete constraints (performance, compatibility, dependency, or policy)." },
159
172
  { section: "Alternatives Table", required: true, validationRule: "At least 2 approaches with real trade-offs (not cosmetic) and recommendation with reasoning." },
160
173
  { section: "Approved Direction", required: true, validationRule: "Must contain explicit approval marker from user. State what was approved." },
161
174
  { section: "Assumptions & Risks", required: true, validationRule: "Explicit assumptions made during design. Known risks. If none, state 'None'." },
@@ -1,4 +1,4 @@
1
1
  export declare const ARTIFACT_TEMPLATES: Record<string, string>;
2
2
  export declare const RULEBOOK_MARKDOWN = "# Cclaw Rulebook\n\n## MUST_ALWAYS\n- Follow flow order: brainstorm -> scope -> design -> spec -> plan -> tdd -> review -> ship\n- Require explicit user confirmation after plan before TDD\n- Keep evidence artifacts in `.cclaw/artifacts/`\n- Enforce RED before GREEN in TDD\n- Run two-layer review (spec_compliance and code_quality) before ship\n- Validate all inputs before processing \u2014 never trust external data without sanitization\n- Prefer immutable data patterns and pure functions where the language supports them\n- Follow existing repo conventions, patterns, and directory structure \u2014 match the codebase\n- Verify claims with fresh evidence: \"tests pass\" requires running tests in this message\n- Use conventional commits: `type(scope): description` (feat, fix, refactor, test, docs, chore)\n\n## MUST_NEVER\n- Skip RED phase and jump directly to GREEN in TDD\n- Ship with critical review findings\n- Start implementation during /brainstorm\n- Modify generated cclaw files manually when CLI can regenerate them\n- Commit `.cclaw/` or generated shim files\n- Expose secrets, tokens, API keys, or absolute system paths in agent output\n- Duplicate existing functionality without explicit justification \u2014 search before building\n- Bypass security checks, linting hooks, or type checking to \"move faster\"\n- Claim success (\"Done,\" \"All good,\" \"Tests pass\") without running verification in this message\n- Make changes outside the blast radius of the current task without user consent\n\n## DELEGATION\nWhen a task requires specialist knowledge (security audit, performance profiling, database review),\ndelegate to a specialized agent or skill if the harness supports it. The primary agent should:\n1. Identify the specialist domain\n2. Provide focused context (relevant files, the specific concern)\n3. Evaluate the specialist output before acting on it \u2014 do not blindly apply recommendations\n";
3
- export declare const CURSOR_WORKFLOW_RULE_MDC = "---\ndescription: cclaw workflow guardrails for Cursor agent sessions\nglobs:\n - \"**/*\"\nalwaysApply: true\n---\n\n<!-- cclaw-managed-cursor-workflow-rule -->\n\n# Cclaw Workflow Guardrails\n\n- Follow stage order: brainstorm -> scope -> design -> spec -> plan -> tdd -> review -> ship.\n- Read `.cclaw/state/flow-state.json` before acting; continue from current stage when active.\n- Use `/cc-next` only after required gates pass; never bypass explicit pause/approval rules.\n- Keep evidence in `.cclaw/artifacts/` and canonical run copies in `.cclaw/runs/<activeRunId>/artifacts/`.\n- For machine-only checks in design/plan/tdd/review/ship, dispatch required specialists automatically when tooling supports it.\n- Ask for user input only at explicit approval gates (scope mode, plan approval, user challenge resolution, ship finalization).\n- Treat `.cclaw/skills/using-cclaw/SKILL.md` as routing source of truth; load contextual utility skills only when their triggers apply.\n";
3
+ export declare const CURSOR_WORKFLOW_RULE_MDC = "---\ndescription: cclaw workflow guardrails for Cursor agent sessions\nglobs:\n - \"**/*\"\nalwaysApply: true\n---\n\n<!-- cclaw-managed-cursor-workflow-rule -->\n\n# Cclaw Workflow Guardrails\n\n- Follow stage order: brainstorm -> scope -> design -> spec -> plan -> tdd -> review -> ship.\n- Read `.cclaw/state/flow-state.json` before acting; continue from current stage when active.\n- Use `/cc-next` only after required gates pass; never bypass explicit pause/approval rules.\n- Keep evidence in `.cclaw/artifacts/`; cclaw sync/runtime maintains run snapshots in `.cclaw/runs/<activeRunId>/artifacts/`.\n- For machine-only checks in design/plan/tdd/review/ship, dispatch required specialists automatically when tooling supports it.\n- Ask for user input only at explicit approval gates (scope mode, plan approval, user challenge resolution, ship finalization).\n- Treat `.cclaw/skills/using-cclaw/SKILL.md` as routing source of truth; load contextual utility skills only when their triggers apply.\n";
4
4
  export declare function buildRulesJson(): Record<string, unknown>;
@@ -8,13 +8,48 @@ export const ARTIFACT_TEMPLATES = {
8
8
  - **Who benefits:**
9
9
  - **Why now:**
10
10
  - **Success signal:**
11
- - **Constraints:**
12
11
 
13
12
  ## Known Context
14
13
  - **Explored files/patterns:**
15
14
  - **Existing behavior:**
16
15
  - **Relevant dependencies:**
17
16
 
17
+ ## Clarification Log
18
+ | Category | Question asked | User answer | Evidence note |
19
+ |---|---|---|---|
20
+ | PURPOSE | | | |
21
+ | SCOPE | | | |
22
+ | BOUNDARIES | | | |
23
+ | ENVIRONMENT | | | |
24
+ | CONSTRAINTS | | | |
25
+
26
+ ## Purpose & Beneficiaries
27
+ - **Project purpose:**
28
+ - **Primary users:**
29
+ - **Value outcome:**
30
+
31
+ ## Scope Boundaries
32
+ ### In Scope
33
+ -
34
+
35
+ ### Out of Scope
36
+ -
37
+
38
+ ## Failure Boundaries
39
+ - **Edge cases to handle:**
40
+ - **Expected failures and behavior:**
41
+ - **Error visibility expectations:**
42
+
43
+ ## Runtime Environment
44
+ - **Runtime/platform:**
45
+ - **Install/distribution model:**
46
+ - **Execution context (local/CI/deploy):**
47
+
48
+ ## Constraints
49
+ - **Performance constraints:**
50
+ - **Compatibility constraints:**
51
+ - **Dependency constraints:**
52
+
18
53
  ## Alternatives Table
19
54
  | Option | Summary | Trade-offs | Recommendation |
20
55
  |---|---|---|---|
@@ -347,7 +382,7 @@ alwaysApply: true
347
382
  - Follow stage order: brainstorm -> scope -> design -> spec -> plan -> tdd -> review -> ship.
348
383
  - Read \`.cclaw/state/flow-state.json\` before acting; continue from current stage when active.
349
384
  - Use \`/cc-next\` only after required gates pass; never bypass explicit pause/approval rules.
350
- - Keep evidence in \`.cclaw/artifacts/\` and canonical run copies in \`.cclaw/runs/<activeRunId>/artifacts/\`.
385
+ - Keep evidence in \`.cclaw/artifacts/\`; cclaw sync/runtime maintains run snapshots in \`.cclaw/runs/<activeRunId>/artifacts/\`.
351
386
  - For machine-only checks in design/plan/tdd/review/ship, dispatch required specialists automatically when tooling supports it.
352
387
  - Ask for user input only at explicit approval gates (scope mode, plan approval, user challenge resolution, ship finalization).
353
388
  - Treat \`.cclaw/skills/using-cclaw/SKILL.md\` as routing source of truth; load contextual utility skills only when their triggers apply.
package/dist/doctor.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import fs from "node:fs/promises";
2
2
  import path from "node:path";
3
3
  import { execFile } from "node:child_process";
4
+ import { pathToFileURL } from "node:url";
4
5
  import { promisify } from "node:util";
5
6
  import { COMMAND_FILE_ORDER, REQUIRED_DIRS, RUNTIME_ROOT } from "./constants.js";
6
7
  import { CCLAW_AGENTS } from "./content/agents.js";
@@ -186,6 +187,47 @@ async function opencodeRegistrationCheck(projectRoot) {
186
187
  }
187
188
  return { ok: false, details: `No opencode.json/opencode.jsonc found with plugin ${expected}` };
188
189
  }
190
+ async function opencodePluginRuntimeShapeCheck(projectRoot) {
191
+ const pluginPath = path.join(projectRoot, ".opencode/plugins/cclaw-plugin.mjs");
192
+ if (!(await exists(pluginPath))) {
193
+ return { ok: false, details: `${path.relative(projectRoot, pluginPath)} not found` };
194
+ }
195
+ try {
196
+ const moduleUrl = `${pathToFileURL(pluginPath).href}?doctor=${Date.now()}`;
197
+ const imported = await import(moduleUrl);
198
+ if (typeof imported.default !== "function") {
199
+ return {
200
+ ok: false,
201
+ details: `${path.relative(projectRoot, pluginPath)} must export a default plugin factory function`
202
+ };
203
+ }
204
+ const plugin = imported.default({ directory: projectRoot });
205
+ const requiredHandlers = [
206
+ "event",
207
+ "tool.execute.before",
208
+ "tool.execute.after",
209
+ "experimental.chat.system.transform"
210
+ ];
211
+ const missing = requiredHandlers.filter((name) => typeof plugin?.[name] !== "function");
212
+ if (missing.length > 0) {
213
+ return {
214
+ ok: false,
215
+ details: `${path.relative(projectRoot, pluginPath)} missing runtime handlers: ${missing.join(", ")}`
216
+ };
217
+ }
218
+ await plugin.event({ event: { type: "session.updated", data: {} } });
219
+ return {
220
+ ok: true,
221
+ details: `${path.relative(projectRoot, pluginPath)} exports compatible runtime handler shape`
222
+ };
223
+ }
224
+ catch (error) {
225
+ return {
226
+ ok: false,
227
+ details: `runtime load failed for .opencode/plugins/cclaw-plugin.mjs: ${error instanceof Error ? error.message : String(error)}`
228
+ };
229
+ }
230
+ }
189
231
  export async function doctorChecks(projectRoot, options = {}) {
190
232
  const checks = [];
191
233
  for (const dir of REQUIRED_DIRS) {
@@ -595,6 +637,12 @@ export async function doctorChecks(projectRoot, options = {}) {
595
637
  ok,
596
638
  details: `${file} must include event lifecycle handler, tool.execute.before/after with prompt/workflow/context hooks, session.idle summarization, and transform rehydration`
597
639
  });
640
+ const runtimeShape = await opencodePluginRuntimeShapeCheck(projectRoot);
641
+ checks.push({
642
+ name: "hook:opencode:runtime_shape",
643
+ ok: runtimeShape.ok,
644
+ details: runtimeShape.details
645
+ });
598
646
  const registration = await opencodeRegistrationCheck(projectRoot);
599
647
  checks.push({
600
648
  name: "hook:opencode:config_registration",
@@ -719,8 +767,8 @@ export async function doctorChecks(projectRoot, options = {}) {
719
767
  });
720
768
  checks.push({
721
769
  name: "run:active_handoff",
722
- ok: await exists(path.join(projectRoot, RUNTIME_ROOT, "runs", flowState.activeRunId, "00-handoff.md")),
723
- details: `${RUNTIME_ROOT}/runs/${flowState.activeRunId}/00-handoff.md must exist`
770
+ ok: await exists(path.join(projectRoot, RUNTIME_ROOT, "runs", flowState.activeRunId, "handoff.md")),
771
+ details: `${RUNTIME_ROOT}/runs/${flowState.activeRunId}/handoff.md must exist`
724
772
  });
725
773
  const delegation = await checkMandatoryDelegations(projectRoot, flowState.currentStage);
726
774
  checks.push({
package/dist/runs.js CHANGED
@@ -7,7 +7,7 @@ const FLOW_STATE_REL_PATH = `${RUNTIME_ROOT}/state/flow-state.json`;
7
7
  const RUNS_DIR_REL_PATH = `${RUNTIME_ROOT}/runs`;
8
8
  const ACTIVE_ARTIFACTS_REL_PATH = `${RUNTIME_ROOT}/artifacts`;
9
9
  const RUN_META_FILE = "run.json";
10
- const RUN_HANDOFF_FILE = "00-handoff.md";
10
+ const RUN_HANDOFF_FILE = "handoff.md";
11
11
  const FLOW_STAGE_SET = new Set(COMMAND_FILE_ORDER);
12
12
  function flowStatePath(projectRoot) {
13
13
  return path.join(projectRoot, FLOW_STATE_REL_PATH);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cclaw-cli",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "Installer-first flow toolkit for coding agents",
5
5
  "type": "module",
6
6
  "bin": {