cclaw-cli 0.48.7 → 0.48.8
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 +1 -0
- package/dist/content/node-hooks.d.ts +14 -0
- package/dist/content/node-hooks.js +1527 -0
- package/dist/install.js +9 -0
- package/dist/internal/advance-stage.js +53 -2
- package/package.json +1 -1
package/dist/install.js
CHANGED
|
@@ -26,6 +26,7 @@ import { sessionHooksSkillMarkdown } from "./content/session-hooks.js";
|
|
|
26
26
|
import { ironLawRuntimeDocument, ironLawsSkillMarkdown } from "./content/iron-laws.js";
|
|
27
27
|
import { hookLibScript, sessionStartScript, stopCheckpointScript, runHookDispatcherScript, stageCompleteScript, preCompactScript, opencodePluginJs, claudeHooksJson, codexHooksJson, cursorHooksJson } from "./content/hooks.js";
|
|
28
28
|
import { contextMonitorScript, promptGuardScript, workflowGuardScript } from "./content/observe.js";
|
|
29
|
+
import { nodeHookRuntimeScript } from "./content/node-hooks.js";
|
|
29
30
|
import { META_SKILL_NAME, usingCclawSkillMarkdown } from "./content/meta-skill.js";
|
|
30
31
|
import { decisionProtocolMarkdown, completionProtocolMarkdown, ethosProtocolMarkdown } from "./content/protocols.js";
|
|
31
32
|
import { ARTIFACT_TEMPLATES, CURSOR_WORKFLOW_RULE_MDC, RULEBOOK_MARKDOWN, buildRulesJson } from "./content/templates.js";
|
|
@@ -646,6 +647,13 @@ async function writeHooks(projectRoot, config) {
|
|
|
646
647
|
tddProductionPathPatterns: config.tdd?.productionPathPatterns
|
|
647
648
|
}));
|
|
648
649
|
await writeFileSafe(path.join(hooksDir, "context-monitor.sh"), contextMonitorScript());
|
|
650
|
+
await writeFileSafe(path.join(hooksDir, "run-hook.mjs"), nodeHookRuntimeScript({
|
|
651
|
+
promptGuardMode: config.promptGuardMode ?? config.strictness ?? "advisory",
|
|
652
|
+
workflowGuardMode: config.strictness ?? "advisory",
|
|
653
|
+
tddEnforcementMode: config.tddEnforcement ?? config.strictness ?? "advisory",
|
|
654
|
+
tddTestPathPatterns: config.tdd?.testPathPatterns ?? config.tddTestGlobs,
|
|
655
|
+
tddProductionPathPatterns: config.tdd?.productionPathPatterns
|
|
656
|
+
}));
|
|
649
657
|
const opencodePluginSource = opencodePluginJs();
|
|
650
658
|
await writeFileSafe(path.join(hooksDir, "opencode-plugin.mjs"), opencodePluginSource);
|
|
651
659
|
try {
|
|
@@ -659,6 +667,7 @@ async function writeHooks(projectRoot, config) {
|
|
|
659
667
|
"prompt-guard.sh",
|
|
660
668
|
"workflow-guard.sh",
|
|
661
669
|
"context-monitor.sh",
|
|
670
|
+
"run-hook.mjs",
|
|
662
671
|
"opencode-plugin.mjs"
|
|
663
672
|
]) {
|
|
664
673
|
await fs.chmod(path.join(hooksDir, script), 0o755);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
import process from "node:process";
|
|
3
5
|
import { RUNTIME_ROOT, SHIP_FINALIZATION_MODES } from "../constants.js";
|
|
4
6
|
import { stageSchema } from "../content/stage-schema.js";
|
|
5
7
|
import { appendDelegation, checkMandatoryDelegations } from "../delegation.js";
|
|
@@ -306,6 +308,17 @@ function parseVerifyCurrentStateArgs(tokens) {
|
|
|
306
308
|
}
|
|
307
309
|
return { quiet };
|
|
308
310
|
}
|
|
311
|
+
function parseHookArgs(tokens) {
|
|
312
|
+
const [hookName, ...rest] = tokens;
|
|
313
|
+
const normalizedHook = typeof hookName === "string" ? hookName.trim() : "";
|
|
314
|
+
if (normalizedHook.length === 0) {
|
|
315
|
+
throw new Error("internal hook requires a hook name: cclaw internal hook <name>.");
|
|
316
|
+
}
|
|
317
|
+
if (rest.length > 0) {
|
|
318
|
+
throw new Error(`Unknown arguments for internal hook: ${rest.join(" ")}`);
|
|
319
|
+
}
|
|
320
|
+
return { hookName: normalizedHook };
|
|
321
|
+
}
|
|
309
322
|
async function buildValidationReport(projectRoot, flowState) {
|
|
310
323
|
const delegation = await checkMandatoryDelegations(projectRoot, flowState.currentStage);
|
|
311
324
|
const gates = await verifyCurrentStageGateEvidence(projectRoot, flowState);
|
|
@@ -621,10 +634,45 @@ async function runVerifyCurrentState(projectRoot, args, io) {
|
|
|
621
634
|
}
|
|
622
635
|
return validation.ok ? 0 : 1;
|
|
623
636
|
}
|
|
637
|
+
async function runHookCommand(projectRoot, args, io) {
|
|
638
|
+
const runHookPath = path.join(projectRoot, RUNTIME_ROOT, "hooks", "run-hook.mjs");
|
|
639
|
+
try {
|
|
640
|
+
await fs.access(runHookPath);
|
|
641
|
+
}
|
|
642
|
+
catch {
|
|
643
|
+
io.stderr.write(`cclaw internal hook: missing hook runtime at ${runHookPath}. Run \`cclaw sync\` first.\n`);
|
|
644
|
+
return 1;
|
|
645
|
+
}
|
|
646
|
+
return await new Promise((resolve) => {
|
|
647
|
+
const child = spawn(process.execPath, [runHookPath, args.hookName], {
|
|
648
|
+
cwd: projectRoot,
|
|
649
|
+
env: process.env,
|
|
650
|
+
stdio: ["inherit", "pipe", "pipe"]
|
|
651
|
+
});
|
|
652
|
+
child.stdout.on("data", (chunk) => {
|
|
653
|
+
io.stdout.write(chunk);
|
|
654
|
+
});
|
|
655
|
+
child.stderr.on("data", (chunk) => {
|
|
656
|
+
io.stderr.write(chunk);
|
|
657
|
+
});
|
|
658
|
+
child.on("error", (err) => {
|
|
659
|
+
io.stderr.write(`cclaw internal hook: failed to launch runtime (${err instanceof Error ? err.message : String(err)}).\n`);
|
|
660
|
+
resolve(1);
|
|
661
|
+
});
|
|
662
|
+
child.on("close", (code, signal) => {
|
|
663
|
+
if (signal) {
|
|
664
|
+
io.stderr.write(`cclaw internal hook: runtime terminated by signal ${signal}.\n`);
|
|
665
|
+
resolve(1);
|
|
666
|
+
return;
|
|
667
|
+
}
|
|
668
|
+
resolve(typeof code === "number" ? code : 1);
|
|
669
|
+
});
|
|
670
|
+
});
|
|
671
|
+
}
|
|
624
672
|
export async function runInternalCommand(projectRoot, argv, io) {
|
|
625
673
|
const [subcommand, ...tokens] = argv;
|
|
626
674
|
if (!subcommand) {
|
|
627
|
-
io.stderr.write("cclaw internal requires a subcommand: advance-stage | verify-flow-state-diff | verify-current-state | knowledge-digest | envelope-validate | tdd-red-evidence\n");
|
|
675
|
+
io.stderr.write("cclaw internal requires a subcommand: advance-stage | verify-flow-state-diff | verify-current-state | knowledge-digest | envelope-validate | tdd-red-evidence | hook\n");
|
|
628
676
|
return 1;
|
|
629
677
|
}
|
|
630
678
|
try {
|
|
@@ -646,7 +694,10 @@ export async function runInternalCommand(projectRoot, argv, io) {
|
|
|
646
694
|
if (subcommand === "tdd-red-evidence") {
|
|
647
695
|
return await runTddRedEvidenceCommand(projectRoot, tokens, io);
|
|
648
696
|
}
|
|
649
|
-
|
|
697
|
+
if (subcommand === "hook") {
|
|
698
|
+
return await runHookCommand(projectRoot, parseHookArgs(tokens), io);
|
|
699
|
+
}
|
|
700
|
+
io.stderr.write(`Unknown internal subcommand: ${subcommand}. Expected advance-stage | verify-flow-state-diff | verify-current-state | knowledge-digest | envelope-validate | tdd-red-evidence | hook\n`);
|
|
650
701
|
return 1;
|
|
651
702
|
}
|
|
652
703
|
catch (err) {
|