claude-symphony 0.8.0 → 0.8.1

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/cli/index.js CHANGED
@@ -1,30 +1,20 @@
1
1
  #!/usr/bin/env node
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __esm = (fn, res) => function __init() {
4
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
5
+ };
2
6
 
3
- // src/cli/index.ts
4
- import { readFileSync } from "fs";
5
- import { fileURLToPath as fileURLToPath3 } from "url";
6
- import path10 from "path";
7
- import { Command } from "commander";
8
-
9
- // src/cli/commands/create.ts
10
- import fs2 from "fs";
11
- import path2 from "path";
7
+ // node_modules/tsup/assets/esm_shims.js
8
+ import path from "path";
12
9
  import { fileURLToPath } from "url";
13
- import { input } from "@inquirer/prompts";
14
- import chalk2 from "chalk";
10
+ var init_esm_shims = __esm({
11
+ "node_modules/tsup/assets/esm_shims.js"() {
12
+ "use strict";
13
+ }
14
+ });
15
15
 
16
16
  // src/utils/logger.ts
17
17
  import chalk from "chalk";
18
- var colorMap = {
19
- red: chalk.red,
20
- green: chalk.green,
21
- yellow: chalk.yellow,
22
- blue: chalk.blue,
23
- cyan: chalk.cyan,
24
- magenta: chalk.magenta,
25
- white: chalk.white,
26
- gray: chalk.gray
27
- };
28
18
  function log(message, color) {
29
19
  if (color && colorMap[color]) {
30
20
  console.log(colorMap[color](message));
@@ -44,30 +34,248 @@ function logWarning(message) {
44
34
  function logError(message) {
45
35
  console.log(`${chalk.red("[ERROR]")} ${message}`);
46
36
  }
47
- var result = {
48
- critical: (message) => {
49
- console.log(` ${chalk.red("\u2717 [CRITICAL]")} ${message}`);
50
- },
51
- high: (message) => {
52
- console.log(` ${chalk.yellow("\u26A0 [HIGH]")} ${message}`);
53
- },
54
- medium: (message) => {
55
- console.log(` ${chalk.magenta("\u25CB [MEDIUM]")} ${message}`);
56
- },
57
- pass: (message, verbose = false) => {
58
- if (verbose) {
59
- console.log(` ${chalk.green("\u2713")} ${message}`);
60
- }
61
- },
62
- fixed: (message) => {
63
- console.log(` ${chalk.green("\u26A1 [FIXED]")} ${message}`);
37
+ var colorMap, result;
38
+ var init_logger = __esm({
39
+ "src/utils/logger.ts"() {
40
+ "use strict";
41
+ init_esm_shims();
42
+ colorMap = {
43
+ red: chalk.red,
44
+ green: chalk.green,
45
+ yellow: chalk.yellow,
46
+ blue: chalk.blue,
47
+ cyan: chalk.cyan,
48
+ magenta: chalk.magenta,
49
+ white: chalk.white,
50
+ gray: chalk.gray
51
+ };
52
+ result = {
53
+ critical: (message) => {
54
+ console.log(` ${chalk.red("\u2717 [CRITICAL]")} ${message}`);
55
+ },
56
+ high: (message) => {
57
+ console.log(` ${chalk.yellow("\u26A0 [HIGH]")} ${message}`);
58
+ },
59
+ medium: (message) => {
60
+ console.log(` ${chalk.magenta("\u25CB [MEDIUM]")} ${message}`);
61
+ },
62
+ pass: (message, verbose = false) => {
63
+ if (verbose) {
64
+ console.log(` ${chalk.green("\u2713")} ${message}`);
65
+ }
66
+ },
67
+ fixed: (message) => {
68
+ console.log(` ${chalk.green("\u26A1 [FIXED]")} ${message}`);
69
+ }
70
+ };
64
71
  }
65
- };
72
+ });
73
+
74
+ // src/utils/shell.ts
75
+ import { execa } from "execa";
76
+ async function exec(command, args = [], options = {}) {
77
+ try {
78
+ const execaOptions = {
79
+ cwd: options.cwd,
80
+ env: { ...process.env, ...options.env },
81
+ timeout: options.timeout,
82
+ shell: options.shell ?? false,
83
+ stdio: options.stdio ?? "pipe",
84
+ reject: false,
85
+ ...options.input !== void 0 && { input: options.input }
86
+ };
87
+ const result2 = await execa(command, args, execaOptions);
88
+ return {
89
+ stdout: typeof result2.stdout === "string" ? result2.stdout : "",
90
+ stderr: typeof result2.stderr === "string" ? result2.stderr : "",
91
+ exitCode: result2.exitCode ?? 0,
92
+ success: result2.exitCode === 0
93
+ };
94
+ } catch (error) {
95
+ const err = error;
96
+ return {
97
+ stdout: "",
98
+ stderr: err.message || err.stderr || "Unknown error",
99
+ exitCode: err.exitCode ?? 1,
100
+ success: false
101
+ };
102
+ }
103
+ }
104
+ async function commandExists(cmd) {
105
+ const result2 = await exec("which", [cmd]);
106
+ return result2.success;
107
+ }
108
+ function getTimestamp() {
109
+ return (/* @__PURE__ */ new Date()).toISOString();
110
+ }
111
+ var init_shell = __esm({
112
+ "src/utils/shell.ts"() {
113
+ "use strict";
114
+ init_esm_shims();
115
+ }
116
+ });
117
+
118
+ // src/integrations/gemini.ts
119
+ async function isGeminiAvailable() {
120
+ return commandExists("gemini");
121
+ }
122
+ async function callGemini(prompt, options = {}) {
123
+ const timeout = options.timeout ?? DEFAULT_TIMEOUT;
124
+ if (!await isGeminiAvailable()) {
125
+ logWarning("gemini CLI is not installed \u2014 falling back to claudecode.");
126
+ return {
127
+ success: false,
128
+ fallbackRequired: true,
129
+ fallbackSignal: "CLI_NOT_FOUND",
130
+ fallbackReason: "Gemini CLI not installed"
131
+ };
132
+ }
133
+ try {
134
+ logInfo(`Calling Gemini CLI (timeout: ${timeout}s)...`);
135
+ const result2 = await exec("gemini", ["-p", prompt, "--yolo"], {
136
+ timeout: timeout * 1e3,
137
+ cwd: options.cwd
138
+ });
139
+ const output = result2.stdout.trim();
140
+ if (!output) {
141
+ logWarning("Gemini returned empty response \u2014 falling back.");
142
+ return {
143
+ success: false,
144
+ fallbackRequired: true,
145
+ fallbackSignal: "TIMEOUT",
146
+ fallbackReason: "Empty response from Gemini CLI"
147
+ };
148
+ }
149
+ const errorPatterns = /rate.limit|quota.exceeded|authentication.failed/i;
150
+ if (!result2.success || errorPatterns.test(output)) {
151
+ logWarning("Gemini API error detected \u2014 falling back.");
152
+ return {
153
+ success: false,
154
+ output,
155
+ fallbackRequired: true,
156
+ fallbackSignal: "API_ERROR",
157
+ fallbackReason: result2.stderr || "API error detected in response"
158
+ };
159
+ }
160
+ logSuccess("Gemini call completed.");
161
+ return {
162
+ success: true,
163
+ output,
164
+ fallbackRequired: false
165
+ };
166
+ } catch (error) {
167
+ logError(`Gemini call failed: ${error}`);
168
+ return {
169
+ success: false,
170
+ fallbackRequired: true,
171
+ fallbackSignal: "API_ERROR",
172
+ fallbackReason: String(error)
173
+ };
174
+ }
175
+ }
176
+ var DEFAULT_TIMEOUT;
177
+ var init_gemini = __esm({
178
+ "src/integrations/gemini.ts"() {
179
+ "use strict";
180
+ init_esm_shims();
181
+ init_shell();
182
+ init_logger();
183
+ DEFAULT_TIMEOUT = 300;
184
+ }
185
+ });
186
+
187
+ // src/integrations/codex.ts
188
+ async function isCodexAvailable() {
189
+ return commandExists("codex");
190
+ }
191
+ async function callCodex(prompt, options = {}) {
192
+ const timeout = options.timeout ?? DEFAULT_TIMEOUT2;
193
+ const fullAuto = options.fullAuto ?? true;
194
+ if (!await isCodexAvailable()) {
195
+ logWarning("codex CLI is not installed \u2014 falling back to claudecode.");
196
+ return {
197
+ success: false,
198
+ fallbackRequired: true,
199
+ fallbackSignal: "CLI_NOT_FOUND",
200
+ fallbackReason: "Codex CLI not installed"
201
+ };
202
+ }
203
+ try {
204
+ const args = fullAuto ? ["exec", "--full-auto", prompt] : ["exec", prompt];
205
+ logInfo(`Calling Codex CLI${fullAuto ? " (--full-auto)" : ""} (timeout: ${timeout}s)...`);
206
+ const result2 = await exec("codex", args, {
207
+ timeout: timeout * 1e3,
208
+ cwd: options.cwd
209
+ });
210
+ const output = result2.stdout.trim();
211
+ if (!output) {
212
+ logWarning("Codex returned empty response \u2014 falling back.");
213
+ return {
214
+ success: false,
215
+ fallbackRequired: true,
216
+ fallbackSignal: "TIMEOUT",
217
+ fallbackReason: "Empty response from Codex CLI"
218
+ };
219
+ }
220
+ const errorPatterns = /rate.limit|quota.exceeded|authentication.failed/i;
221
+ if (!result2.success || errorPatterns.test(output)) {
222
+ logWarning("Codex API error detected \u2014 falling back.");
223
+ return {
224
+ success: false,
225
+ output,
226
+ fallbackRequired: true,
227
+ fallbackSignal: "API_ERROR",
228
+ fallbackReason: result2.stderr || "API error detected in response"
229
+ };
230
+ }
231
+ logSuccess("Codex call completed.");
232
+ return {
233
+ success: true,
234
+ output,
235
+ fallbackRequired: false
236
+ };
237
+ } catch (error) {
238
+ logError(`Codex call failed: ${error}`);
239
+ return {
240
+ success: false,
241
+ fallbackRequired: true,
242
+ fallbackSignal: "API_ERROR",
243
+ fallbackReason: String(error)
244
+ };
245
+ }
246
+ }
247
+ var DEFAULT_TIMEOUT2;
248
+ var init_codex = __esm({
249
+ "src/integrations/codex.ts"() {
250
+ "use strict";
251
+ init_esm_shims();
252
+ init_shell();
253
+ init_logger();
254
+ DEFAULT_TIMEOUT2 = 300;
255
+ }
256
+ });
257
+
258
+ // src/cli/index.ts
259
+ init_esm_shims();
260
+ import { readFileSync as readFileSync2 } from "fs";
261
+ import { fileURLToPath as fileURLToPath4 } from "url";
262
+ import path13 from "path";
263
+ import { Command } from "commander";
264
+
265
+ // src/cli/commands/create.ts
266
+ init_esm_shims();
267
+ init_logger();
268
+ import fs2 from "fs";
269
+ import path3 from "path";
270
+ import { fileURLToPath as fileURLToPath2 } from "url";
271
+ import { input } from "@inquirer/prompts";
272
+ import chalk2 from "chalk";
66
273
 
67
274
  // src/utils/fs.ts
275
+ init_esm_shims();
68
276
  import fs from "fs/promises";
69
277
  import { existsSync, statSync, mkdirSync, copyFileSync, readdirSync } from "fs";
70
- import path from "path";
278
+ import path2 from "path";
71
279
  function pathExists(filePath) {
72
280
  return existsSync(filePath);
73
281
  }
@@ -90,7 +298,7 @@ async function readFile(filePath) {
90
298
  }
91
299
  async function writeFile(filePath, content) {
92
300
  try {
93
- await ensureDirAsync(path.dirname(filePath));
301
+ await ensureDirAsync(path2.dirname(filePath));
94
302
  await fs.writeFile(filePath, content, "utf8");
95
303
  return true;
96
304
  } catch (error) {
@@ -108,7 +316,7 @@ async function readJson(filePath) {
108
316
  }
109
317
  async function writeJson(filePath, data, pretty = true) {
110
318
  try {
111
- await ensureDirAsync(path.dirname(filePath));
319
+ await ensureDirAsync(path2.dirname(filePath));
112
320
  const content = pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);
113
321
  await fs.writeFile(filePath, content, "utf8");
114
322
  return true;
@@ -124,7 +332,7 @@ function copyDirSync(src, dest) {
124
332
  ensureDir(dest);
125
333
  const entries = readdirSync(src);
126
334
  for (const entry of entries) {
127
- copyDirSync(path.join(src, entry), path.join(dest, entry));
335
+ copyDirSync(path2.join(src, entry), path2.join(dest, entry));
128
336
  }
129
337
  } else {
130
338
  copyFileSync(src, dest);
@@ -142,10 +350,10 @@ async function remove(filePath) {
142
350
  }
143
351
 
144
352
  // src/cli/commands/create.ts
145
- var __filename2 = fileURLToPath(import.meta.url);
146
- var __dirname2 = path2.dirname(__filename2);
353
+ var __filename2 = fileURLToPath2(import.meta.url);
354
+ var __dirname2 = path3.dirname(__filename2);
147
355
  function displayAsciiBanner() {
148
- const bannerPath = path2.join(__dirname2, "..", "..", "assets", "claude_symphony_ascii.txt");
356
+ const bannerPath = path3.join(__dirname2, "..", "..", "assets", "claude_symphony_ascii.txt");
149
357
  if (fs2.existsSync(bannerPath)) {
150
358
  const banner = fs2.readFileSync(bannerPath, "utf8");
151
359
  console.log(chalk2.cyan(banner));
@@ -183,7 +391,7 @@ function removeNestedGitDirs(dir, isRoot = true) {
183
391
  if (!fs2.existsSync(dir)) return;
184
392
  const items = fs2.readdirSync(dir);
185
393
  for (const item of items) {
186
- const itemPath = path2.join(dir, item);
394
+ const itemPath = path3.join(dir, item);
187
395
  const stat = fs2.statSync(itemPath);
188
396
  if (stat.isDirectory()) {
189
397
  if (item === ".git" && !isRoot) {
@@ -209,10 +417,10 @@ async function createProject(options) {
209
417
  }
210
418
  });
211
419
  }
212
- const packageRoot = path2.resolve(__dirname2, "..", "..");
213
- const templateDir = path2.join(packageRoot, "template");
214
- const targetDir = path2.resolve(projectName);
215
- const actualProjectName = projectName === "." ? path2.basename(targetDir) : projectName;
420
+ const packageRoot = path3.resolve(__dirname2, "..", "..");
421
+ const templateDir = path3.join(packageRoot, "template");
422
+ const targetDir = path3.resolve(projectName);
423
+ const actualProjectName = projectName === "." ? path3.basename(targetDir) : projectName;
216
424
  if (!fs2.existsSync(templateDir)) {
217
425
  log(`Error: Template directory not found: ${templateDir}`, "red");
218
426
  process.exit(1);
@@ -242,8 +450,8 @@ async function createProject(options) {
242
450
  copyDirSync(templateDir, targetDir);
243
451
  log(" Template installed", "green");
244
452
  removeNestedGitDirs(targetDir);
245
- const progressTemplatePath = path2.join(targetDir, "state", "progress.json.template");
246
- const progressPath = path2.join(targetDir, "state", "progress.json");
453
+ const progressTemplatePath = path3.join(targetDir, "state", "progress.json.template");
454
+ const progressPath = path3.join(targetDir, "state", "progress.json");
247
455
  if (fs2.existsSync(progressTemplatePath)) {
248
456
  let progressContent = fs2.readFileSync(progressTemplatePath, "utf8");
249
457
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
@@ -252,8 +460,8 @@ async function createProject(options) {
252
460
  fs2.unlinkSync(progressTemplatePath);
253
461
  }
254
462
  log(" Progress tracking initialized", "green");
255
- const briefPath = path2.join(targetDir, "stages", "01-brainstorm", "inputs", "project_brief.md");
256
- const briefDir = path2.dirname(briefPath);
463
+ const briefPath = path3.join(targetDir, "stages", "01-brainstorm", "inputs", "project_brief.md");
464
+ const briefDir = path3.dirname(briefPath);
257
465
  ensureDir(briefDir);
258
466
  const briefContent = generateBriefContent(actualProjectName, description);
259
467
  fs2.writeFileSync(briefPath, briefContent);
@@ -283,10 +491,12 @@ async function createProject(options) {
283
491
  }
284
492
 
285
493
  // src/cli/commands/stage.ts
286
- import path4 from "path";
494
+ init_esm_shims();
495
+ import path5 from "path";
287
496
  import { existsSync as existsSync2 } from "fs";
288
497
 
289
498
  // src/utils/yaml.ts
499
+ init_esm_shims();
290
500
  import fs3 from "fs/promises";
291
501
  import yaml from "js-yaml";
292
502
  async function loadYaml(filePath) {
@@ -298,50 +508,21 @@ async function loadYaml(filePath) {
298
508
  }
299
509
  }
300
510
 
301
- // src/utils/shell.ts
302
- import { execa } from "execa";
303
- async function exec(command, args = [], options = {}) {
304
- try {
305
- const execaOptions = {
306
- cwd: options.cwd,
307
- env: { ...process.env, ...options.env },
308
- timeout: options.timeout,
309
- shell: options.shell ?? false,
310
- stdio: options.stdio ?? "pipe",
311
- reject: false
312
- };
313
- const result2 = await execa(command, args, execaOptions);
314
- return {
315
- stdout: typeof result2.stdout === "string" ? result2.stdout : "",
316
- stderr: typeof result2.stderr === "string" ? result2.stderr : "",
317
- exitCode: result2.exitCode ?? 0,
318
- success: result2.exitCode === 0
319
- };
320
- } catch (error) {
321
- const err = error;
322
- return {
323
- stdout: "",
324
- stderr: err.message || err.stderr || "Unknown error",
325
- exitCode: err.exitCode ?? 1,
326
- success: false
327
- };
328
- }
329
- }
330
- async function commandExists(cmd) {
331
- const result2 = await exec("which", [cmd]);
332
- return result2.success;
333
- }
334
- function getTimestamp() {
335
- return (/* @__PURE__ */ new Date()).toISOString();
336
- }
511
+ // src/cli/commands/stage.ts
512
+ init_logger();
513
+ init_shell();
337
514
 
338
515
  // src/core/state/progress.ts
339
- import path3 from "path";
516
+ init_esm_shims();
517
+ import path4 from "path";
518
+ init_shell();
340
519
 
341
520
  // src/types/state.ts
521
+ init_esm_shims();
342
522
  import { z as z2 } from "zod";
343
523
 
344
524
  // src/types/stage.ts
525
+ init_esm_shims();
345
526
  import { z } from "zod";
346
527
  var STAGE_IDS = [
347
528
  "01-brainstorm",
@@ -519,7 +700,7 @@ function createInitialProgress(projectName) {
519
700
 
520
701
  // src/core/state/progress.ts
521
702
  function getProgressPath(projectRoot) {
522
- return path3.join(projectRoot, "state", "progress.json");
703
+ return path4.join(projectRoot, "state", "progress.json");
523
704
  }
524
705
  async function loadProgress(projectRoot) {
525
706
  const progressPath = getProgressPath(projectRoot);
@@ -658,7 +839,7 @@ var ProgressManager = class {
658
839
 
659
840
  // src/cli/commands/stage.ts
660
841
  async function runStage(projectRoot, stageId, options = {}) {
661
- const stageDir = path4.join(projectRoot, "stages", stageId);
842
+ const stageDir = path5.join(projectRoot, "stages", stageId);
662
843
  if (options.complete) {
663
844
  return completeStage(projectRoot, stageId);
664
845
  }
@@ -670,7 +851,7 @@ async function runStage(projectRoot, stageId, options = {}) {
670
851
  console.log(`\u{1F680} Stage Execution: ${stageId}`);
671
852
  console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
672
853
  console.log("\n[1/4] Executing Pre-Stage Hook");
673
- const preStageHook = path4.join(projectRoot, ".claude", "hooks", "pre-stage.sh");
854
+ const preStageHook = path5.join(projectRoot, ".claude", "hooks", "pre-stage.sh");
674
855
  if (existsSync2(preStageHook)) {
675
856
  logInfo(`Pre-stage hook found: ${preStageHook}`);
676
857
  console.log(" (Hook execution delegated to shell wrapper)");
@@ -686,7 +867,7 @@ async function runStage(projectRoot, stageId, options = {}) {
686
867
  logWarning("Could not update progress.json");
687
868
  }
688
869
  console.log("\n[3/4] AI Model Enforcement Check");
689
- const stageConfig = await loadYaml(path4.join(stageDir, "config.yaml"));
870
+ const stageConfig = await loadYaml(path5.join(stageDir, "config.yaml"));
690
871
  if (stageConfig?.auto_invoke?.enabled) {
691
872
  const { model, message, required } = stageConfig.auto_invoke;
692
873
  console.log("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
@@ -705,7 +886,7 @@ async function runStage(projectRoot, stageId, options = {}) {
705
886
  console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
706
887
  }
707
888
  console.log("\n[4/4] Loading Stage Instructions");
708
- const claudeMd = path4.join(stageDir, "CLAUDE.md");
889
+ const claudeMd = path5.join(stageDir, "CLAUDE.md");
709
890
  if (existsSync2(claudeMd)) {
710
891
  console.log("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
711
892
  logSuccess("Stage CLAUDE.md:");
@@ -771,7 +952,7 @@ async function nextStage(projectRoot, options = {}) {
771
952
  }
772
953
  }
773
954
  if (!options.noHandoff && !options.force) {
774
- const handoffPath = path4.join(projectRoot, "stages", currentStage, "HANDOFF.md");
955
+ const handoffPath = path5.join(projectRoot, "stages", currentStage, "HANDOFF.md");
775
956
  if (!existsSync2(handoffPath)) {
776
957
  logWarning("HANDOFF.md not found for current stage.");
777
958
  console.log("Generate HANDOFF.md with /handoff command or use --no-handoff to skip.");
@@ -789,7 +970,7 @@ async function nextStage(projectRoot, options = {}) {
789
970
  return true;
790
971
  }
791
972
  async function handleSprintTransition(projectRoot, currentStage) {
792
- const pipelineConfig = await loadYaml(path4.join(projectRoot, "config", "pipeline.yaml"));
973
+ const pipelineConfig = await loadYaml(path5.join(projectRoot, "config", "pipeline.yaml"));
793
974
  if (!pipelineConfig?.sprint_mode?.enabled) {
794
975
  return false;
795
976
  }
@@ -797,7 +978,7 @@ async function handleSprintTransition(projectRoot, currentStage) {
797
978
  if (!stageIterative) {
798
979
  return false;
799
980
  }
800
- const progressPath = path4.join(projectRoot, "state", "progress.json");
981
+ const progressPath = path5.join(projectRoot, "state", "progress.json");
801
982
  const progress = await readJson(progressPath);
802
983
  const currentSprint = progress?.current_iteration?.current_sprint ?? 1;
803
984
  const totalSprints = progress?.current_iteration?.total_sprints ?? 3;
@@ -855,7 +1036,7 @@ async function gotoStage(projectRoot, targetStage, options = {}) {
855
1036
  console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
856
1037
  console.log("Loop-back History");
857
1038
  console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
858
- const historyPath2 = path4.join(projectRoot, "state", "loopback_history.json");
1039
+ const historyPath2 = path5.join(projectRoot, "state", "loopback_history.json");
859
1040
  const history2 = await readJson(historyPath2);
860
1041
  if (history2 && history2.length > 0) {
861
1042
  for (const entry of history2) {
@@ -882,7 +1063,7 @@ async function gotoStage(projectRoot, targetStage, options = {}) {
882
1063
  console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
883
1064
  console.log(` From: ${currentStage} (${getStageName(currentStage)})`);
884
1065
  console.log(` To: ${targetStage} (${getStageName(targetStage)})`);
885
- const historyPath = path4.join(projectRoot, "state", "loopback_history.json");
1066
+ const historyPath = path5.join(projectRoot, "state", "loopback_history.json");
886
1067
  let history = await readJson(historyPath) ?? [];
887
1068
  const timestamp = getTimestamp();
888
1069
  history.push({
@@ -891,9 +1072,9 @@ async function gotoStage(projectRoot, targetStage, options = {}) {
891
1072
  timestamp,
892
1073
  reason: options.reason
893
1074
  });
894
- await ensureDirAsync(path4.join(projectRoot, "state"));
1075
+ await ensureDirAsync(path5.join(projectRoot, "state"));
895
1076
  await writeJson(historyPath, history);
896
- const handoffPath = path4.join(projectRoot, "stages", currentStage, "HANDOFF.md");
1077
+ const handoffPath = path5.join(projectRoot, "stages", currentStage, "HANDOFF.md");
897
1078
  if (existsSync2(handoffPath)) {
898
1079
  const handoffContent = await readFile(handoffPath);
899
1080
  if (handoffContent) {
@@ -940,22 +1121,25 @@ async function listStages(projectRoot) {
940
1121
  }
941
1122
 
942
1123
  // src/cli/commands/status.ts
943
- import path6 from "path";
1124
+ init_esm_shims();
1125
+ import path7 from "path";
944
1126
  import { existsSync as existsSync4, readdirSync as readdirSync3, statSync as statSync3 } from "fs";
945
1127
 
946
1128
  // src/core/state/checkpoint.ts
947
- import path5 from "path";
1129
+ init_esm_shims();
1130
+ import path6 from "path";
948
1131
  import fs4 from "fs/promises";
949
1132
  import { existsSync as existsSync3, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
1133
+ init_shell();
950
1134
  function generateCheckpointId(stageId) {
951
1135
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").slice(0, 19);
952
1136
  return `checkpoint_${stageId}_${timestamp}`;
953
1137
  }
954
1138
  function getCheckpointsDir(projectRoot) {
955
- return path5.join(projectRoot, "state", "checkpoints");
1139
+ return path6.join(projectRoot, "state", "checkpoints");
956
1140
  }
957
1141
  function getCheckpointPath(projectRoot, checkpointId) {
958
- return path5.join(getCheckpointsDir(projectRoot), checkpointId);
1142
+ return path6.join(getCheckpointsDir(projectRoot), checkpointId);
959
1143
  }
960
1144
  async function listCheckpoints(projectRoot) {
961
1145
  const checkpointsDir = getCheckpointsDir(projectRoot);
@@ -965,8 +1149,8 @@ async function listCheckpoints(projectRoot) {
965
1149
  const entries = readdirSync2(checkpointsDir);
966
1150
  const checkpoints = [];
967
1151
  for (const entry of entries) {
968
- const checkpointPath = path5.join(checkpointsDir, entry);
969
- const metadataPath = path5.join(checkpointPath, "metadata.json");
1152
+ const checkpointPath = path6.join(checkpointsDir, entry);
1153
+ const metadataPath = path6.join(checkpointPath, "metadata.json");
970
1154
  if (statSync2(checkpointPath).isDirectory() && existsSync3(metadataPath)) {
971
1155
  const metadata = await readJson(metadataPath);
972
1156
  if (metadata) {
@@ -979,7 +1163,7 @@ async function listCheckpoints(projectRoot) {
979
1163
  );
980
1164
  }
981
1165
  async function getCheckpointMetadata(projectRoot, checkpointId) {
982
- const metadataPath = path5.join(
1166
+ const metadataPath = path6.join(
983
1167
  getCheckpointPath(projectRoot, checkpointId),
984
1168
  "metadata.json"
985
1169
  );
@@ -998,23 +1182,23 @@ async function createCheckpoint(projectRoot, stageId, options = {}) {
998
1182
  ensureDir(checkpointPath);
999
1183
  const files = [];
1000
1184
  if (includeStages) {
1001
- const stagesDir = path5.join(projectRoot, "stages");
1185
+ const stagesDir = path6.join(projectRoot, "stages");
1002
1186
  if (pathExists(stagesDir)) {
1003
- const destStagesDir = path5.join(checkpointPath, "stages");
1187
+ const destStagesDir = path6.join(checkpointPath, "stages");
1004
1188
  copyDirSync(stagesDir, destStagesDir);
1005
1189
  files.push("stages/");
1006
1190
  }
1007
1191
  }
1008
1192
  if (includeState) {
1009
- const stateDir = path5.join(projectRoot, "state");
1193
+ const stateDir = path6.join(projectRoot, "state");
1010
1194
  if (pathExists(stateDir)) {
1011
- const destStateDir = path5.join(checkpointPath, "state");
1195
+ const destStateDir = path6.join(checkpointPath, "state");
1012
1196
  ensureDir(destStateDir);
1013
1197
  const stateFiles = readdirSync2(stateDir);
1014
1198
  for (const file of stateFiles) {
1015
1199
  if (file === "checkpoints") continue;
1016
- const srcPath = path5.join(stateDir, file);
1017
- const destPath = path5.join(destStateDir, file);
1200
+ const srcPath = path6.join(stateDir, file);
1201
+ const destPath = path6.join(destStateDir, file);
1018
1202
  if (statSync2(srcPath).isDirectory()) {
1019
1203
  copyDirSync(srcPath, destPath);
1020
1204
  } else {
@@ -1026,9 +1210,9 @@ async function createCheckpoint(projectRoot, stageId, options = {}) {
1026
1210
  }
1027
1211
  }
1028
1212
  if (includeConfig) {
1029
- const configDir = path5.join(projectRoot, "config");
1213
+ const configDir = path6.join(projectRoot, "config");
1030
1214
  if (pathExists(configDir)) {
1031
- const destConfigDir = path5.join(checkpointPath, "config");
1215
+ const destConfigDir = path6.join(checkpointPath, "config");
1032
1216
  copyDirSync(configDir, destConfigDir);
1033
1217
  files.push("config/");
1034
1218
  }
@@ -1040,7 +1224,7 @@ async function createCheckpoint(projectRoot, stageId, options = {}) {
1040
1224
  description,
1041
1225
  files
1042
1226
  };
1043
- await writeJson(path5.join(checkpointPath, "metadata.json"), metadata);
1227
+ await writeJson(path6.join(checkpointPath, "metadata.json"), metadata);
1044
1228
  await addCheckpointToProgress(projectRoot, {
1045
1229
  id: checkpointId,
1046
1230
  stage: stageId,
@@ -1069,13 +1253,13 @@ async function restoreCheckpoint(projectRoot, checkpointId, options = {}) {
1069
1253
  try {
1070
1254
  if (partial && files.length > 0) {
1071
1255
  for (const file of files) {
1072
- const srcPath = path5.join(checkpointPath, file);
1073
- const destPath = path5.join(projectRoot, file);
1256
+ const srcPath = path6.join(checkpointPath, file);
1257
+ const destPath = path6.join(projectRoot, file);
1074
1258
  if (pathExists(srcPath)) {
1075
1259
  if (statSync2(srcPath).isDirectory()) {
1076
1260
  copyDirSync(srcPath, destPath);
1077
1261
  } else {
1078
- ensureDir(path5.dirname(destPath));
1262
+ ensureDir(path6.dirname(destPath));
1079
1263
  const content = await fs4.readFile(srcPath);
1080
1264
  await fs4.writeFile(destPath, content);
1081
1265
  }
@@ -1083,21 +1267,21 @@ async function restoreCheckpoint(projectRoot, checkpointId, options = {}) {
1083
1267
  }
1084
1268
  } else {
1085
1269
  if (restoreStages) {
1086
- const srcStagesDir = path5.join(checkpointPath, "stages");
1270
+ const srcStagesDir = path6.join(checkpointPath, "stages");
1087
1271
  if (pathExists(srcStagesDir)) {
1088
- const destStagesDir = path5.join(projectRoot, "stages");
1272
+ const destStagesDir = path6.join(projectRoot, "stages");
1089
1273
  await remove(destStagesDir);
1090
1274
  copyDirSync(srcStagesDir, destStagesDir);
1091
1275
  }
1092
1276
  }
1093
1277
  if (restoreState) {
1094
- const srcStateDir = path5.join(checkpointPath, "state");
1278
+ const srcStateDir = path6.join(checkpointPath, "state");
1095
1279
  if (pathExists(srcStateDir)) {
1096
- const destStateDir = path5.join(projectRoot, "state");
1280
+ const destStateDir = path6.join(projectRoot, "state");
1097
1281
  const stateFiles = readdirSync2(srcStateDir);
1098
1282
  for (const file of stateFiles) {
1099
- const srcPath = path5.join(srcStateDir, file);
1100
- const destPath = path5.join(destStateDir, file);
1283
+ const srcPath = path6.join(srcStateDir, file);
1284
+ const destPath = path6.join(destStateDir, file);
1101
1285
  if (statSync2(srcPath).isDirectory()) {
1102
1286
  if (pathExists(destPath)) await remove(destPath);
1103
1287
  copyDirSync(srcPath, destPath);
@@ -1109,9 +1293,9 @@ async function restoreCheckpoint(projectRoot, checkpointId, options = {}) {
1109
1293
  }
1110
1294
  }
1111
1295
  if (restoreConfig) {
1112
- const srcConfigDir = path5.join(checkpointPath, "config");
1296
+ const srcConfigDir = path6.join(checkpointPath, "config");
1113
1297
  if (pathExists(srcConfigDir)) {
1114
- const destConfigDir = path5.join(projectRoot, "config");
1298
+ const destConfigDir = path6.join(projectRoot, "config");
1115
1299
  await remove(destConfigDir);
1116
1300
  copyDirSync(srcConfigDir, destConfigDir);
1117
1301
  }
@@ -1145,6 +1329,7 @@ async function cleanupCheckpoints(projectRoot, maxRetention = 10, preserveMilest
1145
1329
  }
1146
1330
 
1147
1331
  // src/cli/commands/status.ts
1332
+ init_logger();
1148
1333
  async function showStatus(projectRoot) {
1149
1334
  console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
1150
1335
  console.log("\u{1F4CA} Pipeline Status");
@@ -1246,17 +1431,17 @@ async function showDashboard(projectRoot) {
1246
1431
  console.log("\n\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
1247
1432
  console.log("\u2502 \u{1F4C1} Stage Outputs \u2502");
1248
1433
  console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
1249
- const stagesDir = path6.join(projectRoot, "stages");
1434
+ const stagesDir = path7.join(projectRoot, "stages");
1250
1435
  if (existsSync4(stagesDir)) {
1251
1436
  for (const stage of STAGE_IDS) {
1252
- const outputsDir = path6.join(stagesDir, stage, "outputs");
1437
+ const outputsDir = path7.join(stagesDir, stage, "outputs");
1253
1438
  if (existsSync4(outputsDir)) {
1254
1439
  const files = readdirSync3(outputsDir).filter((f) => f.endsWith(".md"));
1255
1440
  if (files.length > 0) {
1256
1441
  console.log(`
1257
1442
  ${stage}:`);
1258
1443
  for (const file of files.slice(0, 3)) {
1259
- const filePath = path6.join(outputsDir, file);
1444
+ const filePath = path7.join(outputsDir, file);
1260
1445
  const stat = statSync3(filePath);
1261
1446
  const size = formatFileSize(stat.size);
1262
1447
  console.log(` \u2022 ${file} (${size})`);
@@ -1286,12 +1471,16 @@ function formatFileSize(bytes) {
1286
1471
  }
1287
1472
 
1288
1473
  // src/cli/commands/validate.ts
1474
+ init_esm_shims();
1289
1475
  import { existsSync as existsSync6 } from "fs";
1290
- import path8 from "path";
1476
+ import path9 from "path";
1291
1477
 
1292
1478
  // src/core/config/validator.ts
1293
- import path7 from "path";
1479
+ init_esm_shims();
1480
+ import path8 from "path";
1294
1481
  import { existsSync as existsSync5, readdirSync as readdirSync4, statSync as statSync4 } from "fs";
1482
+ init_shell();
1483
+ init_logger();
1295
1484
  var VALIDATION_RULES = [
1296
1485
  "model_references",
1297
1486
  "parallel_alignment",
@@ -1315,8 +1504,8 @@ var ConfigValidator = class {
1315
1504
  summary;
1316
1505
  constructor(projectRoot, options = {}) {
1317
1506
  this.projectRoot = projectRoot;
1318
- this.configDir = path7.join(projectRoot, "config");
1319
- this.stagesDir = path7.join(projectRoot, "stages");
1507
+ this.configDir = path8.join(projectRoot, "config");
1508
+ this.stagesDir = path8.join(projectRoot, "stages");
1320
1509
  this.options = options;
1321
1510
  this.summary = {
1322
1511
  critical: 0,
@@ -1382,7 +1571,7 @@ var ConfigValidator = class {
1382
1571
  */
1383
1572
  async getDefinedModels() {
1384
1573
  const modelsConfig = await loadYaml(
1385
- path7.join(this.configDir, "models.yaml")
1574
+ path8.join(this.configDir, "models.yaml")
1386
1575
  );
1387
1576
  if (!modelsConfig?.models) return [];
1388
1577
  return Object.keys(modelsConfig.models);
@@ -1391,7 +1580,7 @@ var ConfigValidator = class {
1391
1580
  * Get parallel capable stages from ai_collaboration.yaml
1392
1581
  */
1393
1582
  async getParallelStages() {
1394
- const collabConfig = await loadYaml(path7.join(this.configDir, "ai_collaboration.yaml"));
1583
+ const collabConfig = await loadYaml(path8.join(this.configDir, "ai_collaboration.yaml"));
1395
1584
  return collabConfig?.execution_policy?.stage_classification?.parallel_capable ?? [];
1396
1585
  }
1397
1586
  /**
@@ -1403,7 +1592,7 @@ var ConfigValidator = class {
1403
1592
  const definedModels = await this.getDefinedModels();
1404
1593
  const stages = this.getStagesToValidate();
1405
1594
  for (const stage of stages) {
1406
- const configPath = path7.join(this.stagesDir, stage, "config.yaml");
1595
+ const configPath = path8.join(this.stagesDir, stage, "config.yaml");
1407
1596
  if (!existsSync5(configPath)) continue;
1408
1597
  const stageConfig = await loadYaml(configPath);
1409
1598
  if (!stageConfig) continue;
@@ -1450,7 +1639,7 @@ var ConfigValidator = class {
1450
1639
  const parallelStages = await this.getParallelStages();
1451
1640
  const stages = this.getStagesToValidate();
1452
1641
  for (const stage of stages) {
1453
- const configPath = path7.join(this.stagesDir, stage, "config.yaml");
1642
+ const configPath = path8.join(this.stagesDir, stage, "config.yaml");
1454
1643
  if (!existsSync5(configPath)) continue;
1455
1644
  const stageConfig = await loadYaml(configPath);
1456
1645
  if (!stageConfig) continue;
@@ -1491,7 +1680,7 @@ var ConfigValidator = class {
1491
1680
  const parallelStages = await this.getParallelStages();
1492
1681
  for (const stage of parallelStages) {
1493
1682
  if (this.options.stage && this.options.stage !== stage) continue;
1494
- const configPath = path7.join(this.stagesDir, stage, "config.yaml");
1683
+ const configPath = path8.join(this.stagesDir, stage, "config.yaml");
1495
1684
  if (!existsSync5(configPath)) {
1496
1685
  this.addResult("critical", "collaboration_consistency", `parallel stage missing config.yaml`, stage);
1497
1686
  continue;
@@ -1521,17 +1710,17 @@ var ConfigValidator = class {
1521
1710
  log("\n\u25B8 Rule: file_references [HIGH]", "blue");
1522
1711
  const stages = this.getStagesToValidate();
1523
1712
  for (const stage of stages) {
1524
- const configPath = path7.join(this.stagesDir, stage, "config.yaml");
1713
+ const configPath = path8.join(this.stagesDir, stage, "config.yaml");
1525
1714
  if (!existsSync5(configPath)) continue;
1526
1715
  const stageConfig = await loadYaml(configPath);
1527
1716
  if (!stageConfig) continue;
1528
1717
  const requiredInputs = stageConfig.inputs?.required ?? [];
1529
1718
  for (const input2 of requiredInputs) {
1530
- const inputPath = path7.join(this.stagesDir, stage, input2);
1719
+ const inputPath = path8.join(this.stagesDir, stage, input2);
1531
1720
  if (existsSync5(inputPath)) {
1532
1721
  this.addPass(`input file exists: ${input2}`, stage);
1533
1722
  } else if (input2.startsWith("../")) {
1534
- const refPath = path7.join(this.stagesDir, stage, input2);
1723
+ const refPath = path8.join(this.stagesDir, stage, input2);
1535
1724
  if (existsSync5(refPath)) {
1536
1725
  this.addPass(`cross-stage input exists: ${input2}`, stage);
1537
1726
  } else {
@@ -1541,14 +1730,14 @@ var ConfigValidator = class {
1541
1730
  this.addResult("high", "file_references", `required input missing: ${input2}`, stage);
1542
1731
  }
1543
1732
  }
1544
- const templatesDir = path7.join(this.stagesDir, stage, "templates");
1733
+ const templatesDir = path8.join(this.stagesDir, stage, "templates");
1545
1734
  if (existsSync5(templatesDir)) {
1546
1735
  const templates = readdirSync4(templatesDir).filter((f) => f.endsWith(".md"));
1547
1736
  if (templates.length > 0) {
1548
1737
  this.addPass(`${templates.length} output template(s) found`, stage);
1549
1738
  }
1550
1739
  }
1551
- const claudeMd = path7.join(this.stagesDir, stage, "CLAUDE.md");
1740
+ const claudeMd = path8.join(this.stagesDir, stage, "CLAUDE.md");
1552
1741
  if (existsSync5(claudeMd)) {
1553
1742
  this.addPass(`CLAUDE.md exists`, stage);
1554
1743
  } else {
@@ -1564,13 +1753,13 @@ var ConfigValidator = class {
1564
1753
  log("\n\u25B8 Rule: auto_invoke [HIGH]", "blue");
1565
1754
  const stages = this.getStagesToValidate();
1566
1755
  for (const stage of stages) {
1567
- const configPath = path7.join(this.stagesDir, stage, "config.yaml");
1756
+ const configPath = path8.join(this.stagesDir, stage, "config.yaml");
1568
1757
  if (!existsSync5(configPath)) continue;
1569
1758
  const stageConfig = await loadYaml(configPath);
1570
1759
  if (!stageConfig?.auto_invoke?.enabled) continue;
1571
1760
  const wrapper = stageConfig.auto_invoke.wrapper;
1572
1761
  if (wrapper) {
1573
- const wrapperPath = path7.join(this.projectRoot, wrapper);
1762
+ const wrapperPath = path8.join(this.projectRoot, wrapper);
1574
1763
  if (existsSync5(wrapperPath)) {
1575
1764
  try {
1576
1765
  const stat = statSync4(wrapperPath);
@@ -1589,7 +1778,7 @@ var ConfigValidator = class {
1589
1778
  }
1590
1779
  const promptFile = stageConfig.auto_invoke.prompt_file;
1591
1780
  if (promptFile) {
1592
- const promptPath = path7.join(this.stagesDir, stage, promptFile);
1781
+ const promptPath = path8.join(this.stagesDir, stage, promptFile);
1593
1782
  if (existsSync5(promptPath)) {
1594
1783
  this.addPass(`prompt file exists: ${promptFile}`, stage);
1595
1784
  } else {
@@ -1613,9 +1802,9 @@ var ConfigValidator = class {
1613
1802
  async validateExecutionMode() {
1614
1803
  log("\n\u25B8 Rule: execution_mode [HIGH]", "blue");
1615
1804
  const stages = this.getStagesToValidate();
1616
- const modelsConfig = await loadYaml(path7.join(this.configDir, "models.yaml"));
1805
+ const modelsConfig = await loadYaml(path8.join(this.configDir, "models.yaml"));
1617
1806
  for (const stage of stages) {
1618
- const configPath = path7.join(this.stagesDir, stage, "config.yaml");
1807
+ const configPath = path8.join(this.stagesDir, stage, "config.yaml");
1619
1808
  if (!existsSync5(configPath)) continue;
1620
1809
  const stageConfig = await loadYaml(configPath);
1621
1810
  if (!stageConfig?.execution?.mode) continue;
@@ -1638,7 +1827,7 @@ var ConfigValidator = class {
1638
1827
  log("\n\u25B8 Rule: ai_wrapper_health [HIGH]", "blue");
1639
1828
  const wrappers = ["ai-call.sh", "gemini-wrapper.sh", "codex-wrapper.sh"];
1640
1829
  for (const wrapper of wrappers) {
1641
- const wrapperPath = path7.join(this.projectRoot, "scripts", wrapper);
1830
+ const wrapperPath = path8.join(this.projectRoot, "scripts", wrapper);
1642
1831
  if (!existsSync5(wrapperPath)) {
1643
1832
  this.addResult("high", "ai_wrapper_health", `Wrapper script not found: scripts/${wrapper}`);
1644
1833
  continue;
@@ -1667,14 +1856,14 @@ var ConfigValidator = class {
1667
1856
  */
1668
1857
  async validateMCPServers() {
1669
1858
  log("\n\u25B8 Rule: mcp_servers [MEDIUM]", "blue");
1670
- const fallbackConfig = await loadYaml(path7.join(this.configDir, "mcp_fallbacks.yaml"));
1859
+ const fallbackConfig = await loadYaml(path8.join(this.configDir, "mcp_fallbacks.yaml"));
1671
1860
  if (!fallbackConfig) {
1672
1861
  this.addResult("medium", "mcp_servers", `mcp_fallbacks.yaml not found, cannot validate MCP fallbacks`);
1673
1862
  return;
1674
1863
  }
1675
1864
  const stages = this.getStagesToValidate();
1676
1865
  for (const stage of stages) {
1677
- const configPath = path7.join(this.stagesDir, stage, "config.yaml");
1866
+ const configPath = path8.join(this.stagesDir, stage, "config.yaml");
1678
1867
  if (!existsSync5(configPath)) continue;
1679
1868
  const stageConfig = await loadYaml(configPath);
1680
1869
  const mcpServers = stageConfig?.mcp_servers ?? [];
@@ -1694,7 +1883,7 @@ var ConfigValidator = class {
1694
1883
  */
1695
1884
  async validateEpicCycles() {
1696
1885
  log("\n\u25B8 Rule: epic_cycles [MEDIUM]", "blue");
1697
- const epicConfig = await loadYaml(path7.join(this.configDir, "epic_cycles.yaml"));
1886
+ const epicConfig = await loadYaml(path8.join(this.configDir, "epic_cycles.yaml"));
1698
1887
  if (!epicConfig) {
1699
1888
  this.addResult("medium", "epic_cycles", `epic_cycles.yaml not found`);
1700
1889
  return;
@@ -1725,7 +1914,7 @@ var ConfigValidator = class {
1725
1914
  */
1726
1915
  async validateRequirementsRefinement() {
1727
1916
  log("\n\u25B8 Rule: requirements_refinement [MEDIUM]", "blue");
1728
- const reqConfig = await loadYaml(path7.join(this.configDir, "requirements_refinement.yaml"));
1917
+ const reqConfig = await loadYaml(path8.join(this.configDir, "requirements_refinement.yaml"));
1729
1918
  if (!reqConfig) {
1730
1919
  this.addResult("medium", "requirements_refinement", `requirements_refinement.yaml not found`);
1731
1920
  return;
@@ -1755,7 +1944,7 @@ var ConfigValidator = class {
1755
1944
  */
1756
1945
  async validateImplementationOrder() {
1757
1946
  log("\n\u25B8 Rule: implementation_order [MEDIUM]", "blue");
1758
- const implConfig = await loadYaml(path7.join(this.configDir, "implementation_order.yaml"));
1947
+ const implConfig = await loadYaml(path8.join(this.configDir, "implementation_order.yaml"));
1759
1948
  if (!implConfig) {
1760
1949
  this.addResult("medium", "implementation_order", `implementation_order.yaml not found`);
1761
1950
  return;
@@ -1787,7 +1976,7 @@ var ConfigValidator = class {
1787
1976
  */
1788
1977
  async validateNotionIntegration() {
1789
1978
  log("\n\u25B8 Rule: notion_integration [MEDIUM]", "blue");
1790
- const fallbackConfig = await loadYaml(path7.join(this.configDir, "mcp_fallbacks.yaml"));
1979
+ const fallbackConfig = await loadYaml(path8.join(this.configDir, "mcp_fallbacks.yaml"));
1791
1980
  if (!fallbackConfig) {
1792
1981
  this.addResult("medium", "notion_integration", `mcp_fallbacks.yaml not found, cannot validate Notion integration`);
1793
1982
  return;
@@ -1826,7 +2015,7 @@ var ConfigValidator = class {
1826
2015
  log("\n\u25B8 Rule: prerequisites [MEDIUM]", "blue");
1827
2016
  const stages = this.getStagesToValidate();
1828
2017
  for (const stage of stages) {
1829
- const configPath = path7.join(this.stagesDir, stage, "config.yaml");
2018
+ const configPath = path8.join(this.stagesDir, stage, "config.yaml");
1830
2019
  if (!existsSync5(configPath)) continue;
1831
2020
  const stageConfig = await loadYaml(configPath);
1832
2021
  const prereqs = stageConfig?.transition?.prerequisites ?? [];
@@ -1964,13 +2153,14 @@ function printRecoveryGuide() {
1964
2153
  }
1965
2154
 
1966
2155
  // src/cli/commands/validate.ts
2156
+ init_logger();
1967
2157
  async function validateConfig(projectRoot, options = {}) {
1968
2158
  if (options.recoveryGuide) {
1969
2159
  printRecoveryGuide();
1970
2160
  return 0;
1971
2161
  }
1972
- const configDir = path8.join(projectRoot, "config");
1973
- const stagesDir = path8.join(projectRoot, "stages");
2162
+ const configDir = path9.join(projectRoot, "config");
2163
+ const stagesDir = path9.join(projectRoot, "stages");
1974
2164
  if (!existsSync6(configDir)) {
1975
2165
  logError(`Config directory not found: ${configDir}`);
1976
2166
  return 1;
@@ -1979,7 +2169,7 @@ async function validateConfig(projectRoot, options = {}) {
1979
2169
  logError(`Stages directory not found: ${stagesDir}`);
1980
2170
  return 1;
1981
2171
  }
1982
- if (options.stage && !existsSync6(path8.join(stagesDir, options.stage))) {
2172
+ if (options.stage && !existsSync6(path9.join(stagesDir, options.stage))) {
1983
2173
  logError(`Invalid stage: ${options.stage}`);
1984
2174
  return 1;
1985
2175
  }
@@ -2019,6 +2209,8 @@ async function validateConfig(projectRoot, options = {}) {
2019
2209
  }
2020
2210
 
2021
2211
  // src/cli/commands/checkpoint.ts
2212
+ init_esm_shims();
2213
+ init_logger();
2022
2214
  async function createCheckpointCommand(projectRoot, options = {}) {
2023
2215
  console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
2024
2216
  console.log("\u{1F4BE} Create Checkpoint");
@@ -2165,17 +2357,19 @@ async function cleanupCheckpointsCommand(projectRoot, maxRetention = 10) {
2165
2357
  }
2166
2358
 
2167
2359
  // src/cli/commands/import.ts
2360
+ init_esm_shims();
2361
+ init_logger();
2168
2362
  import fs5 from "fs";
2169
- import path9 from "path";
2170
- import { fileURLToPath as fileURLToPath2 } from "url";
2363
+ import path10 from "path";
2364
+ import { fileURLToPath as fileURLToPath3 } from "url";
2171
2365
  import chalk3 from "chalk";
2172
- var __filename3 = fileURLToPath2(import.meta.url);
2173
- var __dirname3 = path9.dirname(__filename3);
2366
+ var __filename3 = fileURLToPath3(import.meta.url);
2367
+ var __dirname3 = path10.dirname(__filename3);
2174
2368
  function detectImplementation(projectRoot) {
2175
2369
  const evidence = [];
2176
2370
  const srcPatterns = ["src/", "app/", "lib/", "pages/", "components/"];
2177
2371
  for (const pattern of srcPatterns) {
2178
- const dir = path9.join(projectRoot, pattern);
2372
+ const dir = path10.join(projectRoot, pattern);
2179
2373
  if (fs5.existsSync(dir)) {
2180
2374
  const files = fs5.readdirSync(dir);
2181
2375
  const codeFiles = files.filter(
@@ -2188,7 +2382,7 @@ function detectImplementation(projectRoot) {
2188
2382
  }
2189
2383
  const projectFiles = ["package.json", "pyproject.toml", "go.mod", "Cargo.toml", "Gemfile"];
2190
2384
  for (const file of projectFiles) {
2191
- if (fs5.existsSync(path9.join(projectRoot, file))) {
2385
+ if (fs5.existsSync(path10.join(projectRoot, file))) {
2192
2386
  evidence.push(`Found ${file}`);
2193
2387
  }
2194
2388
  }
@@ -2203,7 +2397,7 @@ function detectTests(projectRoot) {
2203
2397
  const evidence = [];
2204
2398
  const testDirs = ["test/", "tests/", "__tests__/", "spec/", "e2e/"];
2205
2399
  for (const dir of testDirs) {
2206
- const testPath = path9.join(projectRoot, dir);
2400
+ const testPath = path10.join(projectRoot, dir);
2207
2401
  if (fs5.existsSync(testPath)) {
2208
2402
  evidence.push(`Found test directory: ${dir}`);
2209
2403
  }
@@ -2220,11 +2414,11 @@ function detectTests(projectRoot) {
2220
2414
  "setup.cfg"
2221
2415
  ];
2222
2416
  for (const config of testConfigs) {
2223
- if (fs5.existsSync(path9.join(projectRoot, config))) {
2417
+ if (fs5.existsSync(path10.join(projectRoot, config))) {
2224
2418
  evidence.push(`Found test config: ${config}`);
2225
2419
  }
2226
2420
  }
2227
- const pkgPath = path9.join(projectRoot, "package.json");
2421
+ const pkgPath = path10.join(projectRoot, "package.json");
2228
2422
  if (fs5.existsSync(pkgPath)) {
2229
2423
  try {
2230
2424
  const pkg = JSON.parse(fs5.readFileSync(pkgPath, "utf-8"));
@@ -2259,7 +2453,7 @@ function detectDeployment(projectRoot) {
2259
2453
  "render.yaml"
2260
2454
  ];
2261
2455
  for (const ciPath of ciPaths) {
2262
- const fullPath = path9.join(projectRoot, ciPath);
2456
+ const fullPath = path10.join(projectRoot, ciPath);
2263
2457
  if (fs5.existsSync(fullPath)) {
2264
2458
  evidence.push(`Found CI/CD config: ${ciPath}`);
2265
2459
  }
@@ -2273,12 +2467,12 @@ function detectDeployment(projectRoot) {
2273
2467
  }
2274
2468
  function detectDocumentation(projectRoot) {
2275
2469
  const detections = [];
2276
- const hasReadme = fs5.existsSync(path9.join(projectRoot, "README.md"));
2277
- const hasArchDocs = ["ARCHITECTURE.md", "docs/architecture.md", "docs/ARCHITECTURE.md"].some((p) => fs5.existsSync(path9.join(projectRoot, p)));
2278
- const hasDocs = fs5.existsSync(path9.join(projectRoot, "docs/"));
2470
+ const hasReadme = fs5.existsSync(path10.join(projectRoot, "README.md"));
2471
+ const hasArchDocs = ["ARCHITECTURE.md", "docs/architecture.md", "docs/ARCHITECTURE.md"].some((p) => fs5.existsSync(path10.join(projectRoot, p)));
2472
+ const hasDocs = fs5.existsSync(path10.join(projectRoot, "docs/"));
2279
2473
  const brainstormEvidence = [];
2280
2474
  if (hasReadme) {
2281
- const readme = fs5.readFileSync(path9.join(projectRoot, "README.md"), "utf-8");
2475
+ const readme = fs5.readFileSync(path10.join(projectRoot, "README.md"), "utf-8");
2282
2476
  if (readme.length > 500) {
2283
2477
  brainstormEvidence.push("README.md with substantial content");
2284
2478
  }
@@ -2311,7 +2505,7 @@ function detectUIUX(projectRoot) {
2311
2505
  "src/styles/"
2312
2506
  ];
2313
2507
  for (const dir of uiDirs) {
2314
- if (fs5.existsSync(path9.join(projectRoot, dir))) {
2508
+ if (fs5.existsSync(path10.join(projectRoot, dir))) {
2315
2509
  evidence.push(`Found UI directory: ${dir}`);
2316
2510
  }
2317
2511
  }
@@ -2323,7 +2517,7 @@ function detectUIUX(projectRoot) {
2323
2517
  ".storybook/"
2324
2518
  ];
2325
2519
  for (const config of styleConfigs) {
2326
- if (fs5.existsSync(path9.join(projectRoot, config))) {
2520
+ if (fs5.existsSync(path10.join(projectRoot, config))) {
2327
2521
  evidence.push(`Found style config: ${config}`);
2328
2522
  }
2329
2523
  }
@@ -2350,11 +2544,11 @@ function detectQA(projectRoot) {
2350
2544
  ".stylelintrc"
2351
2545
  ];
2352
2546
  for (const config of qaConfigs) {
2353
- if (fs5.existsSync(path9.join(projectRoot, config))) {
2547
+ if (fs5.existsSync(path10.join(projectRoot, config))) {
2354
2548
  evidence.push(`Found QA config: ${config}`);
2355
2549
  }
2356
2550
  }
2357
- const tsconfigPath = path9.join(projectRoot, "tsconfig.json");
2551
+ const tsconfigPath = path10.join(projectRoot, "tsconfig.json");
2358
2552
  if (fs5.existsSync(tsconfigPath)) {
2359
2553
  try {
2360
2554
  const tsconfig = fs5.readFileSync(tsconfigPath, "utf-8");
@@ -2401,17 +2595,17 @@ function analyzeProject(projectRoot) {
2401
2595
  return detections.sort((a, b) => STAGE_IDS.indexOf(a.stageId) - STAGE_IDS.indexOf(b.stageId));
2402
2596
  }
2403
2597
  async function importProject(targetPath, options = {}) {
2404
- const projectRoot = path9.resolve(targetPath);
2598
+ const projectRoot = path10.resolve(targetPath);
2405
2599
  if (!fs5.existsSync(projectRoot)) {
2406
2600
  log(`Error: Directory not found: ${projectRoot}`, "red");
2407
2601
  process.exit(1);
2408
2602
  }
2409
- if (fs5.existsSync(path9.join(projectRoot, "state", "progress.json"))) {
2603
+ if (fs5.existsSync(path10.join(projectRoot, "state", "progress.json"))) {
2410
2604
  log("This project already has claude-symphony installed.", "yellow");
2411
2605
  log("Use /auto-pilot or /resume to continue the pipeline.", "yellow");
2412
2606
  return;
2413
2607
  }
2414
- const projectName = path9.basename(projectRoot);
2608
+ const projectName = path10.basename(projectRoot);
2415
2609
  console.log("");
2416
2610
  log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501", "cyan");
2417
2611
  log(` Analyzing project: ${projectName}`, "cyan");
@@ -2439,8 +2633,8 @@ async function importProject(targetPath, options = {}) {
2439
2633
  return;
2440
2634
  }
2441
2635
  log("Installing claude-symphony...", "cyan");
2442
- const packageRoot = path9.resolve(__dirname3, "..", "..");
2443
- const templateDir = path9.join(packageRoot, "template");
2636
+ const packageRoot = path10.resolve(__dirname3, "..", "..");
2637
+ const templateDir = path10.join(packageRoot, "template");
2444
2638
  if (!fs5.existsSync(templateDir)) {
2445
2639
  log(`Error: Template directory not found: ${templateDir}`, "red");
2446
2640
  process.exit(1);
@@ -2454,7 +2648,7 @@ async function importProject(targetPath, options = {}) {
2454
2648
  ".claude/agents"
2455
2649
  ];
2456
2650
  for (const dir of symphonyDirs) {
2457
- ensureDir(path9.join(projectRoot, dir));
2651
+ ensureDir(path10.join(projectRoot, dir));
2458
2652
  }
2459
2653
  const templateFiles = [
2460
2654
  "CLAUDE.md",
@@ -2466,45 +2660,45 @@ async function importProject(targetPath, options = {}) {
2466
2660
  ".claude/settings.json"
2467
2661
  ];
2468
2662
  for (const file of templateFiles) {
2469
- const src = path9.join(templateDir, file);
2470
- const dest = path9.join(projectRoot, file);
2663
+ const src = path10.join(templateDir, file);
2664
+ const dest = path10.join(projectRoot, file);
2471
2665
  if (fs5.existsSync(src) && !fs5.existsSync(dest)) {
2472
- ensureDir(path9.dirname(dest));
2666
+ ensureDir(path10.dirname(dest));
2473
2667
  fs5.copyFileSync(src, dest);
2474
2668
  }
2475
2669
  }
2476
- const commandsDir = path9.join(templateDir, ".claude", "commands");
2670
+ const commandsDir = path10.join(templateDir, ".claude", "commands");
2477
2671
  if (fs5.existsSync(commandsDir)) {
2478
- const destCommands = path9.join(projectRoot, ".claude", "commands");
2672
+ const destCommands = path10.join(projectRoot, ".claude", "commands");
2479
2673
  ensureDir(destCommands);
2480
2674
  for (const cmd of fs5.readdirSync(commandsDir)) {
2481
- const dest = path9.join(destCommands, cmd);
2675
+ const dest = path10.join(destCommands, cmd);
2482
2676
  if (!fs5.existsSync(dest)) {
2483
- fs5.copyFileSync(path9.join(commandsDir, cmd), dest);
2677
+ fs5.copyFileSync(path10.join(commandsDir, cmd), dest);
2484
2678
  }
2485
2679
  }
2486
2680
  }
2487
- const agentsDir = path9.join(templateDir, ".claude", "agents");
2681
+ const agentsDir = path10.join(templateDir, ".claude", "agents");
2488
2682
  if (fs5.existsSync(agentsDir)) {
2489
2683
  for (const agent of fs5.readdirSync(agentsDir)) {
2490
- const agentSrc = path9.join(agentsDir, agent);
2491
- const agentDest = path9.join(projectRoot, ".claude", "agents", agent);
2684
+ const agentSrc = path10.join(agentsDir, agent);
2685
+ const agentDest = path10.join(projectRoot, ".claude", "agents", agent);
2492
2686
  if (fs5.statSync(agentSrc).isDirectory() && !fs5.existsSync(agentDest)) {
2493
2687
  copyDirSync(agentSrc, agentDest);
2494
2688
  }
2495
2689
  }
2496
2690
  }
2497
2691
  for (const stageId of STAGE_IDS) {
2498
- const stageDir = path9.join(projectRoot, "stages", stageId);
2499
- ensureDir(path9.join(stageDir, "outputs"));
2500
- const claudeSrc = path9.join(templateDir, "stages", stageId, "CLAUDE.md");
2501
- const claudeDest = path9.join(stageDir, "CLAUDE.md");
2692
+ const stageDir = path10.join(projectRoot, "stages", stageId);
2693
+ ensureDir(path10.join(stageDir, "outputs"));
2694
+ const claudeSrc = path10.join(templateDir, "stages", stageId, "CLAUDE.md");
2695
+ const claudeDest = path10.join(stageDir, "CLAUDE.md");
2502
2696
  if (fs5.existsSync(claudeSrc) && !fs5.existsSync(claudeDest)) {
2503
2697
  fs5.copyFileSync(claudeSrc, claudeDest);
2504
2698
  }
2505
2699
  }
2506
2700
  for (const stageId of STAGE_IDS) {
2507
- ensureDir(path9.join(projectRoot, "references", stageId));
2701
+ ensureDir(path10.join(projectRoot, "references", stageId));
2508
2702
  }
2509
2703
  log(" Template installed (non-destructive)", "green");
2510
2704
  const progress = createInitialProgress(projectName);
@@ -2533,13 +2727,280 @@ async function importProject(targetPath, options = {}) {
2533
2727
  console.log("");
2534
2728
  }
2535
2729
 
2730
+ // src/cli/commands/ai-call.ts
2731
+ init_esm_shims();
2732
+ import { readFileSync } from "fs";
2733
+ import path12 from "path";
2734
+
2735
+ // src/core/ai/orchestrator.ts
2736
+ init_esm_shims();
2737
+ init_gemini();
2738
+ init_codex();
2739
+ init_logger();
2740
+ import path11 from "path";
2741
+ import { existsSync as existsSync7 } from "fs";
2742
+ init_shell();
2743
+ async function logFallback(projectRoot, originalAi, exitCode, reason) {
2744
+ const stateDir = path11.join(projectRoot, "state");
2745
+ const logPath = path11.join(stateDir, "fallback_log.json");
2746
+ try {
2747
+ await ensureDirAsync(stateDir);
2748
+ let log2 = { fallbacks: [] };
2749
+ if (existsSync7(logPath)) {
2750
+ const existing = await readJson(logPath);
2751
+ if (existing) {
2752
+ log2 = existing;
2753
+ }
2754
+ }
2755
+ log2.fallbacks.push({
2756
+ timestamp: getTimestamp(),
2757
+ originalAi,
2758
+ exitCode,
2759
+ reason
2760
+ });
2761
+ await writeJson(logPath, log2);
2762
+ } catch {
2763
+ }
2764
+ }
2765
+ async function callAI(model, prompt, options = {}) {
2766
+ const { timeout = 300, projectRoot, quiet = false } = options;
2767
+ const originalLog = console.log;
2768
+ if (quiet) {
2769
+ console.log = console.error;
2770
+ }
2771
+ try {
2772
+ return await callAIInner(model, prompt, { timeout, projectRoot, quiet });
2773
+ } finally {
2774
+ if (quiet) {
2775
+ console.log = originalLog;
2776
+ }
2777
+ }
2778
+ }
2779
+ async function callAIInner(model, prompt, options) {
2780
+ const { timeout, projectRoot } = options;
2781
+ const normalizedModel = model.toLowerCase();
2782
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
2783
+ logInfo("AI Call Router");
2784
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
2785
+ console.log(` Model: ${normalizedModel}`);
2786
+ console.log(` Timeout: ${timeout}s
2787
+ `);
2788
+ if (normalizedModel === "claudecode" || normalizedModel === "claude") {
2789
+ console.log("Routing to ClaudeCode...\n");
2790
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
2791
+ logSuccess("EXECUTE WITH CLAUDECODE");
2792
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
2793
+ console.log(prompt);
2794
+ console.log("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
2795
+ console.log("ACTION_REQUIRED: CLAUDECODE_EXECUTE");
2796
+ return {
2797
+ success: true,
2798
+ model: "claudecode",
2799
+ output: prompt,
2800
+ fallbackUsed: false
2801
+ };
2802
+ }
2803
+ let result2;
2804
+ switch (normalizedModel) {
2805
+ case "gemini":
2806
+ console.log("Executing gemini wrapper...\n");
2807
+ result2 = await callGemini(prompt, { timeout });
2808
+ break;
2809
+ case "codex":
2810
+ console.log("Executing codex wrapper...\n");
2811
+ result2 = await callCodex(prompt, { timeout });
2812
+ break;
2813
+ default:
2814
+ logError(`Unknown AI model: ${normalizedModel}`);
2815
+ console.log(" Supported: gemini, codex, claudecode");
2816
+ return {
2817
+ success: false,
2818
+ model: normalizedModel,
2819
+ fallbackUsed: false
2820
+ };
2821
+ }
2822
+ if (result2.fallbackRequired) {
2823
+ console.log("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
2824
+ logWarning("AUTO-FALLBACK TRIGGERED");
2825
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
2826
+ console.log(` Primary AI: ${normalizedModel}`);
2827
+ console.log(` Fallback Signal: ${result2.fallbackSignal}`);
2828
+ console.log(` Reason: ${result2.fallbackReason}`);
2829
+ if (projectRoot) {
2830
+ const exitCode = getExitCodeForSignal(result2.fallbackSignal);
2831
+ await logFallback(projectRoot, normalizedModel, exitCode, result2.fallbackReason);
2832
+ }
2833
+ console.log("\nFalling back to ClaudeCode...\n");
2834
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
2835
+ logSuccess("EXECUTE WITH CLAUDECODE");
2836
+ console.log("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
2837
+ console.log(prompt);
2838
+ console.log("\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
2839
+ console.log("ACTION_REQUIRED: CLAUDECODE_FALLBACK");
2840
+ console.log(`ORIGINAL_AI: ${normalizedModel}`);
2841
+ console.log(`FALLBACK_REASON: ${result2.fallbackSignal}`);
2842
+ return {
2843
+ success: false,
2844
+ model: normalizedModel,
2845
+ output: prompt,
2846
+ fallbackUsed: true,
2847
+ fallbackModel: "claudecode",
2848
+ fallbackReason: result2.fallbackReason
2849
+ };
2850
+ }
2851
+ return {
2852
+ success: true,
2853
+ model: normalizedModel,
2854
+ output: result2.output,
2855
+ fallbackUsed: false
2856
+ };
2857
+ }
2858
+ function getExitCodeForSignal(signal) {
2859
+ switch (signal) {
2860
+ case "CLI_NOT_FOUND":
2861
+ return 100;
2862
+ case "TIMEOUT":
2863
+ return 101;
2864
+ case "API_ERROR":
2865
+ return 102;
2866
+ case "OUTPUT_FAILED":
2867
+ return 103;
2868
+ default:
2869
+ return 1;
2870
+ }
2871
+ }
2872
+
2873
+ // src/cli/commands/ai-call.ts
2874
+ init_logger();
2875
+
2876
+ // src/utils/jsonc.ts
2877
+ init_esm_shims();
2878
+ import fs6 from "fs/promises";
2879
+ import { parse as parseJsonc, modify, applyEdits, format } from "jsonc-parser";
2880
+ async function loadJsonc(filePath) {
2881
+ try {
2882
+ const content = await fs6.readFile(filePath, "utf8");
2883
+ const errors = [];
2884
+ const result2 = parseJsonc(content, errors, {
2885
+ allowTrailingComma: true,
2886
+ allowEmptyContent: true
2887
+ });
2888
+ if (errors.length > 0) {
2889
+ console.error(`JSONC parse errors in ${filePath}:`, errors);
2890
+ }
2891
+ return result2;
2892
+ } catch {
2893
+ return null;
2894
+ }
2895
+ }
2896
+
2897
+ // src/cli/commands/ai-call.ts
2898
+ var EXIT_SUCCESS = 0;
2899
+ var EXIT_FALLBACK = 10;
2900
+ var EXIT_ERROR = 1;
2901
+ async function getStageModels(projectRoot, stageId) {
2902
+ const pipelinePath = path12.join(projectRoot, "config", "pipeline.jsonc");
2903
+ const config = await loadJsonc(pipelinePath);
2904
+ if (!config) return [];
2905
+ const stages = config.stages ?? [];
2906
+ const stage = stages.find((s) => s.id === stageId);
2907
+ return stage?.models ?? [];
2908
+ }
2909
+ function findExternalModel(models) {
2910
+ for (const m of models) {
2911
+ const lower = m.toLowerCase();
2912
+ if (lower !== "claudecode" && lower !== "claude") {
2913
+ return lower;
2914
+ }
2915
+ }
2916
+ return null;
2917
+ }
2918
+ async function aiCallCommand(options) {
2919
+ const startTime = Date.now();
2920
+ const projectRoot = process.cwd();
2921
+ const { stage, timeout: timeoutStr } = options;
2922
+ const timeout = parseInt(timeoutStr ?? "300", 10);
2923
+ let prompt;
2924
+ if (options.promptFile) {
2925
+ try {
2926
+ prompt = readFileSync(path12.resolve(options.promptFile), "utf8");
2927
+ } catch (err) {
2928
+ logError(`Failed to read prompt file: ${options.promptFile}`);
2929
+ return EXIT_ERROR;
2930
+ }
2931
+ } else if (options.prompt) {
2932
+ prompt = options.prompt;
2933
+ } else {
2934
+ logError("Either --prompt or --prompt-file is required");
2935
+ return EXIT_ERROR;
2936
+ }
2937
+ const models = await getStageModels(projectRoot, stage);
2938
+ const externalModel = findExternalModel(models);
2939
+ if (!externalModel) {
2940
+ const output = JSON.stringify({
2941
+ success: false,
2942
+ model: null,
2943
+ output: null,
2944
+ fallback: { used: true, reason: "claudecode-only stage" },
2945
+ stage,
2946
+ duration_ms: Date.now() - startTime
2947
+ });
2948
+ process.stdout.write(output + "\n");
2949
+ return EXIT_FALLBACK;
2950
+ }
2951
+ try {
2952
+ const result2 = await callAI(externalModel, prompt, {
2953
+ timeout,
2954
+ projectRoot,
2955
+ quiet: true
2956
+ });
2957
+ if (result2.success) {
2958
+ const output2 = JSON.stringify({
2959
+ success: true,
2960
+ model: result2.model,
2961
+ output: result2.output,
2962
+ fallback: { used: false },
2963
+ stage,
2964
+ duration_ms: Date.now() - startTime
2965
+ });
2966
+ process.stdout.write(output2 + "\n");
2967
+ return EXIT_SUCCESS;
2968
+ }
2969
+ const output = JSON.stringify({
2970
+ success: false,
2971
+ model: result2.model,
2972
+ output: null,
2973
+ fallback: {
2974
+ used: true,
2975
+ reason: result2.fallbackReason ?? "model call failed"
2976
+ },
2977
+ stage,
2978
+ duration_ms: Date.now() - startTime
2979
+ });
2980
+ process.stdout.write(output + "\n");
2981
+ return result2.fallbackUsed ? EXIT_FALLBACK : EXIT_ERROR;
2982
+ } catch (err) {
2983
+ logError(`ai-call error: ${err instanceof Error ? err.message : String(err)}`);
2984
+ const output = JSON.stringify({
2985
+ success: false,
2986
+ model: externalModel,
2987
+ output: null,
2988
+ fallback: { used: true, reason: String(err) },
2989
+ stage,
2990
+ duration_ms: Date.now() - startTime
2991
+ });
2992
+ process.stdout.write(output + "\n");
2993
+ return EXIT_ERROR;
2994
+ }
2995
+ }
2996
+
2536
2997
  // src/cli/index.ts
2537
- var __filename4 = fileURLToPath3(import.meta.url);
2538
- var __dirname4 = path10.dirname(__filename4);
2998
+ var __filename4 = fileURLToPath4(import.meta.url);
2999
+ var __dirname4 = path13.dirname(__filename4);
2539
3000
  function getPackageVersion() {
2540
3001
  try {
2541
- const pkgPath = path10.resolve(__dirname4, "../../package.json");
2542
- const pkg = JSON.parse(readFileSync(pkgPath, "utf8"));
3002
+ const pkgPath = path13.resolve(__dirname4, "../../package.json");
3003
+ const pkg = JSON.parse(readFileSync2(pkgPath, "utf8"));
2543
3004
  return pkg.version || "0.0.0";
2544
3005
  } catch {
2545
3006
  return "0.0.0";
@@ -2613,4 +3074,8 @@ program.command("checkpoint-cleanup").description("Cleanup old checkpoints").opt
2613
3074
  const maxRetention = parseInt(options.max, 10);
2614
3075
  await cleanupCheckpointsCommand(projectRoot, maxRetention);
2615
3076
  });
3077
+ program.command("ai-call").description("Call external AI model for a pipeline stage").requiredOption("--stage <id>", "Stage ID (e.g. 01-brainstorm)").option("--prompt <text>", "Prompt text").option("--prompt-file <path>", "Path to prompt file").option("--timeout <seconds>", "Timeout in seconds", "300").action(async (options) => {
3078
+ const exitCode = await aiCallCommand(options);
3079
+ process.exit(exitCode);
3080
+ });
2616
3081
  program.parse();