cclaw-cli 0.51.29 → 0.55.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.
Files changed (151) hide show
  1. package/README.md +22 -16
  2. package/dist/artifact-linter/brainstorm.d.ts +2 -0
  3. package/dist/artifact-linter/brainstorm.js +245 -0
  4. package/dist/artifact-linter/design.d.ts +2 -0
  5. package/dist/artifact-linter/design.js +323 -0
  6. package/dist/artifact-linter/plan.d.ts +2 -0
  7. package/dist/artifact-linter/plan.js +162 -0
  8. package/dist/artifact-linter/review-army.d.ts +24 -0
  9. package/dist/artifact-linter/review-army.js +365 -0
  10. package/dist/artifact-linter/review.d.ts +2 -0
  11. package/dist/artifact-linter/review.js +65 -0
  12. package/dist/artifact-linter/scope.d.ts +2 -0
  13. package/dist/artifact-linter/scope.js +115 -0
  14. package/dist/artifact-linter/shared.d.ts +246 -0
  15. package/dist/artifact-linter/shared.js +1488 -0
  16. package/dist/artifact-linter/ship.d.ts +2 -0
  17. package/dist/artifact-linter/ship.js +46 -0
  18. package/dist/artifact-linter/spec.d.ts +2 -0
  19. package/dist/artifact-linter/spec.js +108 -0
  20. package/dist/artifact-linter/tdd.d.ts +2 -0
  21. package/dist/artifact-linter/tdd.js +124 -0
  22. package/dist/artifact-linter.d.ts +4 -76
  23. package/dist/artifact-linter.js +56 -2949
  24. package/dist/cli.d.ts +2 -18
  25. package/dist/cli.js +8 -246
  26. package/dist/codex-feature-flag.d.ts +1 -1
  27. package/dist/codex-feature-flag.js +1 -1
  28. package/dist/config.d.ts +3 -2
  29. package/dist/config.js +67 -3
  30. package/dist/constants.d.ts +1 -7
  31. package/dist/constants.js +9 -15
  32. package/dist/content/cancel-command.js +2 -2
  33. package/dist/content/closeout-guidance.js +13 -10
  34. package/dist/content/core-agents.d.ts +18 -0
  35. package/dist/content/core-agents.js +51 -7
  36. package/dist/content/decision-protocol.d.ts +1 -1
  37. package/dist/content/decision-protocol.js +1 -1
  38. package/dist/content/examples.js +6 -6
  39. package/dist/content/harness-doc.js +20 -2
  40. package/dist/content/hook-inline-snippets.d.ts +17 -4
  41. package/dist/content/hook-inline-snippets.js +218 -5
  42. package/dist/content/hook-manifest.d.ts +2 -2
  43. package/dist/content/hook-manifest.js +2 -2
  44. package/dist/content/hooks.d.ts +1 -0
  45. package/dist/content/hooks.js +32 -137
  46. package/dist/content/idea-command.d.ts +8 -0
  47. package/dist/content/{ideate-command.js → idea-command.js} +57 -50
  48. package/dist/content/idea-frames.d.ts +31 -0
  49. package/dist/content/{ideate-frames.js → idea-frames.js} +9 -9
  50. package/dist/content/idea-ranking.d.ts +25 -0
  51. package/dist/content/{ideate-ranking.js → idea-ranking.js} +5 -5
  52. package/dist/content/iron-laws.d.ts +0 -1
  53. package/dist/content/iron-laws.js +31 -16
  54. package/dist/content/learnings.js +1 -1
  55. package/dist/content/meta-skill.js +11 -13
  56. package/dist/content/node-hooks.d.ts +10 -0
  57. package/dist/content/node-hooks.js +45 -11
  58. package/dist/content/opencode-plugin.js +3 -3
  59. package/dist/content/session-hooks.js +1 -1
  60. package/dist/content/skills.js +19 -7
  61. package/dist/content/stage-command.js +1 -1
  62. package/dist/content/stage-schema.js +44 -2
  63. package/dist/content/stages/_lint-metadata/index.js +26 -2
  64. package/dist/content/stages/brainstorm.js +13 -7
  65. package/dist/content/stages/design.js +16 -11
  66. package/dist/content/stages/plan.js +9 -6
  67. package/dist/content/stages/review.js +4 -4
  68. package/dist/content/stages/schema-types.d.ts +1 -1
  69. package/dist/content/stages/scope.js +15 -12
  70. package/dist/content/stages/ship.js +2 -2
  71. package/dist/content/stages/spec.js +9 -3
  72. package/dist/content/stages/tdd.js +14 -4
  73. package/dist/content/start-command.d.ts +2 -2
  74. package/dist/content/start-command.js +24 -21
  75. package/dist/content/status-command.js +8 -8
  76. package/dist/content/subagents.js +61 -7
  77. package/dist/content/templates.d.ts +1 -1
  78. package/dist/content/templates.js +104 -152
  79. package/dist/content/tree-command.js +2 -2
  80. package/dist/content/utility-skills.d.ts +2 -2
  81. package/dist/content/utility-skills.js +2 -2
  82. package/dist/content/view-command.js +4 -2
  83. package/dist/delegation.d.ts +2 -0
  84. package/dist/delegation.js +2 -1
  85. package/dist/early-loop.d.ts +66 -0
  86. package/dist/early-loop.js +275 -0
  87. package/dist/flow-state.d.ts +1 -1
  88. package/dist/flow-state.js +1 -1
  89. package/dist/gate-evidence.d.ts +8 -0
  90. package/dist/gate-evidence.js +141 -5
  91. package/dist/harness-adapters.d.ts +2 -2
  92. package/dist/harness-adapters.js +54 -122
  93. package/dist/harness-selection.d.ts +31 -0
  94. package/dist/harness-selection.js +214 -0
  95. package/dist/install.js +166 -38
  96. package/dist/internal/advance-stage/advance.d.ts +50 -0
  97. package/dist/internal/advance-stage/advance.js +480 -0
  98. package/dist/internal/advance-stage/cancel-run.d.ts +8 -0
  99. package/dist/internal/advance-stage/cancel-run.js +19 -0
  100. package/dist/internal/advance-stage/flow-state-coercion.d.ts +3 -0
  101. package/dist/internal/advance-stage/flow-state-coercion.js +81 -0
  102. package/dist/internal/advance-stage/helpers.d.ts +14 -0
  103. package/dist/internal/advance-stage/helpers.js +145 -0
  104. package/dist/internal/advance-stage/hook.d.ts +8 -0
  105. package/dist/internal/advance-stage/hook.js +40 -0
  106. package/dist/internal/advance-stage/parsers.d.ts +54 -0
  107. package/dist/internal/advance-stage/parsers.js +307 -0
  108. package/dist/internal/advance-stage/review-loop.d.ts +7 -0
  109. package/dist/internal/advance-stage/review-loop.js +170 -0
  110. package/dist/internal/advance-stage/rewind.d.ts +14 -0
  111. package/dist/internal/advance-stage/rewind.js +108 -0
  112. package/dist/internal/advance-stage/start-flow.d.ts +11 -0
  113. package/dist/internal/advance-stage/start-flow.js +136 -0
  114. package/dist/internal/advance-stage/verify.d.ts +29 -0
  115. package/dist/internal/advance-stage/verify.js +225 -0
  116. package/dist/internal/advance-stage.js +21 -1470
  117. package/dist/internal/compound-readiness.d.ts +1 -1
  118. package/dist/internal/compound-readiness.js +2 -2
  119. package/dist/internal/early-loop-status.d.ts +7 -0
  120. package/dist/internal/early-loop-status.js +90 -0
  121. package/dist/internal/runtime-integrity.d.ts +7 -0
  122. package/dist/internal/runtime-integrity.js +288 -0
  123. package/dist/internal/tdd-red-evidence.js +1 -1
  124. package/dist/knowledge-store.d.ts +3 -8
  125. package/dist/knowledge-store.js +16 -29
  126. package/dist/managed-resources.js +24 -2
  127. package/dist/policy.js +5 -7
  128. package/dist/run-archive.d.ts +1 -1
  129. package/dist/run-archive.js +16 -16
  130. package/dist/run-persistence.js +112 -12
  131. package/dist/tdd-cycle.d.ts +3 -3
  132. package/dist/tdd-cycle.js +1 -1
  133. package/dist/types.d.ts +18 -10
  134. package/package.json +1 -1
  135. package/dist/content/finish-command.d.ts +0 -2
  136. package/dist/content/finish-command.js +0 -26
  137. package/dist/content/ideate-command.d.ts +0 -8
  138. package/dist/content/ideate-frames.d.ts +0 -31
  139. package/dist/content/ideate-ranking.d.ts +0 -25
  140. package/dist/content/next-command.d.ts +0 -20
  141. package/dist/content/next-command.js +0 -298
  142. package/dist/content/seed-shelf.d.ts +0 -36
  143. package/dist/content/seed-shelf.js +0 -301
  144. package/dist/content/stage-common-guidance.d.ts +0 -1
  145. package/dist/content/stage-common-guidance.js +0 -106
  146. package/dist/doctor-registry.d.ts +0 -10
  147. package/dist/doctor-registry.js +0 -186
  148. package/dist/doctor.d.ts +0 -17
  149. package/dist/doctor.js +0 -2206
  150. package/dist/internal/hook-manifest.d.ts +0 -16
  151. package/dist/internal/hook-manifest.js +0 -77
@@ -0,0 +1,145 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { FLOW_STAGES } from "../../types.js";
4
+ export function unique(values) {
5
+ return [...new Set(values)];
6
+ }
7
+ export function asRecord(value) {
8
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
9
+ return null;
10
+ }
11
+ return value;
12
+ }
13
+ export function parseStringList(raw) {
14
+ if (!Array.isArray(raw))
15
+ return [];
16
+ return raw
17
+ .filter((item) => typeof item === "string")
18
+ .map((item) => item.trim())
19
+ .filter((item) => item.length > 0);
20
+ }
21
+ export function isFlowStageValue(value) {
22
+ return typeof value === "string" && FLOW_STAGES.includes(value);
23
+ }
24
+ export function parseGuardEvidence(value) {
25
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
26
+ return {};
27
+ }
28
+ const next = {};
29
+ for (const [key, raw] of Object.entries(value)) {
30
+ if (typeof raw !== "string")
31
+ continue;
32
+ const trimmed = raw.trim();
33
+ if (trimmed.length === 0)
34
+ continue;
35
+ next[key] = trimmed;
36
+ }
37
+ return next;
38
+ }
39
+ export function emptyGateState() {
40
+ return {
41
+ required: [],
42
+ recommended: [],
43
+ conditional: [],
44
+ triggered: [],
45
+ passed: [],
46
+ blocked: []
47
+ };
48
+ }
49
+ export function stringifyGateEvidenceValue(value) {
50
+ if (typeof value === "string")
51
+ return value;
52
+ if (typeof value === "boolean")
53
+ return value ? "passed" : "failed";
54
+ if (typeof value === "number" || typeof value === "bigint")
55
+ return String(value);
56
+ if (value === null || value === undefined)
57
+ return "";
58
+ if (typeof value === "object")
59
+ return JSON.stringify(value);
60
+ return String(value);
61
+ }
62
+ export function parseEvidenceByGate(raw) {
63
+ if (!raw || raw.trim().length === 0) {
64
+ return {};
65
+ }
66
+ let parsed;
67
+ try {
68
+ parsed = JSON.parse(raw);
69
+ }
70
+ catch (err) {
71
+ throw new Error(`--evidence-json must be valid JSON object: ${err instanceof Error ? err.message : String(err)}`);
72
+ }
73
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
74
+ throw new Error("--evidence-json must deserialize to an object.");
75
+ }
76
+ const next = {};
77
+ for (const [key, value] of Object.entries(parsed)) {
78
+ const normalized = stringifyGateEvidenceValue(value).trim();
79
+ if (normalized.length === 0)
80
+ continue;
81
+ next[key] = normalized;
82
+ }
83
+ return next;
84
+ }
85
+ export function parseCsv(raw) {
86
+ if (!raw)
87
+ return [];
88
+ return raw
89
+ .split(",")
90
+ .map((item) => item.trim())
91
+ .filter((item) => item.length > 0);
92
+ }
93
+ export async function pathExists(projectRoot, relPath) {
94
+ try {
95
+ await fs.stat(path.join(projectRoot, relPath));
96
+ return true;
97
+ }
98
+ catch {
99
+ return false;
100
+ }
101
+ }
102
+ export async function listExistingFiles(projectRoot, relPaths) {
103
+ const matches = [];
104
+ for (const relPath of relPaths) {
105
+ try {
106
+ const stat = await fs.stat(path.join(projectRoot, relPath));
107
+ if (stat.isFile())
108
+ matches.push(relPath);
109
+ }
110
+ catch {
111
+ // continue
112
+ }
113
+ }
114
+ return matches;
115
+ }
116
+ export async function listFilesUnder(projectRoot, relDir, limit = 20) {
117
+ const root = path.join(projectRoot, relDir);
118
+ const out = [];
119
+ async function walk(absDir) {
120
+ if (out.length >= limit)
121
+ return;
122
+ let entries;
123
+ try {
124
+ entries = await fs.readdir(absDir, { withFileTypes: true });
125
+ }
126
+ catch {
127
+ return;
128
+ }
129
+ for (const entry of entries) {
130
+ if (out.length >= limit)
131
+ return;
132
+ if (entry.name.startsWith("."))
133
+ continue;
134
+ const abs = path.join(absDir, entry.name);
135
+ if (entry.isDirectory()) {
136
+ await walk(abs);
137
+ }
138
+ else if (entry.isFile()) {
139
+ out.push(path.relative(projectRoot, abs).split(path.sep).join("/"));
140
+ }
141
+ }
142
+ }
143
+ await walk(root);
144
+ return out;
145
+ }
@@ -0,0 +1,8 @@
1
+ import type { HookArgs } from "./parsers.js";
2
+ import type { Writable } from "node:stream";
3
+ interface InternalIo {
4
+ stdout: Writable;
5
+ stderr: Writable;
6
+ }
7
+ export declare function runHookCommand(projectRoot: string, args: HookArgs, io: InternalIo): Promise<number>;
8
+ export {};
@@ -0,0 +1,40 @@
1
+ import fs from "node:fs/promises";
2
+ import path from "node:path";
3
+ import { spawn } from "node:child_process";
4
+ import process from "node:process";
5
+ import { RUNTIME_ROOT } from "../../constants.js";
6
+ export async function runHookCommand(projectRoot, args, io) {
7
+ const runHookPath = path.join(projectRoot, RUNTIME_ROOT, "hooks", "run-hook.mjs");
8
+ try {
9
+ await fs.access(runHookPath);
10
+ }
11
+ catch {
12
+ io.stderr.write(`cclaw internal hook: missing hook runtime at ${runHookPath}. Run \`cclaw sync\` first.\n`);
13
+ return 1;
14
+ }
15
+ return await new Promise((resolve) => {
16
+ const child = spawn(process.execPath, [runHookPath, args.hookName], {
17
+ cwd: projectRoot,
18
+ env: process.env,
19
+ stdio: ["inherit", "pipe", "pipe"]
20
+ });
21
+ child.stdout.on("data", (chunk) => {
22
+ io.stdout.write(chunk);
23
+ });
24
+ child.stderr.on("data", (chunk) => {
25
+ io.stderr.write(chunk);
26
+ });
27
+ child.on("error", (err) => {
28
+ io.stderr.write(`cclaw internal hook: failed to launch runtime (${err instanceof Error ? err.message : String(err)}).\n`);
29
+ resolve(1);
30
+ });
31
+ child.on("close", (code, signal) => {
32
+ if (signal) {
33
+ io.stderr.write(`cclaw internal hook: runtime terminated by signal ${signal}.\n`);
34
+ resolve(1);
35
+ return;
36
+ }
37
+ resolve(typeof code === "number" ? code : 1);
38
+ });
39
+ });
40
+ }
@@ -0,0 +1,54 @@
1
+ import { type FlowStage, type FlowTrack } from "../../types.js";
2
+ import type { ArchiveDisposition } from "../../runs.js";
3
+ export interface AdvanceStageArgs {
4
+ stage: FlowStage;
5
+ passedGateIds: string[];
6
+ evidenceByGate: Record<string, string>;
7
+ waiveDelegations: string[];
8
+ waiverReason?: string;
9
+ acceptProactiveWaiver: boolean;
10
+ acceptProactiveWaiverReason?: string;
11
+ quiet: boolean;
12
+ json: boolean;
13
+ }
14
+ export interface VerifyFlowStateDiffArgs {
15
+ afterJson?: string;
16
+ afterFile?: string;
17
+ quiet: boolean;
18
+ }
19
+ export interface VerifyCurrentStateArgs {
20
+ quiet: boolean;
21
+ }
22
+ export interface HookArgs {
23
+ hookName: string;
24
+ }
25
+ export interface RewindArgs {
26
+ mode: "rewind" | "ack";
27
+ targetStage: FlowStage;
28
+ reason?: string;
29
+ quiet: boolean;
30
+ json: boolean;
31
+ }
32
+ export interface StartFlowArgs {
33
+ track: FlowTrack;
34
+ className?: string;
35
+ prompt?: string;
36
+ reason?: string;
37
+ stack?: string;
38
+ forceReset: boolean;
39
+ reclassify: boolean;
40
+ quiet: boolean;
41
+ }
42
+ export interface CancelRunArgs {
43
+ reason: string;
44
+ disposition: Extract<ArchiveDisposition, "cancelled" | "abandoned">;
45
+ name?: string;
46
+ quiet: boolean;
47
+ }
48
+ export declare function parseAdvanceStageArgs(tokens: string[]): AdvanceStageArgs;
49
+ export declare function parseVerifyFlowStateDiffArgs(tokens: string[]): VerifyFlowStateDiffArgs;
50
+ export declare function parseVerifyCurrentStateArgs(tokens: string[]): VerifyCurrentStateArgs;
51
+ export declare function parseRewindArgs(tokens: string[]): RewindArgs;
52
+ export declare function parseHookArgs(tokens: string[]): HookArgs;
53
+ export declare function parseStartFlowArgs(tokens: string[]): StartFlowArgs;
54
+ export declare function parseCancelRunArgs(tokens: string[]): CancelRunArgs;
@@ -0,0 +1,307 @@
1
+ import { FLOW_STAGES } from "../../types.js";
2
+ import { isFlowTrack } from "../../flow-state.js";
3
+ import { isFlowStageValue, parseCsv, parseEvidenceByGate, unique } from "./helpers.js";
4
+ export function parseAdvanceStageArgs(tokens) {
5
+ const [stageRaw, ...flagTokens] = tokens;
6
+ if (!isFlowStageValue(stageRaw)) {
7
+ throw new Error(`internal advance-stage requires a stage positional argument (${FLOW_STAGES.join(", ")}).`);
8
+ }
9
+ let evidenceJson;
10
+ let passed = [];
11
+ let waiveDelegations = [];
12
+ let waiverReason;
13
+ let acceptProactiveWaiver = false;
14
+ let acceptProactiveWaiverReason;
15
+ let quiet = false;
16
+ let json = false;
17
+ for (let i = 0; i < flagTokens.length; i += 1) {
18
+ const token = flagTokens[i];
19
+ const nextToken = flagTokens[i + 1];
20
+ if (token === "--json") {
21
+ json = true;
22
+ continue;
23
+ }
24
+ if (token === "--quiet") {
25
+ quiet = true;
26
+ continue;
27
+ }
28
+ if (token === "--evidence-json") {
29
+ if (!nextToken || nextToken.startsWith("--")) {
30
+ throw new Error("--evidence-json requires a JSON object value.");
31
+ }
32
+ evidenceJson = nextToken;
33
+ i += 1;
34
+ continue;
35
+ }
36
+ if (token.startsWith("--evidence-json=")) {
37
+ evidenceJson = token.slice("--evidence-json=".length);
38
+ continue;
39
+ }
40
+ if (token === "--passed") {
41
+ if (!nextToken || nextToken.startsWith("--")) {
42
+ throw new Error("--passed requires a comma-separated gate list.");
43
+ }
44
+ passed = [...passed, ...parseCsv(nextToken)];
45
+ i += 1;
46
+ continue;
47
+ }
48
+ if (token.startsWith("--passed=")) {
49
+ passed = [...passed, ...parseCsv(token.slice("--passed=".length))];
50
+ continue;
51
+ }
52
+ if (token === "--waive-delegation") {
53
+ if (!nextToken || nextToken.startsWith("--")) {
54
+ throw new Error("--waive-delegation requires a comma-separated agent list.");
55
+ }
56
+ waiveDelegations = [...waiveDelegations, ...parseCsv(nextToken)];
57
+ i += 1;
58
+ continue;
59
+ }
60
+ if (token.startsWith("--waive-delegation=")) {
61
+ waiveDelegations = [
62
+ ...waiveDelegations,
63
+ ...parseCsv(token.slice("--waive-delegation=".length))
64
+ ];
65
+ continue;
66
+ }
67
+ if (token === "--waiver-reason") {
68
+ if (!nextToken || nextToken.startsWith("--")) {
69
+ throw new Error("--waiver-reason requires a text value.");
70
+ }
71
+ waiverReason = nextToken.trim();
72
+ i += 1;
73
+ continue;
74
+ }
75
+ if (token.startsWith("--waiver-reason=")) {
76
+ waiverReason = token.slice("--waiver-reason=".length).trim();
77
+ continue;
78
+ }
79
+ if (token === "--accept-proactive-waiver") {
80
+ acceptProactiveWaiver = true;
81
+ continue;
82
+ }
83
+ if (token === "--accept-proactive-waiver-reason") {
84
+ if (!nextToken || nextToken.startsWith("--")) {
85
+ throw new Error("--accept-proactive-waiver-reason requires a text value.");
86
+ }
87
+ acceptProactiveWaiverReason = nextToken.trim();
88
+ i += 1;
89
+ continue;
90
+ }
91
+ if (token.startsWith("--accept-proactive-waiver-reason=")) {
92
+ acceptProactiveWaiverReason = token.slice("--accept-proactive-waiver-reason=".length).trim();
93
+ continue;
94
+ }
95
+ throw new Error(`Unknown flag for internal advance-stage: ${token}`);
96
+ }
97
+ return {
98
+ stage: stageRaw,
99
+ passedGateIds: unique(passed),
100
+ evidenceByGate: parseEvidenceByGate(evidenceJson),
101
+ waiveDelegations: unique(waiveDelegations),
102
+ waiverReason,
103
+ acceptProactiveWaiver,
104
+ acceptProactiveWaiverReason,
105
+ quiet,
106
+ json
107
+ };
108
+ }
109
+ export function parseVerifyFlowStateDiffArgs(tokens) {
110
+ let afterJson;
111
+ let afterFile;
112
+ let quiet = false;
113
+ for (const token of tokens) {
114
+ if (token === "--quiet") {
115
+ quiet = true;
116
+ continue;
117
+ }
118
+ if (token.startsWith("--after-json=")) {
119
+ afterJson = token.replace("--after-json=", "");
120
+ continue;
121
+ }
122
+ if (token.startsWith("--after-file=")) {
123
+ afterFile = token.replace("--after-file=", "");
124
+ continue;
125
+ }
126
+ throw new Error(`Unknown flag for internal verify-flow-state-diff: ${token}`);
127
+ }
128
+ if (!afterJson && !afterFile) {
129
+ throw new Error("internal verify-flow-state-diff requires --after-json=<json> or --after-file=<path>.");
130
+ }
131
+ return { afterJson, afterFile, quiet };
132
+ }
133
+ export function parseVerifyCurrentStateArgs(tokens) {
134
+ let quiet = false;
135
+ for (const token of tokens) {
136
+ if (token === "--quiet") {
137
+ quiet = true;
138
+ continue;
139
+ }
140
+ throw new Error(`Unknown flag for internal verify-current-state: ${token}`);
141
+ }
142
+ return { quiet };
143
+ }
144
+ export function parseRewindArgs(tokens) {
145
+ let quiet = false;
146
+ let json = false;
147
+ const positional = [];
148
+ for (let i = 0; i < tokens.length; i += 1) {
149
+ const token = tokens[i];
150
+ const nextToken = tokens[i + 1];
151
+ if (token === "--quiet") {
152
+ quiet = true;
153
+ continue;
154
+ }
155
+ if (token === "--json") {
156
+ json = true;
157
+ continue;
158
+ }
159
+ if (token === "--ack") {
160
+ if (!nextToken || nextToken.startsWith("--")) {
161
+ throw new Error("--ack requires a stage value.");
162
+ }
163
+ if (!isFlowStageValue(nextToken)) {
164
+ throw new Error(`--ack stage must be one of: ${FLOW_STAGES.join(", ")}.`);
165
+ }
166
+ i += 1;
167
+ return { mode: "ack", targetStage: nextToken, quiet, json };
168
+ }
169
+ if (token.startsWith("--ack=")) {
170
+ const stage = token.slice("--ack=".length);
171
+ if (!isFlowStageValue(stage)) {
172
+ throw new Error(`--ack stage must be one of: ${FLOW_STAGES.join(", ")}.`);
173
+ }
174
+ return { mode: "ack", targetStage: stage, quiet, json };
175
+ }
176
+ positional.push(token);
177
+ }
178
+ const [targetStage, ...reasonParts] = positional;
179
+ if (!isFlowStageValue(targetStage)) {
180
+ throw new Error(`internal rewind requires a target stage (${FLOW_STAGES.join(", ")}) or --ack <stage>.`);
181
+ }
182
+ const reason = reasonParts.join(" ").trim();
183
+ if (reason.length === 0) {
184
+ throw new Error('internal rewind requires a reason, for example: cclaw internal rewind tdd "review_blocked_by_critical".');
185
+ }
186
+ return { mode: "rewind", targetStage, reason, quiet, json };
187
+ }
188
+ export function parseHookArgs(tokens) {
189
+ const [hookName, ...rest] = tokens;
190
+ const normalizedHook = typeof hookName === "string" ? hookName.trim() : "";
191
+ if (normalizedHook.length === 0) {
192
+ throw new Error("internal hook requires a hook name: cclaw internal hook <name>.");
193
+ }
194
+ if (rest.length > 0) {
195
+ throw new Error(`Unknown arguments for internal hook: ${rest.join(" ")}`);
196
+ }
197
+ return { hookName: normalizedHook };
198
+ }
199
+ export function parseStartFlowArgs(tokens) {
200
+ let track;
201
+ let className;
202
+ let prompt;
203
+ let reason;
204
+ let stack;
205
+ let forceReset = false;
206
+ let reclassify = false;
207
+ let quiet = false;
208
+ for (let i = 0; i < tokens.length; i += 1) {
209
+ const token = tokens[i];
210
+ const nextToken = tokens[i + 1];
211
+ const readValue = (flag) => {
212
+ if (token.startsWith(`${flag}=`))
213
+ return token.slice(flag.length + 1);
214
+ if (token === flag && nextToken && !nextToken.startsWith("--")) {
215
+ i += 1;
216
+ return nextToken;
217
+ }
218
+ throw new Error(`${flag} requires a value.`);
219
+ };
220
+ if (token === "--quiet") {
221
+ quiet = true;
222
+ continue;
223
+ }
224
+ if (token === "--force-reset") {
225
+ forceReset = true;
226
+ continue;
227
+ }
228
+ if (token === "--reclassify") {
229
+ reclassify = true;
230
+ continue;
231
+ }
232
+ if (token === "--track" || token.startsWith("--track=")) {
233
+ const raw = readValue("--track").trim();
234
+ if (!isFlowTrack(raw)) {
235
+ throw new Error(`--track must be one of: standard, medium, quick.`);
236
+ }
237
+ track = raw;
238
+ continue;
239
+ }
240
+ if (token === "--class" || token.startsWith("--class=")) {
241
+ className = readValue("--class").trim();
242
+ continue;
243
+ }
244
+ if (token === "--prompt" || token.startsWith("--prompt=")) {
245
+ prompt = readValue("--prompt").trim();
246
+ continue;
247
+ }
248
+ if (token === "--reason" || token.startsWith("--reason=")) {
249
+ reason = readValue("--reason").trim();
250
+ continue;
251
+ }
252
+ if (token === "--stack" || token.startsWith("--stack=")) {
253
+ stack = readValue("--stack").trim();
254
+ continue;
255
+ }
256
+ throw new Error(`Unknown flag for internal start-flow: ${token}`);
257
+ }
258
+ if (!track) {
259
+ throw new Error("internal start-flow requires --track=<standard|medium|quick>.");
260
+ }
261
+ return { track, className, prompt, reason, stack, forceReset, reclassify, quiet };
262
+ }
263
+ export function parseCancelRunArgs(tokens) {
264
+ let reason;
265
+ let disposition = "cancelled";
266
+ let name;
267
+ let quiet = false;
268
+ for (let i = 0; i < tokens.length; i += 1) {
269
+ const token = tokens[i];
270
+ const nextToken = tokens[i + 1];
271
+ const readValue = (flag) => {
272
+ if (token.startsWith(`${flag}=`))
273
+ return token.slice(flag.length + 1);
274
+ if (token === flag && nextToken && !nextToken.startsWith("--")) {
275
+ i += 1;
276
+ return nextToken;
277
+ }
278
+ throw new Error(`${flag} requires a value.`);
279
+ };
280
+ if (token === "--quiet") {
281
+ quiet = true;
282
+ continue;
283
+ }
284
+ if (token === "--reason" || token.startsWith("--reason=")) {
285
+ reason = readValue("--reason").trim();
286
+ continue;
287
+ }
288
+ if (token === "--name" || token.startsWith("--name=")) {
289
+ const raw = readValue("--name").trim();
290
+ name = raw.length > 0 ? raw : undefined;
291
+ continue;
292
+ }
293
+ if (token === "--disposition" || token.startsWith("--disposition=")) {
294
+ const raw = readValue("--disposition").trim();
295
+ if (raw !== "cancelled" && raw !== "abandoned") {
296
+ throw new Error("--disposition must be cancelled or abandoned.");
297
+ }
298
+ disposition = raw;
299
+ continue;
300
+ }
301
+ throw new Error(`Unknown flag for internal cancel-run: ${token}`);
302
+ }
303
+ if (!reason || reason.length === 0) {
304
+ throw new Error("internal cancel-run requires --reason=<text>.");
305
+ }
306
+ return { reason, disposition, name, quiet };
307
+ }
@@ -0,0 +1,7 @@
1
+ import type { FlowStage } from "../../types.js";
2
+ export declare const AUTO_REVIEW_LOOP_GATE_BY_STAGE: Partial<Record<FlowStage, string>>;
3
+ export declare function pickReviewLoopEnvelope(value: unknown): Record<string, unknown> | null;
4
+ export declare function validateReviewLoopGateEvidence(stage: "scope" | "design", evidence: string): string | null;
5
+ export declare function validateUserApprovalEvidence(evidence: string): string | null;
6
+ export declare function validateGateEvidenceShape(projectRoot: string, stage: FlowStage, gateId: string, evidence: string): Promise<string | null>;
7
+ export declare function reviewLoopArtifactFixHint(stage: FlowStage, gateId: string): string;