cclaw-cli 0.48.8 → 0.48.10
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/dist/config.d.ts +1 -1
- package/dist/config.js +1 -1
- package/dist/content/harness-doc.js +1 -1
- package/dist/content/harness-playbooks.js +7 -7
- package/dist/content/hook-events.js +19 -19
- package/dist/content/hooks.d.ts +0 -16
- package/dist/content/hooks.js +112 -1220
- package/dist/content/learnings.js +2 -2
- package/dist/content/next-command.js +2 -2
- package/dist/content/node-hooks.js +96 -7
- package/dist/content/observe.d.ts +0 -38
- package/dist/content/observe.js +28 -1719
- package/dist/content/opencode-plugin.js +10 -10
- package/dist/content/protocols.js +5 -9
- package/dist/content/skills.js +1 -1
- package/dist/content/stage-common-guidance.js +1 -1
- package/dist/content/stages/design.js +1 -1
- package/dist/content/stages/plan.js +2 -2
- package/dist/content/stages/scope.js +1 -1
- package/dist/doctor.js +64 -53
- package/dist/install.js +125 -53
- package/dist/policy.js +13 -13
- package/package.json +2 -3
|
@@ -58,7 +58,7 @@ Knowledge capture is now stage-native:
|
|
|
58
58
|
- Allowed payloads:
|
|
59
59
|
- \`- None this stage.\` (explicit no-op)
|
|
60
60
|
- JSON bullets with required keys \`type\`, \`trigger\`, \`action\`, \`confidence\` (optional keys may mirror the full JSONL schema fields).
|
|
61
|
-
- During \`
|
|
61
|
+
- During \`node .cclaw/hooks/stage-complete.mjs <stage>\`, cclaw:
|
|
62
62
|
1. validates \`## Learnings\`,
|
|
63
63
|
2. appends deduped entries to \`${KNOWLEDGE_PATH}\`,
|
|
64
64
|
3. writes a harvest marker into the artifact.
|
|
@@ -157,7 +157,7 @@ Manage the project knowledge store. One canonical file, strict JSONL:
|
|
|
157
157
|
- \`${KNOWLEDGE_ARCHIVE_PATH}\` — soft-archive target written only by curate.
|
|
158
158
|
|
|
159
159
|
Stage-native pipeline:
|
|
160
|
-
- During \`stage-complete.
|
|
160
|
+
- During \`stage-complete.mjs\`, cclaw harvests \`## Learnings\` from the current
|
|
161
161
|
stage artifact into \`${KNOWLEDGE_PATH}\` automatically.
|
|
162
162
|
- Use \`/cc-learn\` for query, backfill, and curation workflows.
|
|
163
163
|
|
|
@@ -58,7 +58,7 @@ This is the only progression command the user needs to drive the entire flow. St
|
|
|
58
58
|
|
|
59
59
|
→ Load **\`${RUNTIME_ROOT}/skills/<skillFolder>/SKILL.md\`** and **\`${RUNTIME_ROOT}/commands/<currentStage>.md\`** for the current stage.
|
|
60
60
|
→ Execute that stage's protocol. The stage skill handles the full interaction including STOP points and gate tracking.
|
|
61
|
-
→ Stage completion must use \`
|
|
61
|
+
→ Stage completion must use \`node .cclaw/hooks/stage-complete.mjs <currentStage>\` (canonical), which validates delegations + gate evidence before mutating \`flow-state.json\`.
|
|
62
62
|
|
|
63
63
|
### Path B: Current stage IS complete (all gates passed, all delegations satisfied)
|
|
64
64
|
|
|
@@ -188,7 +188,7 @@ Load the current stage's skill and command contract:
|
|
|
188
188
|
- \`${RUNTIME_ROOT}/skills/<skillFolder>/SKILL.md\`
|
|
189
189
|
- \`${RUNTIME_ROOT}/commands/<currentStage>.md\`
|
|
190
190
|
|
|
191
|
-
Execute the stage protocol. The stage skill handles interaction, STOP points, gate tracking, and stage completion via \`
|
|
191
|
+
Execute the stage protocol. The stage skill handles interaction, STOP points, gate tracking, and stage completion via \`node .cclaw/hooks/stage-complete.mjs <stage>\` (canonical flow-state mutation path).
|
|
192
192
|
|
|
193
193
|
Special-case for review: if \`review_criticals_resolved\` is in \`blocked\`, route to rework instead of looping review forever — recommend \`/cc-ops rewind tdd "review_blocked_by_critical"\`.
|
|
194
194
|
|
|
@@ -99,6 +99,72 @@ async function readStdin() {
|
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
async function runCclawInternal(root, args) {
|
|
103
|
+
return await new Promise((resolve) => {
|
|
104
|
+
const isWindows = process.platform === "win32";
|
|
105
|
+
let settled = false;
|
|
106
|
+
let stderr = "";
|
|
107
|
+
const finalize = (value) => {
|
|
108
|
+
if (settled) return;
|
|
109
|
+
settled = true;
|
|
110
|
+
resolve(value);
|
|
111
|
+
};
|
|
112
|
+
let child;
|
|
113
|
+
try {
|
|
114
|
+
child = spawn(
|
|
115
|
+
isWindows ? "cmd.exe" : "cclaw",
|
|
116
|
+
isWindows ? ["/d", "/s", "/c", "cclaw", "internal", ...args] : ["internal", ...args],
|
|
117
|
+
{
|
|
118
|
+
cwd: root,
|
|
119
|
+
env: process.env,
|
|
120
|
+
stdio: ["ignore", "ignore", "pipe"]
|
|
121
|
+
}
|
|
122
|
+
);
|
|
123
|
+
} catch (error) {
|
|
124
|
+
const code = error && typeof error === "object" && "code" in error ? String(error.code) : "";
|
|
125
|
+
finalize({
|
|
126
|
+
code: 1,
|
|
127
|
+
stderr,
|
|
128
|
+
missingBinary: code === "ENOENT" || (isWindows && code === "EINVAL")
|
|
129
|
+
});
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
child.stderr?.on("data", (chunk) => {
|
|
133
|
+
stderr += String(chunk ?? "");
|
|
134
|
+
if (stderr.length > 8000) {
|
|
135
|
+
stderr = stderr.slice(-8000);
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
child.on("error", (error) => {
|
|
139
|
+
const code = error && typeof error === "object" && "code" in error ? String(error.code) : "";
|
|
140
|
+
finalize({
|
|
141
|
+
code: 1,
|
|
142
|
+
stderr,
|
|
143
|
+
missingBinary: code === "ENOENT" || (isWindows && code === "EINVAL")
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
child.on("close", (code, signal) => {
|
|
147
|
+
if (signal) {
|
|
148
|
+
finalize({
|
|
149
|
+
code: 1,
|
|
150
|
+
stderr,
|
|
151
|
+
missingBinary: false
|
|
152
|
+
});
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const stderrLower = stderr.toLowerCase();
|
|
156
|
+
const missingBinary = isWindows
|
|
157
|
+
? stderrLower.includes("is not recognized as an internal or external command")
|
|
158
|
+
: false;
|
|
159
|
+
finalize({
|
|
160
|
+
code: typeof code === "number" ? code : 1,
|
|
161
|
+
stderr,
|
|
162
|
+
missingBinary
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
|
|
102
168
|
function detectHarness(env) {
|
|
103
169
|
if (env.CLAUDE_PROJECT_DIR) return "claude";
|
|
104
170
|
if (env.CURSOR_PROJECT_DIR || env.CURSOR_PROJECT_ROOT) return "cursor";
|
|
@@ -1446,14 +1512,33 @@ async function handleContextMonitor(runtime) {
|
|
|
1446
1512
|
return 0;
|
|
1447
1513
|
}
|
|
1448
1514
|
|
|
1515
|
+
async function handleVerifyCurrentState(runtime) {
|
|
1516
|
+
const mode = process.env.CCLAW_WORKFLOW_GUARD_MODE === "strict"
|
|
1517
|
+
? "strict"
|
|
1518
|
+
: DEFAULT_WORKFLOW_GUARD_MODE;
|
|
1519
|
+
const result = await runCclawInternal(runtime.root, ["verify-current-state", "--quiet"]);
|
|
1520
|
+
if (result.missingBinary) {
|
|
1521
|
+
process.stderr.write("[cclaw] codex hook: cclaw binary is required for verify-current-state\\n");
|
|
1522
|
+
return 1;
|
|
1523
|
+
}
|
|
1524
|
+
if (mode === "strict") {
|
|
1525
|
+
if (result.code !== 0 && result.stderr.trim().length > 0) {
|
|
1526
|
+
process.stderr.write(result.stderr);
|
|
1527
|
+
}
|
|
1528
|
+
return result.code === 0 ? 0 : 1;
|
|
1529
|
+
}
|
|
1530
|
+
return 0;
|
|
1531
|
+
}
|
|
1532
|
+
|
|
1449
1533
|
function normalizeHookName(rawName) {
|
|
1450
1534
|
const value = normalizeText(rawName).toLowerCase();
|
|
1451
|
-
if (value === "session-start"
|
|
1452
|
-
if (value === "stop-checkpoint"
|
|
1453
|
-
if (value === "pre-compact"
|
|
1454
|
-
if (value === "prompt-guard"
|
|
1455
|
-
if (value === "workflow-guard"
|
|
1456
|
-
if (value === "context-monitor"
|
|
1535
|
+
if (value === "session-start") return "session-start";
|
|
1536
|
+
if (value === "stop-checkpoint") return "stop-checkpoint";
|
|
1537
|
+
if (value === "pre-compact") return "pre-compact";
|
|
1538
|
+
if (value === "prompt-guard") return "prompt-guard";
|
|
1539
|
+
if (value === "workflow-guard") return "workflow-guard";
|
|
1540
|
+
if (value === "context-monitor") return "context-monitor";
|
|
1541
|
+
if (value === "verify-current-state") return "verify-current-state";
|
|
1457
1542
|
return "";
|
|
1458
1543
|
}
|
|
1459
1544
|
|
|
@@ -1463,7 +1548,7 @@ async function main() {
|
|
|
1463
1548
|
process.stderr.write(
|
|
1464
1549
|
"[cclaw] run-hook: usage: node " +
|
|
1465
1550
|
RUNTIME_ROOT +
|
|
1466
|
-
"/hooks/run-hook.mjs <session-start|stop-checkpoint|pre-compact|prompt-guard|workflow-guard|context-monitor>\\n"
|
|
1551
|
+
"/hooks/run-hook.mjs <session-start|stop-checkpoint|pre-compact|prompt-guard|workflow-guard|context-monitor|verify-current-state>\\n"
|
|
1467
1552
|
);
|
|
1468
1553
|
process.exitCode = 1;
|
|
1469
1554
|
return;
|
|
@@ -1508,6 +1593,10 @@ async function main() {
|
|
|
1508
1593
|
process.exitCode = await handleContextMonitor(runtime);
|
|
1509
1594
|
return;
|
|
1510
1595
|
}
|
|
1596
|
+
if (hookName === "verify-current-state") {
|
|
1597
|
+
process.exitCode = await handleVerifyCurrentState(runtime);
|
|
1598
|
+
return;
|
|
1599
|
+
}
|
|
1511
1600
|
process.stderr.write("[cclaw] run-hook: unsupported hook " + hookName + "\\n");
|
|
1512
1601
|
process.exitCode = 1;
|
|
1513
1602
|
} catch (error) {
|
|
@@ -1,41 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Hook helper scripts and harness hook JSON generators.
|
|
3
|
-
*
|
|
4
|
-
* This module still provides prompt/workflow/context guard scripts and
|
|
5
|
-
* cross-harness hook wiring. Observation pipeline scripts are retained only
|
|
6
|
-
* for backward compatibility and are not wired by default runtime generation.
|
|
7
|
-
*/
|
|
8
|
-
export interface PromptGuardOptions {
|
|
9
|
-
strictMode?: boolean;
|
|
10
|
-
}
|
|
11
|
-
export declare function promptGuardScript(options?: PromptGuardOptions): string;
|
|
12
|
-
export interface WorkflowGuardOptions {
|
|
13
|
-
workflowGuardMode?: "advisory" | "strict";
|
|
14
|
-
tddEnforcementMode?: "advisory" | "strict";
|
|
15
|
-
tddTestPathPatterns?: string[];
|
|
16
|
-
tddProductionPathPatterns?: string[];
|
|
17
|
-
}
|
|
18
|
-
export declare function workflowGuardScript(options?: WorkflowGuardOptions): string;
|
|
19
|
-
export declare function contextMonitorScript(): string;
|
|
20
1
|
export declare function claudeHooksJsonWithObservation(): string;
|
|
21
2
|
export declare function cursorHooksJsonWithObservation(): string;
|
|
22
|
-
/**
|
|
23
|
-
* Codex CLI ≥ v0.114 hooks. Differences vs. the Claude shape:
|
|
24
|
-
*
|
|
25
|
-
* - `SessionStart` matcher is limited to `startup|resume` — Codex does
|
|
26
|
-
* not emit `clear` or `compact` lifecycle phases.
|
|
27
|
-
* - `PreToolUse` / `PostToolUse` fire **only for the `Bash` tool**
|
|
28
|
-
* (documented Codex limitation, v0.114/v0.115). We match both `Bash`
|
|
29
|
-
* and `bash` variants to tolerate casing drift across Codex builds.
|
|
30
|
-
* - `UserPromptSubmit` is supported and is the closest analogue to
|
|
31
|
-
* Cursor's `preToolUse` for non-Bash tooling — we run prompt-guard
|
|
32
|
-
* there so workflow/prompt checks still fire when the tool being
|
|
33
|
-
* used is `Write` or `Edit` rather than `Bash`.
|
|
34
|
-
* - There is no `PreCompact` event in Codex CLI — pre-compact
|
|
35
|
-
* semantics are carried by the agent itself inside `/cc-ops retro`.
|
|
36
|
-
*
|
|
37
|
-
* The entire file is inert unless the user opts into
|
|
38
|
-
* `[features] codex_hooks = true` in `~/.codex/config.toml`; cclaw
|
|
39
|
-
* doctor and the init prompt handle that flag.
|
|
40
|
-
*/
|
|
41
3
|
export declare function codexHooksJsonWithObservation(): string;
|