cclaw-cli 0.51.0 → 0.51.2
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/README.md +3 -2
- package/dist/content/closeout-guidance.js +1 -1
- package/dist/content/core-agents.js +4 -8
- package/dist/content/hooks.js +44 -23
- package/dist/content/ideate-command.js +3 -0
- package/dist/content/language-policy.d.ts +2 -0
- package/dist/content/language-policy.js +13 -0
- package/dist/content/learnings.js +3 -1
- package/dist/content/meta-skill.js +8 -7
- package/dist/content/next-command.js +4 -1
- package/dist/content/node-hooks.js +1 -3
- package/dist/content/opencode-plugin.js +3 -3
- package/dist/content/session-hooks.js +2 -2
- package/dist/content/skills.js +5 -2
- package/dist/content/stage-common-guidance.js +4 -2
- package/dist/content/start-command.js +3 -0
- package/dist/content/subagents.js +8 -4
- package/dist/content/templates.d.ts +1 -1
- package/dist/content/templates.js +1 -1
- package/dist/content/tree-command.js +2 -2
- package/dist/content/view-command.js +2 -0
- package/dist/harness-adapters.js +3 -1
- package/dist/internal/advance-stage.js +55 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -443,8 +443,7 @@ Derived diagnostics are produced on demand by `cclaw doctor`.
|
|
|
443
443
|
|
|
444
444
|
## CLI reference
|
|
445
445
|
|
|
446
|
-
|
|
447
|
-
your harness.
|
|
446
|
+
`cclaw-cli` is deliberately small: it installs, syncs, upgrades, diagnoses, and removes the generated harness runtime. Day-to-day flow work happens inside your harness via `/cc*` commands and Node hooks.
|
|
448
447
|
|
|
449
448
|
```bash
|
|
450
449
|
npx cclaw-cli # launches interactive setup (or prints
|
|
@@ -456,6 +455,8 @@ npx cclaw-cli uninstall # remove .cclaw + generated harness shims
|
|
|
456
455
|
npx cclaw-cli --version
|
|
457
456
|
```
|
|
458
457
|
|
|
458
|
+
The generated `node .cclaw/hooks/stage-complete.mjs <stage>` helper is the canonical stage-closeout path and must not require a runtime `cclaw` binary in `PATH`.
|
|
459
|
+
|
|
459
460
|
For CI or scripted installs, `cclaw-cli init --harnesses=<list>
|
|
460
461
|
--no-interactive` is the non-interactive form. All other tunables
|
|
461
462
|
(prompt-guard strictness, TDD enforcement, language rule packs, track
|
|
@@ -31,7 +31,7 @@ export function closeoutSubstateProtocolBullets() {
|
|
|
31
31
|
session transcripts for matching historical learnings; only do it after opt-in.
|
|
32
32
|
Ask **one** structured question (apply / skip) per candidate cluster or a
|
|
33
33
|
single accept-all / skip choice, then advance substate.
|
|
34
|
-
- \`"ready_to_archive"\` -> run \`cclaw archive\` (or \`cclaw archive --name=<slug>\`) and reset state.
|
|
34
|
+
- \`"ready_to_archive"\` -> run \`npx cclaw-cli archive\` (or \`npx cclaw-cli archive --name=<slug>\`) and reset state.
|
|
35
35
|
- \`"archived"\` (transient) -> report "run archived" and stop.`;
|
|
36
36
|
}
|
|
37
37
|
export function closeoutFlowMapSentence() {
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Agent persona content for cclaw.
|
|
3
|
-
*
|
|
4
|
-
* cclaw materializes markdown agent definitions (`.md` with YAML frontmatter)
|
|
5
|
-
* under `.cclaw/agents/` for harness delegation. Research work that does not
|
|
6
|
-
* need isolated subagent context lives in `.cclaw/skills/research/*.md`
|
|
7
|
-
* playbooks and is executed in-thread by the primary agent.
|
|
8
|
-
*/
|
|
1
|
+
import { conversationLanguagePolicyBullets } from "./language-policy.js";
|
|
9
2
|
function yamlScalarString(value) {
|
|
10
3
|
// JSON double-quoted strings are valid YAML scalars and escape reliably.
|
|
11
4
|
return JSON.stringify(value);
|
|
@@ -196,6 +189,9 @@ ${agent.body}
|
|
|
196
189
|
|
|
197
190
|
## Rules
|
|
198
191
|
|
|
192
|
+
## Conversation Language Policy
|
|
193
|
+
|
|
194
|
+
${conversationLanguagePolicyBullets()}
|
|
199
195
|
- Cite file:line for every finding
|
|
200
196
|
- Do not make changes outside your specialist domain
|
|
201
197
|
- Report findings with severity classification
|
package/dist/content/hooks.js
CHANGED
|
@@ -1,12 +1,31 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
1
4
|
import { RUNTIME_ROOT } from "../constants.js";
|
|
5
|
+
function resolveCliEntrypointForGeneratedHook() {
|
|
6
|
+
const here = fileURLToPath(import.meta.url);
|
|
7
|
+
const candidates = [
|
|
8
|
+
path.resolve(path.dirname(here), "..", "cli.js"),
|
|
9
|
+
path.resolve(path.dirname(here), "..", "..", "dist", "cli.js")
|
|
10
|
+
];
|
|
11
|
+
for (const candidate of candidates) {
|
|
12
|
+
// Synchronous probe runs only during cclaw-cli init/sync generation.
|
|
13
|
+
// The generated hook receives a concrete path and does not need a global bin.
|
|
14
|
+
if (existsSync(candidate))
|
|
15
|
+
return candidate;
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
2
19
|
export function stageCompleteScript() {
|
|
20
|
+
const cliEntrypoint = resolveCliEntrypointForGeneratedHook();
|
|
3
21
|
return `#!/usr/bin/env node
|
|
4
22
|
import fs from "node:fs/promises";
|
|
5
23
|
import path from "node:path";
|
|
6
24
|
import process from "node:process";
|
|
7
|
-
import { spawn
|
|
25
|
+
import { spawn } from "node:child_process";
|
|
8
26
|
|
|
9
27
|
const RUNTIME_ROOT = ${JSON.stringify(RUNTIME_ROOT)};
|
|
28
|
+
const CCLAW_CLI_ENTRYPOINT = ${JSON.stringify(cliEntrypoint)};
|
|
10
29
|
|
|
11
30
|
async function detectRoot() {
|
|
12
31
|
const candidates = [
|
|
@@ -58,27 +77,29 @@ async function main() {
|
|
|
58
77
|
return;
|
|
59
78
|
}
|
|
60
79
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
80
|
+
const cliEntrypoint = process.env.CCLAW_CLI_JS || CCLAW_CLI_ENTRYPOINT;
|
|
81
|
+
if (!cliEntrypoint || cliEntrypoint.trim().length === 0) {
|
|
82
|
+
process.stderr.write(
|
|
83
|
+
"[cclaw] stage-complete: local Node runtime entrypoint is missing. Re-run npx cclaw-cli sync or npx cclaw-cli upgrade to regenerate hooks.\\n"
|
|
84
|
+
);
|
|
85
|
+
process.exitCode = 1;
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const stat = await fs.stat(cliEntrypoint);
|
|
91
|
+
if (!stat.isFile()) throw new Error("not-file");
|
|
92
|
+
} catch {
|
|
93
|
+
process.stderr.write(
|
|
94
|
+
"[cclaw] stage-complete: local Node runtime entrypoint not found at " + cliEntrypoint + ". Re-run npx cclaw-cli sync or npx cclaw-cli upgrade to regenerate hooks.\\n"
|
|
95
|
+
);
|
|
96
|
+
process.exitCode = 1;
|
|
97
|
+
return;
|
|
74
98
|
}
|
|
75
99
|
|
|
76
|
-
const isWindows = process.platform === "win32";
|
|
77
100
|
const child = spawn(
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
? ["/d", "/s", "/c", "cclaw", "internal", "advance-stage", stage, ...flags]
|
|
81
|
-
: ["internal", "advance-stage", stage, ...flags],
|
|
101
|
+
process.execPath,
|
|
102
|
+
[cliEntrypoint, "internal", "advance-stage", stage, ...flags],
|
|
82
103
|
{
|
|
83
104
|
cwd: root,
|
|
84
105
|
env: process.env,
|
|
@@ -92,11 +113,11 @@ async function main() {
|
|
|
92
113
|
const code = error && typeof error === "object" && "code" in error ? String(error.code) : "";
|
|
93
114
|
if (code === "ENOENT") {
|
|
94
115
|
process.stderr.write(
|
|
95
|
-
"[cclaw] stage-complete:
|
|
116
|
+
"[cclaw] stage-complete: node executable not found while invoking local runtime. Re-run npx cclaw-cli doctor.\\n"
|
|
96
117
|
);
|
|
97
118
|
} else {
|
|
98
119
|
process.stderr.write(
|
|
99
|
-
"[cclaw] stage-complete: failed to invoke
|
|
120
|
+
"[cclaw] stage-complete: failed to invoke local Node advance-stage runtime (" +
|
|
100
121
|
(error instanceof Error ? error.message : String(error)) +
|
|
101
122
|
").\\n"
|
|
102
123
|
);
|
|
@@ -134,7 +155,7 @@ set "RUNTIME=%HOOK_DIR%run-hook.mjs"
|
|
|
134
155
|
where node >nul 2>nul
|
|
135
156
|
if %ERRORLEVEL% neq 0 (
|
|
136
157
|
REM Best-effort: missing node should not block harness execution loops.
|
|
137
|
-
echo [cclaw] run-hook.cmd: node not found; cclaw hook skipped. Run cclaw doctor. >&2
|
|
158
|
+
echo [cclaw] run-hook.cmd: node not found; cclaw hook skipped. Run npx cclaw-cli doctor. >&2
|
|
138
159
|
exit /b 0
|
|
139
160
|
)
|
|
140
161
|
node "%RUNTIME%" %*
|
|
@@ -146,7 +167,7 @@ if [ "$#" -lt 1 ]; then
|
|
|
146
167
|
exit 1
|
|
147
168
|
fi
|
|
148
169
|
if ! command -v node >/dev/null 2>&1; then
|
|
149
|
-
echo "[cclaw] run-hook.cmd: node not found; cclaw hook skipped. Run cclaw doctor." >&2
|
|
170
|
+
echo "[cclaw] run-hook.cmd: node not found; cclaw hook skipped. Run npx cclaw-cli doctor." >&2
|
|
150
171
|
exit 0
|
|
151
172
|
fi
|
|
152
173
|
exec node "\${SCRIPT_DIR}/run-hook.mjs" "$@"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { RUNTIME_ROOT } from "../constants.js";
|
|
2
2
|
import { resolveIdeateFrames } from "./ideate-frames.js";
|
|
3
3
|
import { ideateStructuredAskToolsWithFallback } from "./decision-protocol.js";
|
|
4
|
+
import { conversationLanguagePolicyMarkdown } from "./language-policy.js";
|
|
4
5
|
const IDEATE_SKILL_FOLDER = "flow-ideate";
|
|
5
6
|
const IDEATE_SKILL_NAME = "flow-ideate";
|
|
6
7
|
/**
|
|
@@ -43,6 +44,7 @@ same session, or save/discard the backlog.
|
|
|
43
44
|
|
|
44
45
|
## HARD-GATE
|
|
45
46
|
|
|
47
|
+
${conversationLanguagePolicyMarkdown()}
|
|
46
48
|
- Ideate mode only. Never mutate \`.cclaw/state/flow-state.json\`.
|
|
47
49
|
- Every recommendation cites evidence from the current repository
|
|
48
50
|
(file path, command output, or knowledge-store entry id).
|
|
@@ -125,6 +127,7 @@ repository. Will persist a ranked backlog to
|
|
|
125
127
|
|
|
126
128
|
## HARD-GATE
|
|
127
129
|
|
|
130
|
+
${conversationLanguagePolicyMarkdown()}
|
|
128
131
|
- Do not start coding in ideate mode.
|
|
129
132
|
- Do not mutate \`.cclaw/state/flow-state.json\` — ideate mode sits outside
|
|
130
133
|
the critical-path flow.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function conversationLanguagePolicyMarkdown() {
|
|
2
|
+
return `## Conversation Language Policy
|
|
3
|
+
|
|
4
|
+
- Infer the user-facing language from the latest substantive user message.
|
|
5
|
+
- Write user-facing prose, summaries, recommendations, and structured question text/options in that language unless the user asks otherwise.
|
|
6
|
+
- Do not translate stable machine surfaces: commands, file paths, stage ids, gate ids, JSON keys, enum/status values, artifact headings/frontmatter, logs, code identifiers, and quoted source text.
|
|
7
|
+
- If the request mixes languages, use the language of the actual ask sentence for narrative output.
|
|
8
|
+
`;
|
|
9
|
+
}
|
|
10
|
+
export function conversationLanguagePolicyBullets() {
|
|
11
|
+
return `- User-facing narrative follows the latest substantive user message language.
|
|
12
|
+
- Do not translate commands, paths, ids, JSON keys/enums, artifact headings, logs, code identifiers, or quoted source.`;
|
|
13
|
+
}
|
|
@@ -64,7 +64,9 @@ Knowledge capture is now stage-native:
|
|
|
64
64
|
3. writes a harvest marker into the artifact.
|
|
65
65
|
|
|
66
66
|
Manual/query operations (search, backfill, curation) use this skill when the
|
|
67
|
-
user asks for knowledge work.
|
|
67
|
+
user asks for knowledge work. If a stage artifact contains JSON learnings but
|
|
68
|
+
\`${KNOWLEDGE_PATH}\` did not change, the missing step is almost always running
|
|
69
|
+
\`node .cclaw/hooks/stage-complete.mjs <stage>\` successfully.
|
|
68
70
|
|
|
69
71
|
## HARD-GATE
|
|
70
72
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { conversationLanguagePolicyMarkdown } from "./language-policy.js";
|
|
1
2
|
import { CLOSEOUT_CHAIN, closeoutChainInline, closeoutFlowMapSentence, closeoutProtocolBehaviorSentence } from "./closeout-guidance.js";
|
|
2
3
|
export const META_SKILL_NAME = "using-cclaw";
|
|
3
4
|
export function usingCclawSkillMarkdown() {
|
|
@@ -18,6 +19,7 @@ description: "Routing brain for cclaw. Decide whether to start/resume a stage, a
|
|
|
18
19
|
|
|
19
20
|
If the user explicitly overrides a stage rule, record it in the artifact.
|
|
20
21
|
|
|
22
|
+
${conversationLanguagePolicyMarkdown()}
|
|
21
23
|
## Skill-before-response gate
|
|
22
24
|
|
|
23
25
|
If \`.cclaw/state/flow-state.json\` exists and \`currentStage\` is set,
|
|
@@ -60,7 +62,7 @@ Task arrives
|
|
|
60
62
|
├─ Knowledge operation? -> load the learnings skill
|
|
61
63
|
├─ Read-only workspace view? -> /cc-view [status|tree|diff]
|
|
62
64
|
├─ Normal post-ship closeout? -> /cc-next drives ${closeoutChainInline()}
|
|
63
|
-
└─ Explicit early archival/reset? -> cclaw archive [--name=<slug>]
|
|
65
|
+
└─ Explicit early archival/reset? -> npx cclaw-cli archive [--name=<slug>]
|
|
64
66
|
\`\`\`
|
|
65
67
|
|
|
66
68
|
## Task classification
|
|
@@ -84,7 +86,7 @@ Before stage work:
|
|
|
84
86
|
## Platform reliability notes
|
|
85
87
|
|
|
86
88
|
- Managed hook dispatch uses \`.cclaw/hooks/run-hook.cmd\` (cross-platform wrapper).
|
|
87
|
-
- If hooks fail due missing runtime deps (for example \`node\` not on \`PATH\`), run \`cclaw doctor\` before continuing.
|
|
89
|
+
- If hooks fail due missing runtime deps (for example \`node\` not on \`PATH\`), run \`npx cclaw-cli doctor\` before continuing.
|
|
88
90
|
- Prefer cross-platform commands in artifacts/examples (\`npm test\`, \`pnpm test\`, \`python -m pytest\`, etc.) over shell-specific aliases whenever possible.
|
|
89
91
|
|
|
90
92
|
## Stage quick map
|
|
@@ -93,11 +95,10 @@ Use \`/cc <idea>\` for new work, \`/cc-next\` for progression and closeout, \`/c
|
|
|
93
95
|
|
|
94
96
|
## Main vs Operator Surfaces
|
|
95
97
|
|
|
96
|
-
- **Main workflow:** \`/cc\`, \`/cc-next\`, \`/cc-ideate\`, \`/cc-view status
|
|
97
|
-
- **
|
|
98
|
-
|
|
99
|
-
- Use operator/support surfaces only for install/runtime diagnosis, explicit
|
|
100
|
-
archival, or deeper inspection. Do not make them part of the happy path.
|
|
98
|
+
- **Main workflow:** \`/cc\`, \`/cc-next\`, \`/cc-ideate\`, \`/cc-view status\`, and \`node .cclaw/hooks/stage-complete.mjs <stage>\` inside the installed harness runtime.
|
|
99
|
+
- **Installer/support surface:** \`npx cclaw-cli init\`, \`npx cclaw-cli sync\`, \`npx cclaw-cli upgrade\`, \`npx cclaw-cli doctor\`, and explicit support/archive actions. Do not ask users to install or run a \`cclaw\` binary during normal stage flow.
|
|
100
|
+
- **Read-only support:** \`/cc-view tree\` and \`/cc-view diff\`.
|
|
101
|
+
- Use operator/support surfaces only for install/runtime diagnosis, explicit archival, or deeper inspection. Do not make them part of the happy path.
|
|
101
102
|
|
|
102
103
|
## Whole flow map
|
|
103
104
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RUNTIME_ROOT } from "../constants.js";
|
|
2
|
+
import { conversationLanguagePolicyMarkdown } from "./language-policy.js";
|
|
2
3
|
import { stageSchema } from "./stage-schema.js";
|
|
3
4
|
import { closeoutChainInline, closeoutNextCommandGuidance, closeoutSubstateInline, closeoutSubstateProtocolBullets } from "./closeout-guidance.js";
|
|
4
5
|
import { stageSkillFolder } from "./skills.js";
|
|
@@ -65,6 +66,7 @@ This is the only progression command the user needs to drive the entire flow. St
|
|
|
65
66
|
|
|
66
67
|
## HARD-GATE
|
|
67
68
|
|
|
69
|
+
${conversationLanguagePolicyMarkdown()}
|
|
68
70
|
- **Do not** invent gate completion: use only \`${flowPath}\` plus observable evidence in repo artifacts.
|
|
69
71
|
- **Do not** skip stages: advance only from \`currentStage\` to its configured successor.
|
|
70
72
|
- ${closeoutNextCommandGuidance()}
|
|
@@ -170,6 +172,7 @@ description: "The primary progression command. Reads flow state, starts/resumes
|
|
|
170
172
|
|
|
171
173
|
## Operator Output Contract
|
|
172
174
|
|
|
175
|
+
${conversationLanguagePolicyMarkdown()}
|
|
173
176
|
Default output should be compact, like OMC/OMX operator surfaces:
|
|
174
177
|
|
|
175
178
|
\`\`\`
|
|
@@ -243,7 +246,7 @@ by inspecting ${closeoutSubstateInline()}:
|
|
|
243
246
|
| \`idle\` / missing | Flip to \`retro_review\` and start retro protocol |
|
|
244
247
|
| \`retro_review\` | Draft/update \`09-retro.md\`, ask accept/edit/skip |
|
|
245
248
|
| \`compound_review\` | Compound closeout: overlap scan, refresh/supersede, ask approve/skip |
|
|
246
|
-
| \`ready_to_archive\` | Run \`cclaw archive\`; reset flow-state on success |
|
|
249
|
+
| \`ready_to_archive\` | Run \`npx cclaw-cli archive\`; reset flow-state on success |
|
|
247
250
|
| \`archived\` | Report "run archived"; stop |
|
|
248
251
|
|
|
249
252
|
Each step owns its own state transition. \`/cc-next\` keeps retro and compound
|
|
@@ -1066,9 +1066,7 @@ async function handleStopHandoff(runtime) {
|
|
|
1066
1066
|
state.activeRunId +
|
|
1067
1067
|
"). Active artifacts stay in " +
|
|
1068
1068
|
RUNTIME_ROOT +
|
|
1069
|
-
"/artifacts until
|
|
1070
|
-
RUNTIME_ROOT +
|
|
1071
|
-
"/knowledge.jsonl, (4) commit or revert pending changes.";
|
|
1069
|
+
"/artifacts until archive. Before stopping: (1) confirm flow-state reflects reality, (2) ensure artifact changes match current intent, (3) if you discovered a non-obvious rule/pattern during stage work, add it to the current artifact ## Learnings section so stage-complete can harvest it, (4) commit or revert pending changes.";
|
|
1072
1070
|
|
|
1073
1071
|
if (runtime.harness === "cursor") {
|
|
1074
1072
|
if (loopCount === 0) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { RUNTIME_ROOT } from "../constants.js";
|
|
2
2
|
import { META_SKILL_NAME } from "./meta-skill.js";
|
|
3
3
|
export function opencodePluginJs(_options = {}) {
|
|
4
|
-
return `// cclaw OpenCode plugin — generated by cclaw sync
|
|
4
|
+
return `// cclaw OpenCode plugin — generated by npx cclaw-cli sync
|
|
5
5
|
import { appendFileSync, existsSync, mkdirSync } from "node:fs";
|
|
6
6
|
import { readFile, stat } from "node:fs/promises";
|
|
7
7
|
import { join } from "node:path";
|
|
@@ -98,7 +98,7 @@ export default function cclawPlugin(ctx) {
|
|
|
98
98
|
if (knowledge.length > 0) parts.push("Knowledge digest (top relevant entries):", ...knowledge);
|
|
99
99
|
|
|
100
100
|
parts.push(
|
|
101
|
-
"If you discover a non-obvious rule or pattern,
|
|
101
|
+
"If you discover a non-obvious rule or pattern during stage work, add it to the current artifact ## Learnings section; stage-complete harvests it into .cclaw/knowledge.jsonl. Direct JSONL append is only for explicit manual learnings operations."
|
|
102
102
|
);
|
|
103
103
|
|
|
104
104
|
const meta = (await readFileText(metaSkillPath)).trim();
|
|
@@ -646,7 +646,7 @@ export default function cclawPlugin(ctx) {
|
|
|
646
646
|
throw new Error(
|
|
647
647
|
"cclaw " + failed + " blocked tool.execute.before.\\n" +
|
|
648
648
|
"Reason: " + detail + "\\n" +
|
|
649
|
-
"Diagnose: run \`cclaw doctor\` in project root.\\n" +
|
|
649
|
+
"Diagnose: run \`npx cclaw-cli doctor\` in project root.\\n" +
|
|
650
650
|
"Bypass (temporary): export CCLAW_DISABLE=1 before starting OpenCode,\\n" +
|
|
651
651
|
"or set \`strictness: advisory\` in .cclaw/config.yaml."
|
|
652
652
|
);
|
|
@@ -45,7 +45,7 @@ Before ending a session or when context is full:
|
|
|
45
45
|
|
|
46
46
|
1. **Verify no pending changes:** All modified files must be either committed or explicitly reverted.
|
|
47
47
|
2. **Update flow state:** Mark the current stage as its actual status (DONE / DONE_WITH_CONCERNS / BLOCKED).
|
|
48
|
-
3. **
|
|
48
|
+
3. **Capture knowledge:** If any non-obvious reusable insight appears during stage work, add a strict JSON bullet to the current artifact \`## Learnings\`; stage completion harvests it into \`.cclaw/knowledge.jsonl\`.
|
|
49
49
|
4. **Leave handoff context:** Put blockers and remaining work in the current stage artifact, not a separate state file.
|
|
50
50
|
|
|
51
51
|
### Stop conditions (agent must halt and report)
|
|
@@ -98,7 +98,7 @@ export function sessionHooksAgentsMdBlock() {
|
|
|
98
98
|
|
|
99
99
|
Session boundary behavior (real hooks inject context automatically; guidelines cover manual steps):
|
|
100
100
|
- **Start:** Hooks inject flow state + knowledge snapshot. Check for in-progress work, show status.
|
|
101
|
-
- **Stop:** Hooks remind about handoff. Verify no pending changes, update
|
|
101
|
+
- **Stop:** Hooks remind about handoff. Verify no pending changes, update the current artifact handoff, and capture reusable knowledge in \`## Learnings\`; stage completion harvests it.
|
|
102
102
|
- **Resume:** Re-read state, verify artifact, re-load knowledge, continue from last step. For compound closeout, optional session-history scans require user opt-in.
|
|
103
103
|
|
|
104
104
|
Skill: \`.cclaw/skills/session/SKILL.md\`
|
package/dist/content/skills.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { RUNTIME_ROOT, STAGE_TO_SKILL_FOLDER } from "../constants.js";
|
|
2
2
|
import { stageExamples } from "./examples.js";
|
|
3
3
|
import { reviewStackAwareRoutes, reviewStackAwareRoutingSummary, stageAutoSubagentDispatch, stageSchema, stageTrackRenderContext } from "./stage-schema.js";
|
|
4
|
+
import { conversationLanguagePolicyMarkdown } from "./language-policy.js";
|
|
4
5
|
const VERIFICATION_STAGES = ["tdd", "review", "ship"];
|
|
5
6
|
function whenNotToUseBlock(items) {
|
|
6
7
|
if (items.length === 0) {
|
|
@@ -215,10 +216,11 @@ function completionParametersBlock(schema, track) {
|
|
|
215
216
|
- \`artifact\`: \`${RUNTIME_ROOT}/artifacts/${schema.artifactRules.artifactFile}\`
|
|
216
217
|
- \`mandatory delegations\`: ${mandatory}
|
|
217
218
|
- \`completion helper\`: \`node .cclaw/hooks/stage-complete.mjs ${schema.stage}\`
|
|
219
|
+
- \`completion helper with evidence\`: \`node .cclaw/hooks/stage-complete.mjs ${schema.stage} --evidence-json '{"<gate_id>":"<evidence note>"}' --passed=<gate_id>[,<gate_id>]\`
|
|
218
220
|
- Fill \`## Learnings\` before closeout: either \`- None this stage.\` or JSON bullets with required keys \`type\`, \`trigger\`, \`action\`, \`confidence\` (knowledge-schema compatible).
|
|
219
221
|
- Record mandatory delegation completion/waiver in \`${RUNTIME_ROOT}/state/delegation-log.json\` with rationale as needed.
|
|
220
|
-
-
|
|
221
|
-
- Completion protocol: verify required gates, update the artifact, then use the completion helper.
|
|
222
|
+
- Never edit raw \`flow-state.json\` to complete a stage, even in advisory mode; that bypasses validation, gate evidence, and Learnings harvest. If the helper fails, stop and report the exact command/output instead of applying a manual state workaround.
|
|
223
|
+
- Completion protocol: verify required gates, update the artifact, then use the completion helper with \`--evidence-json\` and \`--passed\` for every satisfied gate.
|
|
222
224
|
`;
|
|
223
225
|
}
|
|
224
226
|
function quickStartBlock(stage, track) {
|
|
@@ -357,6 +359,7 @@ If you are about to violate the Iron Law, STOP. No amount of urgency, partial pr
|
|
|
357
359
|
|
|
358
360
|
${quickStartBlock(stage, track)}
|
|
359
361
|
|
|
362
|
+
${conversationLanguagePolicyMarkdown()}
|
|
360
363
|
## Philosophy
|
|
361
364
|
${philosophy.purpose}
|
|
362
365
|
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { conversationLanguagePolicyMarkdown } from "./language-policy.js";
|
|
1
2
|
export function stageCommonGuidanceMarkdown() {
|
|
2
3
|
return `# Common Stage Guidance
|
|
3
4
|
|
|
4
5
|
Shared guidance loaded by every stage skill. Keep this file concise and stable so
|
|
5
6
|
per-stage skills can stay focused on stage-specific work.
|
|
6
7
|
|
|
8
|
+
${conversationLanguagePolicyMarkdown()}
|
|
7
9
|
## Shared completion protocol
|
|
8
10
|
|
|
9
11
|
- Stage-specific skills expose **Completion Parameters** plus the gates that
|
|
@@ -26,8 +28,8 @@ Use this same closeout menu for every stage:
|
|
|
26
28
|
- **A) Advance** — run \`/cc-next\` and continue the critical path; after \`ship\`, the same command drives \`retro -> compound -> archive\`.
|
|
27
29
|
- **B) Revise this stage** — stay on current stage and apply feedback.
|
|
28
30
|
- **C) Pause / park** — run \`/cc-view status\`, then stop and resume later.
|
|
29
|
-
- **D) Rewind** — run \`cclaw internal rewind <target-stage> "<reason>"
|
|
30
|
-
- **E) Abandon** — only when the user explicitly wants to end a non-ship active run early, archive with \`cclaw archive --skip-retro --retro-reason="<reason>"\`. Once in post-ship closeout, continue \`/cc-next\` through retro/compound/archive instead.
|
|
31
|
+
- **D) Rewind** — run \`npx cclaw-cli internal rewind <target-stage> "<reason>"\` as a support/runtime repair action.
|
|
32
|
+
- **E) Abandon** — only when the user explicitly wants to end a non-ship active run early, archive with \`npx cclaw-cli archive --skip-retro --retro-reason="<reason>"\`. Once in post-ship closeout, continue \`/cc-next\` through retro/compound/archive instead.
|
|
31
33
|
|
|
32
34
|
Recommendation defaults:
|
|
33
35
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { RUNTIME_ROOT } from "../constants.js";
|
|
2
|
+
import { conversationLanguagePolicyMarkdown } from "./language-policy.js";
|
|
2
3
|
const START_SKILL_FOLDER = "flow-start";
|
|
3
4
|
const START_SKILL_NAME = "flow-start";
|
|
4
5
|
function flowStatePath() {
|
|
@@ -25,6 +26,7 @@ This is the **recommended way to start** working with cclaw. Use \`/cc-next\` fo
|
|
|
25
26
|
|
|
26
27
|
## HARD-GATE
|
|
27
28
|
|
|
29
|
+
${conversationLanguagePolicyMarkdown()}
|
|
28
30
|
- **Do not** skip reading \`${flowPath}\` — always check current state before acting.
|
|
29
31
|
- **Do not** start implementation stages directly from \`/cc <prompt>\` — always begin at the first stage of the resolved track (brainstorm for medium/standard, spec for quick).
|
|
30
32
|
- **Do not** start a stage pipeline for a task that is not a software change (pure question, non-software task, conversation).
|
|
@@ -150,6 +152,7 @@ description: "Unified entry point for the cclaw flow. No args = resume/next. Wit
|
|
|
150
152
|
|
|
151
153
|
Do **not** silently discard an existing flow when the user provides a prompt. If completed stages exist, inform and confirm before resetting.
|
|
152
154
|
|
|
155
|
+
${conversationLanguagePolicyMarkdown()}
|
|
153
156
|
## Protocol
|
|
154
157
|
|
|
155
158
|
### Path A: \`/cc <prompt>\`
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { stageDelegationSummary } from "./stage-schema.js";
|
|
2
|
+
import { conversationLanguagePolicyMarkdown } from "./language-policy.js";
|
|
2
3
|
/**
|
|
3
4
|
* Markdown content generators for Cclaw’s subagent orchestration skills and enhanced
|
|
4
5
|
* specialist payloads. Cclaw materializes static instructions — this module does not
|
|
@@ -80,10 +81,10 @@ can enforce phase-appropriate write boundaries. Use separate workers only when t
|
|
|
80
81
|
|
|
81
82
|
| Harness | Fallback | Delegation tool | Structured ask | Capability source |
|
|
82
83
|
|---|---|---|---|---|
|
|
83
|
-
| Claude | \`native\` | Task (named subagent_type) | AskUserQuestion | \`cclaw doctor\` |
|
|
84
|
-
| Cursor | \`generic-dispatch\` | Task (generic subagent_type: explore/generalPurpose/…) | AskQuestion | \`cclaw doctor\` |
|
|
85
|
-
| OpenCode | \`role-switch\` | plugin dispatch _or_ in-session role-switch | \`question\` (permission-gated; \`permission.question: "allow"\`) | \`cclaw doctor\` |
|
|
86
|
-
| Codex | \`role-switch\` | in-session role-switch (mandatory evidenceRefs) | \`request_user_input\` (experimental; Plan / Collaboration mode) | \`cclaw doctor\` |
|
|
84
|
+
| Claude | \`native\` | Task (named subagent_type) | AskUserQuestion | \`npx cclaw-cli doctor\` |
|
|
85
|
+
| Cursor | \`generic-dispatch\` | Task (generic subagent_type: explore/generalPurpose/…) | AskQuestion | \`npx cclaw-cli doctor\` |
|
|
86
|
+
| OpenCode | \`role-switch\` | plugin dispatch _or_ in-session role-switch | \`question\` (permission-gated; \`permission.question: "allow"\`) | \`npx cclaw-cli doctor\` |
|
|
87
|
+
| Codex | \`role-switch\` | in-session role-switch (mandatory evidenceRefs) | \`request_user_input\` (experimental; Plan / Collaboration mode) | \`npx cclaw-cli doctor\` |
|
|
87
88
|
|
|
88
89
|
**Dispatch rules driven by \`subagentFallback\`:**
|
|
89
90
|
|
|
@@ -136,6 +137,7 @@ Concrete per-stage rules so the controller does not have to guess which tier fit
|
|
|
136
137
|
|
|
137
138
|
## HARD-GATE
|
|
138
139
|
|
|
140
|
+
${conversationLanguagePolicyMarkdown()}
|
|
139
141
|
**Never dispatch a subagent without a concrete, self-contained task description pasted into the prompt. Do not pass file references the subagent must read to understand its task.**
|
|
140
142
|
|
|
141
143
|
If you catch yourself writing “read PLAN.md Task 3” or “implement the next unchecked item,” stop: expand the work into explicit text in the Task body before dispatching.
|
|
@@ -194,6 +196,7 @@ CONTEXT: {paste relevant file paths, types, patterns}
|
|
|
194
196
|
CONSTRAINTS: {paste from spec — what NOT to do}
|
|
195
197
|
|
|
196
198
|
After implementation:
|
|
199
|
+
0. Write user-facing narrative in the parent/user language; keep status tokens unchanged.
|
|
197
200
|
1. Run the full test suite
|
|
198
201
|
2. Report your status: DONE / DONE_WITH_CONCERNS / NEEDS_CONTEXT / BLOCKED
|
|
199
202
|
3. If DONE_WITH_CONCERNS, list each concern
|
|
@@ -335,6 +338,7 @@ This document bridges **Superpowers-style task isolation** with the **gstack “
|
|
|
335
338
|
|
|
336
339
|
## HARD-GATE
|
|
337
340
|
|
|
341
|
+
${conversationLanguagePolicyMarkdown()}
|
|
338
342
|
**Never dispatch parallel IMPLEMENTATION agents that write to the same codebase. Parallel agents are for investigation, analysis, and review ONLY.**
|
|
339
343
|
|
|
340
344
|
Implementation that touches shared source trees must remain **sequential** unless you have proven disjoint filesystem ownership (rare) and an explicit merge protocol.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export declare const ARTIFACT_TEMPLATES: Record<string, string>;
|
|
2
2
|
export declare const RULEBOOK_MARKDOWN = "# Cclaw Rulebook\n\n## MUST_ALWAYS\n- Follow flow order: brainstorm -> scope -> design -> spec -> plan -> tdd -> review -> ship\n- Require explicit user confirmation after plan before TDD\n- Keep evidence artifacts in `.cclaw/artifacts/`\n- Enforce RED before GREEN in TDD\n- Run two-layer review (spec_compliance and code_quality) before ship\n- Validate all inputs before processing \u2014 never trust external data without sanitization\n- Prefer immutable data patterns and pure functions where the language supports them\n- Follow existing repo conventions, patterns, and directory structure \u2014 match the codebase\n- Verify claims with fresh evidence: \"tests pass\" requires running tests in this message\n- Use conventional commits: `type(scope): description` (feat, fix, refactor, test, docs, chore)\n\n## MUST_NEVER\n- Skip RED phase and jump directly to GREEN in TDD\n- Ship with critical review findings\n- Start implementation during /brainstorm\n- Modify generated cclaw files manually when CLI can regenerate them\n- Commit `.cclaw/` or generated shim files\n- Expose secrets, tokens, API keys, or absolute system paths in agent output\n- Duplicate existing functionality without explicit justification \u2014 search before building\n- Bypass security checks, linting hooks, or type checking to \"move faster\"\n- Claim success (\"Done,\" \"All good,\" \"Tests pass\") without running verification in this message\n- Make changes outside the blast radius of the current task without user consent\n\n## DELEGATION\nWhen a task requires specialist knowledge (security audit, performance profiling, database review),\ndelegate to a specialized agent or skill if the harness supports it. The primary agent should:\n1. Identify the specialist domain\n2. Provide focused context (relevant files, the specific concern)\n3. Evaluate the specialist output before acting on it \u2014 do not blindly apply recommendations\n";
|
|
3
|
-
export declare const CURSOR_WORKFLOW_RULE_MDC = "---\ndescription: cclaw workflow guardrails for Cursor agent sessions\nglobs:\n - \"**/*\"\nalwaysApply: true\n---\n\n<!-- cclaw-managed-cursor-workflow-rule -->\n\n# Cclaw Workflow Guardrails\n\n## Activation Rule\n\nBefore responding to coding work:\n1. Read `.cclaw/state/flow-state.json`.\n2. Start with `/cc` or continue with `/cc-next`.\n3. If no software-stage flow applies, respond normally.\n\n## Stage Order\n\n`brainstorm -> scope -> design -> spec -> plan -> tdd -> review -> ship`\n\nTrack-specific skips are allowed only when `flow-state.track` + `skippedStages` explicitly say so.\n\n## Task Classification\n\n| Class | Route |\n|---|---|\n| non-trivial software work | `/cc <idea>` |\n| trivial software fix | `/cc <idea>` (quick or medium track) |\n| bugfix with repro | `/cc <idea>` and enforce RED-first in tdd |\n| pure question / non-software | direct answer (no stage flow) |\n\n## Command Surface\n\n- `/cc` = entry and resume.\n- `/cc-next` = only progression path.\n- Knowledge capture and recall use the `learnings` skill when requested.\n\n## Verification Discipline\n\n- No completion claim without fresh command evidence in this turn.\n- Do not mark gates passed from memory.\n- Keep evidence in `.cclaw/artifacts/`; archive via `cclaw archive`.\n\n## Delegation And Approvals\n\n- Machine-only checks in design/plan/tdd/review/ship should auto-dispatch when tooling supports it.\n- Ask for user input only at explicit approval gates (scope mode, plan approval, challenge resolution, ship finalization).\n- If harness capabilities are partial, record waiver reasons in delegation logs.\n\n## Routing Source Of Truth\n\n- Primary router: `.cclaw/skills/using-cclaw/SKILL.md`.\n- Stage behavior: current stage skill plus `.cclaw/state/flow-state.json`.\n- Preamble budget: keep role/status announcements brief and avoid repeating\n them unless the stage or role changes.\n";
|
|
3
|
+
export declare const CURSOR_WORKFLOW_RULE_MDC = "---\ndescription: cclaw workflow guardrails for Cursor agent sessions\nglobs:\n - \"**/*\"\nalwaysApply: true\n---\n\n<!-- cclaw-managed-cursor-workflow-rule -->\n\n# Cclaw Workflow Guardrails\n\n## Activation Rule\n\nBefore responding to coding work:\n1. Read `.cclaw/state/flow-state.json`.\n2. Start with `/cc` or continue with `/cc-next`.\n3. If no software-stage flow applies, respond normally.\n\n## Stage Order\n\n`brainstorm -> scope -> design -> spec -> plan -> tdd -> review -> ship`\n\nTrack-specific skips are allowed only when `flow-state.track` + `skippedStages` explicitly say so.\n\n## Task Classification\n\n| Class | Route |\n|---|---|\n| non-trivial software work | `/cc <idea>` |\n| trivial software fix | `/cc <idea>` (quick or medium track) |\n| bugfix with repro | `/cc <idea>` and enforce RED-first in tdd |\n| pure question / non-software | direct answer (no stage flow) |\n\n## Command Surface\n\n- `/cc` = entry and resume.\n- `/cc-next` = only progression path.\n- Knowledge capture and recall use the `learnings` skill when requested.\n\n## Verification Discipline\n\n- No completion claim without fresh command evidence in this turn.\n- Do not mark gates passed from memory.\n- Keep evidence in `.cclaw/artifacts/`; archive via `npx cclaw-cli archive`.\n\n## Delegation And Approvals\n\n- Machine-only checks in design/plan/tdd/review/ship should auto-dispatch when tooling supports it.\n- Ask for user input only at explicit approval gates (scope mode, plan approval, challenge resolution, ship finalization).\n- If harness capabilities are partial, record waiver reasons in delegation logs.\n\n## Routing Source Of Truth\n\n- Primary router: `.cclaw/skills/using-cclaw/SKILL.md`.\n- Stage behavior: current stage skill plus `.cclaw/state/flow-state.json`.\n- Preamble budget: keep role/status announcements brief and avoid repeating\n them unless the stage or role changes.\n";
|
|
4
4
|
export declare function buildRulesJson(): Record<string, unknown>;
|
|
@@ -915,7 +915,7 @@ Track-specific skips are allowed only when \`flow-state.track\` + \`skippedStage
|
|
|
915
915
|
|
|
916
916
|
- No completion claim without fresh command evidence in this turn.
|
|
917
917
|
- Do not mark gates passed from memory.
|
|
918
|
-
- Keep evidence in \`.cclaw/artifacts/\`; archive via \`cclaw archive\`.
|
|
918
|
+
- Keep evidence in \`.cclaw/artifacts/\`; archive via \`npx cclaw-cli archive\`.
|
|
919
919
|
|
|
920
920
|
## Delegation And Approvals
|
|
921
921
|
|
|
@@ -25,7 +25,7 @@ Do not modify state in this command. It is a pure read/render operation.
|
|
|
25
25
|
\`fulfillmentMode\` / \`evidenceRefs\`.
|
|
26
26
|
3. Inspect \`${artifactsPath()}\` for per-stage artifact presence and stale copies,
|
|
27
27
|
and for the retro artifact \`09-retro.md\`.
|
|
28
|
-
4. Use \`cclaw doctor --explain\` for harness capability status when needed.
|
|
28
|
+
4. Use \`npx cclaw-cli doctor --explain\` for harness capability status when needed.
|
|
29
29
|
5. Render one compact tree:
|
|
30
30
|
- stage marker: passed/current/pending/skipped/stale,
|
|
31
31
|
- gates summary,
|
|
@@ -41,7 +41,7 @@ Do not modify state in this command. It is a pure read/render operation.
|
|
|
41
41
|
then \`next\`; the transient \`archived\` substate surfaces only if the
|
|
42
42
|
archive step failed mid-run.
|
|
43
43
|
7. Append a \`harnesses:\` branch. For each installed harness derive the tier
|
|
44
|
-
and fallback from cclaw capability metadata; use \`cclaw doctor --explain\`
|
|
44
|
+
and fallback from cclaw capability metadata; use \`npx cclaw-cli doctor --explain\`
|
|
45
45
|
for remediation details when needed.
|
|
46
46
|
8. If rewind records exist in \`${rewindLogPath()}\`, include latest rewind note in footer.
|
|
47
47
|
|
|
@@ -2,6 +2,7 @@ import { RUNTIME_ROOT } from "../constants.js";
|
|
|
2
2
|
import { diffSubcommandMarkdown } from "./diff-command.js";
|
|
3
3
|
import { statusSubcommandMarkdown } from "./status-command.js";
|
|
4
4
|
import { treeSubcommandMarkdown } from "./tree-command.js";
|
|
5
|
+
import { conversationLanguagePolicyMarkdown } from "./language-policy.js";
|
|
5
6
|
const VIEW_SKILL_FOLDER = "flow-view";
|
|
6
7
|
const VIEW_SKILL_NAME = "flow-view";
|
|
7
8
|
export function viewCommandContract() {
|
|
@@ -18,6 +19,7 @@ Subcommands:
|
|
|
18
19
|
|
|
19
20
|
## HARD-GATE
|
|
20
21
|
|
|
22
|
+
${conversationLanguagePolicyMarkdown()}
|
|
21
23
|
- \`/cc-view\` is strictly read-only at wrapper level.
|
|
22
24
|
- Do not mutate flow-state or derived state from any subcommand.
|
|
23
25
|
|
package/dist/harness-adapters.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { RUNTIME_ROOT } from "./constants.js";
|
|
4
|
+
import { conversationLanguagePolicyMarkdown } from "./content/language-policy.js";
|
|
4
5
|
import { CCLAW_AGENTS, agentMarkdown } from "./content/core-agents.js";
|
|
5
6
|
import { ironLawsAgentsMdBlock } from "./content/iron-laws.js";
|
|
6
7
|
import { ensureDir, exists, writeFileSafe } from "./fs-utils.js";
|
|
@@ -159,6 +160,7 @@ function agentsMdBlock() {
|
|
|
159
160
|
> Auto-generated by \`cclaw sync\`. Do not edit this managed block manually.
|
|
160
161
|
> Existing project rules in this repository take precedence over cclaw defaults.
|
|
161
162
|
|
|
163
|
+
${conversationLanguagePolicyMarkdown()}
|
|
162
164
|
## Anti-Slop Guard
|
|
163
165
|
|
|
164
166
|
Treat quality as a hard requirement, not style preference:
|
|
@@ -377,7 +379,7 @@ Codex CLI v0.89 (Jan 2026). cclaw ships its entry points as skills
|
|
|
377
379
|
under \`.agents/skills/${skillSlug}/\` so the user can either:
|
|
378
380
|
|
|
379
381
|
- Type \`/use ${skillSlug}\` at the Codex prompt, or
|
|
380
|
-
- Type \`${slashToken} …\` (or describe the intent in
|
|
382
|
+
- Type \`${slashToken} …\` (or describe the intent in natural language) — Codex's
|
|
381
383
|
skill matcher picks this skill up via the description frontmatter.
|
|
382
384
|
|
|
383
385
|
Lifecycle hooks **are** available in Codex CLI v0.114+ (behind the
|
|
@@ -309,6 +309,19 @@ function coerceCandidateFlowState(raw, fallback) {
|
|
|
309
309
|
stageGateCatalog: parseCandidateGateCatalog(typed.stageGateCatalog, fallback.stageGateCatalog)
|
|
310
310
|
};
|
|
311
311
|
}
|
|
312
|
+
function stringifyGateEvidenceValue(value) {
|
|
313
|
+
if (typeof value === "string")
|
|
314
|
+
return value;
|
|
315
|
+
if (typeof value === "boolean")
|
|
316
|
+
return value ? "passed" : "failed";
|
|
317
|
+
if (typeof value === "number" || typeof value === "bigint")
|
|
318
|
+
return String(value);
|
|
319
|
+
if (value === null || value === undefined)
|
|
320
|
+
return "";
|
|
321
|
+
if (typeof value === "object")
|
|
322
|
+
return JSON.stringify(value);
|
|
323
|
+
return String(value);
|
|
324
|
+
}
|
|
312
325
|
function parseEvidenceByGate(raw) {
|
|
313
326
|
if (!raw || raw.trim().length === 0) {
|
|
314
327
|
return {};
|
|
@@ -325,12 +338,10 @@ function parseEvidenceByGate(raw) {
|
|
|
325
338
|
}
|
|
326
339
|
const next = {};
|
|
327
340
|
for (const [key, value] of Object.entries(parsed)) {
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
const trimmed = value.trim();
|
|
331
|
-
if (trimmed.length === 0)
|
|
341
|
+
const normalized = stringifyGateEvidenceValue(value).trim();
|
|
342
|
+
if (normalized.length === 0)
|
|
332
343
|
continue;
|
|
333
|
-
next[key] =
|
|
344
|
+
next[key] = normalized;
|
|
334
345
|
}
|
|
335
346
|
return next;
|
|
336
347
|
}
|
|
@@ -381,28 +392,62 @@ function parseAdvanceStageArgs(tokens) {
|
|
|
381
392
|
let waiveDelegations = [];
|
|
382
393
|
let waiverReason;
|
|
383
394
|
let quiet = false;
|
|
384
|
-
for (
|
|
395
|
+
for (let i = 0; i < flagTokens.length; i += 1) {
|
|
396
|
+
const token = flagTokens[i];
|
|
397
|
+
const nextToken = flagTokens[i + 1];
|
|
385
398
|
if (token === "--quiet") {
|
|
386
399
|
quiet = true;
|
|
387
400
|
continue;
|
|
388
401
|
}
|
|
402
|
+
if (token === "--evidence-json") {
|
|
403
|
+
if (!nextToken || nextToken.startsWith("--")) {
|
|
404
|
+
throw new Error("--evidence-json requires a JSON object value.");
|
|
405
|
+
}
|
|
406
|
+
evidenceJson = nextToken;
|
|
407
|
+
i += 1;
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
389
410
|
if (token.startsWith("--evidence-json=")) {
|
|
390
|
-
evidenceJson = token.
|
|
411
|
+
evidenceJson = token.slice("--evidence-json=".length);
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
if (token === "--passed") {
|
|
415
|
+
if (!nextToken || nextToken.startsWith("--")) {
|
|
416
|
+
throw new Error("--passed requires a comma-separated gate list.");
|
|
417
|
+
}
|
|
418
|
+
passed = [...passed, ...parseCsv(nextToken)];
|
|
419
|
+
i += 1;
|
|
391
420
|
continue;
|
|
392
421
|
}
|
|
393
422
|
if (token.startsWith("--passed=")) {
|
|
394
|
-
passed = [...passed, ...parseCsv(token.
|
|
423
|
+
passed = [...passed, ...parseCsv(token.slice("--passed=".length))];
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
if (token === "--waive-delegation") {
|
|
427
|
+
if (!nextToken || nextToken.startsWith("--")) {
|
|
428
|
+
throw new Error("--waive-delegation requires a comma-separated agent list.");
|
|
429
|
+
}
|
|
430
|
+
waiveDelegations = [...waiveDelegations, ...parseCsv(nextToken)];
|
|
431
|
+
i += 1;
|
|
395
432
|
continue;
|
|
396
433
|
}
|
|
397
434
|
if (token.startsWith("--waive-delegation=")) {
|
|
398
435
|
waiveDelegations = [
|
|
399
436
|
...waiveDelegations,
|
|
400
|
-
...parseCsv(token.
|
|
437
|
+
...parseCsv(token.slice("--waive-delegation=".length))
|
|
401
438
|
];
|
|
402
439
|
continue;
|
|
403
440
|
}
|
|
441
|
+
if (token === "--waiver-reason") {
|
|
442
|
+
if (!nextToken || nextToken.startsWith("--")) {
|
|
443
|
+
throw new Error("--waiver-reason requires a text value.");
|
|
444
|
+
}
|
|
445
|
+
waiverReason = nextToken.trim();
|
|
446
|
+
i += 1;
|
|
447
|
+
continue;
|
|
448
|
+
}
|
|
404
449
|
if (token.startsWith("--waiver-reason=")) {
|
|
405
|
-
waiverReason = token.
|
|
450
|
+
waiverReason = token.slice("--waiver-reason=".length).trim();
|
|
406
451
|
continue;
|
|
407
452
|
}
|
|
408
453
|
throw new Error(`Unknown flag for internal advance-stage: ${token}`);
|