cclaw-cli 0.51.5 → 0.51.6
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/content/hooks.d.ts +1 -0
- package/dist/content/hooks.js +122 -0
- package/dist/content/start-command.js +4 -4
- package/dist/doctor.js +2 -1
- package/dist/install.js +3 -1
- package/package.json +1 -1
package/dist/content/hooks.d.ts
CHANGED
package/dist/content/hooks.js
CHANGED
|
@@ -16,6 +16,128 @@ function resolveCliEntrypointForGeneratedHook() {
|
|
|
16
16
|
}
|
|
17
17
|
return null;
|
|
18
18
|
}
|
|
19
|
+
function internalHelperScript(helperName, internalSubcommand, usage) {
|
|
20
|
+
const cliEntrypoint = resolveCliEntrypointForGeneratedHook();
|
|
21
|
+
return `#!/usr/bin/env node
|
|
22
|
+
import fs from "node:fs/promises";
|
|
23
|
+
import path from "node:path";
|
|
24
|
+
import process from "node:process";
|
|
25
|
+
import { spawn } from "node:child_process";
|
|
26
|
+
|
|
27
|
+
const RUNTIME_ROOT = ${JSON.stringify(RUNTIME_ROOT)};
|
|
28
|
+
const CCLAW_CLI_ENTRYPOINT = ${JSON.stringify(cliEntrypoint)};
|
|
29
|
+
const HELPER_NAME = ${JSON.stringify(helperName)};
|
|
30
|
+
const INTERNAL_SUBCOMMAND = ${JSON.stringify(internalSubcommand)};
|
|
31
|
+
const USAGE = ${JSON.stringify(usage)};
|
|
32
|
+
|
|
33
|
+
async function detectRoot() {
|
|
34
|
+
const candidates = [
|
|
35
|
+
process.env.CCLAW_PROJECT_ROOT,
|
|
36
|
+
process.env.CLAUDE_PROJECT_DIR,
|
|
37
|
+
process.env.CURSOR_PROJECT_DIR,
|
|
38
|
+
process.env.CURSOR_PROJECT_ROOT,
|
|
39
|
+
process.env.OPENCODE_PROJECT_DIR,
|
|
40
|
+
process.env.OPENCODE_PROJECT_ROOT,
|
|
41
|
+
process.cwd()
|
|
42
|
+
].filter((value) => typeof value === "string" && value.length > 0);
|
|
43
|
+
|
|
44
|
+
for (const candidate of candidates) {
|
|
45
|
+
try {
|
|
46
|
+
const runtimePath = path.join(candidate, RUNTIME_ROOT);
|
|
47
|
+
const stat = await fs.stat(runtimePath);
|
|
48
|
+
if (stat.isDirectory()) return candidate;
|
|
49
|
+
} catch {
|
|
50
|
+
// continue
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return candidates[0] || process.cwd();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function printUsage() {
|
|
57
|
+
process.stderr.write(USAGE + "\\n");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function main() {
|
|
61
|
+
const [, , ...flags] = process.argv;
|
|
62
|
+
if (flags.includes("--help") || flags.includes("-h")) {
|
|
63
|
+
printUsage();
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const root = await detectRoot();
|
|
68
|
+
const runtimePath = path.join(root, RUNTIME_ROOT);
|
|
69
|
+
try {
|
|
70
|
+
const stat = await fs.stat(runtimePath);
|
|
71
|
+
if (!stat.isDirectory()) throw new Error("not-dir");
|
|
72
|
+
} catch {
|
|
73
|
+
process.stderr.write("[cclaw] " + HELPER_NAME + ": runtime root not found at " + runtimePath + "\\n");
|
|
74
|
+
process.exitCode = 1;
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const cliEntrypoint = process.env.CCLAW_CLI_JS || CCLAW_CLI_ENTRYPOINT;
|
|
79
|
+
if (!cliEntrypoint || cliEntrypoint.trim().length === 0) {
|
|
80
|
+
process.stderr.write(
|
|
81
|
+
"[cclaw] " + HELPER_NAME + ": local Node runtime entrypoint is missing. Re-run npx cclaw-cli sync or npx cclaw-cli upgrade to regenerate hooks.\\n"
|
|
82
|
+
);
|
|
83
|
+
process.exitCode = 1;
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
const stat = await fs.stat(cliEntrypoint);
|
|
89
|
+
if (!stat.isFile()) throw new Error("not-file");
|
|
90
|
+
} catch {
|
|
91
|
+
process.stderr.write(
|
|
92
|
+
"[cclaw] " + HELPER_NAME + ": local Node runtime entrypoint not found at " + cliEntrypoint + ". Re-run npx cclaw-cli sync or npx cclaw-cli upgrade to regenerate hooks.\\n"
|
|
93
|
+
);
|
|
94
|
+
process.exitCode = 1;
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const child = spawn(process.execPath, [cliEntrypoint, "internal", INTERNAL_SUBCOMMAND, ...flags], {
|
|
99
|
+
cwd: root,
|
|
100
|
+
env: process.env,
|
|
101
|
+
stdio: "inherit"
|
|
102
|
+
});
|
|
103
|
+
let spawnErrored = false;
|
|
104
|
+
|
|
105
|
+
child.on("error", (error) => {
|
|
106
|
+
spawnErrored = true;
|
|
107
|
+
const code = error && typeof error === "object" && "code" in error ? String(error.code) : "";
|
|
108
|
+
if (code === "ENOENT") {
|
|
109
|
+
process.stderr.write(
|
|
110
|
+
"[cclaw] " + HELPER_NAME + ": node executable not found while invoking local runtime. Re-run npx cclaw-cli doctor.\\n"
|
|
111
|
+
);
|
|
112
|
+
} else {
|
|
113
|
+
process.stderr.write(
|
|
114
|
+
"[cclaw] " + HELPER_NAME + ": failed to invoke local Node runtime (" +
|
|
115
|
+
(error instanceof Error ? error.message : String(error)) +
|
|
116
|
+
").\\n"
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
process.exitCode = 1;
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
child.on("close", (code, signal) => {
|
|
123
|
+
if (spawnErrored) {
|
|
124
|
+
process.exitCode = 1;
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (signal) {
|
|
128
|
+
process.exitCode = 1;
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
process.exitCode = typeof code === "number" && code >= 0 ? code : 1;
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
void main();
|
|
136
|
+
`;
|
|
137
|
+
}
|
|
138
|
+
export function startFlowScript() {
|
|
139
|
+
return internalHelperScript("start-flow", "start-flow", "Usage: node " + RUNTIME_ROOT + "/hooks/start-flow.mjs --track=<standard|medium|quick> [--class=...] [--prompt=...] [--stack=...] [--reason=...] [--reclassify] [--force-reset]");
|
|
140
|
+
}
|
|
19
141
|
export function stageCompleteScript() {
|
|
20
142
|
const cliEntrypoint = resolveCliEntrypointForGeneratedHook();
|
|
21
143
|
return `#!/usr/bin/env node
|
|
@@ -86,7 +86,7 @@ ${conversationLanguagePolicyMarkdown()}
|
|
|
86
86
|
> Override? (A) keep \`<recommended>\` (B) switch track (C) cancel.
|
|
87
87
|
If the harness's native ask tool is available (\`AskUserQuestion\` / \`AskQuestion\` / \`question\` / \`request_user_input\`), send exactly ONE question; on schema error, fall back to a plain-text lettered list.
|
|
88
88
|
10. Start the tracked flow only through the managed helper:
|
|
89
|
-
\`cclaw
|
|
89
|
+
\`node .cclaw/hooks/start-flow.mjs --track=<quick|medium|standard> --class=<class> --prompt=<prompt> --stack=<stack> --reason=<matched heuristic>\`
|
|
90
90
|
If this helper fails, STOP and report the exact command/output. Do **not** manually edit \`${flowPath}\`.
|
|
91
91
|
11. The helper persists \`${flowPath}\`, computes \`skippedStages\`, sets the first stage for the track, resets the gate catalog, and writes \`.cclaw/artifacts/00-idea.md\`.
|
|
92
92
|
12. Load the **first-stage skill for the chosen track** and its command file:
|
|
@@ -102,7 +102,7 @@ If during any stage the agent discovers evidence that contradicts the initial Ph
|
|
|
102
102
|
1. Surface the new evidence in plain text.
|
|
103
103
|
2. Propose the updated \`Class\` + \`Track\` with a one-line reason.
|
|
104
104
|
3. Use the Decision Protocol to let the user accept, override, or cancel.
|
|
105
|
-
4. On acceptance: run \`cclaw
|
|
105
|
+
4. On acceptance: run \`node .cclaw/hooks/start-flow.mjs --reclassify --track=<new-track> --class=<new-class> --reason=<why>\`. The helper appends a \`Reclassification:\` entry to \`00-idea.md\` and updates flow state atomically. If it fails, STOP and report the exact output; do NOT manually edit \`flow-state.json\`.
|
|
106
106
|
|
|
107
107
|
### Without prompt (\`/cc\`)
|
|
108
108
|
|
|
@@ -181,12 +181,12 @@ ${conversationLanguagePolicyMarkdown()}
|
|
|
181
181
|
|
|
182
182
|
- On conflict, prefer \`standard\` over \`medium\`, and \`medium\` over \`quick\`.
|
|
183
183
|
- Always state the recommendation as a one-line reason citing matched triggers.
|
|
184
|
-
8. Run the managed start helper: \`cclaw
|
|
184
|
+
8. Run the managed start helper: \`node .cclaw/hooks/start-flow.mjs --track=<quick|medium|standard> --class=<class> --prompt=<prompt> --stack=<stack> --reason=<matched heuristic>\`. The helper writes \`${flowPath}\`, computes \`skippedStages\`, resets the gate catalog, and writes \`${RUNTIME_ROOT}/artifacts/00-idea.md\`. If it fails, STOP and report the exact command/output; do not manually edit flow state.
|
|
185
185
|
9. Load and execute the **first stage skill of the chosen track** (\`brainstorming\` for medium/standard, \`specification-authoring\` for quick) plus its matching command file.
|
|
186
186
|
|
|
187
187
|
### Reclassification on discovery
|
|
188
188
|
|
|
189
|
-
If mid-stage evidence contradicts the initial Class/Track decision (the "trivial" change needs a migration, the "quick" bug fix needs architecture work, an origin doc multiplies scope), STOP and re-classify using the Decision Protocol. On acceptance, run \`cclaw
|
|
189
|
+
If mid-stage evidence contradicts the initial Class/Track decision (the "trivial" change needs a migration, the "quick" bug fix needs architecture work, an origin doc multiplies scope), STOP and re-classify using the Decision Protocol. On acceptance, run \`node .cclaw/hooks/start-flow.mjs --reclassify --track=<new-track> --class=<new-class> --reason=<why>\`; the helper records \`Reclassification:\` in \`00-idea.md\` and updates state atomically. Do NOT rewrite prior artifacts or manually edit flow-state.
|
|
190
190
|
|
|
191
191
|
### Path B: \`/cc\` (no arguments)
|
|
192
192
|
|
package/dist/doctor.js
CHANGED
|
@@ -92,7 +92,7 @@ function extractGeneratedCliEntrypoints(scriptContent) {
|
|
|
92
92
|
return paths;
|
|
93
93
|
}
|
|
94
94
|
async function generatedCliEntrypointsOk(projectRoot) {
|
|
95
|
-
const hookScripts = ["stage-complete.mjs", "run-hook.mjs"];
|
|
95
|
+
const hookScripts = ["stage-complete.mjs", "start-flow.mjs", "run-hook.mjs"];
|
|
96
96
|
const problems = [];
|
|
97
97
|
const checked = [];
|
|
98
98
|
for (const script of hookScripts) {
|
|
@@ -644,6 +644,7 @@ export async function doctorChecks(projectRoot, options = {}) {
|
|
|
644
644
|
"run-hook.mjs",
|
|
645
645
|
"run-hook.cmd",
|
|
646
646
|
"stage-complete.mjs",
|
|
647
|
+
"start-flow.mjs",
|
|
647
648
|
"opencode-plugin.mjs"
|
|
648
649
|
]) {
|
|
649
650
|
const scriptPath = path.join(projectRoot, RUNTIME_ROOT, "hooks", script);
|
package/dist/install.js
CHANGED
|
@@ -12,7 +12,7 @@ import { viewCommandContract, viewCommandSkillMarkdown } from "./content/view-co
|
|
|
12
12
|
import { subagentDrivenDevSkill, parallelAgentsSkill } from "./content/subagents.js";
|
|
13
13
|
import { sessionHooksSkillMarkdown } from "./content/session-hooks.js";
|
|
14
14
|
import { ironLawRuntimeDocument, ironLawsSkillMarkdown } from "./content/iron-laws.js";
|
|
15
|
-
import { stageCompleteScript, runHookCmdScript, opencodePluginJs, claudeHooksJson, codexHooksJson, cursorHooksJson } from "./content/hooks.js";
|
|
15
|
+
import { stageCompleteScript, startFlowScript, runHookCmdScript, opencodePluginJs, claudeHooksJson, codexHooksJson, cursorHooksJson } from "./content/hooks.js";
|
|
16
16
|
import { nodeHookRuntimeScript } from "./content/node-hooks.js";
|
|
17
17
|
import { META_SKILL_NAME, usingCclawSkillMarkdown } from "./content/meta-skill.js";
|
|
18
18
|
import { ARTIFACT_TEMPLATES, CURSOR_WORKFLOW_RULE_MDC, RULEBOOK_MARKDOWN, buildRulesJson } from "./content/templates.js";
|
|
@@ -705,6 +705,7 @@ async function writeHooks(projectRoot, config) {
|
|
|
705
705
|
strictLaws: config.ironLaws?.strictLaws
|
|
706
706
|
}), null, 2)}\n`);
|
|
707
707
|
await writeFileSafe(path.join(hooksDir, "stage-complete.mjs"), stageCompleteScript());
|
|
708
|
+
await writeFileSafe(path.join(hooksDir, "start-flow.mjs"), startFlowScript());
|
|
708
709
|
await writeFileSafe(path.join(hooksDir, "run-hook.mjs"), nodeHookRuntimeScript({
|
|
709
710
|
strictness: effectiveStrictness,
|
|
710
711
|
tddTestPathPatterns: config.tdd?.testPathPatterns ?? config.tddTestGlobs,
|
|
@@ -717,6 +718,7 @@ async function writeHooks(projectRoot, config) {
|
|
|
717
718
|
try {
|
|
718
719
|
for (const script of [
|
|
719
720
|
"stage-complete.mjs",
|
|
721
|
+
"start-flow.mjs",
|
|
720
722
|
"run-hook.mjs",
|
|
721
723
|
"run-hook.cmd",
|
|
722
724
|
"opencode-plugin.mjs"
|