cclaw-cli 1.0.0 → 3.0.0
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/artifact-linter/brainstorm.js +15 -1
- package/dist/artifact-linter/design.js +14 -0
- package/dist/artifact-linter/scope.js +14 -0
- package/dist/artifact-linter/shared.d.ts +1 -0
- package/dist/artifact-linter/shared.js +32 -0
- package/dist/artifact-linter.js +13 -5
- package/dist/cli.js +2 -9
- package/dist/config.d.ts +11 -67
- package/dist/config.js +59 -649
- package/dist/content/hook-events.js +1 -5
- package/dist/content/hook-manifest.d.ts +6 -4
- package/dist/content/hook-manifest.js +16 -65
- package/dist/content/hooks.js +54 -14
- package/dist/content/meta-skill.js +4 -3
- package/dist/content/node-hooks.d.ts +0 -26
- package/dist/content/node-hooks.js +459 -157
- package/dist/content/observe.js +5 -4
- package/dist/content/opencode-plugin.js +1 -78
- package/dist/content/skills-elicitation.d.ts +1 -0
- package/dist/content/skills-elicitation.js +123 -0
- package/dist/content/skills.js +6 -4
- package/dist/content/stages/brainstorm.js +7 -3
- package/dist/content/stages/design.js +6 -2
- package/dist/content/stages/plan.js +2 -2
- package/dist/content/stages/scope.js +9 -5
- package/dist/content/stages/tdd.js +11 -11
- package/dist/content/start-command.js +4 -4
- package/dist/content/templates.js +21 -0
- package/dist/flow-state.d.ts +7 -0
- package/dist/flow-state.js +1 -0
- package/dist/gate-evidence.js +1 -5
- package/dist/hook-schema.js +3 -0
- package/dist/hook-schemas/claude-hooks.v1.json +2 -5
- package/dist/hook-schemas/codex-hooks.v1.json +1 -4
- package/dist/hook-schemas/cursor-hooks.v1.json +1 -3
- package/dist/install.d.ts +2 -7
- package/dist/install.js +32 -123
- package/dist/internal/advance-stage/advance.js +22 -1
- package/dist/internal/advance-stage/parsers.d.ts +1 -0
- package/dist/internal/advance-stage/parsers.js +6 -0
- package/dist/internal/compound-readiness.js +1 -16
- package/dist/internal/early-loop-status.js +1 -3
- package/dist/internal/runtime-integrity.js +0 -20
- package/dist/policy.js +6 -9
- package/dist/run-persistence.d.ts +1 -1
- package/dist/run-persistence.js +29 -2
- package/dist/runtime/run-hook.mjs +459 -265
- package/dist/tdd-verification-evidence.js +6 -18
- package/dist/track-heuristics.d.ts +7 -1
- package/dist/track-heuristics.js +12 -0
- package/dist/types.d.ts +0 -56
- package/package.json +1 -1
|
@@ -8,11 +8,7 @@ export { HOOK_SEMANTIC_EVENTS } from "./hook-manifest.js";
|
|
|
8
8
|
*/
|
|
9
9
|
const OPENCODE_SEMANTIC_COVERAGE = {
|
|
10
10
|
session_rehydrate: "plugin event handlers + transform rehydration",
|
|
11
|
-
|
|
12
|
-
pre_tool_workflow_guard: "plugin tool.execute.before -> workflow-guard",
|
|
13
|
-
post_tool_context_monitor: "plugin tool.execute.after -> context-monitor",
|
|
14
|
-
stop_handoff: "plugin session.idle -> stop-handoff",
|
|
15
|
-
precompact_compat: "plugin session.compacted -> pre-compact"
|
|
11
|
+
stop_handoff: "plugin session.idle -> stop-handoff"
|
|
16
12
|
};
|
|
17
13
|
/**
|
|
18
14
|
* Public semantic coverage map derived from `HOOK_MANIFEST` for
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
*/
|
|
22
22
|
export declare const HOOK_MANIFEST_HARNESSES: readonly ["claude", "cursor", "codex"];
|
|
23
23
|
export type HookManifestHarness = (typeof HOOK_MANIFEST_HARNESSES)[number];
|
|
24
|
-
export declare const HOOK_HANDLERS: readonly ["session-start", "
|
|
24
|
+
export declare const HOOK_HANDLERS: readonly ["session-start", "stop-handoff"];
|
|
25
25
|
export type HookHandlerId = (typeof HOOK_HANDLERS)[number];
|
|
26
26
|
export interface HookBinding {
|
|
27
27
|
/**
|
|
@@ -31,12 +31,13 @@ export interface HookBinding {
|
|
|
31
31
|
event: string;
|
|
32
32
|
matcher?: string;
|
|
33
33
|
timeout?: number;
|
|
34
|
+
/** Optional harness UI status line while this hook runs. */
|
|
35
|
+
statusMessage?: string;
|
|
34
36
|
/**
|
|
35
37
|
* Within a single (harness, event) group, entries are sorted by
|
|
36
38
|
* `priority` ASC, ties broken by manifest-declaration order. Use
|
|
37
39
|
* this to express "this handler must run BEFORE/AFTER that handler
|
|
38
|
-
* on the same event"
|
|
39
|
-
* on cursor `sessionCompact`). Default `0`.
|
|
40
|
+
* on the same event". Default `0`.
|
|
40
41
|
*/
|
|
41
42
|
priority?: number;
|
|
42
43
|
}
|
|
@@ -50,7 +51,7 @@ export interface HookHandlerSpec {
|
|
|
50
51
|
semantic: HookSemanticEvent | null;
|
|
51
52
|
bindings: Partial<Record<HookManifestHarness, HookBinding[]>>;
|
|
52
53
|
}
|
|
53
|
-
export declare const HOOK_SEMANTIC_EVENTS: readonly ["session_rehydrate", "
|
|
54
|
+
export declare const HOOK_SEMANTIC_EVENTS: readonly ["session_rehydrate", "stop_handoff"];
|
|
54
55
|
export type HookSemanticEvent = (typeof HOOK_SEMANTIC_EVENTS)[number];
|
|
55
56
|
export declare const HOOK_MANIFEST: readonly HookHandlerSpec[];
|
|
56
57
|
export interface EventGroup {
|
|
@@ -63,6 +64,7 @@ export interface EventGroup {
|
|
|
63
64
|
handler: HookHandlerId;
|
|
64
65
|
matcher?: string;
|
|
65
66
|
timeout?: number;
|
|
67
|
+
statusMessage?: string;
|
|
66
68
|
}>;
|
|
67
69
|
}
|
|
68
70
|
/**
|
|
@@ -22,26 +22,16 @@
|
|
|
22
22
|
export const HOOK_MANIFEST_HARNESSES = ["claude", "cursor", "codex"];
|
|
23
23
|
export const HOOK_HANDLERS = [
|
|
24
24
|
"session-start",
|
|
25
|
-
"
|
|
26
|
-
"workflow-guard",
|
|
27
|
-
"context-monitor",
|
|
28
|
-
"stop-handoff",
|
|
29
|
-
"pre-compact",
|
|
30
|
-
"verify-current-state"
|
|
25
|
+
"stop-handoff"
|
|
31
26
|
];
|
|
32
27
|
export const HOOK_SEMANTIC_EVENTS = [
|
|
33
28
|
"session_rehydrate",
|
|
34
|
-
"
|
|
35
|
-
"pre_tool_workflow_guard",
|
|
36
|
-
"post_tool_context_monitor",
|
|
37
|
-
"stop_handoff",
|
|
38
|
-
"precompact_compat",
|
|
39
|
-
"strict_state_verify"
|
|
29
|
+
"stop_handoff"
|
|
40
30
|
];
|
|
41
31
|
export const HOOK_MANIFEST = [
|
|
42
32
|
{
|
|
43
33
|
handler: "session-start",
|
|
44
|
-
description: "Rehydrate flow state
|
|
34
|
+
description: "Rehydrate flow state and emit bootstrap digest.",
|
|
45
35
|
semantic: "session_rehydrate",
|
|
46
36
|
bindings: {
|
|
47
37
|
claude: [{ event: "SessionStart", matcher: "startup|resume|clear|compact" }],
|
|
@@ -51,42 +41,15 @@ export const HOOK_MANIFEST = [
|
|
|
51
41
|
{ event: "sessionClear" },
|
|
52
42
|
{ event: "sessionCompact" }
|
|
53
43
|
],
|
|
54
|
-
codex: [{ event: "SessionStart", matcher: "startup|resume" }]
|
|
55
|
-
}
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
handler: "prompt-guard",
|
|
59
|
-
description: "Stage-aware prompt gate (iron-laws + strictness).",
|
|
60
|
-
semantic: "pre_tool_prompt_guard",
|
|
61
|
-
bindings: {
|
|
62
|
-
claude: [{ event: "PreToolUse", matcher: "*" }],
|
|
63
|
-
cursor: [{ event: "preToolUse", matcher: "*" }],
|
|
64
44
|
codex: [
|
|
65
|
-
{
|
|
66
|
-
|
|
45
|
+
{
|
|
46
|
+
event: "SessionStart",
|
|
47
|
+
matcher: "startup|resume",
|
|
48
|
+
statusMessage: "Running cclaw session startup checks"
|
|
49
|
+
}
|
|
67
50
|
]
|
|
68
51
|
}
|
|
69
52
|
},
|
|
70
|
-
{
|
|
71
|
-
handler: "workflow-guard",
|
|
72
|
-
description: "TDD and workflow gate on Write/Edit/Bash style tool invocations.",
|
|
73
|
-
semantic: "pre_tool_workflow_guard",
|
|
74
|
-
bindings: {
|
|
75
|
-
claude: [{ event: "PreToolUse", matcher: "Write|Edit|MultiEdit|NotebookEdit|Bash" }],
|
|
76
|
-
cursor: [{ event: "preToolUse", matcher: "*" }],
|
|
77
|
-
codex: [{ event: "PreToolUse", matcher: "Bash|bash" }]
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
handler: "context-monitor",
|
|
82
|
-
description: "Post-tool context usage + stage signal monitor.",
|
|
83
|
-
semantic: "post_tool_context_monitor",
|
|
84
|
-
bindings: {
|
|
85
|
-
claude: [{ event: "PostToolUse", matcher: "*" }],
|
|
86
|
-
cursor: [{ event: "postToolUse", matcher: "*" }],
|
|
87
|
-
codex: [{ event: "PostToolUse", matcher: "Bash|bash" }]
|
|
88
|
-
}
|
|
89
|
-
},
|
|
90
53
|
{
|
|
91
54
|
handler: "stop-handoff",
|
|
92
55
|
description: "Remind about clean handoff with stage + run context on session stop.",
|
|
@@ -94,26 +57,13 @@ export const HOOK_MANIFEST = [
|
|
|
94
57
|
bindings: {
|
|
95
58
|
claude: [{ event: "Stop", timeout: 10 }],
|
|
96
59
|
cursor: [{ event: "stop", timeout: 10 }],
|
|
97
|
-
codex: [
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
bindings: {
|
|
105
|
-
claude: [{ event: "PreCompact", matcher: "manual|auto", timeout: 10 }],
|
|
106
|
-
// Keep this before session-start on cursor `sessionCompact` so the
|
|
107
|
-
// compatibility handler runs before rehydration.
|
|
108
|
-
cursor: [{ event: "sessionCompact", priority: -10 }]
|
|
109
|
-
}
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
handler: "verify-current-state",
|
|
113
|
-
description: "Supplementary Codex strict-mode guard that runs on UserPromptSubmit to assert the live state matches the flow.",
|
|
114
|
-
semantic: "strict_state_verify",
|
|
115
|
-
bindings: {
|
|
116
|
-
codex: [{ event: "UserPromptSubmit" }]
|
|
60
|
+
codex: [
|
|
61
|
+
{
|
|
62
|
+
event: "Stop",
|
|
63
|
+
timeout: 10,
|
|
64
|
+
statusMessage: "Preparing cclaw handoff checklist"
|
|
65
|
+
}
|
|
66
|
+
]
|
|
117
67
|
}
|
|
118
68
|
}
|
|
119
69
|
];
|
|
@@ -144,6 +94,7 @@ export function groupBindingsByEvent(harness) {
|
|
|
144
94
|
handler: spec.handler,
|
|
145
95
|
...(binding.matcher !== undefined ? { matcher: binding.matcher } : {}),
|
|
146
96
|
...(binding.timeout !== undefined ? { timeout: binding.timeout } : {}),
|
|
97
|
+
...(binding.statusMessage !== undefined ? { statusMessage: binding.statusMessage } : {}),
|
|
147
98
|
priority: binding.priority ?? 0,
|
|
148
99
|
seq: seq++
|
|
149
100
|
});
|
package/dist/content/hooks.js
CHANGED
|
@@ -5,6 +5,15 @@ import { RUNTIME_ROOT } from "../constants.js";
|
|
|
5
5
|
import { DELEGATION_DISPATCH_SURFACES, DELEGATION_DISPATCH_SURFACE_PATH_PREFIXES } from "../delegation.js";
|
|
6
6
|
function resolveCliRuntimeForGeneratedHook() {
|
|
7
7
|
const here = fileURLToPath(import.meta.url);
|
|
8
|
+
// Vitest runs init/sync from src/ and expects helpers to execute the same
|
|
9
|
+
// source runtime, even when a stale dist/ exists in the repository.
|
|
10
|
+
if (process.env.VITEST === "true") {
|
|
11
|
+
const sourceCli = path.resolve(path.dirname(here), "..", "cli.ts");
|
|
12
|
+
const viteNode = path.resolve(path.dirname(here), "..", "..", "node_modules", "vite-node", "vite-node.mjs");
|
|
13
|
+
if (existsSync(sourceCli) && existsSync(viteNode)) {
|
|
14
|
+
return { entrypoint: viteNode, argsPrefix: ["--script", sourceCli] };
|
|
15
|
+
}
|
|
16
|
+
}
|
|
8
17
|
const candidates = [
|
|
9
18
|
path.resolve(path.dirname(here), "..", "cli.js"),
|
|
10
19
|
path.resolve(path.dirname(here), "..", "..", "dist", "cli.js")
|
|
@@ -15,15 +24,6 @@ function resolveCliRuntimeForGeneratedHook() {
|
|
|
15
24
|
if (existsSync(candidate))
|
|
16
25
|
return { entrypoint: candidate, argsPrefix: [] };
|
|
17
26
|
}
|
|
18
|
-
// Vitest exercises init/sync directly from src/ without a compiled dist/.
|
|
19
|
-
// Route that dev-only shape through vite-node so hooks still prove a local runtime.
|
|
20
|
-
if (process.env.VITEST === "true") {
|
|
21
|
-
const sourceCli = path.resolve(path.dirname(here), "..", "cli.ts");
|
|
22
|
-
const viteNode = path.resolve(path.dirname(here), "..", "..", "node_modules", "vite-node", "vite-node.mjs");
|
|
23
|
-
if (existsSync(sourceCli) && existsSync(viteNode)) {
|
|
24
|
-
return { entrypoint: viteNode, argsPrefix: ["--script", sourceCli] };
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
27
|
return { entrypoint: null, argsPrefix: [] };
|
|
28
28
|
}
|
|
29
29
|
function internalHelperScript(helperName, internalSubcommand, usage, options) {
|
|
@@ -42,6 +42,7 @@ const INTERNAL_SUBCOMMAND = ${JSON.stringify(internalSubcommand)};
|
|
|
42
42
|
const USAGE = ${JSON.stringify(usage)};
|
|
43
43
|
const POSITIONAL_ARG_NAME = ${JSON.stringify(options?.positionalArgName ?? null)};
|
|
44
44
|
const POSITIONAL_ARG_REQUIRED = ${JSON.stringify(options?.positionalArgRequired === true)};
|
|
45
|
+
const DEFAULT_QUIET_ENV_VAR = ${JSON.stringify(options?.defaultQuietEnvVar ?? null)};
|
|
45
46
|
|
|
46
47
|
async function detectRoot() {
|
|
47
48
|
const candidates = [
|
|
@@ -88,6 +89,19 @@ async function main() {
|
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
91
|
|
|
92
|
+
if (DEFAULT_QUIET_ENV_VAR !== null) {
|
|
93
|
+
const envRaw = process.env[DEFAULT_QUIET_ENV_VAR];
|
|
94
|
+
if (typeof envRaw !== "string" || envRaw.trim().length === 0) {
|
|
95
|
+
process.env[DEFAULT_QUIET_ENV_VAR] = "1";
|
|
96
|
+
}
|
|
97
|
+
const quietRaw = (process.env[DEFAULT_QUIET_ENV_VAR] ?? "").trim().toLowerCase();
|
|
98
|
+
const quietEnabled = !/^(0|false|no|off)$/u.test(quietRaw);
|
|
99
|
+
const alreadyQuiet = flags.includes("--quiet");
|
|
100
|
+
if (quietEnabled && !alreadyQuiet) {
|
|
101
|
+
flags = [...flags, "--quiet"];
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
91
105
|
const root = await detectRoot();
|
|
92
106
|
const runtimePath = path.join(root, RUNTIME_ROOT);
|
|
93
107
|
try {
|
|
@@ -171,13 +185,13 @@ void main();
|
|
|
171
185
|
`;
|
|
172
186
|
}
|
|
173
187
|
export function startFlowScript() {
|
|
174
|
-
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]");
|
|
188
|
+
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]", { defaultQuietEnvVar: "CCLAW_START_FLOW_QUIET" });
|
|
175
189
|
}
|
|
176
190
|
export function cancelRunScript() {
|
|
177
191
|
return internalHelperScript("cancel-run", "cancel-run", "Usage: node " + RUNTIME_ROOT + "/hooks/cancel-run.mjs --reason=<text> [--disposition=<cancelled|abandoned>] [--name=<slug>]");
|
|
178
192
|
}
|
|
179
193
|
export function stageCompleteScript() {
|
|
180
|
-
return internalHelperScript("stage-complete", "advance-stage", "Usage: node " + RUNTIME_ROOT + "/hooks/stage-complete.mjs <stage> [--passed=...] [--evidence-json=...] [--waive-delegation=...] [--waiver-reason=...] [--accept-proactive-waiver] [--accept-proactive-waiver-reason=...] [--json]", {
|
|
194
|
+
return internalHelperScript("stage-complete", "advance-stage", "Usage: node " + RUNTIME_ROOT + "/hooks/stage-complete.mjs <stage> [--passed=...] [--evidence-json=...] [--waive-delegation=...] [--waiver-reason=...] [--accept-proactive-waiver] [--accept-proactive-waiver-reason=...] [--skip-questions] [--json]", {
|
|
181
195
|
positionalArgName: "stage",
|
|
182
196
|
positionalArgRequired: true
|
|
183
197
|
});
|
|
@@ -280,7 +294,7 @@ function usage() {
|
|
|
280
294
|
process.stderr.write([
|
|
281
295
|
"Usage:",
|
|
282
296
|
" node .cclaw/hooks/delegation-record.mjs --stage=<stage> --agent=<agent> --mode=<mandatory|proactive> --status=<scheduled|launched|acknowledged|completed|failed|waived|stale> --span-id=<id> [--dispatch-id=<id>] [--worker-run-id=<id>] [--dispatch-surface=<surface>] [--agent-definition-path=<path>] [--ack-ts=<iso>] [--launched-ts=<iso>] [--completed-ts=<iso>] [--evidence-ref=<ref>] [--waiver-reason=<text>] [--json]",
|
|
283
|
-
" node .cclaw/hooks/delegation-record.mjs --rerecord --span-id=<id> --dispatch-id=<id> --dispatch-surface=<surface> --agent-definition-path=<path> [--ack-ts=<iso>] [--completed-ts=<iso>] [--json]",
|
|
297
|
+
" node .cclaw/hooks/delegation-record.mjs --rerecord --span-id=<id> --dispatch-id=<id> --dispatch-surface=<surface> --agent-definition-path=<path> [--ack-ts=<iso>] [--completed-ts=<iso>] [--evidence-ref=<ref>] [--json]",
|
|
284
298
|
"",
|
|
285
299
|
"Allowed --dispatch-surface values:",
|
|
286
300
|
" " + VALID_DISPATCH_SURFACES.join(", "),
|
|
@@ -322,6 +336,18 @@ async function pathExists(filePath) {
|
|
|
322
336
|
}
|
|
323
337
|
}
|
|
324
338
|
|
|
339
|
+
function normalizeEvidenceRefs(args) {
|
|
340
|
+
if (Array.isArray(args["evidence-refs"])) {
|
|
341
|
+
return args["evidence-refs"]
|
|
342
|
+
.filter((ref) => typeof ref === "string" && ref.trim().length > 0)
|
|
343
|
+
.map((ref) => ref.trim());
|
|
344
|
+
}
|
|
345
|
+
if (typeof args["evidence-ref"] === "string" && args["evidence-ref"].trim().length > 0) {
|
|
346
|
+
return [args["evidence-ref"].trim()];
|
|
347
|
+
}
|
|
348
|
+
return [];
|
|
349
|
+
}
|
|
350
|
+
|
|
325
351
|
function buildRow(args, status, runId, now) {
|
|
326
352
|
const fulfillmentMode = args["dispatch-surface"] === "role-switch"
|
|
327
353
|
? "role-switch"
|
|
@@ -340,7 +366,7 @@ function buildRow(args, status, runId, now) {
|
|
|
340
366
|
agentDefinitionPath: args["agent-definition-path"],
|
|
341
367
|
fulfillmentMode,
|
|
342
368
|
waiverReason: args["waiver-reason"],
|
|
343
|
-
evidenceRefs: args
|
|
369
|
+
evidenceRefs: normalizeEvidenceRefs(args),
|
|
344
370
|
runId,
|
|
345
371
|
startTs: now,
|
|
346
372
|
ts: now,
|
|
@@ -420,6 +446,18 @@ async function runRerecord(args, json) {
|
|
|
420
446
|
emitProblems(["no legacy ledger entry found for --span-id=" + args["span-id"]], json, 1);
|
|
421
447
|
return;
|
|
422
448
|
}
|
|
449
|
+
const explicitEvidenceRef =
|
|
450
|
+
typeof args["evidence-ref"] === "string" && args["evidence-ref"].trim().length > 0
|
|
451
|
+
? args["evidence-ref"].trim()
|
|
452
|
+
: "";
|
|
453
|
+
const legacyEvidenceRefs = Array.isArray(legacyEntry.evidenceRefs)
|
|
454
|
+
? legacyEntry.evidenceRefs
|
|
455
|
+
.filter((ref) => typeof ref === "string" && ref.trim().length > 0)
|
|
456
|
+
.map((ref) => ref.trim())
|
|
457
|
+
: [];
|
|
458
|
+
const mergedEvidenceRefs = explicitEvidenceRef.length > 0
|
|
459
|
+
? [explicitEvidenceRef]
|
|
460
|
+
: legacyEvidenceRefs;
|
|
423
461
|
if (args["dispatch-surface"] !== "role-switch") {
|
|
424
462
|
if (!dispatchSurfaceMatchesPath(args["dispatch-surface"], args["agent-definition-path"])) {
|
|
425
463
|
const allowedPrefixes = SURFACE_PATH_PREFIXES[args["dispatch-surface"]];
|
|
@@ -445,7 +483,9 @@ async function runRerecord(args, json) {
|
|
|
445
483
|
"agent-definition-path": args["agent-definition-path"],
|
|
446
484
|
"ack-ts": args["ack-ts"] || legacyEntry.ackTs || now,
|
|
447
485
|
"completed-ts": args["completed-ts"] || legacyEntry.completedTs || now,
|
|
448
|
-
"launched-ts": args["launched-ts"] || legacyEntry.launchedTs || now
|
|
486
|
+
"launched-ts": args["launched-ts"] || legacyEntry.launchedTs || now,
|
|
487
|
+
"evidence-ref": explicitEvidenceRef.length > 0 ? explicitEvidenceRef : undefined,
|
|
488
|
+
"evidence-refs": mergedEvidenceRefs
|
|
449
489
|
};
|
|
450
490
|
const status = "completed";
|
|
451
491
|
const clean = Object.fromEntries(Object.entries(buildRow(merged, status, runId, now)).filter(([, value]) => value !== undefined));
|
|
@@ -44,9 +44,10 @@ Substantive vs. non-substantive:
|
|
|
44
44
|
- **Non-substantive** (skill load optional): one-line acknowledgement,
|
|
45
45
|
clarifying a typo, confirming a prior answer, pure conversation.
|
|
46
46
|
|
|
47
|
-
If
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
If \`.cclaw/state/flow-state.json\` is missing, treat it as a normal fresh-init
|
|
48
|
+
state and route through \`/cc <idea>\` to start the first tracked run.
|
|
49
|
+
If the file exists but is corrupt/unreadable, stop and route through \`/cc\`
|
|
50
|
+
before any substantive response.
|
|
50
51
|
|
|
51
52
|
## Red Flags (stop and re-route)
|
|
52
53
|
|
|
@@ -1,30 +1,4 @@
|
|
|
1
1
|
export interface NodeHookRuntimeOptions {
|
|
2
|
-
/**
|
|
3
|
-
* Single enforcement knob derived from `config.strictness`. Generated hooks
|
|
4
|
-
* embed this value as the default for every guard (prompt, workflow, TDD,
|
|
5
|
-
* iron-laws-coupled blocks). `CCLAW_STRICTNESS` env var overrides at run
|
|
6
|
-
* time; per-law strictness still flows through `iron-laws.json`.
|
|
7
|
-
*/
|
|
8
|
-
strictness?: "advisory" | "strict";
|
|
9
|
-
tddTestPathPatterns?: string[];
|
|
10
|
-
tddProductionPathPatterns?: string[];
|
|
11
|
-
/**
|
|
12
|
-
* Baked-in default recurrence threshold for compound-readiness computed
|
|
13
|
-
* by the session-start hook. Derived from
|
|
14
|
-
* `config.compound.recurrenceThreshold` at install time; re-run
|
|
15
|
-
* `cclaw sync` after changing the config value so hook and CLI agree.
|
|
16
|
-
*/
|
|
17
|
-
compoundRecurrenceThreshold?: number;
|
|
18
|
-
/**
|
|
19
|
-
* Enables early-stage producer/critic loop diagnostics in session-start.
|
|
20
|
-
* Defaults to true.
|
|
21
|
-
*/
|
|
22
|
-
earlyLoopEnabled?: boolean;
|
|
23
|
-
/**
|
|
24
|
-
* Baked-in max iterations for brainstorm/scope/design early-loop status.
|
|
25
|
-
* Derived from `config.earlyLoop.maxIterations`.
|
|
26
|
-
*/
|
|
27
|
-
earlyLoopMaxIterations?: number;
|
|
28
2
|
}
|
|
29
3
|
/**
|
|
30
4
|
* Node-only hook runtime (single entrypoint).
|