cclaw-cli 0.48.9 → 0.48.11
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/doctor-references.js +11 -7
- 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 +31 -15
- package/dist/content/observe.d.ts +0 -38
- package/dist/content/observe.js +31 -1718
- package/dist/content/opencode-plugin.js +10 -7
- 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-registry.js +0 -9
- package/dist/doctor.js +58 -66
- package/dist/install.js +134 -54
- 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
|
|
|
@@ -101,6 +101,7 @@ async function readStdin() {
|
|
|
101
101
|
|
|
102
102
|
async function runCclawInternal(root, args) {
|
|
103
103
|
return await new Promise((resolve) => {
|
|
104
|
+
const isWindows = process.platform === "win32";
|
|
104
105
|
let settled = false;
|
|
105
106
|
let stderr = "";
|
|
106
107
|
const finalize = (value) => {
|
|
@@ -110,17 +111,21 @@ async function runCclawInternal(root, args) {
|
|
|
110
111
|
};
|
|
111
112
|
let child;
|
|
112
113
|
try {
|
|
113
|
-
child = spawn(
|
|
114
|
+
child = spawn(
|
|
115
|
+
isWindows ? "cmd.exe" : "cclaw",
|
|
116
|
+
isWindows ? ["/d", "/s", "/c", "cclaw", "internal", ...args] : ["internal", ...args],
|
|
117
|
+
{
|
|
114
118
|
cwd: root,
|
|
115
119
|
env: process.env,
|
|
116
120
|
stdio: ["ignore", "ignore", "pipe"]
|
|
117
|
-
}
|
|
121
|
+
}
|
|
122
|
+
);
|
|
118
123
|
} catch (error) {
|
|
119
124
|
const code = error && typeof error === "object" && "code" in error ? String(error.code) : "";
|
|
120
125
|
finalize({
|
|
121
126
|
code: 1,
|
|
122
127
|
stderr,
|
|
123
|
-
missingBinary: code === "ENOENT"
|
|
128
|
+
missingBinary: code === "ENOENT" || (isWindows && code === "EINVAL")
|
|
124
129
|
});
|
|
125
130
|
return;
|
|
126
131
|
}
|
|
@@ -135,7 +140,7 @@ async function runCclawInternal(root, args) {
|
|
|
135
140
|
finalize({
|
|
136
141
|
code: 1,
|
|
137
142
|
stderr,
|
|
138
|
-
missingBinary: code === "ENOENT"
|
|
143
|
+
missingBinary: code === "ENOENT" || (isWindows && code === "EINVAL")
|
|
139
144
|
});
|
|
140
145
|
});
|
|
141
146
|
child.on("close", (code, signal) => {
|
|
@@ -147,10 +152,14 @@ async function runCclawInternal(root, args) {
|
|
|
147
152
|
});
|
|
148
153
|
return;
|
|
149
154
|
}
|
|
155
|
+
const stderrLower = stderr.toLowerCase();
|
|
156
|
+
const missingBinary = isWindows
|
|
157
|
+
? stderrLower.includes("is not recognized as an internal or external command")
|
|
158
|
+
: false;
|
|
150
159
|
finalize({
|
|
151
160
|
code: typeof code === "number" ? code : 1,
|
|
152
161
|
stderr,
|
|
153
|
-
missingBinary
|
|
162
|
+
missingBinary
|
|
154
163
|
});
|
|
155
164
|
});
|
|
156
165
|
});
|
|
@@ -177,12 +186,12 @@ async function detectRoot(env) {
|
|
|
177
186
|
try {
|
|
178
187
|
const runtimePath = path.join(candidate, RUNTIME_ROOT);
|
|
179
188
|
const stat = await fs.stat(runtimePath);
|
|
180
|
-
if (stat.isDirectory()) return candidate;
|
|
189
|
+
if (stat.isDirectory()) return { root: candidate, foundRuntime: true };
|
|
181
190
|
} catch {
|
|
182
191
|
// continue
|
|
183
192
|
}
|
|
184
193
|
}
|
|
185
|
-
return candidates[0] || process.cwd();
|
|
194
|
+
return { root: candidates[0] || process.cwd(), foundRuntime: false };
|
|
186
195
|
}
|
|
187
196
|
|
|
188
197
|
function toLower(value) {
|
|
@@ -1509,7 +1518,7 @@ async function handleVerifyCurrentState(runtime) {
|
|
|
1509
1518
|
: DEFAULT_WORKFLOW_GUARD_MODE;
|
|
1510
1519
|
const result = await runCclawInternal(runtime.root, ["verify-current-state", "--quiet"]);
|
|
1511
1520
|
if (result.missingBinary) {
|
|
1512
|
-
process.stderr.write("[cclaw]
|
|
1521
|
+
process.stderr.write("[cclaw] hook: cclaw binary is required for verify-current-state\\n");
|
|
1513
1522
|
return 1;
|
|
1514
1523
|
}
|
|
1515
1524
|
if (mode === "strict") {
|
|
@@ -1523,12 +1532,12 @@ async function handleVerifyCurrentState(runtime) {
|
|
|
1523
1532
|
|
|
1524
1533
|
function normalizeHookName(rawName) {
|
|
1525
1534
|
const value = normalizeText(rawName).toLowerCase();
|
|
1526
|
-
if (value === "session-start"
|
|
1527
|
-
if (value === "stop-checkpoint"
|
|
1528
|
-
if (value === "pre-compact"
|
|
1529
|
-
if (value === "prompt-guard"
|
|
1530
|
-
if (value === "workflow-guard"
|
|
1531
|
-
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";
|
|
1532
1541
|
if (value === "verify-current-state") return "verify-current-state";
|
|
1533
1542
|
return "";
|
|
1534
1543
|
}
|
|
@@ -1546,7 +1555,14 @@ async function main() {
|
|
|
1546
1555
|
}
|
|
1547
1556
|
|
|
1548
1557
|
const harness = detectHarness(process.env);
|
|
1549
|
-
const root = await detectRoot(process.env);
|
|
1558
|
+
const { root, foundRuntime } = await detectRoot(process.env);
|
|
1559
|
+
if (!foundRuntime) {
|
|
1560
|
+
// No .cclaw/ runtime in any candidate root — this directory is not
|
|
1561
|
+
// initialized for cclaw. Exit 0 silently so hooks never block harnesses
|
|
1562
|
+
// that run in unrelated repos; users initialize with \`cclaw init\`.
|
|
1563
|
+
process.exitCode = 0;
|
|
1564
|
+
return;
|
|
1565
|
+
}
|
|
1550
1566
|
const inputRaw = await readStdin();
|
|
1551
1567
|
const inputData = safeParseJson(inputRaw, {});
|
|
1552
1568
|
const runtime = {
|
|
@@ -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;
|