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/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
- io.stderr.write(`Unknown internal subcommand: ${subcommand}. Expected advance-stage | verify-flow-state-diff | verify-current-state | knowledge-digest | envelope-validate | tdd-red-evidence\n`);
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cclaw-cli",
3
- "version": "0.48.7",
3
+ "version": "0.48.8",
4
4
  "description": "Installer-first flow toolkit for coding agents",
5
5
  "type": "module",
6
6
  "bin": {