cclaw-cli 0.46.2 → 0.46.4
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 +50 -0
- package/dist/content/observe.d.ts +0 -3
- package/dist/content/observe.js +24 -21
- package/dist/content/stage-schema.js +1 -1
- package/dist/content/stages/tdd.js +5 -0
- package/dist/doctor.js +1 -0
- package/dist/install.js +5 -2
- package/dist/internal/advance-stage.js +34 -0
- package/package.json +1 -1
package/dist/content/hooks.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export interface HookRuntimeOptions {
|
|
|
11
11
|
export declare const RUNTIME_SHELL_DETECT_ROOT = "HARNESS=\"codex\"\nif [ -n \"${CLAUDE_PROJECT_DIR:-}\" ]; then\n HARNESS=\"claude\"\nelif [ -n \"${CURSOR_PROJECT_DIR:-}\" ] || [ -n \"${CURSOR_PROJECT_ROOT:-}\" ]; then\n HARNESS=\"cursor\"\nelif [ -n \"${OPENCODE_PROJECT_DIR:-}\" ] || [ -n \"${OPENCODE_PROJECT_ROOT:-}\" ]; then\n HARNESS=\"opencode\"\nfi\n\nROOT=\"\"\nfor candidate in \"${CCLAW_PROJECT_ROOT:-}\" \"${CLAUDE_PROJECT_DIR:-}\" \"${CURSOR_PROJECT_DIR:-}\" \"${CURSOR_PROJECT_ROOT:-}\" \"${OPENCODE_PROJECT_DIR:-}\" \"${OPENCODE_PROJECT_ROOT:-}\" \"${PWD:-}\"; do\n if [ -n \"$candidate\" ] && [ -d \"$candidate/.cclaw\" ]; then\n ROOT=\"$candidate\"\n break\n fi\ndone\nif [ -z \"$ROOT\" ]; then\n ROOT=\"${CCLAW_PROJECT_ROOT:-${CLAUDE_PROJECT_DIR:-${CURSOR_PROJECT_DIR:-${CURSOR_PROJECT_ROOT:-${OPENCODE_PROJECT_DIR:-${OPENCODE_PROJECT_ROOT:-${PWD}}}}}}}\"\nfi";
|
|
12
12
|
export declare function sessionStartScript(_options?: HookRuntimeOptions): string;
|
|
13
13
|
export declare function stopCheckpointScript(): string;
|
|
14
|
+
export declare function runHookDispatcherScript(): string;
|
|
14
15
|
export declare function stageCompleteScript(): string;
|
|
15
16
|
export declare function preCompactScript(): string;
|
|
16
17
|
export { claudeHooksJsonWithObservation as claudeHooksJson } from "./observe.js";
|
package/dist/content/hooks.js
CHANGED
|
@@ -769,6 +769,56 @@ case "$HARNESS" in
|
|
|
769
769
|
esac
|
|
770
770
|
`;
|
|
771
771
|
}
|
|
772
|
+
export function runHookDispatcherScript() {
|
|
773
|
+
return `#!/usr/bin/env bash
|
|
774
|
+
# cclaw hook dispatcher — generated by cclaw sync
|
|
775
|
+
# Single entrypoint used by harness hook JSON wiring.
|
|
776
|
+
set -euo pipefail
|
|
777
|
+
|
|
778
|
+
${DETECT_ROOT}
|
|
779
|
+
|
|
780
|
+
if [ "$#" -lt 1 ]; then
|
|
781
|
+
printf 'Usage: bash ${RUNTIME_ROOT}/hooks/run-hook.cmd <session-start|stop-checkpoint|pre-compact|prompt-guard|workflow-guard|context-monitor>\\n' >&2
|
|
782
|
+
exit 1
|
|
783
|
+
fi
|
|
784
|
+
|
|
785
|
+
HOOK_NAME="$1"
|
|
786
|
+
shift || true
|
|
787
|
+
|
|
788
|
+
case "$HOOK_NAME" in
|
|
789
|
+
session-start|session-start.sh)
|
|
790
|
+
HOOK_FILE="session-start.sh"
|
|
791
|
+
;;
|
|
792
|
+
stop-checkpoint|stop-checkpoint.sh)
|
|
793
|
+
HOOK_FILE="stop-checkpoint.sh"
|
|
794
|
+
;;
|
|
795
|
+
pre-compact|pre-compact.sh)
|
|
796
|
+
HOOK_FILE="pre-compact.sh"
|
|
797
|
+
;;
|
|
798
|
+
prompt-guard|prompt-guard.sh)
|
|
799
|
+
HOOK_FILE="prompt-guard.sh"
|
|
800
|
+
;;
|
|
801
|
+
workflow-guard|workflow-guard.sh)
|
|
802
|
+
HOOK_FILE="workflow-guard.sh"
|
|
803
|
+
;;
|
|
804
|
+
context-monitor|context-monitor.sh)
|
|
805
|
+
HOOK_FILE="context-monitor.sh"
|
|
806
|
+
;;
|
|
807
|
+
*)
|
|
808
|
+
printf '[cclaw] run-hook: unsupported hook "%s".\\n' "$HOOK_NAME" >&2
|
|
809
|
+
exit 1
|
|
810
|
+
;;
|
|
811
|
+
esac
|
|
812
|
+
|
|
813
|
+
HOOK_PATH="$ROOT/${RUNTIME_ROOT}/hooks/$HOOK_FILE"
|
|
814
|
+
if [ ! -f "$HOOK_PATH" ]; then
|
|
815
|
+
printf '[cclaw] run-hook: hook script not found at %s\\n' "$HOOK_PATH" >&2
|
|
816
|
+
exit 1
|
|
817
|
+
fi
|
|
818
|
+
|
|
819
|
+
exec bash "$HOOK_PATH" "$@"
|
|
820
|
+
`;
|
|
821
|
+
}
|
|
772
822
|
export function stageCompleteScript() {
|
|
773
823
|
return `#!/usr/bin/env bash
|
|
774
824
|
# cclaw stage-complete helper — generated by cclaw sync
|
|
@@ -19,9 +19,6 @@ export declare function observeScript(): string;
|
|
|
19
19
|
export declare function contextMonitorScript(): string;
|
|
20
20
|
export declare function summarizeObservationsRuntimeModule(): string;
|
|
21
21
|
export declare function summarizeObservationsScript(): string;
|
|
22
|
-
/**
|
|
23
|
-
* Updated hooks.json generators with PreToolUse/PostToolUse observation.
|
|
24
|
-
*/
|
|
25
22
|
export declare function claudeHooksJsonWithObservation(): string;
|
|
26
23
|
export declare function cursorHooksJsonWithObservation(): string;
|
|
27
24
|
/**
|
package/dist/content/observe.js
CHANGED
|
@@ -1808,6 +1808,9 @@ exit 0
|
|
|
1808
1808
|
/**
|
|
1809
1809
|
* Updated hooks.json generators with PreToolUse/PostToolUse observation.
|
|
1810
1810
|
*/
|
|
1811
|
+
function hookDispatcherCommand(scriptName) {
|
|
1812
|
+
return `bash ${RUNTIME_ROOT}/hooks/run-hook.cmd ${scriptName}`;
|
|
1813
|
+
}
|
|
1811
1814
|
export function claudeHooksJsonWithObservation() {
|
|
1812
1815
|
return JSON.stringify({
|
|
1813
1816
|
cclawHookSchemaVersion: 1,
|
|
@@ -1816,30 +1819,30 @@ export function claudeHooksJsonWithObservation() {
|
|
|
1816
1819
|
matcher: "startup|resume|clear|compact",
|
|
1817
1820
|
hooks: [{
|
|
1818
1821
|
type: "command",
|
|
1819
|
-
command:
|
|
1822
|
+
command: hookDispatcherCommand("session-start.sh")
|
|
1820
1823
|
}]
|
|
1821
1824
|
}],
|
|
1822
1825
|
PreToolUse: [{
|
|
1823
1826
|
matcher: "*",
|
|
1824
1827
|
hooks: [{
|
|
1825
1828
|
type: "command",
|
|
1826
|
-
command:
|
|
1829
|
+
command: hookDispatcherCommand("prompt-guard.sh")
|
|
1827
1830
|
}, {
|
|
1828
1831
|
type: "command",
|
|
1829
|
-
command:
|
|
1832
|
+
command: hookDispatcherCommand("workflow-guard.sh")
|
|
1830
1833
|
}]
|
|
1831
1834
|
}],
|
|
1832
1835
|
PostToolUse: [{
|
|
1833
1836
|
matcher: "*",
|
|
1834
1837
|
hooks: [{
|
|
1835
1838
|
type: "command",
|
|
1836
|
-
command:
|
|
1839
|
+
command: hookDispatcherCommand("context-monitor.sh")
|
|
1837
1840
|
}]
|
|
1838
1841
|
}],
|
|
1839
1842
|
Stop: [{
|
|
1840
1843
|
hooks: [{
|
|
1841
1844
|
type: "command",
|
|
1842
|
-
command:
|
|
1845
|
+
command: hookDispatcherCommand("stop-checkpoint.sh"),
|
|
1843
1846
|
timeout: 10
|
|
1844
1847
|
}]
|
|
1845
1848
|
}],
|
|
@@ -1847,7 +1850,7 @@ export function claudeHooksJsonWithObservation() {
|
|
|
1847
1850
|
matcher: "manual|auto",
|
|
1848
1851
|
hooks: [{
|
|
1849
1852
|
type: "command",
|
|
1850
|
-
command:
|
|
1853
|
+
command: hookDispatcherCommand("pre-compact.sh"),
|
|
1851
1854
|
timeout: 10
|
|
1852
1855
|
}]
|
|
1853
1856
|
}]
|
|
@@ -1860,31 +1863,31 @@ export function cursorHooksJsonWithObservation() {
|
|
|
1860
1863
|
version: 1,
|
|
1861
1864
|
hooks: {
|
|
1862
1865
|
sessionStart: [{
|
|
1863
|
-
command:
|
|
1866
|
+
command: hookDispatcherCommand("session-start.sh")
|
|
1864
1867
|
}],
|
|
1865
1868
|
sessionResume: [{
|
|
1866
|
-
command:
|
|
1869
|
+
command: hookDispatcherCommand("session-start.sh")
|
|
1867
1870
|
}],
|
|
1868
1871
|
sessionClear: [{
|
|
1869
|
-
command:
|
|
1872
|
+
command: hookDispatcherCommand("session-start.sh")
|
|
1870
1873
|
}],
|
|
1871
1874
|
sessionCompact: [{
|
|
1872
|
-
command:
|
|
1875
|
+
command: hookDispatcherCommand("pre-compact.sh")
|
|
1873
1876
|
}, {
|
|
1874
|
-
command:
|
|
1877
|
+
command: hookDispatcherCommand("session-start.sh")
|
|
1875
1878
|
}],
|
|
1876
1879
|
preToolUse: [{
|
|
1877
1880
|
matcher: "*",
|
|
1878
|
-
command:
|
|
1881
|
+
command: hookDispatcherCommand("prompt-guard.sh")
|
|
1879
1882
|
}, {
|
|
1880
1883
|
matcher: "*",
|
|
1881
|
-
command:
|
|
1884
|
+
command: hookDispatcherCommand("workflow-guard.sh")
|
|
1882
1885
|
}],
|
|
1883
1886
|
postToolUse: [{
|
|
1884
1887
|
matcher: "*",
|
|
1885
|
-
command:
|
|
1888
|
+
command: hookDispatcherCommand("context-monitor.sh")
|
|
1886
1889
|
}],
|
|
1887
|
-
stop: [{ command:
|
|
1890
|
+
stop: [{ command: hookDispatcherCommand("stop-checkpoint.sh"), timeout: 10 }]
|
|
1888
1891
|
}
|
|
1889
1892
|
}, null, 2);
|
|
1890
1893
|
}
|
|
@@ -1915,13 +1918,13 @@ export function codexHooksJsonWithObservation() {
|
|
|
1915
1918
|
matcher: "startup|resume",
|
|
1916
1919
|
hooks: [{
|
|
1917
1920
|
type: "command",
|
|
1918
|
-
command:
|
|
1921
|
+
command: hookDispatcherCommand("session-start.sh")
|
|
1919
1922
|
}]
|
|
1920
1923
|
}],
|
|
1921
1924
|
UserPromptSubmit: [{
|
|
1922
1925
|
hooks: [{
|
|
1923
1926
|
type: "command",
|
|
1924
|
-
command:
|
|
1927
|
+
command: hookDispatcherCommand("prompt-guard.sh")
|
|
1925
1928
|
}, {
|
|
1926
1929
|
type: "command",
|
|
1927
1930
|
command: "bash -lc 'if command -v cclaw >/dev/null 2>&1; then cclaw internal verify-current-state --quiet >/dev/null || true; else npx -y cclaw-cli internal verify-current-state --quiet >/dev/null || true; fi'"
|
|
@@ -1931,23 +1934,23 @@ export function codexHooksJsonWithObservation() {
|
|
|
1931
1934
|
matcher: "Bash",
|
|
1932
1935
|
hooks: [{
|
|
1933
1936
|
type: "command",
|
|
1934
|
-
command:
|
|
1937
|
+
command: hookDispatcherCommand("prompt-guard.sh")
|
|
1935
1938
|
}, {
|
|
1936
1939
|
type: "command",
|
|
1937
|
-
command:
|
|
1940
|
+
command: hookDispatcherCommand("workflow-guard.sh")
|
|
1938
1941
|
}]
|
|
1939
1942
|
}],
|
|
1940
1943
|
PostToolUse: [{
|
|
1941
1944
|
matcher: "Bash",
|
|
1942
1945
|
hooks: [{
|
|
1943
1946
|
type: "command",
|
|
1944
|
-
command:
|
|
1947
|
+
command: hookDispatcherCommand("context-monitor.sh")
|
|
1945
1948
|
}]
|
|
1946
1949
|
}],
|
|
1947
1950
|
Stop: [{
|
|
1948
1951
|
hooks: [{
|
|
1949
1952
|
type: "command",
|
|
1950
|
-
command:
|
|
1953
|
+
command: hookDispatcherCommand("stop-checkpoint.sh"),
|
|
1951
1954
|
timeout: 10
|
|
1952
1955
|
}]
|
|
1953
1956
|
}]
|
|
@@ -27,6 +27,7 @@ export const TDD = {
|
|
|
27
27
|
"Dispatch `test-author` subagent in `BUILD_GREEN_REFACTOR` mode — minimal implementation + full-suite GREEN + refactor notes.",
|
|
28
28
|
"GREEN: Run full suite — execute ALL tests, not just the ones you wrote. The full suite must be GREEN.",
|
|
29
29
|
"GREEN: Verify no regressions — if any existing test breaks, fix the regression before proceeding.",
|
|
30
|
+
"Run verification-before-completion discipline for the slice — capture a fresh test command, commit SHA, and explicit PASS/FAIL status before completion claims.",
|
|
30
31
|
"REFACTOR: Improve code quality — without changing behavior. Document what you changed and why.",
|
|
31
32
|
"Record evidence — capture RED failure, GREEN output, and REFACTOR notes in the TDD artifact.",
|
|
32
33
|
"Annotate traceability — link to plan task ID and spec criterion.",
|
|
@@ -40,6 +41,7 @@ export const TDD = {
|
|
|
40
41
|
"Capture and store failing output as RED evidence.",
|
|
41
42
|
"Apply minimal change to satisfy RED tests (GREEN).",
|
|
42
43
|
"Run full suite, not partial checks, for GREEN validation.",
|
|
44
|
+
"Before declaring the slice complete, run a fresh verification check and record command + commit SHA + PASS/FAIL.",
|
|
43
45
|
"Refactor without changing behavior and document rationale (REFACTOR).",
|
|
44
46
|
"Stop if regressions appear and fix before proceeding.",
|
|
45
47
|
"If a test passes unexpectedly, investigate: does the behavior already exist, or is the test wrong?",
|
|
@@ -51,6 +53,7 @@ export const TDD = {
|
|
|
51
53
|
"Run tests and capture failure output.",
|
|
52
54
|
"Dispatch `test-author` in BUILD_GREEN_REFACTOR mode and implement smallest change needed for GREEN.",
|
|
53
55
|
"Run full tests and build checks.",
|
|
56
|
+
"Run a fresh verification-before-completion check and capture command + commit SHA + PASS/FAIL in guard evidence.",
|
|
54
57
|
"Perform refactor pass preserving behavior.",
|
|
55
58
|
"Record RED, GREEN, and REFACTOR evidence in artifact.",
|
|
56
59
|
"Annotate traceability to plan task and spec criterion; on `sliceReview` triggers, append a Per-Slice Review entry before closing the slice."
|
|
@@ -59,12 +62,14 @@ export const TDD = {
|
|
|
59
62
|
{ id: "tdd_red_test_written", description: "Failing tests exist before implementation changes." },
|
|
60
63
|
{ id: "tdd_green_full_suite", description: "Full relevant suite passes in GREEN state." },
|
|
61
64
|
{ id: "tdd_refactor_completed", description: "Refactor pass completed with behavior preservation verified." },
|
|
65
|
+
{ id: "tdd_verified_before_complete", description: "Fresh verification evidence includes test command, commit SHA, and explicit pass/fail status." },
|
|
62
66
|
{ id: "tdd_traceable_to_plan", description: "Change traceability to plan slice is explicit." }
|
|
63
67
|
],
|
|
64
68
|
requiredEvidence: [
|
|
65
69
|
"Artifact updated at `.cclaw/artifacts/06-tdd.md` with RED, GREEN, and REFACTOR sections.",
|
|
66
70
|
"Failing command output captured (RED).",
|
|
67
71
|
"Full test/build output recorded (GREEN).",
|
|
72
|
+
"Fresh verification evidence recorded with command, commit SHA, and PASS/FAIL status before completion.",
|
|
68
73
|
"Acceptance mapping documented.",
|
|
69
74
|
"Failure reason analysis recorded.",
|
|
70
75
|
"Refactor rationale captured.",
|
package/dist/doctor.js
CHANGED
package/dist/install.js
CHANGED
|
@@ -23,7 +23,7 @@ import { archiveCommandContract, archiveCommandSkillMarkdown } from "./content/a
|
|
|
23
23
|
import { rewindCommandContract, rewindCommandSkillMarkdown } from "./content/rewind-command.js";
|
|
24
24
|
import { subagentDrivenDevSkill, parallelAgentsSkill } from "./content/subagents.js";
|
|
25
25
|
import { sessionHooksSkillMarkdown } from "./content/session-hooks.js";
|
|
26
|
-
import { sessionStartScript, stopCheckpointScript, stageCompleteScript, preCompactScript, opencodePluginJs, claudeHooksJson, codexHooksJson, cursorHooksJson } from "./content/hooks.js";
|
|
26
|
+
import { sessionStartScript, stopCheckpointScript, runHookDispatcherScript, stageCompleteScript, preCompactScript, opencodePluginJs, claudeHooksJson, codexHooksJson, cursorHooksJson } from "./content/hooks.js";
|
|
27
27
|
import { contextMonitorScript, promptGuardScript, workflowGuardScript } from "./content/observe.js";
|
|
28
28
|
import { META_SKILL_NAME, usingCclawSkillMarkdown } from "./content/meta-skill.js";
|
|
29
29
|
import { decisionProtocolMarkdown, completionProtocolMarkdown, ethosProtocolMarkdown } from "./content/protocols.js";
|
|
@@ -616,6 +616,7 @@ async function writeHooks(projectRoot, config) {
|
|
|
616
616
|
await ensureDir(hooksDir);
|
|
617
617
|
await writeFileSafe(path.join(hooksDir, "session-start.sh"), sessionStartScript());
|
|
618
618
|
await writeFileSafe(path.join(hooksDir, "stop-checkpoint.sh"), stopCheckpointScript());
|
|
619
|
+
await writeFileSafe(path.join(hooksDir, "run-hook.cmd"), runHookDispatcherScript());
|
|
619
620
|
await writeFileSafe(path.join(hooksDir, "stage-complete.sh"), stageCompleteScript());
|
|
620
621
|
await writeFileSafe(path.join(hooksDir, "pre-compact.sh"), preCompactScript());
|
|
621
622
|
await writeFileSafe(path.join(hooksDir, "prompt-guard.sh"), promptGuardScript({
|
|
@@ -633,6 +634,7 @@ async function writeHooks(projectRoot, config) {
|
|
|
633
634
|
for (const script of [
|
|
634
635
|
"session-start.sh",
|
|
635
636
|
"stop-checkpoint.sh",
|
|
637
|
+
"run-hook.cmd",
|
|
636
638
|
"stage-complete.sh",
|
|
637
639
|
"pre-compact.sh",
|
|
638
640
|
"prompt-guard.sh",
|
|
@@ -1263,7 +1265,8 @@ function stripManagedHookCommands(value) {
|
|
|
1263
1265
|
}
|
|
1264
1266
|
function isManagedRuntimeHookCommand(command) {
|
|
1265
1267
|
const normalized = command.trim().replace(/\s+/gu, " ");
|
|
1266
|
-
if (/(^|\s)(?:bash\s+)?(?:\.\/)?\.cclaw\/hooks\/(?:session-start|stop-checkpoint|pre-compact|prompt-guard|workflow-guard|context-monitor)\.sh(?:\s|$)/u.test(normalized)
|
|
1268
|
+
if (/(^|\s)(?:bash\s+)?(?:\.\/)?\.cclaw\/hooks\/(?:session-start|stop-checkpoint|pre-compact|prompt-guard|workflow-guard|context-monitor)\.sh(?:\s|$)/u.test(normalized) ||
|
|
1269
|
+
/(^|\s)(?:bash\s+)?(?:\.\/)?\.cclaw\/hooks\/run-hook\.cmd\s+(?:session-start|stop-checkpoint|pre-compact|prompt-guard|workflow-guard|context-monitor)(?:\.sh)?(?:\s|$)/u.test(normalized)) {
|
|
1267
1270
|
return true;
|
|
1268
1271
|
}
|
|
1269
1272
|
// Codex UserPromptSubmit non-blocking state nudge:
|
|
@@ -13,6 +13,25 @@ import { FLOW_STAGES } from "../types.js";
|
|
|
13
13
|
function unique(values) {
|
|
14
14
|
return [...new Set(values)];
|
|
15
15
|
}
|
|
16
|
+
const TEST_COMMAND_HINT_PATTERN = /\b(?:npm test|pnpm test|yarn test|bun test|vitest|jest|pytest|go test|cargo test|mvn test|gradle test|dotnet test)\b/iu;
|
|
17
|
+
const SHA_WITH_LABEL_PATTERN = /\b(?:sha|commit)(?:\s*[:=]|\s+)\s*[0-9a-f]{7,40}\b/iu;
|
|
18
|
+
const PASS_STATUS_PATTERN = /\b(?:pass|passed|green|ok)\b/iu;
|
|
19
|
+
function validateGateEvidenceShape(stage, gateId, evidence) {
|
|
20
|
+
if (stage !== "tdd" || gateId !== "tdd_verified_before_complete") {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const trimmed = evidence.trim();
|
|
24
|
+
if (!TEST_COMMAND_HINT_PATTERN.test(trimmed)) {
|
|
25
|
+
return "must include the fresh verification command that was run (for example `npm test`, `pytest`, `go test`, or equivalent).";
|
|
26
|
+
}
|
|
27
|
+
if (!SHA_WITH_LABEL_PATTERN.test(trimmed)) {
|
|
28
|
+
return "must include a commit SHA token prefixed with `sha` or `commit` (for example `sha: abc1234`).";
|
|
29
|
+
}
|
|
30
|
+
if (!PASS_STATUS_PATTERN.test(trimmed)) {
|
|
31
|
+
return "must include explicit success status (for example `PASS` or `GREEN`).";
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
16
35
|
function parseStringList(raw) {
|
|
17
36
|
if (!Array.isArray(raw))
|
|
18
37
|
return [];
|
|
@@ -392,6 +411,21 @@ async function runAdvanceStage(projectRoot, args, io) {
|
|
|
392
411
|
io.stderr.write(`cclaw internal advance-stage: missing --evidence-json entries for passed gates: ${missingGuardEvidence.join(", ")}.\n`);
|
|
393
412
|
return 1;
|
|
394
413
|
}
|
|
414
|
+
const malformedGateEvidence = nextPassed.flatMap((gateId) => {
|
|
415
|
+
const provided = args.evidenceByGate[gateId];
|
|
416
|
+
const existing = flowState.guardEvidence[gateId];
|
|
417
|
+
const effectiveEvidence = typeof provided === "string" && provided.trim().length > 0
|
|
418
|
+
? provided
|
|
419
|
+
: typeof existing === "string" && existing.trim().length > 0
|
|
420
|
+
? existing
|
|
421
|
+
: "";
|
|
422
|
+
const issue = validateGateEvidenceShape(args.stage, gateId, effectiveEvidence);
|
|
423
|
+
return issue ? [`${gateId}: ${issue}`] : [];
|
|
424
|
+
});
|
|
425
|
+
if (malformedGateEvidence.length > 0) {
|
|
426
|
+
io.stderr.write(`cclaw internal advance-stage: gate evidence format check failed: ${malformedGateEvidence.join(" | ")}.\n`);
|
|
427
|
+
return 1;
|
|
428
|
+
}
|
|
395
429
|
const nextGuardEvidence = { ...flowState.guardEvidence };
|
|
396
430
|
for (const gateId of nextPassed) {
|
|
397
431
|
const provided = args.evidenceByGate[gateId];
|