reygent-code 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -5,7 +5,7 @@ import { Command } from "commander";
5
5
  import { readFileSync as readFileSync12 } from "fs";
6
6
  import { dirname as dirname7, join as join14 } from "path";
7
7
  import { fileURLToPath as fileURLToPath2 } from "url";
8
- import chalk29 from "chalk";
8
+ import chalk30 from "chalk";
9
9
 
10
10
  // src/child-registry.ts
11
11
  var activeChildProcesses = /* @__PURE__ */ new Set();
@@ -52,6 +52,9 @@ function isDebug() {
52
52
  return debugEnabled || process.env.REYGENT_DEBUG === "1";
53
53
  }
54
54
 
55
+ // src/model.ts
56
+ import chalk6 from "chalk";
57
+
55
58
  // src/config.ts
56
59
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
57
60
  import { join as join2 } from "path";
@@ -524,6 +527,7 @@ var SHORT_ALIASES = {
524
527
  "claude-3-opus": "claude-3-opus-20240229"
525
528
  };
526
529
  var DEFAULT_MODEL = "claude-sonnet-4-5-20250929";
530
+ var vertexAiLoggedForClaude = false;
527
531
  function extractTokenUsage(msg) {
528
532
  const usageData = msg.usage;
529
533
  const hasInput = usageData?.input_tokens !== void 0 || usageData?.cache_creation_input_tokens !== void 0 || usageData?.cache_read_input_tokens !== void 0 || msg.input_tokens !== void 0;
@@ -576,6 +580,18 @@ var claudeAdapter = {
576
580
  if (options.autoApprove) {
577
581
  args.push("--allowedTools", "Bash", "Edit", "Write", "Read", "Glob", "Grep");
578
582
  }
583
+ const name = options.agentName;
584
+ const vertexProject = process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT;
585
+ const vertexRegion = process.env.GOOGLE_CLOUD_REGION;
586
+ const hasVertexConfig = !!vertexProject;
587
+ if (hasVertexConfig && !options.quiet && !vertexAiLoggedForClaude) {
588
+ const region = vertexRegion ?? "(using CLI default)";
589
+ process.stderr.write(
590
+ chalk2.gray(`[${name}] Vertex AI detected: project=${vertexProject}, region=${region}
591
+ `)
592
+ );
593
+ vertexAiLoggedForClaude = true;
594
+ }
579
595
  const stdinMode = options.autoApprove === false ? "inherit" : "ignore";
580
596
  const child = spawn("claude", args, {
581
597
  stdio: [stdinMode, "pipe", "pipe"],
@@ -584,9 +600,10 @@ var claudeAdapter = {
584
600
  });
585
601
  registerChildProcess(child);
586
602
  let resultText = "";
603
+ let resultErrorMessage;
604
+ let resultApiErrorStatus;
587
605
  let resultUsage;
588
606
  const textChunks = [];
589
- const name = options.agentName;
590
607
  const timeout = setTimeout(() => {
591
608
  if (child.pid && process.platform !== "win32") {
592
609
  try {
@@ -606,7 +623,13 @@ var claudeAdapter = {
606
623
  if (stdoutEnded && stderrEnded && processExitCode !== null) {
607
624
  clearTimeout(timeout);
608
625
  const stdout = resultText || textChunks.join("\n");
609
- resolve5({ stdout, exitCode: processExitCode, usage: resultUsage });
626
+ resolve5({
627
+ stdout,
628
+ exitCode: processExitCode,
629
+ usage: resultUsage,
630
+ errorMessage: resultErrorMessage,
631
+ apiErrorStatus: resultApiErrorStatus
632
+ });
610
633
  }
611
634
  };
612
635
  const stdoutRL = createInterface({ input: child.stdout });
@@ -641,6 +664,10 @@ var claudeAdapter = {
641
664
  } else if (event.type === "result") {
642
665
  const msg = event;
643
666
  resultText = msg.result;
667
+ if (msg.is_error) {
668
+ resultErrorMessage = msg.result;
669
+ resultApiErrorStatus = msg.api_error_status;
670
+ }
644
671
  const { inputTokens, outputTokens, cachedTokens, cacheWriteTokens } = extractTokenUsage(msg);
645
672
  const hasUsage = msg.total_cost_usd !== void 0 || msg.duration_ms !== void 0 || msg.num_turns !== void 0 || inputTokens !== void 0 || outputTokens !== void 0;
646
673
  if (hasUsage) {
@@ -730,6 +757,7 @@ var SUPPORTED_MODELS2 = [
730
757
  ];
731
758
  var SHORT_ALIASES2 = {};
732
759
  var DEFAULT_MODEL2 = "gemini-2.5-pro";
760
+ var vertexAiLoggedForGemini = false;
733
761
  var availabilityCache2 = null;
734
762
  var geminiAdapter = {
735
763
  name: "gemini",
@@ -764,6 +792,17 @@ var geminiAdapter = {
764
792
  }
765
793
  const name = options.agentName;
766
794
  const stdinMode = options.autoApprove === false ? "inherit" : "ignore";
795
+ const vertexProject = process.env.GOOGLE_CLOUD_PROJECT || process.env.GCLOUD_PROJECT;
796
+ const vertexRegion = process.env.GOOGLE_CLOUD_REGION;
797
+ const hasVertexConfig = !!vertexProject;
798
+ if (hasVertexConfig && !options.quiet && !vertexAiLoggedForGemini) {
799
+ const region = vertexRegion ?? "(using CLI default)";
800
+ process.stderr.write(
801
+ chalk3.gray(`[${name}] Vertex AI detected: project=${vertexProject}, region=${region}
802
+ `)
803
+ );
804
+ vertexAiLoggedForGemini = true;
805
+ }
767
806
  const child = spawn2("gemini", args, {
768
807
  stdio: [stdinMode, "pipe", "pipe"],
769
808
  env: { ...process.env, GEMINI_CLI_TRUST_WORKSPACE: "true" },
@@ -809,14 +848,47 @@ var geminiAdapter = {
809
848
  let inputTokens;
810
849
  let outputTokens;
811
850
  let cachedTokens;
851
+ let errorMessage;
852
+ let apiErrorStatus;
812
853
  try {
813
854
  const parsed = JSON.parse(stdout);
814
855
  resultText = parsed.response ?? parsed.text ?? stdout;
815
856
  inputTokens = parsed.usage_metadata?.prompt_token_count ?? parsed.input_tokens;
816
857
  outputTokens = parsed.usage_metadata?.candidates_token_count ?? parsed.output_tokens;
817
858
  cachedTokens = parsed.usage_metadata?.cached_content_token_count;
859
+ if (parsed.error) {
860
+ errorMessage = parsed.error.message;
861
+ let statusCode = parsed.error.status;
862
+ if (parsed.error.code) {
863
+ if (typeof parsed.error.code === "number") {
864
+ statusCode = parsed.error.code;
865
+ } else if (typeof parsed.error.code === "string") {
866
+ const code2 = parsed.error.code.toLowerCase();
867
+ if (code2 === "not_found" || code2 === "model_not_found") {
868
+ statusCode = 404;
869
+ } else if (code2 === "permission_denied" || code2 === "unauthenticated") {
870
+ statusCode = 403;
871
+ } else if (code2 === "invalid_api_key" || code2 === "invalid_authentication") {
872
+ statusCode = 401;
873
+ } else if (code2 === "resource_exhausted" || code2 === "rate_limit_exceeded") {
874
+ statusCode = 429;
875
+ } else if (code2 === "internal" || code2 === "server_error") {
876
+ statusCode = 500;
877
+ } else if (code2 === "invalid_argument") {
878
+ statusCode = 400;
879
+ }
880
+ }
881
+ }
882
+ apiErrorStatus = statusCode;
883
+ }
818
884
  } catch {
819
885
  }
886
+ if (code !== 0 && !errorMessage && stderrChunks.length > 0) {
887
+ const stderr = stderrChunks.join("").trim();
888
+ if (stderr) {
889
+ errorMessage = stderr;
890
+ }
891
+ }
820
892
  resolve5({
821
893
  stdout: resultText,
822
894
  exitCode: code ?? 1,
@@ -826,7 +898,9 @@ var geminiAdapter = {
826
898
  outputTokens,
827
899
  cachedTokens,
828
900
  provider: "gemini"
829
- }
901
+ },
902
+ errorMessage,
903
+ apiErrorStatus
830
904
  });
831
905
  });
832
906
  });
@@ -922,8 +996,10 @@ var codexAdapter = {
922
996
  child.stdout.on("data", (chunk) => {
923
997
  stdout += chunk.toString();
924
998
  });
999
+ const stderrChunks = [];
925
1000
  child.stderr.on("data", (chunk) => {
926
1001
  const text = chunk.toString();
1002
+ stderrChunks.push(text);
927
1003
  if (options.onActivity) {
928
1004
  const line = text.trim();
929
1005
  if (line) options.onActivity({ agent: name, detail: line.slice(0, 80) });
@@ -942,14 +1018,44 @@ var codexAdapter = {
942
1018
  let inputTokens;
943
1019
  let outputTokens;
944
1020
  let cachedTokens;
1021
+ let errorMessage;
1022
+ let apiErrorStatus;
945
1023
  try {
946
1024
  const parsed = JSON.parse(stdout);
947
1025
  resultText = parsed.response ?? parsed.text ?? stdout;
948
1026
  inputTokens = parsed.usage?.prompt_tokens ?? parsed.input_tokens;
949
1027
  outputTokens = parsed.usage?.completion_tokens ?? parsed.output_tokens;
950
1028
  cachedTokens = parsed.usage?.prompt_tokens_details?.cached_tokens ?? parsed.cached_tokens;
1029
+ if (parsed.error) {
1030
+ errorMessage = parsed.error.message;
1031
+ if (typeof parsed.error.code === "string") {
1032
+ const code2 = parsed.error.code;
1033
+ if (code2 === "model_not_found" || code2 === "invalid_model") {
1034
+ apiErrorStatus = 404;
1035
+ } else if (code2 === "invalid_api_key" || code2 === "invalid_request_error") {
1036
+ apiErrorStatus = 401;
1037
+ } else if (code2 === "rate_limit_exceeded") {
1038
+ apiErrorStatus = 429;
1039
+ } else if (code2 === "insufficient_quota") {
1040
+ apiErrorStatus = 402;
1041
+ } else if (code2 === "server_error") {
1042
+ apiErrorStatus = 500;
1043
+ } else if (code2.includes("not_found")) {
1044
+ apiErrorStatus = 404;
1045
+ } else if (code2.includes("auth") || code2.includes("unauthorized")) {
1046
+ apiErrorStatus = 401;
1047
+ }
1048
+ }
1049
+ apiErrorStatus = apiErrorStatus ?? parsed.error.status;
1050
+ }
951
1051
  } catch {
952
1052
  }
1053
+ if (code !== 0 && !errorMessage && stderrChunks.length > 0) {
1054
+ const stderr = stderrChunks.join("").trim();
1055
+ if (stderr) {
1056
+ errorMessage = stderr;
1057
+ }
1058
+ }
953
1059
  resolve5({
954
1060
  stdout: resultText,
955
1061
  exitCode: code ?? 1,
@@ -960,7 +1066,9 @@ var codexAdapter = {
960
1066
  cachedTokens,
961
1067
  // Note: cacheWriteTokens not extracted — OpenAI doesn't currently expose this field
962
1068
  provider: "codex"
963
- }
1069
+ },
1070
+ errorMessage,
1071
+ apiErrorStatus
964
1072
  });
965
1073
  });
966
1074
  });
@@ -1113,6 +1221,7 @@ var SUPPORTED_MODELS5 = getProvider("claude").supportedModels;
1113
1221
  var DEFAULT_MODEL5 = getProvider("claude").defaultModel;
1114
1222
  var modelOverride = null;
1115
1223
  var providerOverride = null;
1224
+ var warnedCustomModels = /* @__PURE__ */ new Set();
1116
1225
  function setModelOverride(id) {
1117
1226
  modelOverride = id;
1118
1227
  }
@@ -1126,17 +1235,20 @@ function validateModel(id, providerName) {
1126
1235
  if (name === "openrouter") return resolved;
1127
1236
  const valid = provider.supportedModels.some((m) => m.id === resolved);
1128
1237
  if (!valid) {
1129
- const list = provider.supportedModels.map((m) => ` ${m.id} \u2014 ${m.label}`).join("\n");
1130
- const aliases = Object.entries(provider.shortAliases).map(([alias, full]) => ` ${alias} \u2192 ${full}`).join("\n");
1131
- let msg = `Unknown model: ${id}
1132
-
1133
- Supported models for ${name}:
1134
- ${list}`;
1135
- if (aliases) msg += `
1136
-
1137
- Short aliases:
1138
- ${aliases}`;
1139
- throw new TaskError(msg);
1238
+ const warningKey = `${name}:${resolved}`;
1239
+ if (!warnedCustomModels.has(warningKey)) {
1240
+ const list = provider.supportedModels.map((m) => ` ${m.id} \u2014 ${m.label}`).join("\n");
1241
+ const aliases = Object.entries(provider.shortAliases).map(([alias, full]) => ` ${alias} \u2192 ${full}`).join("\n");
1242
+ console.log(chalk6.yellow("Warning:"), `"${id}" not in ${name} supported models list. Using custom model.`);
1243
+ console.log(chalk6.gray("Supported models for"), chalk6.cyan(name) + chalk6.gray(":"));
1244
+ console.log(list);
1245
+ if (aliases) {
1246
+ console.log(chalk6.gray("\nShort aliases:"));
1247
+ console.log(aliases);
1248
+ }
1249
+ console.log("");
1250
+ warnedCustomModels.add(warningKey);
1251
+ }
1140
1252
  }
1141
1253
  return resolved;
1142
1254
  }
@@ -1184,12 +1296,12 @@ function resolveTelemetryEnabled(override, config) {
1184
1296
 
1185
1297
  // src/commands/agent.ts
1186
1298
  import { select } from "@inquirer/prompts";
1187
- import chalk8 from "chalk";
1299
+ import chalk9 from "chalk";
1188
1300
 
1189
1301
  // src/spec.ts
1190
1302
  import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
1191
1303
  import { basename as basename2, extname, resolve as resolve3 } from "path";
1192
- import chalk7 from "chalk";
1304
+ import chalk8 from "chalk";
1193
1305
 
1194
1306
  // src/linear.ts
1195
1307
  var LINEAR_URL_PATTERN = /^https:\/\/linear\.app\/[^/]+\/issue\/([A-Z]+-\d+)/;
@@ -1407,7 +1519,7 @@ function loadEnvFile() {
1407
1519
 
1408
1520
  // src/chesstrace/index.ts
1409
1521
  import { randomUUID } from "crypto";
1410
- import chalk6 from "chalk";
1522
+ import chalk7 from "chalk";
1411
1523
 
1412
1524
  // src/chesstrace/events.ts
1413
1525
  var TelemetryLevel = /* @__PURE__ */ ((TelemetryLevel2) => {
@@ -1598,7 +1710,7 @@ var Chesstrace = class {
1598
1710
  try {
1599
1711
  const deleted = await backend.prune(olderThan);
1600
1712
  if (deleted > 0) {
1601
- console.log(chalk6.gray(`Pruned ${deleted} event(s) older than ${retentionDays} days`));
1713
+ console.log(chalk7.gray(`Pruned ${deleted} event(s) older than ${retentionDays} days`));
1602
1714
  }
1603
1715
  } catch (err) {
1604
1716
  this.config.onError?.(err, "auto-prune");
@@ -1778,7 +1890,7 @@ function readSpec(filePath) {
1778
1890
  }
1779
1891
  const ext = extname(resolved).toLowerCase();
1780
1892
  if (ext !== ".md" && ext !== ".markdown") {
1781
- console.log(chalk7.yellow("Warning:"), `${basename2(resolved)} is not a .md file`);
1893
+ console.log(chalk8.yellow("Warning:"), `${basename2(resolved)} is not a .md file`);
1782
1894
  }
1783
1895
  const content = readFileSync4(resolved, "utf-8");
1784
1896
  if (!content.trim()) {
@@ -2337,7 +2449,7 @@ async function agentCommand(name, options) {
2337
2449
  const found = agents.find((a) => a.name === name);
2338
2450
  if (!found) {
2339
2451
  const validNames = agents.map((a) => a.name).join(", ");
2340
- console.log(chalk8.red.bold("Error:"), `Unknown agent "${name}". Valid agents: ${validNames}`);
2452
+ console.log(chalk9.red.bold("Error:"), `Unknown agent "${name}". Valid agents: ${validNames}`);
2341
2453
  process.exit(1);
2342
2454
  }
2343
2455
  agent = found;
@@ -2348,9 +2460,9 @@ async function agentCommand(name, options) {
2348
2460
  if (!process.stdin.isTTY) {
2349
2461
  const validNames = agents.map((a) => a.name);
2350
2462
  const displayNames = validNames.length > 5 ? `${validNames.slice(0, 5).join(", ")}, ... (${validNames.length - 5} more)` : validNames.join(", ");
2351
- console.log(chalk8.red.bold("Error:"), `Agent name required in non-interactive mode. Valid agents: ${displayNames}`);
2463
+ console.log(chalk9.red.bold("Error:"), `Agent name required in non-interactive mode. Valid agents: ${displayNames}`);
2352
2464
  if (validNames.length > 5) {
2353
- console.log(chalk8.gray(" Run 'reygent list' to see all agents."));
2465
+ console.log(chalk9.gray(" Run 'reygent list' to see all agents."));
2354
2466
  }
2355
2467
  process.exit(1);
2356
2468
  }
@@ -2380,19 +2492,19 @@ ${spec.content}`;
2380
2492
  const provider = getProvider(providerName);
2381
2493
  const modelId = agent.model ? validateModel(agent.model, providerName) : await resolveModel(providerName);
2382
2494
  console.log(
2383
- chalk8.bold.cyan(`
2384
- Starting session with ${agent.name} agent`) + chalk8.gray(` (${providerName}/${modelId})`) + "\n"
2495
+ chalk9.bold.cyan(`
2496
+ Starting session with ${agent.name} agent`) + chalk9.gray(` (${providerName}/${modelId})`) + "\n"
2385
2497
  );
2386
2498
  const exitCode = await provider.spawnInteractive(systemPrompt, modelId);
2387
2499
  process.exit(exitCode);
2388
2500
  } catch (err) {
2389
2501
  if (err instanceof SpecError || err instanceof TaskError) {
2390
- console.log(chalk8.red.bold("Error:"), err.message);
2502
+ console.log(chalk9.red.bold("Error:"), err.message);
2391
2503
  if (isDebug()) console.error(err.stack);
2392
2504
  process.exit(1);
2393
2505
  }
2394
2506
  const message = err instanceof Error ? err.message : String(err);
2395
- console.log(chalk8.red.bold("Internal error:"), message);
2507
+ console.log(chalk9.red.bold("Internal error:"), message);
2396
2508
  if (isDebug()) console.error(err instanceof Error ? err.stack : err);
2397
2509
  process.exit(2);
2398
2510
  }
@@ -2403,12 +2515,12 @@ Starting session with ${agent.name} agent`) + chalk8.gray(` (${providerName}/${m
2403
2515
  import { createInterface as createInterface2 } from "readline";
2404
2516
  import { writeFileSync } from "fs";
2405
2517
  import { resolve as resolve4 } from "path";
2406
- import chalk11 from "chalk";
2518
+ import chalk12 from "chalk";
2407
2519
 
2408
2520
  // src/knowledge/loader.ts
2409
2521
  import { existsSync as existsSync7, readFileSync as readFileSync5, readdirSync as readdirSync2, statSync as statSync3 } from "fs";
2410
2522
  import { join as join5 } from "path";
2411
- import chalk9 from "chalk";
2523
+ import chalk10 from "chalk";
2412
2524
  import { marked } from "marked";
2413
2525
 
2414
2526
  // src/test-env.ts
@@ -2436,7 +2548,7 @@ function readMarkdown(filePath) {
2436
2548
  const content = readFileSync5(filePath, "utf-8");
2437
2549
  if (!content || content.trim().length === 0) return "";
2438
2550
  if (!validateMarkdown(content)) {
2439
- console.warn(chalk9.yellow(`\u26A0 Suspicious content detected in ${filePath}, skipping`));
2551
+ console.warn(chalk10.yellow(`\u26A0 Suspicious content detected in ${filePath}, skipping`));
2440
2552
  return null;
2441
2553
  }
2442
2554
  return sanitizeMarkdown(content);
@@ -2517,7 +2629,7 @@ async function loadKnowledge(agentName, stage) {
2517
2629
  const knowledgeDir = findKnowledgeDir();
2518
2630
  if (!knowledgeDir) {
2519
2631
  if (!isTestEnvironment() && process.env.REYGENT_DEBUG !== "knowledge") {
2520
- console.warn(chalk9.yellow("\u26A0 No knowledge directory found. Run 'reygent init' to create .reygent/knowledge/"));
2632
+ console.warn(chalk10.yellow("\u26A0 No knowledge directory found. Run 'reygent init' to create .reygent/knowledge/"));
2521
2633
  }
2522
2634
  return {
2523
2635
  agentTips: "",
@@ -2616,7 +2728,56 @@ function searchKnowledge(query) {
2616
2728
  return results;
2617
2729
  }
2618
2730
 
2731
+ // src/telemetry-helpers.ts
2732
+ function emitErrorTask(message, stage, options) {
2733
+ const chesstrace = getChesstrace();
2734
+ if (chesstrace) {
2735
+ try {
2736
+ chesstrace.emit(Events.ERROR_TASK, {
2737
+ type: "TaskError",
2738
+ message,
2739
+ stage,
2740
+ ...options?.agent && { agent: options.agent },
2741
+ ...options?.errorMessage && { errorMessage: options.errorMessage },
2742
+ ...options?.apiErrorStatus && { apiErrorStatus: options.apiErrorStatus }
2743
+ });
2744
+ } catch (err) {
2745
+ if (isDebug()) {
2746
+ const errMsg = err instanceof Error ? err.message : String(err);
2747
+ console.error(`[DEBUG] Telemetry emit failed (ERROR_TASK): ${errMsg}`);
2748
+ }
2749
+ }
2750
+ }
2751
+ }
2752
+
2619
2753
  // src/spawn.ts
2754
+ function looksLikeMalformedModel(model) {
2755
+ if (!model) return false;
2756
+ const trimmed = model.trim();
2757
+ if (trimmed.length === 0) return true;
2758
+ if (/\s/.test(trimmed)) return true;
2759
+ if (/^[^a-zA-Z0-9]|[^a-zA-Z0-9]$/.test(trimmed)) return true;
2760
+ if (trimmed.length < 3) return true;
2761
+ return false;
2762
+ }
2763
+ function formatExitDetail(result, model) {
2764
+ if (result.errorMessage) {
2765
+ const status = result.apiErrorStatus ? ` (HTTP ${result.apiErrorStatus})` : "";
2766
+ let detail = `
2767
+ ${result.errorMessage}${status}`;
2768
+ if (result.apiErrorStatus === 404 && /not available/i.test(result.errorMessage) && looksLikeMalformedModel(model)) {
2769
+ detail += `
2770
+ Tip: edit .reygent/config.json "model" field, or run \`reygent config\` to pick a supported model.`;
2771
+ }
2772
+ return detail;
2773
+ }
2774
+ const trimmed = result.stdout.trim();
2775
+ if (!trimmed) return "";
2776
+ const truncated = trimmed.slice(0, 500);
2777
+ const suffix = trimmed.length > 500 ? "..." : "";
2778
+ return `
2779
+ ${truncated}${suffix}`;
2780
+ }
2620
2781
  async function spawnAgentStream(name, prompt2, timeoutMs, options) {
2621
2782
  const providerName = options?.provider ?? resolveProvider();
2622
2783
  const adapter = getProvider(providerName);
@@ -2628,13 +2789,12 @@ async function spawnAgentStream(name, prompt2, timeoutMs, options) {
2628
2789
  provider: providerName,
2629
2790
  reason
2630
2791
  });
2631
- chesstrace.emit(Events.ERROR_TASK, {
2632
- type: "TaskError",
2633
- message: `Provider "${providerName}" is not available: ${reason}`,
2634
- stage: options?.stage ?? "spawn",
2635
- agent: name
2636
- });
2637
2792
  }
2793
+ emitErrorTask(
2794
+ `Provider "${providerName}" is not available: ${reason}`,
2795
+ options?.stage ?? "spawn",
2796
+ { agent: name }
2797
+ );
2638
2798
  throw new TaskError(`Provider "${providerName}" is not available: ${reason}`);
2639
2799
  }
2640
2800
  const modelId = options?.model ?? await resolveModel(providerName);
@@ -2818,18 +2978,16 @@ async function runPlanner(spec, previousAnswers, options) {
2818
2978
  const agents = getAgents();
2819
2979
  const plannerAgent = agents.find((a) => a.name === "planner");
2820
2980
  const prompt2 = buildPrompt(spec, previousAnswers, options);
2821
- const { stdout: raw, exitCode, usage } = await spawnAgentStream("planner", prompt2, 3e5, { quiet: true, onActivity: options?.onActivity, provider: plannerAgent?.provider, model: plannerAgent?.model });
2981
+ const spawnResult = await spawnAgentStream("planner", prompt2, 3e5, { quiet: true, onActivity: options?.onActivity, provider: plannerAgent?.provider, model: plannerAgent?.model });
2982
+ const { stdout: raw, exitCode, usage, errorMessage, apiErrorStatus } = spawnResult;
2822
2983
  if (exitCode !== 0) {
2823
- const chesstrace2 = getChesstrace();
2824
- if (chesstrace2) {
2825
- chesstrace2.emit(Events.ERROR_TASK, {
2826
- type: "TaskError",
2827
- message: `Planner: agent exited with code ${exitCode}`,
2828
- stage: "plan",
2829
- agent: "planner"
2830
- });
2831
- }
2832
- throw new TaskError(`Planner: agent exited with code ${exitCode}`);
2984
+ const detail = formatExitDetail(spawnResult, plannerAgent?.model);
2985
+ emitErrorTask(
2986
+ `Planner: agent exited with code ${exitCode}${detail}`,
2987
+ "plan",
2988
+ { agent: "planner", errorMessage, apiErrorStatus }
2989
+ );
2990
+ throw new TaskError(`Planner: agent exited with code ${exitCode}${detail}`);
2833
2991
  }
2834
2992
  let parsed;
2835
2993
  try {
@@ -2857,31 +3015,23 @@ async function runPlanner(spec, previousAnswers, options) {
2857
3015
  }
2858
3016
  }
2859
3017
  const errors = Array.isArray(obj.errors) ? obj.errors.join("\n - ") : "unknown validation error";
2860
- const chesstrace2 = getChesstrace();
2861
- if (chesstrace2) {
2862
- chesstrace2.emit(Events.ERROR_TASK, {
2863
- type: "TaskError",
2864
- message: `Planner: spec validation failed:
3018
+ emitErrorTask(
3019
+ `Planner: spec validation failed:
2865
3020
  - ${errors}`,
2866
- stage: "plan",
2867
- agent: "planner"
2868
- });
2869
- }
3021
+ "plan",
3022
+ { agent: "planner" }
3023
+ );
2870
3024
  throw new TaskError(
2871
3025
  `Planner: spec validation failed:
2872
3026
  - ${errors}`
2873
3027
  );
2874
3028
  }
2875
3029
  if (obj.valid !== true) {
2876
- const chesstrace2 = getChesstrace();
2877
- if (chesstrace2) {
2878
- chesstrace2.emit(Events.ERROR_TASK, {
2879
- type: "TaskError",
2880
- message: "Planner: unexpected response \u2014 missing 'valid' field",
2881
- stage: "plan",
2882
- agent: "planner"
2883
- });
2884
- }
3030
+ emitErrorTask(
3031
+ "Planner: unexpected response \u2014 missing 'valid' field",
3032
+ "plan",
3033
+ { agent: "planner" }
3034
+ );
2885
3035
  throw new TaskError(
2886
3036
  "Planner: unexpected response \u2014 missing 'valid' field"
2887
3037
  );
@@ -2889,49 +3039,37 @@ async function runPlanner(spec, previousAnswers, options) {
2889
3039
  const { goals, tasks, constraints, dod } = obj;
2890
3040
  const chesstrace = getChesstrace();
2891
3041
  if (!isNonEmptyStringArray(goals)) {
2892
- if (chesstrace) {
2893
- chesstrace.emit(Events.ERROR_TASK, {
2894
- type: "TaskError",
2895
- message: "Planner: 'goals' must be a non-empty string array",
2896
- stage: "plan",
2897
- agent: "planner"
2898
- });
2899
- }
3042
+ emitErrorTask(
3043
+ "Planner: 'goals' must be a non-empty string array",
3044
+ "plan",
3045
+ { agent: "planner" }
3046
+ );
2900
3047
  throw new TaskError("Planner: 'goals' must be a non-empty string array");
2901
3048
  }
2902
3049
  if (!isNonEmptyStringArray(tasks)) {
2903
- if (chesstrace) {
2904
- chesstrace.emit(Events.ERROR_TASK, {
2905
- type: "TaskError",
2906
- message: "Planner: 'tasks' must be a non-empty string array",
2907
- stage: "plan",
2908
- agent: "planner"
2909
- });
2910
- }
3050
+ emitErrorTask(
3051
+ "Planner: 'tasks' must be a non-empty string array",
3052
+ "plan",
3053
+ { agent: "planner" }
3054
+ );
2911
3055
  throw new TaskError("Planner: 'tasks' must be a non-empty string array");
2912
3056
  }
2913
3057
  if (!isNonEmptyStringArray(constraints)) {
2914
- if (chesstrace) {
2915
- chesstrace.emit(Events.ERROR_TASK, {
2916
- type: "TaskError",
2917
- message: "Planner: 'constraints' must be a non-empty string array",
2918
- stage: "plan",
2919
- agent: "planner"
2920
- });
2921
- }
3058
+ emitErrorTask(
3059
+ "Planner: 'constraints' must be a non-empty string array",
3060
+ "plan",
3061
+ { agent: "planner" }
3062
+ );
2922
3063
  throw new TaskError(
2923
3064
  "Planner: 'constraints' must be a non-empty string array"
2924
3065
  );
2925
3066
  }
2926
3067
  if (!isNonEmptyStringArray(dod)) {
2927
- if (chesstrace) {
2928
- chesstrace.emit(Events.ERROR_TASK, {
2929
- type: "TaskError",
2930
- message: "Planner: 'dod' must be a non-empty string array",
2931
- stage: "plan",
2932
- agent: "planner"
2933
- });
2934
- }
3068
+ emitErrorTask(
3069
+ "Planner: 'dod' must be a non-empty string array",
3070
+ "plan",
3071
+ { agent: "planner" }
3072
+ );
2935
3073
  throw new TaskError("Planner: 'dod' must be a non-empty string array");
2936
3074
  }
2937
3075
  return { result: { goals, tasks, constraints, dod }, usage };
@@ -3017,10 +3155,19 @@ Be specific and actionable. Expand the description into concrete requirements th
3017
3155
  **Description:** ${description}${answersContext}`;
3018
3156
  }
3019
3157
  async function runClarification(description, previousAnswers, onActivity) {
3158
+ const agents = getAgents();
3159
+ const plannerAgent = agents.find((a) => a.name === "planner");
3020
3160
  const prompt2 = buildClarificationPrompt(description, previousAnswers);
3021
- const { stdout: raw, exitCode } = await spawnAgentStream("generate-spec", prompt2, 12e4, { quiet: true, onActivity });
3161
+ const clarifyResult = await spawnAgentStream("generate-spec", prompt2, 12e4, { quiet: true, onActivity });
3162
+ const { stdout: raw, exitCode, errorMessage, apiErrorStatus } = clarifyResult;
3022
3163
  if (exitCode !== 0) {
3023
- throw new TaskError(`generate-spec: agent exited with code ${exitCode}`);
3164
+ const detail = formatExitDetail(clarifyResult, plannerAgent?.model);
3165
+ emitErrorTask(
3166
+ `generate-spec: agent exited with code ${exitCode}${detail}`,
3167
+ "clarification",
3168
+ { agent: "generate-spec", errorMessage, apiErrorStatus }
3169
+ );
3170
+ throw new TaskError(`generate-spec: agent exited with code ${exitCode}${detail}`);
3024
3171
  }
3025
3172
  let parsed;
3026
3173
  try {
@@ -3052,10 +3199,19 @@ async function runClarification(description, previousAnswers, onActivity) {
3052
3199
  return { ready: true };
3053
3200
  }
3054
3201
  async function generateSpec(description, clarificationAnswers, onActivity) {
3202
+ const agents = getAgents();
3203
+ const plannerAgent = agents.find((a) => a.name === "planner");
3055
3204
  const prompt2 = buildGeneratePrompt(description, clarificationAnswers);
3056
- const { stdout, exitCode } = await spawnAgentStream("generate-spec", prompt2, 12e4, { onActivity });
3205
+ const specResult = await spawnAgentStream("generate-spec", prompt2, 12e4, { onActivity });
3206
+ const { stdout, exitCode, errorMessage, apiErrorStatus } = specResult;
3057
3207
  if (exitCode !== 0) {
3058
- throw new TaskError(`generate-spec: agent exited with code ${exitCode}`);
3208
+ const detail = formatExitDetail(specResult, plannerAgent?.model);
3209
+ emitErrorTask(
3210
+ `generate-spec: agent exited with code ${exitCode}${detail}`,
3211
+ "generate",
3212
+ { agent: "generate-spec", errorMessage, apiErrorStatus }
3213
+ );
3214
+ throw new TaskError(`generate-spec: agent exited with code ${exitCode}${detail}`);
3059
3215
  }
3060
3216
  if (!stdout) {
3061
3217
  throw new TaskError("generate-spec: empty result from agent");
@@ -3064,7 +3220,7 @@ async function generateSpec(description, clarificationAnswers, onActivity) {
3064
3220
  }
3065
3221
 
3066
3222
  // src/live-status.ts
3067
- import chalk10 from "chalk";
3223
+ import chalk11 from "chalk";
3068
3224
  import ora from "ora";
3069
3225
  var TRACK_LENGTH = 4;
3070
3226
  var PAW_POSITIONS = [0, 1, 2, 3, 2, 1];
@@ -3096,16 +3252,16 @@ function truncateToWidth(text, maxWidth) {
3096
3252
  function buildAnimationFrame(position, label, elapsed, lastActivity) {
3097
3253
  const track = Array.from(
3098
3254
  { length: TRACK_LENGTH },
3099
- (_, i) => i === position ? chalk10.yellowBright("\u{1F43E}") : chalk10.gray("\xB7")
3255
+ (_, i) => i === position ? chalk11.yellowBright("\u{1F43E}") : chalk11.gray("\xB7")
3100
3256
  ).join(" ");
3101
- const mainLine = `${track} ${chalk10.blue(label)} ${chalk10.gray(elapsed)}`;
3257
+ const mainLine = `${track} ${chalk11.blue(label)} ${chalk11.gray(elapsed)}`;
3102
3258
  if (lastActivity) {
3103
3259
  const parts = [lastActivity.agent];
3104
3260
  if (lastActivity.tool) parts.push(lastActivity.tool);
3105
3261
  if (lastActivity.detail) parts.push(lastActivity.detail.replace(/[\r\n]+/g, " "));
3106
- const activityText = chalk10.cyan(parts.join(" \u2192 "));
3262
+ const activityText = chalk11.cyan(parts.join(" \u2192 "));
3107
3263
  const terminalWidth = process.stdout.columns || 120;
3108
- const separator = chalk10.gray(" | ");
3264
+ const separator = chalk11.gray(" | ");
3109
3265
  const combined = `${mainLine}${separator}${activityText}`;
3110
3266
  return truncateToWidth(combined, terminalWidth - 2);
3111
3267
  }
@@ -3224,6 +3380,35 @@ function createLiveStatus(label) {
3224
3380
  };
3225
3381
  }
3226
3382
 
3383
+ // src/format.ts
3384
+ function stripAnsi2(str) {
3385
+ return str.replace(/\x1b\[[0-9;]*m/g, "");
3386
+ }
3387
+ function wrapText(text, indent, maxWidth, continuationPrefix) {
3388
+ if (!text || text.trim().length === 0) return text || "";
3389
+ if (maxWidth <= 0) return text;
3390
+ if (indent < 0) indent = 0;
3391
+ const available = maxWidth - indent;
3392
+ if (available > 20 && stripAnsi2(text).length <= available) return text;
3393
+ const minAvailable = Math.max(available, 10);
3394
+ const words = text.split(" ");
3395
+ const wrappedLines = [];
3396
+ let currentLine = "";
3397
+ for (const word of words) {
3398
+ if (currentLine.length === 0) {
3399
+ currentLine = word;
3400
+ } else if (stripAnsi2(currentLine).length + 1 + stripAnsi2(word).length <= minAvailable) {
3401
+ currentLine += " " + word;
3402
+ } else {
3403
+ wrappedLines.push(currentLine);
3404
+ currentLine = word;
3405
+ }
3406
+ }
3407
+ if (currentLine) wrappedLines.push(currentLine);
3408
+ const pad = continuationPrefix ?? " ".repeat(indent);
3409
+ return wrappedLines.join("\n" + pad);
3410
+ }
3411
+
3227
3412
  // src/commands/generate-spec.ts
3228
3413
  async function prompt(question, fallback) {
3229
3414
  const rl = createInterface2({ input: process.stdin, output: process.stdout });
@@ -3239,7 +3424,7 @@ async function generateSpecCommand(description, options) {
3239
3424
  if (!description) {
3240
3425
  description = await prompt("Feature description: ");
3241
3426
  if (!description) {
3242
- console.log(chalk11.red.bold("Error:"), "Description is required.");
3427
+ console.log(chalk12.red.bold("Error:"), "Description is required.");
3243
3428
  process.exit(1);
3244
3429
  }
3245
3430
  }
@@ -3259,7 +3444,7 @@ async function generateSpecCommand(description, options) {
3259
3444
  try {
3260
3445
  result = await runClarification(description, clarificationAnswers, clarifyStatus.onActivity);
3261
3446
  } catch (err) {
3262
- clarifyStatus.fail(chalk11.red("Failed to check clarification needs"));
3447
+ clarifyStatus.fail(chalk12.red("Failed to check clarification needs"));
3263
3448
  if (err instanceof TaskError) {
3264
3449
  throw err;
3265
3450
  }
@@ -3267,66 +3452,76 @@ async function generateSpecCommand(description, options) {
3267
3452
  throw new TaskError(`Clarification check failed: ${message}`);
3268
3453
  }
3269
3454
  if ("ready" in result && result.ready) {
3270
- clarifyStatus.succeed(chalk11.green("No clarification needed"));
3455
+ clarifyStatus.succeed(chalk12.green("No clarification needed"));
3271
3456
  ready = true;
3272
3457
  break;
3273
3458
  }
3274
3459
  if ("needsClarification" in result && result.needsClarification) {
3275
3460
  clarifyStatus.stop();
3276
3461
  resetTerminalForInput();
3277
- console.log(chalk11.yellow("\nClarifying questions:\n"));
3462
+ console.log(chalk12.yellow("\n\u2501\u2501\u2501 Clarifying Questions \u2501\u2501\u2501\n"));
3278
3463
  const answers = [];
3279
3464
  const rl = createInterface2({
3280
3465
  input: process.stdin,
3281
3466
  output: process.stdout
3282
3467
  });
3468
+ const termWidth = Math.max(process.stdout.columns || 80, 40);
3283
3469
  try {
3284
3470
  for (let i = 0; i < result.questions.length; i++) {
3285
3471
  const question = result.questions[i];
3472
+ if (i === 0) {
3473
+ console.log();
3474
+ }
3475
+ const counter = chalk12.cyan(`Question ${i + 1} of ${result.questions.length}`);
3476
+ console.log(counter);
3477
+ const wrapped = wrapText(question, 2, termWidth, " ");
3478
+ console.log(` ${wrapped}`);
3286
3479
  const answer = await new Promise((resolve5) => {
3287
- rl.question(` [${i + 1}/${result.questions.length}] ${question}
3288
- > `, resolve5);
3480
+ rl.question(chalk12.gray("> "), resolve5);
3289
3481
  });
3290
3482
  if (answer.trim().toLowerCase() === "abort" || answer.trim().toLowerCase() === "cancel") {
3291
- console.log(chalk11.red("Aborted."));
3483
+ console.log(chalk12.red("\nAborted."));
3292
3484
  process.exit(0);
3293
3485
  }
3294
3486
  answers.push(`Q: ${question}
3295
3487
  A: ${answer}`);
3488
+ if (i < result.questions.length - 1) {
3489
+ console.log();
3490
+ }
3296
3491
  }
3297
3492
  } finally {
3298
3493
  rl.close();
3299
3494
  }
3300
3495
  clarificationAnswers = answers.join("\n\n");
3301
3496
  if (attempts < maxAttempts) {
3302
- console.log(chalk11.blue("\nRe-checking with your answers...\n"));
3497
+ console.log(chalk12.blue("\n\u2501\u2501\u2501 Re-checking with your answers \u2501\u2501\u2501\n"));
3303
3498
  }
3304
3499
  }
3305
3500
  }
3306
3501
  if (!ready && attempts >= maxAttempts) {
3307
- console.log(chalk11.yellow("Max clarification rounds reached, generating spec with answers so far..."));
3502
+ console.log(chalk12.yellow("Max clarification rounds reached, generating spec with answers so far..."));
3308
3503
  }
3309
3504
  }
3310
3505
  const genStatus = createLiveStatus("Generating spec...");
3311
3506
  let markdown;
3312
3507
  try {
3313
3508
  markdown = await generateSpec(description, clarificationAnswers, genStatus.onActivity);
3314
- genStatus.succeed(chalk11.green("Spec generated"));
3509
+ genStatus.succeed(chalk12.green("Spec generated"));
3315
3510
  } catch (err) {
3316
- genStatus.fail(chalk11.red("Failed to generate spec"));
3511
+ genStatus.fail(chalk12.red("Failed to generate spec"));
3317
3512
  throw err;
3318
3513
  }
3319
3514
  const outPath = resolve4(process.cwd(), output);
3320
3515
  writeFileSync(outPath, markdown, "utf-8");
3321
- console.log(chalk11.gray("Spec written to"), chalk11.cyan(outPath));
3516
+ console.log(chalk12.gray("Spec written to"), chalk12.cyan(outPath));
3322
3517
  } catch (err) {
3323
3518
  if (err instanceof TaskError) {
3324
- console.log(chalk11.red.bold("Error:"), err.message);
3519
+ console.log(chalk12.red.bold("Error:"), err.message);
3325
3520
  if (isDebug()) console.error(err.stack);
3326
3521
  process.exit(1);
3327
3522
  }
3328
3523
  const message = err instanceof Error ? err.message : String(err);
3329
- console.log(chalk11.red.bold("Internal error:"), message);
3524
+ console.log(chalk12.red.bold("Internal error:"), message);
3330
3525
  if (isDebug()) console.error(err instanceof Error ? err.stack : err);
3331
3526
  process.exit(2);
3332
3527
  }
@@ -3334,7 +3529,7 @@ A: ${answer}`);
3334
3529
  }
3335
3530
 
3336
3531
  // src/commands/spec.ts
3337
- import chalk12 from "chalk";
3532
+ import chalk13 from "chalk";
3338
3533
  import { select as select2 } from "@inquirer/prompts";
3339
3534
 
3340
3535
  // src/cursor-aware-input.ts
@@ -3535,33 +3730,6 @@ async function pasteableInput(config, context) {
3535
3730
 
3536
3731
  // src/commands/spec.ts
3537
3732
  import { ExitPromptError } from "@inquirer/core";
3538
-
3539
- // src/format.ts
3540
- function stripAnsi2(str) {
3541
- return str.replace(/\x1b\[[0-9;]*m/g, "");
3542
- }
3543
- function wrapText(text, indent, maxWidth, continuationPrefix) {
3544
- const available = maxWidth - indent;
3545
- if (available <= 20 || stripAnsi2(text).length <= available) return text;
3546
- const words = text.split(" ");
3547
- const wrappedLines = [];
3548
- let currentLine = "";
3549
- for (const word of words) {
3550
- if (currentLine.length === 0) {
3551
- currentLine = word;
3552
- } else if (stripAnsi2(currentLine).length + 1 + stripAnsi2(word).length <= available) {
3553
- currentLine += " " + word;
3554
- } else {
3555
- wrappedLines.push(currentLine);
3556
- currentLine = word;
3557
- }
3558
- }
3559
- if (currentLine) wrappedLines.push(currentLine);
3560
- const pad = continuationPrefix ?? " ".repeat(indent);
3561
- return wrappedLines.join("\n" + pad);
3562
- }
3563
-
3564
- // src/commands/spec.ts
3565
3733
  var VALID_PROVIDERS = ["jira", "linear", "local"];
3566
3734
  function inferProvider(source) {
3567
3735
  if (/^https:\/\/linear\.app\//.test(source)) {
@@ -3578,7 +3746,7 @@ async function specCommand(source, options) {
3578
3746
  if (options.source !== void 0) {
3579
3747
  if (!VALID_PROVIDERS.includes(options.source)) {
3580
3748
  console.log(
3581
- chalk12.red.bold("Error:"),
3749
+ chalk13.red.bold("Error:"),
3582
3750
  `Invalid source provider "${options.source}". Must be one of: ${VALID_PROVIDERS.join(", ")}`
3583
3751
  );
3584
3752
  process.exit(1);
@@ -3591,17 +3759,17 @@ async function specCommand(source, options) {
3591
3759
  const isIssueKey = ISSUE_KEY_PATTERN.test(source);
3592
3760
  if (provider === "local" && isLinearUrl2) {
3593
3761
  console.log(
3594
- chalk12.yellow("Warning:"),
3762
+ chalk13.yellow("Warning:"),
3595
3763
  `Source "${source}" is a Linear URL, but --source=local treats it as a file path.`
3596
3764
  );
3597
3765
  } else if (provider === "linear" && hasMdExt) {
3598
3766
  console.log(
3599
- chalk12.yellow("Warning:"),
3767
+ chalk13.yellow("Warning:"),
3600
3768
  `Source "${source}" ends in .md/.markdown, but --source=linear treats it as a Linear issue ID.`
3601
3769
  );
3602
3770
  } else if (provider === "jira" && hasMdExt) {
3603
3771
  console.log(
3604
- chalk12.yellow("Warning:"),
3772
+ chalk13.yellow("Warning:"),
3605
3773
  `Source "${source}" ends in .md/.markdown, but --source=jira treats it as a Jira issue key.`
3606
3774
  );
3607
3775
  }
@@ -3612,7 +3780,7 @@ async function specCommand(source, options) {
3612
3780
  if (!provider) {
3613
3781
  if (!process.stdin.isTTY) {
3614
3782
  console.log(
3615
- chalk12.red.bold("Error:"),
3783
+ chalk13.red.bold("Error:"),
3616
3784
  `Cannot determine provider for "${source}" in non-interactive mode. Use --source <jira|linear|local>.`
3617
3785
  );
3618
3786
  process.exit(1);
@@ -3643,7 +3811,7 @@ async function specCommand(source, options) {
3643
3811
  if ("needsClarification" in result && result.needsClarification) {
3644
3812
  status.stop();
3645
3813
  resetTerminalForInput();
3646
- console.log(chalk12.yellow("\nPlanner needs clarification:\n"));
3814
+ console.log(chalk13.yellow("\nPlanner needs clarification:\n"));
3647
3815
  const answers = [];
3648
3816
  for (let i = 0; i < result.questions.length; i++) {
3649
3817
  const question = result.questions[i];
@@ -3657,37 +3825,37 @@ async function specCommand(source, options) {
3657
3825
  A: ${answer}`);
3658
3826
  }
3659
3827
  clarificationAnswers = answers.join("\n\n");
3660
- console.log(chalk12.blue("\nRe-running planner with clarifications...\n"));
3828
+ console.log(chalk13.blue("\nRe-running planner with clarifications...\n"));
3661
3829
  status.start();
3662
3830
  } else {
3663
3831
  plan = result;
3664
3832
  }
3665
3833
  }
3666
3834
  if (!plan) {
3667
- status.fail(chalk12.red("Planner failed"));
3835
+ status.fail(chalk13.red("Planner failed"));
3668
3836
  throw new TaskError(`Planner: failed to create valid plan after ${maxAttempts} attempts`);
3669
3837
  }
3670
- status.succeed(chalk12.green("Plan created"));
3838
+ status.succeed(chalk13.green("Plan created"));
3671
3839
  const cols = process.stdout.columns || 80;
3672
- console.log(chalk12.cyan("\nGoals:"));
3673
- for (const g of plan.goals) console.log(` ${chalk12.gray("-")} ${wrapText(g, 4, cols)}`);
3674
- console.log(chalk12.cyan("\nTasks:"));
3675
- for (const t of plan.tasks) console.log(` ${chalk12.gray("-")} ${wrapText(t, 4, cols)}`);
3676
- console.log(chalk12.cyan("\nConstraints:"));
3677
- for (const c of plan.constraints) console.log(` ${chalk12.gray("-")} ${wrapText(c, 4, cols)}`);
3678
- console.log(chalk12.cyan("\nDefinition of Done:"));
3679
- for (const d of plan.dod) console.log(` ${chalk12.gray("-")} ${wrapText(d, 4, cols)}`);
3840
+ console.log(chalk13.cyan("\nGoals:"));
3841
+ for (const g of plan.goals) console.log(` ${chalk13.gray("-")} ${wrapText(g, 4, cols)}`);
3842
+ console.log(chalk13.cyan("\nTasks:"));
3843
+ for (const t of plan.tasks) console.log(` ${chalk13.gray("-")} ${wrapText(t, 4, cols)}`);
3844
+ console.log(chalk13.cyan("\nConstraints:"));
3845
+ for (const c of plan.constraints) console.log(` ${chalk13.gray("-")} ${wrapText(c, 4, cols)}`);
3846
+ console.log(chalk13.cyan("\nDefinition of Done:"));
3847
+ for (const d of plan.dod) console.log(` ${chalk13.gray("-")} ${wrapText(d, 4, cols)}`);
3680
3848
  } catch (err) {
3681
3849
  if (err instanceof ExitPromptError) {
3682
3850
  process.exit(0);
3683
3851
  }
3684
3852
  if (err instanceof SpecError || err instanceof TaskError) {
3685
- console.log(chalk12.red.bold("Error:"), err.message);
3853
+ console.log(chalk13.red.bold("Error:"), err.message);
3686
3854
  if (isDebug()) console.error(err.stack);
3687
3855
  process.exit(1);
3688
3856
  }
3689
3857
  const message = err instanceof Error ? err.message : String(err);
3690
- console.log(chalk12.red.bold("Internal error:"), message);
3858
+ console.log(chalk13.red.bold("Internal error:"), message);
3691
3859
  if (isDebug()) console.error(err instanceof Error ? err.stack : err);
3692
3860
  process.exit(2);
3693
3861
  }
@@ -3697,12 +3865,12 @@ A: ${answer}`);
3697
3865
  // src/commands/run.ts
3698
3866
  import { createInterface as createInterface4 } from "readline";
3699
3867
  import { join as join6 } from "path";
3700
- import chalk18 from "chalk";
3868
+ import chalk19 from "chalk";
3701
3869
  import ora2 from "ora";
3702
3870
  import { select as select3 } from "@inquirer/prompts";
3703
3871
 
3704
3872
  // src/implement.ts
3705
- import chalk13 from "chalk";
3873
+ import chalk14 from "chalk";
3706
3874
  function getFailureSummary(stdout, maxLen = 300) {
3707
3875
  const trimmed = stdout.trim();
3708
3876
  if (!trimmed) return "";
@@ -3861,15 +4029,11 @@ async function runImplement(spec, plan, options, retryOptions) {
3861
4029
  const devAgent = agents.find((a) => a.name === "dev");
3862
4030
  const qeAgent = agents.find((a) => a.name === "qe");
3863
4031
  if (!devAgent || !qeAgent) {
3864
- const chesstrace2 = getChesstrace();
3865
- if (chesstrace2) {
3866
- chesstrace2.emit(Events.ERROR_TASK, {
3867
- type: "TaskError",
3868
- message: "Implement: missing dev or qe agent config",
3869
- stage: options?.stage ?? "implement",
3870
- agent: "implement"
3871
- });
3872
- }
4032
+ emitErrorTask(
4033
+ "Implement: missing dev or qe agent config",
4034
+ options?.stage ?? "implement",
4035
+ { agent: "implement" }
4036
+ );
3873
4037
  throw new TaskError("Implement: missing dev or qe agent config");
3874
4038
  }
3875
4039
  const agentsToRun = retryOptions?.agentsToRun ?? ["dev", "qe"];
@@ -3908,12 +4072,15 @@ async function runImplement(spec, plan, options, retryOptions) {
3908
4072
  if (devResult.value.exitCode === 0) {
3909
4073
  dev = extractDevOutput(devResult.value.stdout);
3910
4074
  } else {
3911
- console.log(chalk13.red("dev agent failed:"), `exit code ${devResult.value.exitCode}`);
3912
- const summary = getFailureSummary(devResult.value.stdout);
3913
- if (summary) console.log(chalk13.gray(" \u21B3"), chalk13.gray(summary));
4075
+ const detail = formatExitDetail(devResult.value, devAgent.model);
4076
+ console.log(chalk14.red("dev agent failed:"), `exit code ${devResult.value.exitCode}${detail}`);
4077
+ if (!devResult.value.errorMessage || devResult.value.errorMessage.length < 50) {
4078
+ const summary = getFailureSummary(devResult.value.stdout);
4079
+ if (summary) console.log(chalk14.gray(" \u21B3"), chalk14.gray(summary));
4080
+ }
3914
4081
  }
3915
4082
  } else {
3916
- console.log(chalk13.red("dev agent failed:"), devResult.reason);
4083
+ console.log(chalk14.red("dev agent failed:"), devResult.reason);
3917
4084
  }
3918
4085
  }
3919
4086
  if (runQE) {
@@ -3923,17 +4090,20 @@ async function runImplement(spec, plan, options, retryOptions) {
3923
4090
  if (qeResult.value.exitCode === 0) {
3924
4091
  qe = extractQEOutput(qeResult.value.stdout);
3925
4092
  } else {
3926
- console.log(chalk13.red("qe agent failed:"), `exit code ${qeResult.value.exitCode}`);
3927
- const summary = getFailureSummary(qeResult.value.stdout);
3928
- if (summary) console.log(chalk13.gray(" \u21B3"), chalk13.gray(summary));
4093
+ const detail = formatExitDetail(qeResult.value, qeAgent.model);
4094
+ console.log(chalk14.red("qe agent failed:"), `exit code ${qeResult.value.exitCode}${detail}`);
4095
+ if (!qeResult.value.errorMessage || qeResult.value.errorMessage.length < 50) {
4096
+ const summary = getFailureSummary(qeResult.value.stdout);
4097
+ if (summary) console.log(chalk14.gray(" \u21B3"), chalk14.gray(summary));
4098
+ }
3929
4099
  }
3930
4100
  } else {
3931
- console.log(chalk13.red("qe agent failed:"), qeResult.reason);
4101
+ console.log(chalk14.red("qe agent failed:"), qeResult.reason);
3932
4102
  }
3933
4103
  }
3934
4104
  } else {
3935
4105
  if (runDev) {
3936
- console.log(chalk13.blue("Running dev agent (approve edits as prompted)..."));
4106
+ console.log(chalk14.blue("Running dev agent (approve edits as prompted)..."));
3937
4107
  try {
3938
4108
  const devResult = await spawnAgent("dev", devPrompt, { ...options, provider: devAgent.provider, model: devAgent.model, stage: "implement" });
3939
4109
  if (devResult.exitCode === 0) {
@@ -3941,16 +4111,19 @@ async function runImplement(spec, plan, options, retryOptions) {
3941
4111
  }
3942
4112
  usages.push({ agent: "dev", usage: devResult.usage });
3943
4113
  if (devResult.exitCode !== 0) {
3944
- console.log(chalk13.red("dev agent failed:"), `exit code ${devResult.exitCode}`);
3945
- const summary = getFailureSummary(devResult.stdout);
3946
- if (summary) console.log(chalk13.gray(" \u21B3"), chalk13.gray(summary));
4114
+ const detail = formatExitDetail(devResult);
4115
+ console.log(chalk14.red("dev agent failed:"), `exit code ${devResult.exitCode}${detail}`);
4116
+ if (!devResult.errorMessage) {
4117
+ const summary = getFailureSummary(devResult.stdout);
4118
+ if (summary) console.log(chalk14.gray(" \u21B3"), chalk14.gray(summary));
4119
+ }
3947
4120
  }
3948
4121
  } catch (err) {
3949
- console.log(chalk13.red("dev agent failed:"), err);
4122
+ console.log(chalk14.red("dev agent failed:"), err);
3950
4123
  }
3951
4124
  }
3952
4125
  if (runQE) {
3953
- console.log(chalk13.blue("Running qe agent (approve edits as prompted)..."));
4126
+ console.log(chalk14.blue("Running qe agent (approve edits as prompted)..."));
3954
4127
  try {
3955
4128
  const qeResult = await spawnAgent("qe", qePrompt, { ...options, provider: qeAgent.provider, model: qeAgent.model, stage: "implement" });
3956
4129
  if (qeResult.exitCode === 0) {
@@ -3958,47 +4131,41 @@ async function runImplement(spec, plan, options, retryOptions) {
3958
4131
  }
3959
4132
  usages.push({ agent: "qe", usage: qeResult.usage });
3960
4133
  if (qeResult.exitCode !== 0) {
3961
- console.log(chalk13.red("qe agent failed:"), `exit code ${qeResult.exitCode}`);
3962
- const summary = getFailureSummary(qeResult.stdout);
3963
- if (summary) console.log(chalk13.gray(" \u21B3"), chalk13.gray(summary));
4134
+ const detail = formatExitDetail(qeResult);
4135
+ console.log(chalk14.red("qe agent failed:"), `exit code ${qeResult.exitCode}${detail}`);
4136
+ if (!qeResult.errorMessage) {
4137
+ const summary = getFailureSummary(qeResult.stdout);
4138
+ if (summary) console.log(chalk14.gray(" \u21B3"), chalk14.gray(summary));
4139
+ }
3964
4140
  }
3965
4141
  } catch (err) {
3966
- console.log(chalk13.red("qe agent failed:"), err);
4142
+ console.log(chalk14.red("qe agent failed:"), err);
3967
4143
  }
3968
4144
  }
3969
4145
  }
3970
4146
  const chesstrace = getChesstrace();
3971
4147
  if (runDev && dev === null && (runQE && qe === null)) {
3972
- if (chesstrace) {
3973
- chesstrace.emit(Events.ERROR_TASK, {
3974
- type: "TaskError",
3975
- message: "Implement: all requested agents failed",
3976
- stage: options?.stage ?? "implement",
3977
- agent: "implement"
3978
- });
3979
- }
4148
+ emitErrorTask(
4149
+ "Implement: all requested agents failed",
4150
+ options?.stage ?? "implement",
4151
+ { agent: "implement" }
4152
+ );
3980
4153
  throw new TaskError("Implement: all requested agents failed");
3981
4154
  }
3982
4155
  if (runDev && !runQE && dev === null) {
3983
- if (chesstrace) {
3984
- chesstrace.emit(Events.ERROR_TASK, {
3985
- type: "TaskError",
3986
- message: "Implement: dev agent failed",
3987
- stage: options?.stage ?? "implement",
3988
- agent: "dev"
3989
- });
3990
- }
4156
+ emitErrorTask(
4157
+ "Implement: dev agent failed",
4158
+ options?.stage ?? "implement",
4159
+ { agent: "dev" }
4160
+ );
3991
4161
  throw new TaskError("Implement: dev agent failed");
3992
4162
  }
3993
4163
  if (!runDev && runQE && qe === null) {
3994
- if (chesstrace) {
3995
- chesstrace.emit(Events.ERROR_TASK, {
3996
- type: "TaskError",
3997
- message: "Implement: qe agent failed",
3998
- stage: options?.stage ?? "implement",
3999
- agent: "qe"
4000
- });
4001
- }
4164
+ emitErrorTask(
4165
+ "Implement: qe agent failed",
4166
+ options?.stage ?? "implement",
4167
+ { agent: "qe" }
4168
+ );
4002
4169
  throw new TaskError("Implement: qe agent failed");
4003
4170
  }
4004
4171
  return { implement: { dev, qe }, usages };
@@ -4624,7 +4791,7 @@ function detectTypeFromLinearLabels(labels) {
4624
4791
 
4625
4792
  // src/pr-review.ts
4626
4793
  import { execFile as execFile2 } from "child_process";
4627
- import chalk14 from "chalk";
4794
+ import chalk15 from "chalk";
4628
4795
 
4629
4796
  // src/diff-split.ts
4630
4797
  function estimateTokens(text) {
@@ -4850,11 +5017,11 @@ function formatPRReviewTerminal(output) {
4850
5017
  const lines = [];
4851
5018
  const cols = process.stdout.columns || 80;
4852
5019
  lines.push("");
4853
- lines.push(chalk14.cyan.bold("Summary"));
5020
+ lines.push(chalk15.cyan.bold("Summary"));
4854
5021
  lines.push(` ${wrapText(output.summary, 2, cols)}`);
4855
5022
  lines.push("");
4856
5023
  if (output.comments.length > 0) {
4857
- lines.push(chalk14.cyan.bold(`Comments (${output.comments.length}):`));
5024
+ lines.push(chalk15.cyan.bold(`Comments (${output.comments.length}):`));
4858
5025
  const byFile = /* @__PURE__ */ new Map();
4859
5026
  for (const c of output.comments) {
4860
5027
  const group = byFile.get(c.file) ?? [];
@@ -4864,22 +5031,22 @@ function formatPRReviewTerminal(output) {
4864
5031
  const commentIndent = 6;
4865
5032
  for (const [file, comments] of byFile) {
4866
5033
  lines.push("");
4867
- lines.push(` ${chalk14.bold(file)}`);
5034
+ lines.push(` ${chalk15.bold(file)}`);
4868
5035
  for (const c of comments) {
4869
5036
  const lineRef = c.line !== null ? `:${c.line}` : "";
4870
5037
  const prefix = lineRef ? `${lineRef} ` : "";
4871
5038
  const wrapped = wrapText(prefix + c.comment, commentIndent, cols);
4872
- const display = c.line !== null ? chalk14.gray(`:${c.line}`) + " " + wrapped.slice(prefix.length) : wrapped;
4873
- lines.push(` ${chalk14.yellow("\u2022")} ${display}`);
5039
+ const display = c.line !== null ? chalk15.gray(`:${c.line}`) + " " + wrapped.slice(prefix.length) : wrapped;
5040
+ lines.push(` ${chalk15.yellow("\u2022")} ${display}`);
4874
5041
  }
4875
5042
  }
4876
5043
  lines.push("");
4877
5044
  }
4878
5045
  if (output.recommendedActions.length > 0) {
4879
- lines.push(chalk14.cyan.bold("Recommended Actions:"));
5046
+ lines.push(chalk15.cyan.bold("Recommended Actions:"));
4880
5047
  lines.push("");
4881
5048
  for (const action of output.recommendedActions) {
4882
- lines.push(` ${chalk14.gray("-")} ${wrapText(action, 4, cols)}`);
5049
+ lines.push(` ${chalk15.gray("-")} ${wrapText(action, 4, cols)}`);
4883
5050
  }
4884
5051
  }
4885
5052
  return lines.join("\n");
@@ -4973,9 +5140,9 @@ async function resolvePRNumber(context) {
4973
5140
  if (context.prCreate) {
4974
5141
  return context.prCreate.prNumber;
4975
5142
  }
4976
- console.log(chalk14.blue("No PR number provided \u2014 detecting from current branch..."));
5143
+ console.log(chalk15.blue("No PR number provided \u2014 detecting from current branch..."));
4977
5144
  const detected = await detectPRFromBranch();
4978
- console.log(chalk14.green(`Found PR #${detected.prNumber} on branch "${detected.branch}"`));
5145
+ console.log(chalk15.green(`Found PR #${detected.prNumber} on branch "${detected.branch}"`));
4979
5146
  return detected.prNumber;
4980
5147
  }
4981
5148
  async function runPRReview(context, options) {
@@ -5014,7 +5181,7 @@ async function postPRReviewComment(context, review) {
5014
5181
  }
5015
5182
 
5016
5183
  // src/security-review.ts
5017
- import chalk15 from "chalk";
5184
+ import chalk16 from "chalk";
5018
5185
  var SEVERITY_ORDER = {
5019
5186
  LOW: 0,
5020
5187
  MEDIUM: 1,
@@ -5134,27 +5301,27 @@ function extractSecurityReviewOutput(stdout) {
5134
5301
  }
5135
5302
  function formatFindings(findings, threshold) {
5136
5303
  if (findings.length === 0) {
5137
- return chalk15.gray(" No findings.");
5304
+ return chalk16.gray(" No findings.");
5138
5305
  }
5139
5306
  return findings.map((f) => {
5140
5307
  const isBlocking = severityAtOrAbove(f.severity, threshold);
5141
- const marker = isBlocking ? chalk15.red.bold("!! ") : " ";
5308
+ const marker = isBlocking ? chalk16.red.bold("!! ") : " ";
5142
5309
  let severityLabel;
5143
5310
  switch (f.severity) {
5144
5311
  case "CRITICAL":
5145
- severityLabel = chalk15.red.bold(`[${f.severity}]`);
5312
+ severityLabel = chalk16.red.bold(`[${f.severity}]`);
5146
5313
  break;
5147
5314
  case "HIGH":
5148
- severityLabel = chalk15.red(`[${f.severity}]`);
5315
+ severityLabel = chalk16.red(`[${f.severity}]`);
5149
5316
  break;
5150
5317
  case "MEDIUM":
5151
- severityLabel = chalk15.yellow(`[${f.severity}]`);
5318
+ severityLabel = chalk16.yellow(`[${f.severity}]`);
5152
5319
  break;
5153
5320
  case "LOW":
5154
- severityLabel = chalk15.blue(`[${f.severity}]`);
5321
+ severityLabel = chalk16.blue(`[${f.severity}]`);
5155
5322
  break;
5156
5323
  }
5157
- const loc = f.location ? chalk15.gray(
5324
+ const loc = f.location ? chalk16.gray(
5158
5325
  ` (${f.location.file}${f.location.line ? `:${f.location.line}` : ""})`
5159
5326
  ) : "";
5160
5327
  const cols = process.stdout.columns || 80;
@@ -5183,7 +5350,7 @@ async function runSecurityReview(context, threshold, options) {
5183
5350
  }
5184
5351
 
5185
5352
  // src/usage.ts
5186
- import chalk16 from "chalk";
5353
+ import chalk17 from "chalk";
5187
5354
 
5188
5355
  // src/pricing.ts
5189
5356
  var PROVIDER_PRICING = {
@@ -5315,7 +5482,7 @@ function printCacheWarnings(tracker) {
5315
5482
  const noCacheHit = (usage.cachedTokens ?? 0) === 0;
5316
5483
  if (hasInput && noCacheHit) {
5317
5484
  console.error(
5318
- chalk16.yellow("\u26A0") + chalk16.yellow(` [${agent}] Prompt caching appears inactive for ${provider} provider. `) + chalk16.yellow("Repeated context is not being cached \u2014 costs may be higher than expected.")
5485
+ chalk17.yellow("\u26A0") + chalk17.yellow(` [${agent}] Prompt caching appears inactive for ${provider} provider. `) + chalk17.yellow("Repeated context is not being cached \u2014 costs may be higher than expected.")
5319
5486
  );
5320
5487
  warned.add(agent);
5321
5488
  }
@@ -5332,21 +5499,21 @@ function printUsageSummary(tracker) {
5332
5499
  const totalSavings = entries.reduce((sum, e) => sum + calculateCacheSavings(e.usage), 0);
5333
5500
  const byAgent = tracker.getByAgent();
5334
5501
  console.log("");
5335
- console.log(chalk16.bold.cyan("\u250C\u2500 Usage Summary"));
5336
- console.log(chalk16.cyan("\u2502") + ` Total cost: ${chalk16.bold(formatCost(totalCost))}`);
5337
- console.log(chalk16.cyan("\u2502") + ` Duration: ${formatDuration(totalDuration)}`);
5502
+ console.log(chalk17.bold.cyan("\u250C\u2500 Usage Summary"));
5503
+ console.log(chalk17.cyan("\u2502") + ` Total cost: ${chalk17.bold(formatCost(totalCost))}`);
5504
+ console.log(chalk17.cyan("\u2502") + ` Duration: ${formatDuration(totalDuration)}`);
5338
5505
  if (totalInput > 0 || totalOutput > 0) {
5339
5506
  const cachedSuffix = totalCached > 0 ? ` / ${formatTokenCount(totalCached)} cached` : "";
5340
- console.log(chalk16.cyan("\u2502") + ` Tokens: ${formatTokenCount(totalInput)} in / ${formatTokenCount(totalOutput)} out${cachedSuffix}`);
5507
+ console.log(chalk17.cyan("\u2502") + ` Tokens: ${formatTokenCount(totalInput)} in / ${formatTokenCount(totalOutput)} out${cachedSuffix}`);
5341
5508
  }
5342
5509
  if (totalSavings > 0 && Math.round(totalSavings * 100) >= 1) {
5343
- console.log(chalk16.cyan("\u2502") + ` Cache saves: ${chalk16.green(formatCost(totalSavings))}`);
5510
+ console.log(chalk17.cyan("\u2502") + ` Cache saves: ${chalk17.green(formatCost(totalSavings))}`);
5344
5511
  }
5345
- console.log(chalk16.cyan("\u2502"));
5346
- console.log(chalk16.cyan("\u2502") + ` By agent:`);
5512
+ console.log(chalk17.cyan("\u2502"));
5513
+ console.log(chalk17.cyan("\u2502") + ` By agent:`);
5347
5514
  for (const [agent, stats] of byAgent) {
5348
5515
  const callLabel = stats.calls === 1 ? "1 call" : `${stats.calls} calls`;
5349
- const prefix = chalk16.cyan("\u2502") + " ";
5516
+ const prefix = chalk17.cyan("\u2502") + " ";
5350
5517
  console.log(prefix + `${agent.padEnd(12)} ${formatCost(stats.cost).padStart(7)} (${callLabel})`);
5351
5518
  if (stats.inputTokens > 0 || stats.outputTokens > 0) {
5352
5519
  const tokenParts = [];
@@ -5355,30 +5522,30 @@ function printUsageSummary(tracker) {
5355
5522
  if (stats.cachedTokens > 0) {
5356
5523
  tokenParts.push(`${formatTokenCount(stats.cachedTokens)} cached`);
5357
5524
  }
5358
- console.log(prefix + chalk16.gray(` ${tokenParts.join(" / ")}`));
5525
+ console.log(prefix + chalk17.gray(` ${tokenParts.join(" / ")}`));
5359
5526
  }
5360
5527
  const agentSavings = stats.cachedTokens > 0 && stats.provider ? calculateCacheSavings({ cachedTokens: stats.cachedTokens, provider: stats.provider }) : 0;
5361
5528
  const hitRate = stats.inputTokens > 0 && stats.cachedTokens > 0 ? Math.round(stats.cachedTokens / stats.inputTokens * 100) : 0;
5362
5529
  if (agentSavings > 0 || hitRate > 0) {
5363
5530
  const parts = [];
5364
- if (agentSavings > 0) parts.push(chalk16.green(formatCost(agentSavings) + " saved"));
5365
- if (hitRate > 0) parts.push(chalk16.green(hitRate + "% hit"));
5531
+ if (agentSavings > 0) parts.push(chalk17.green(formatCost(agentSavings) + " saved"));
5532
+ if (hitRate > 0) parts.push(chalk17.green(hitRate + "% hit"));
5366
5533
  console.log(prefix + ` ${parts.join(" ")}`);
5367
5534
  }
5368
5535
  }
5369
- console.log(chalk16.cyan("\u2514\u2500"));
5536
+ console.log(chalk17.cyan("\u2514\u2500"));
5370
5537
  printCacheWarnings(tracker);
5371
5538
  }
5372
5539
  function printVerboseUsage(tracker) {
5373
5540
  const entries = tracker.getEntries();
5374
5541
  if (entries.length === 0) return;
5375
5542
  console.log("");
5376
- console.log(chalk16.bold.cyan("\u250C\u2500 Detailed Usage") + chalk16.gray(" (--verbose)"));
5543
+ console.log(chalk17.bold.cyan("\u250C\u2500 Detailed Usage") + chalk17.gray(" (--verbose)"));
5377
5544
  for (const entry of entries) {
5378
5545
  const { agent, stage, usage } = entry;
5379
5546
  const tokens = usage.inputTokens || usage.outputTokens ? ` ${formatTokenCount(usage.inputTokens ?? 0)} in / ${formatTokenCount(usage.outputTokens ?? 0)} out` : "";
5380
5547
  console.log(
5381
- chalk16.cyan("\u2502") + ` ${chalk16.bold(agent)} ${chalk16.gray(`(${stage})`)} ${formatCost(usage.costUsd ?? 0)} ${formatDuration(usage.durationMs ?? 0)} ${usage.numTurns ?? 0} turns${tokens}`
5548
+ chalk17.cyan("\u2502") + ` ${chalk17.bold(agent)} ${chalk17.gray(`(${stage})`)} ${formatCost(usage.costUsd ?? 0)} ${formatDuration(usage.durationMs ?? 0)} ${usage.numTurns ?? 0} turns${tokens}`
5382
5549
  );
5383
5550
  const hasCacheData = (usage.cachedTokens ?? 0) > 0 || (usage.cacheWriteTokens ?? 0) > 0 || (usage.cacheDiscount ?? 0) > 0;
5384
5551
  if (hasCacheData) {
@@ -5390,11 +5557,11 @@ function printVerboseUsage(tracker) {
5390
5557
  if (savings > 0) parts.push(`saved: ${formatCost(savings)}`);
5391
5558
  if (usage.provider) parts.push(`provider: ${usage.provider}`);
5392
5559
  console.log(
5393
- chalk16.cyan("\u2502") + ` ${chalk16.gray("cache: { " + parts.join(", ") + " }")}`
5560
+ chalk17.cyan("\u2502") + ` ${chalk17.gray("cache: { " + parts.join(", ") + " }")}`
5394
5561
  );
5395
5562
  }
5396
5563
  }
5397
- console.log(chalk16.cyan("\u2514\u2500"));
5564
+ console.log(chalk17.cyan("\u2514\u2500"));
5398
5565
  }
5399
5566
 
5400
5567
  // src/knowledge/analyzer.ts
@@ -5848,7 +6015,7 @@ import { existsSync as existsSync8, mkdirSync as mkdirSync2 } from "fs";
5848
6015
 
5849
6016
  // src/retry-prompt.ts
5850
6017
  import { createInterface as createInterface3 } from "readline";
5851
- import chalk17 from "chalk";
6018
+ import chalk18 from "chalk";
5852
6019
  async function promptForRetry(options) {
5853
6020
  const { taskName, attempt, maxRetries, autoApprove = false, telemetry } = options;
5854
6021
  if (maxRetries === 0) {
@@ -5891,7 +6058,7 @@ async function promptForRetry(options) {
5891
6058
  const rl = createInterface3({ input: process.stdin, output: process.stdout });
5892
6059
  const answer = await new Promise((resolve5) => {
5893
6060
  rl.question(
5894
- chalk17.yellow(`
6061
+ chalk18.yellow(`
5895
6062
  ${taskName} failed after ${maxRetries} retries. Continue retrying? (y/n) `),
5896
6063
  resolve5
5897
6064
  );
@@ -5914,7 +6081,7 @@ ${taskName} failed after ${maxRetries} retries. Continue retrying? (y/n) `),
5914
6081
  }
5915
6082
  throw new TaskError(`${taskName} failed - user declined to retry after ${maxRetries} attempts`);
5916
6083
  }
5917
- console.log(chalk17.blue("\nContinuing retries...\n"));
6084
+ console.log(chalk18.blue("\nContinuing retries...\n"));
5918
6085
  return true;
5919
6086
  }
5920
6087
  if (!autoApprove) {
@@ -5923,14 +6090,14 @@ ${taskName} failed after ${maxRetries} retries. Continue retrying? (y/n) `),
5923
6090
  const attemptInfo = maxRetries > 0 ? `(attempt ${attempt}/${maxRetries})` : `(attempt ${attempt})`;
5924
6091
  const answer = await new Promise((resolve5) => {
5925
6092
  rl.question(
5926
- chalk17.yellow(`
6093
+ chalk18.yellow(`
5927
6094
  ${taskName} failed. Retry? ${attemptInfo} (y/n) `),
5928
6095
  resolve5
5929
6096
  );
5930
6097
  });
5931
6098
  rl.close();
5932
6099
  if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
5933
- console.log(chalk17.red("Aborted by user."));
6100
+ console.log(chalk18.red("Aborted by user."));
5934
6101
  process.exit(1);
5935
6102
  }
5936
6103
  }
@@ -6094,7 +6261,7 @@ async function retryGate(opts) {
6094
6261
  }
6095
6262
  }
6096
6263
  const attemptDisplay = maxRetries > 0 ? `${attempt}/${maxRetries}` : `${attempt}`;
6097
- console.log(chalk18.yellow(`
6264
+ console.log(chalk19.yellow(`
6098
6265
  Retrying ${gateName} (attempt ${attemptDisplay})...`));
6099
6266
  const failureContext = {
6100
6267
  gateName,
@@ -6118,7 +6285,7 @@ Retrying ${gateName} (attempt ${attemptDisplay})...`));
6118
6285
  if (retryResult.qe && context.implement) {
6119
6286
  context.implement.qe = retryResult.qe;
6120
6287
  }
6121
- status.succeed(chalk18.green("Retry implementation complete"));
6288
+ status.succeed(chalk19.green("Retry implementation complete"));
6122
6289
  const retryStatus = createLiveStatus(`re-running ${gateName}...`);
6123
6290
  const { gate: gateResult, usage: gateUsage } = await gateRunner(attempt + 1);
6124
6291
  const gateAgentName = gateName === "unit tests" ? "gate:unit-tests" : "gate:functional-tests";
@@ -6130,17 +6297,17 @@ Retrying ${gateName} (attempt ${attemptDisplay})...`));
6130
6297
  context.gates.functionalTests = gateResult;
6131
6298
  }
6132
6299
  if (gateResult.passed) {
6133
- retryStatus.succeed(chalk18.green(`${gateName} PASSED on retry ${attempt}`));
6300
+ retryStatus.succeed(chalk19.green(`${gateName} PASSED on retry ${attempt}`));
6134
6301
  return gateResult;
6135
6302
  }
6136
6303
  const attemptDisplayFail = maxRetries > 0 ? `${attempt}/${maxRetries}` : `${attempt}`;
6137
- retryStatus.fail(chalk18.red(`${gateName} FAILED (retry ${attemptDisplayFail})`));
6304
+ retryStatus.fail(chalk19.red(`${gateName} FAILED (retry ${attemptDisplayFail})`));
6138
6305
  }
6139
6306
  }
6140
6307
  async function promptLinearSpec() {
6141
6308
  loadEnvFile();
6142
6309
  if (!process.env.LINEAR_API_KEY) {
6143
- console.log(chalk18.red.bold("Error:"), "LINEAR_API_KEY not set. Add it to your .env file.");
6310
+ console.log(chalk19.red.bold("Error:"), "LINEAR_API_KEY not set. Add it to your .env file.");
6144
6311
  process.exit(1);
6145
6312
  }
6146
6313
  resetTerminalForInput();
@@ -6163,7 +6330,7 @@ async function promptJiraSpec() {
6163
6330
  if (!process.env.JIRA_EMAIL) missing.push("JIRA_EMAIL");
6164
6331
  if (!process.env.JIRA_API_TOKEN) missing.push("JIRA_API_TOKEN");
6165
6332
  if (missing.length > 0) {
6166
- console.log(chalk18.red.bold("Error:"), `Missing env vars: ${missing.join(", ")}. Add them to your .env file.`);
6333
+ console.log(chalk19.red.bold("Error:"), `Missing env vars: ${missing.join(", ")}. Add them to your .env file.`);
6167
6334
  process.exit(1);
6168
6335
  }
6169
6336
  resetTerminalForInput();
@@ -6228,7 +6395,7 @@ async function runCommand(options) {
6228
6395
  createdReygentDir = true;
6229
6396
  } catch (err) {
6230
6397
  if (isDebug()) {
6231
- console.error(chalk18.gray("Failed to create .reygent:"), err);
6398
+ console.error(chalk19.gray("Failed to create .reygent:"), err);
6232
6399
  }
6233
6400
  }
6234
6401
  }
@@ -6241,12 +6408,12 @@ async function runCommand(options) {
6241
6408
  await chesstrace.init(backend);
6242
6409
  await chesstrace.startRun();
6243
6410
  if (createdReygentDir) {
6244
- console.log(chalk18.green("\u2713"), chalk18.gray("Created .reygent/ for local knowledge learning"));
6411
+ console.log(chalk19.green("\u2713"), chalk19.gray("Created .reygent/ for local knowledge learning"));
6245
6412
  console.log("");
6246
6413
  }
6247
6414
  } catch (err) {
6248
6415
  if (isDebug()) {
6249
- console.error(chalk18.gray("Telemetry init failed:"), err);
6416
+ console.error(chalk19.gray("Telemetry init failed:"), err);
6250
6417
  }
6251
6418
  chesstrace = null;
6252
6419
  }
@@ -6256,7 +6423,7 @@ async function runCommand(options) {
6256
6423
  let specSource = options.spec;
6257
6424
  if (!specSource) {
6258
6425
  if (!process.stdin.isTTY) {
6259
- console.log(chalk18.red.bold("Error:"), "--spec is required in non-interactive environments.");
6426
+ console.log(chalk19.red.bold("Error:"), "--spec is required in non-interactive environments.");
6260
6427
  await chesstrace?.close();
6261
6428
  process.exit(1);
6262
6429
  }
@@ -6264,32 +6431,32 @@ async function runCommand(options) {
6264
6431
  }
6265
6432
  const spec = await loadSpec(specSource);
6266
6433
  if (options.dryRun) {
6267
- console.log(chalk18.yellow.bold("[dry-run]"), "No changes will be made.\n");
6434
+ console.log(chalk19.yellow.bold("[dry-run]"), "No changes will be made.\n");
6268
6435
  console.log("");
6269
- console.log(chalk18.bold.cyan("\u250C\u2500 Specification"));
6270
- console.log(chalk18.cyan("\u2502"), chalk18.bold(spec.title));
6271
- console.log(chalk18.cyan("\u2502"), chalk18.gray(`source: ${spec.source}`));
6272
- console.log(chalk18.cyan("\u2514\u2500"));
6436
+ console.log(chalk19.bold.cyan("\u250C\u2500 Specification"));
6437
+ console.log(chalk19.cyan("\u2502"), chalk19.bold(spec.title));
6438
+ console.log(chalk19.cyan("\u2502"), chalk19.gray(`source: ${spec.source}`));
6439
+ console.log(chalk19.cyan("\u2514\u2500"));
6273
6440
  console.log("");
6274
- console.log(chalk18.bold.cyan("\u250C\u2500 Workflow Stages"));
6441
+ console.log(chalk19.bold.cyan("\u250C\u2500 Workflow Stages"));
6275
6442
  for (let i = 0; i < PIPELINE.length; i++) {
6276
6443
  const stage = PIPELINE[i];
6277
6444
  const isLast = i === PIPELINE.length - 1;
6278
6445
  const prefix = isLast ? "\u2514\u2500" : "\u251C\u2500";
6279
6446
  const continuation = isLast ? " " : "\u2502 ";
6280
- console.log(chalk18.cyan(prefix), chalk18.bold.white(stage.name));
6281
- console.log(chalk18.cyan(continuation), chalk18.gray(stage.description));
6447
+ console.log(chalk19.cyan(prefix), chalk19.bold.white(stage.name));
6448
+ console.log(chalk19.cyan(continuation), chalk19.gray(stage.description));
6282
6449
  let execInfo = "";
6283
6450
  if (stage.execution.kind === "agent") {
6284
- execInfo = chalk18.blue(`agent: ${stage.execution.agent}`);
6451
+ execInfo = chalk19.blue(`agent: ${stage.execution.agent}`);
6285
6452
  } else if (stage.execution.kind === "parallel") {
6286
- execInfo = chalk18.magenta(`parallel: ${stage.execution.agents.join(", ")}`);
6453
+ execInfo = chalk19.magenta(`parallel: ${stage.execution.agents.join(", ")}`);
6287
6454
  } else if (stage.execution.kind === "gate") {
6288
- execInfo = chalk18.yellow(`gate: ${stage.execution.condition} (${stage.execution.agent})`);
6455
+ execInfo = chalk19.yellow(`gate: ${stage.execution.condition} (${stage.execution.agent})`);
6289
6456
  }
6290
- console.log(chalk18.cyan(continuation), execInfo);
6457
+ console.log(chalk19.cyan(continuation), execInfo);
6291
6458
  if (!isLast) {
6292
- console.log(chalk18.cyan("\u2502"));
6459
+ console.log(chalk19.cyan("\u2502"));
6293
6460
  }
6294
6461
  }
6295
6462
  console.log("");
@@ -6304,7 +6471,7 @@ async function runCommand(options) {
6304
6471
  context = { spec, results: [] };
6305
6472
  const threshold = options.securityThreshold.toUpperCase();
6306
6473
  if (!VALID_SEVERITIES.has(threshold)) {
6307
- console.log(chalk18.red.bold("Error:"), `Invalid --security-threshold "${options.securityThreshold}". Must be one of: CRITICAL, HIGH, MEDIUM, LOW`);
6474
+ console.log(chalk19.red.bold("Error:"), `Invalid --security-threshold "${options.securityThreshold}". Must be one of: CRITICAL, HIGH, MEDIUM, LOW`);
6308
6475
  process.exit(1);
6309
6476
  }
6310
6477
  let autoApprove = options.autoApprove;
@@ -6383,7 +6550,7 @@ async function runCommand(options) {
6383
6550
  { makeAssumptions: true, ...withActivity(agentOptions, status, toolTracker) }
6384
6551
  );
6385
6552
  if ("needsClarification" in result2 && result2.needsClarification) {
6386
- status.fail(chalk18.red("Planner asked questions despite skip flag"));
6553
+ status.fail(chalk19.red("Planner asked questions despite skip flag"));
6387
6554
  const chesstrace2 = getChesstrace();
6388
6555
  if (chesstrace2) {
6389
6556
  try {
@@ -6415,7 +6582,7 @@ async function runCommand(options) {
6415
6582
  if ("needsClarification" in result2 && result2.needsClarification) {
6416
6583
  status.stop();
6417
6584
  resetTerminalForInput();
6418
- console.log(chalk18.yellow("\nPlanner needs clarification:\n"));
6585
+ console.log(chalk19.yellow("\nPlanner needs clarification:\n"));
6419
6586
  const answers = [];
6420
6587
  for (let i = 0; i < result2.questions.length; i++) {
6421
6588
  const question = result2.questions[i];
@@ -6441,14 +6608,14 @@ async function runCommand(options) {
6441
6608
  A: ${answer}`);
6442
6609
  }
6443
6610
  clarificationAnswers = answers.join("\n\n");
6444
- console.log(chalk18.blue("\nRe-running planner with clarifications...\n"));
6611
+ console.log(chalk19.blue("\nRe-running planner with clarifications...\n"));
6445
6612
  status.start();
6446
6613
  } else {
6447
6614
  plan = result2;
6448
6615
  }
6449
6616
  }
6450
6617
  if (!plan) {
6451
- status.fail(chalk18.red("Planner failed"));
6618
+ status.fail(chalk19.red("Planner failed"));
6452
6619
  const chesstrace2 = getChesstrace();
6453
6620
  if (chesstrace2) {
6454
6621
  try {
@@ -6466,17 +6633,17 @@ A: ${answer}`);
6466
6633
  );
6467
6634
  }
6468
6635
  }
6469
- status.succeed(chalk18.green("Plan created"));
6636
+ status.succeed(chalk19.green("Plan created"));
6470
6637
  context.plan = plan;
6471
6638
  const cols = process.stdout.columns || 80;
6472
- console.log(chalk18.cyan("\nGoals:"));
6473
- for (const g of plan.goals) console.log(` ${chalk18.gray("-")} ${wrapText(g, 4, cols)}`);
6474
- console.log(chalk18.cyan("\nTasks:"));
6475
- for (const t of plan.tasks) console.log(` ${chalk18.gray("-")} ${wrapText(t, 4, cols)}`);
6476
- console.log(chalk18.cyan("\nConstraints:"));
6477
- for (const c of plan.constraints) console.log(` ${chalk18.gray("-")} ${wrapText(c, 4, cols)}`);
6478
- console.log(chalk18.cyan("\nDefinition of Done:"));
6479
- for (const d of plan.dod) console.log(` ${chalk18.gray("-")} ${wrapText(d, 4, cols)}`);
6639
+ console.log(chalk19.cyan("\nGoals:"));
6640
+ for (const g of plan.goals) console.log(` ${chalk19.gray("-")} ${wrapText(g, 4, cols)}`);
6641
+ console.log(chalk19.cyan("\nTasks:"));
6642
+ for (const t of plan.tasks) console.log(` ${chalk19.gray("-")} ${wrapText(t, 4, cols)}`);
6643
+ console.log(chalk19.cyan("\nConstraints:"));
6644
+ for (const c of plan.constraints) console.log(` ${chalk19.gray("-")} ${wrapText(c, 4, cols)}`);
6645
+ console.log(chalk19.cyan("\nDefinition of Done:"));
6646
+ for (const d of plan.dod) console.log(` ${chalk19.gray("-")} ${wrapText(d, 4, cols)}`);
6480
6647
  console.log();
6481
6648
  context.results.push({
6482
6649
  stage: stage.name,
@@ -6514,15 +6681,15 @@ A: ${answer}`);
6514
6681
  let devSuccess = impl.dev !== null;
6515
6682
  let qeSuccess = impl.qe !== null;
6516
6683
  if (devSuccess && qeSuccess) {
6517
- implStatus.succeed(chalk18.green("Implementation complete"));
6684
+ implStatus.succeed(chalk19.green("Implementation complete"));
6518
6685
  } else {
6519
- implStatus.warn(chalk18.yellow("Implementation partially failed"));
6686
+ implStatus.warn(chalk19.yellow("Implementation partially failed"));
6520
6687
  }
6521
6688
  if (impl.dev) {
6522
- console.log(chalk18.gray("dev files:"), impl.dev.files.join(", ") || chalk18.gray("(none)"));
6689
+ console.log(chalk19.gray("dev files:"), impl.dev.files.join(", ") || chalk19.gray("(none)"));
6523
6690
  }
6524
6691
  if (impl.qe) {
6525
- console.log(chalk18.gray("qe test files:"), impl.qe.testFiles.join(", ") || chalk18.gray("(none)"));
6692
+ console.log(chalk19.gray("qe test files:"), impl.qe.testFiles.join(", ") || chalk19.gray("(none)"));
6526
6693
  }
6527
6694
  let attempt = 0;
6528
6695
  while (!devSuccess || !qeSuccess) {
@@ -6545,7 +6712,7 @@ A: ${answer}`);
6545
6712
  if (!devSuccess) agentsToRetry.push("dev");
6546
6713
  if (!qeSuccess) agentsToRetry.push("qe");
6547
6714
  const attemptDisplay = maxRetries > 0 ? `${attempt}/${maxRetries}` : `${attempt}`;
6548
- console.log(chalk18.yellow(`
6715
+ console.log(chalk19.yellow(`
6549
6716
  Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`));
6550
6717
  const retryStatus = createLiveStatus(`re-running ${agentsToRetry.join(" + ")} agent(s)...`);
6551
6718
  try {
@@ -6567,18 +6734,18 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
6567
6734
  qeSuccess = true;
6568
6735
  }
6569
6736
  if (devSuccess && qeSuccess) {
6570
- retryStatus.succeed(chalk18.green("Implementation complete on retry"));
6737
+ retryStatus.succeed(chalk19.green("Implementation complete on retry"));
6571
6738
  if (context.implement.dev) {
6572
- console.log(chalk18.gray("dev files:"), context.implement.dev.files.join(", ") || chalk18.gray("(none)"));
6739
+ console.log(chalk19.gray("dev files:"), context.implement.dev.files.join(", ") || chalk19.gray("(none)"));
6573
6740
  }
6574
6741
  if (context.implement.qe) {
6575
- console.log(chalk18.gray("qe test files:"), context.implement.qe.testFiles.join(", ") || chalk18.gray("(none)"));
6742
+ console.log(chalk19.gray("qe test files:"), context.implement.qe.testFiles.join(", ") || chalk19.gray("(none)"));
6576
6743
  }
6577
6744
  } else {
6578
- retryStatus.warn(chalk18.yellow(`Retry ${attempt} partially failed`));
6745
+ retryStatus.warn(chalk19.yellow(`Retry ${attempt} partially failed`));
6579
6746
  }
6580
6747
  } catch {
6581
- retryStatus.fail(chalk18.red(`Retry ${attempt} failed`));
6748
+ retryStatus.fail(chalk19.red(`Retry ${attempt} failed`));
6582
6749
  }
6583
6750
  }
6584
6751
  context.results.push({
@@ -6614,7 +6781,7 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
6614
6781
  if (!context.gates) context.gates = {};
6615
6782
  context.gates.unitTests = gateResult;
6616
6783
  if (gateResult.passed) {
6617
- unitStatus.succeed(chalk18.green("Unit tests PASSED"));
6784
+ unitStatus.succeed(chalk19.green("Unit tests PASSED"));
6618
6785
  context.results.push({
6619
6786
  stage: stage.name,
6620
6787
  success: true,
@@ -6623,7 +6790,7 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
6623
6790
  emitStageEnd(chesstrace, stage.name, stageStartTime, true, void 0, toolTracker);
6624
6791
  continue;
6625
6792
  }
6626
- unitStatus.fail(chalk18.red("Unit tests FAILED"));
6793
+ unitStatus.fail(chalk19.red("Unit tests FAILED"));
6627
6794
  try {
6628
6795
  gateResult = await retryGate({
6629
6796
  gateName: "unit tests",
@@ -6675,7 +6842,7 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
6675
6842
  if (!context.gates) context.gates = {};
6676
6843
  context.gates.functionalTests = gateResult;
6677
6844
  if (gateResult.passed) {
6678
- funcStatus.succeed(chalk18.green("Functional tests PASSED"));
6845
+ funcStatus.succeed(chalk19.green("Functional tests PASSED"));
6679
6846
  context.results.push({
6680
6847
  stage: stage.name,
6681
6848
  success: true,
@@ -6684,7 +6851,7 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
6684
6851
  emitStageEnd(chesstrace, stage.name, stageStartTime, true, void 0, toolTracker);
6685
6852
  continue;
6686
6853
  }
6687
- funcStatus.fail(chalk18.red("Functional tests FAILED"));
6854
+ funcStatus.fail(chalk19.red("Functional tests FAILED"));
6688
6855
  console.log(gateResult.output);
6689
6856
  try {
6690
6857
  gateResult = await retryGate({
@@ -6736,12 +6903,12 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
6736
6903
  if (secUsage) tracker.record("security-review", stage.name, secUsage);
6737
6904
  context.securityReview = output;
6738
6905
  if (passed) {
6739
- secStatus.succeed(chalk18.green("Security review PASSED"));
6906
+ secStatus.succeed(chalk19.green("Security review PASSED"));
6740
6907
  } else {
6741
- secStatus.fail(chalk18.red("Security review FAILED"));
6908
+ secStatus.fail(chalk19.red("Security review FAILED"));
6742
6909
  }
6743
6910
  console.log("");
6744
- console.log(chalk18.cyan.bold(`Security Findings (${output.findings.length}):`));
6911
+ console.log(chalk19.cyan.bold(`Security Findings (${output.findings.length}):`));
6745
6912
  console.log(formatFindings(output.findings, threshold));
6746
6913
  console.log("");
6747
6914
  if (passed) {
@@ -6753,7 +6920,7 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
6753
6920
  emitStageEnd(chesstrace, stage.name, stageStartTime, true, void 0, toolTracker);
6754
6921
  continue;
6755
6922
  }
6756
- console.log(chalk18.yellow(`Findings at or above ${threshold} threshold`));
6923
+ console.log(chalk19.yellow(`Findings at or above ${threshold} threshold`));
6757
6924
  context.results.push({
6758
6925
  stage: stage.name,
6759
6926
  success: false,
@@ -6761,7 +6928,7 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
6761
6928
  });
6762
6929
  emitStageEnd(chesstrace, stage.name, stageStartTime, false, void 0, toolTracker);
6763
6930
  if (autoApprove) {
6764
- console.log(chalk18.yellow("Auto-approved \u2014 bypassing security gate..."));
6931
+ console.log(chalk19.yellow("Auto-approved \u2014 bypassing security gate..."));
6765
6932
  } else {
6766
6933
  resetTerminalForInput();
6767
6934
  const rl = createInterface4({
@@ -6770,16 +6937,16 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
6770
6937
  });
6771
6938
  const answer = await new Promise((resolve5) => {
6772
6939
  rl.question(
6773
- chalk18.yellow("\nSecurity review failed. Continue with PR creation anyway? (y/n) "),
6940
+ chalk19.yellow("\nSecurity review failed. Continue with PR creation anyway? (y/n) "),
6774
6941
  resolve5
6775
6942
  );
6776
6943
  });
6777
6944
  rl.close();
6778
6945
  if (answer.toLowerCase() !== "y" && answer.toLowerCase() !== "yes") {
6779
- console.log(chalk18.red("Aborted by user."));
6946
+ console.log(chalk19.red("Aborted by user."));
6780
6947
  process.exit(1);
6781
6948
  }
6782
- console.log(chalk18.yellow("Bypassed by user \u2014 continuing..."));
6949
+ console.log(chalk19.yellow("Bypassed by user \u2014 continuing..."));
6783
6950
  }
6784
6951
  continue;
6785
6952
  }
@@ -6818,12 +6985,12 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
6818
6985
  });
6819
6986
  }
6820
6987
  }
6821
- const spinner = ora2(chalk18.blue("creating pull request...")).start();
6988
+ const spinner = ora2(chalk19.blue("creating pull request...")).start();
6822
6989
  const prResult = await runPRCreate(context, { insecure: options.insecure, branchType });
6823
6990
  context.prCreate = prResult;
6824
- spinner.succeed(chalk18.green("PR created"));
6825
- console.log(chalk18.gray("branch:"), chalk18.cyan(prResult.branch));
6826
- console.log(chalk18.gray("PR:"), chalk18.blue(prResult.prUrl));
6991
+ spinner.succeed(chalk19.green("PR created"));
6992
+ console.log(chalk19.gray("branch:"), chalk19.cyan(prResult.branch));
6993
+ console.log(chalk19.gray("PR:"), chalk19.blue(prResult.prUrl));
6827
6994
  context.results.push({
6828
6995
  stage: stage.name,
6829
6996
  success: true,
@@ -6840,15 +7007,15 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
6840
7007
  );
6841
7008
  context.prReview = reviewOutput;
6842
7009
  if (prUsage) tracker.record("pr-review", stage.name, prUsage);
6843
- prStatus.succeed(chalk18.green("PR review complete"));
7010
+ prStatus.succeed(chalk19.green("PR review complete"));
6844
7011
  console.log(formatPRReviewTerminal(reviewOutput));
6845
- const commentSpinner = ora2(chalk18.blue("posting review comment to PR...")).start();
7012
+ const commentSpinner = ora2(chalk19.blue("posting review comment to PR...")).start();
6846
7013
  try {
6847
7014
  await postPRReviewComment(context, reviewOutput);
6848
- commentSpinner.succeed(chalk18.green("Review posted to PR"));
7015
+ commentSpinner.succeed(chalk19.green("Review posted to PR"));
6849
7016
  } catch (err) {
6850
7017
  const msg = err instanceof Error ? err.message : String(err);
6851
- commentSpinner.fail(chalk18.yellow(`Could not post review to PR: ${msg}`));
7018
+ commentSpinner.fail(chalk19.yellow(`Could not post review to PR: ${msg}`));
6852
7019
  }
6853
7020
  context.results.push({
6854
7021
  stage: stage.name,
@@ -6863,7 +7030,7 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
6863
7030
  success: true,
6864
7031
  output: "skipped"
6865
7032
  };
6866
- console.log(chalk18.gray(`[${stage.name}] skipped`));
7033
+ console.log(chalk19.gray(`[${stage.name}] skipped`));
6867
7034
  context.results.push(result);
6868
7035
  emitStageEnd(chesstrace, stage.name, stageStartTime, true, void 0, toolTracker);
6869
7036
  }
@@ -6947,13 +7114,13 @@ Retrying ${agentsToRetry.join(" + ")} agent(s) (attempt ${attemptDisplay})...`))
6947
7114
  process.exit(0);
6948
7115
  }
6949
7116
  if (err instanceof SpecError || err instanceof TaskError) {
6950
- console.log(chalk18.red.bold("Error:"), err.message);
7117
+ console.log(chalk19.red.bold("Error:"), err.message);
6951
7118
  if (isDebug()) console.error(err.stack);
6952
7119
  if (isTest) throw err;
6953
7120
  process.exit(1);
6954
7121
  }
6955
7122
  const message = err instanceof Error ? err.message : String(err);
6956
- console.log(chalk18.red.bold("Internal error:"), message);
7123
+ console.log(chalk19.red.bold("Internal error:"), message);
6957
7124
  if (isDebug()) console.error(err instanceof Error ? err.stack : err);
6958
7125
  if (isTest) throw err;
6959
7126
  process.exit(2);
@@ -6965,7 +7132,7 @@ import { existsSync as existsSync9, mkdirSync as mkdirSync3, writeFileSync as wr
6965
7132
  import { join as join7 } from "path";
6966
7133
  import { ExitPromptError as ExitPromptError2 } from "@inquirer/core";
6967
7134
  import { select as select4 } from "@inquirer/prompts";
6968
- import chalk19 from "chalk";
7135
+ import chalk20 from "chalk";
6969
7136
  import ora3 from "ora";
6970
7137
  async function initCommand(options = { dryRun: false }) {
6971
7138
  const targetDir = join7(process.cwd(), ".reygent");
@@ -6977,25 +7144,25 @@ async function initCommand(options = { dryRun: false }) {
6977
7144
  model: DEFAULT_MODEL5
6978
7145
  };
6979
7146
  if (options.dryRun) {
6980
- console.log(chalk19.yellow.bold("[dry-run]"), "No changes will be made.\n");
6981
- console.log(chalk19.bold("Would create:"));
6982
- console.log(chalk19.gray(" dir: "), chalk19.cyan(targetDir));
6983
- console.log(chalk19.gray(" dir: "), chalk19.cyan(skillsDir));
6984
- console.log(chalk19.gray(" file: "), chalk19.cyan(configPath));
7147
+ console.log(chalk20.yellow.bold("[dry-run]"), "No changes will be made.\n");
7148
+ console.log(chalk20.bold("Would create:"));
7149
+ console.log(chalk20.gray(" dir: "), chalk20.cyan(targetDir));
7150
+ console.log(chalk20.gray(" dir: "), chalk20.cyan(skillsDir));
7151
+ console.log(chalk20.gray(" file: "), chalk20.cyan(configPath));
6985
7152
  console.log("");
6986
- console.log(chalk19.bold("Config preview:"));
6987
- console.log(chalk19.gray(JSON.stringify(defaultConfig, null, 2)));
7153
+ console.log(chalk20.bold("Config preview:"));
7154
+ console.log(chalk20.gray(JSON.stringify(defaultConfig, null, 2)));
6988
7155
  console.log("");
6989
7156
  return;
6990
7157
  }
6991
7158
  try {
6992
7159
  if (existsSync9(targetDir)) {
6993
- console.log(chalk19.yellow.bold("Warning:"), `.reygent folder already exists`);
6994
- console.log(chalk19.gray(` Path: ${targetDir}
7160
+ console.log(chalk20.yellow.bold("Warning:"), `.reygent folder already exists`);
7161
+ console.log(chalk20.gray(` Path: ${targetDir}
6995
7162
  `));
6996
7163
  if (existsSync9(configPath)) {
6997
7164
  if (!process.stdin.isTTY) {
6998
- console.log(chalk19.red.bold("Error:"), "Cannot prompt in non-interactive mode. Use --dry-run to preview or remove existing .reygent/ first.");
7165
+ console.log(chalk20.red.bold("Error:"), "Cannot prompt in non-interactive mode. Use --dry-run to preview or remove existing .reygent/ first.");
6999
7166
  process.exit(1);
7000
7167
  }
7001
7168
  resetTerminalForInput();
@@ -7008,16 +7175,16 @@ async function initCommand(options = { dryRun: false }) {
7008
7175
  ]
7009
7176
  });
7010
7177
  if (action === "cancel") {
7011
- console.log(chalk19.gray("No changes made.\n"));
7178
+ console.log(chalk20.gray("No changes made.\n"));
7012
7179
  return;
7013
7180
  }
7014
7181
  if (action === "edit") {
7015
- console.log(chalk19.cyan("Run"), chalk19.bold("reygent config"), chalk19.cyan("to edit your configuration.\n"));
7182
+ console.log(chalk20.cyan("Run"), chalk20.bold("reygent config"), chalk20.cyan("to edit your configuration.\n"));
7016
7183
  return;
7017
7184
  }
7018
- console.log(chalk19.cyan("Resetting config to defaults...\n"));
7185
+ console.log(chalk20.cyan("Resetting config to defaults...\n"));
7019
7186
  } else {
7020
- console.log(chalk19.cyan("No config.json found. Creating default config...\n"));
7187
+ console.log(chalk20.cyan("No config.json found. Creating default config...\n"));
7021
7188
  }
7022
7189
  }
7023
7190
  const spinnerText = existsSync9(targetDir) ? "Writing config" : "Creating .reygent folder";
@@ -7044,24 +7211,24 @@ knowledge/success-patterns.md
7044
7211
  # - knowledge/agents/*.md (curated agent tips)
7045
7212
  `;
7046
7213
  writeFileSync2(gitignorePath, gitignoreContent, "utf-8");
7047
- spinner.succeed(chalk19.green("Initialized .reygent folder"));
7214
+ spinner.succeed(chalk20.green("Initialized .reygent folder"));
7048
7215
  console.log("");
7049
- console.log(chalk19.bold("Next steps:"));
7050
- console.log(chalk19.gray(" \u2022 Edit"), chalk19.cyan(".reygent/config.json"), chalk19.gray("to customize agents"));
7051
- console.log(chalk19.gray(" \u2022 Add custom agents to the"), chalk19.cyan("agents"), chalk19.gray("array"));
7052
- console.log(chalk19.gray(" \u2022 Add skills to"), chalk19.cyan(".reygent/skills/"), chalk19.gray("(each in its own folder with SKILL.md)"));
7053
- console.log(chalk19.gray(" \u2022 Populate"), chalk19.cyan(".reygent/knowledge/"), chalk19.gray("with project conventions"));
7054
- console.log(chalk19.gray(" \u2022 Run"), chalk19.cyan("reygent agent <name>"), chalk19.gray("to use your local config"));
7216
+ console.log(chalk20.bold("Next steps:"));
7217
+ console.log(chalk20.gray(" \u2022 Edit"), chalk20.cyan(".reygent/config.json"), chalk20.gray("to customize agents"));
7218
+ console.log(chalk20.gray(" \u2022 Add custom agents to the"), chalk20.cyan("agents"), chalk20.gray("array"));
7219
+ console.log(chalk20.gray(" \u2022 Add skills to"), chalk20.cyan(".reygent/skills/"), chalk20.gray("(each in its own folder with SKILL.md)"));
7220
+ console.log(chalk20.gray(" \u2022 Populate"), chalk20.cyan(".reygent/knowledge/"), chalk20.gray("with project conventions"));
7221
+ console.log(chalk20.gray(" \u2022 Run"), chalk20.cyan("reygent agent <name>"), chalk20.gray("to use your local config"));
7055
7222
  console.log("");
7056
7223
  } catch (err) {
7057
7224
  const message = err instanceof Error ? err.message : String(err);
7058
- spinner.fail(chalk19.red(`Failed: ${message}`));
7225
+ spinner.fail(chalk20.red(`Failed: ${message}`));
7059
7226
  if (isDebug()) console.error(err instanceof Error ? err.stack : err);
7060
7227
  process.exit(2);
7061
7228
  }
7062
7229
  } catch (err) {
7063
7230
  if (err instanceof ExitPromptError2) {
7064
- console.log(chalk19.yellow("\nInitialization cancelled."));
7231
+ console.log(chalk20.yellow("\nInitialization cancelled."));
7065
7232
  process.exit(0);
7066
7233
  }
7067
7234
  throw err;
@@ -7072,7 +7239,7 @@ knowledge/success-patterns.md
7072
7239
  import { existsSync as existsSync11, mkdirSync as mkdirSync5, writeFileSync as writeFileSync3, rmSync, readdirSync as readdirSync4, statSync as statSync5, readFileSync as readFileSync8 } from "fs";
7073
7240
  import { join as join9, dirname as dirname4 } from "path";
7074
7241
  import { fileURLToPath } from "url";
7075
- import chalk20 from "chalk";
7242
+ import chalk21 from "chalk";
7076
7243
  import ora4 from "ora";
7077
7244
 
7078
7245
  // src/registry.ts
@@ -7228,33 +7395,33 @@ async function listAction() {
7228
7395
  try {
7229
7396
  const skills = await listRemoteSkills();
7230
7397
  const installed = getInstalledSkillNames();
7231
- spinner.succeed(chalk20.green(`Found ${skills.length} skill${skills.length !== 1 ? "s" : ""}`));
7398
+ spinner.succeed(chalk21.green(`Found ${skills.length} skill${skills.length !== 1 ? "s" : ""}`));
7232
7399
  console.log("");
7233
7400
  if (skills.length === 0) {
7234
- console.log(chalk20.gray(" No skills available in registry."));
7401
+ console.log(chalk21.gray(" No skills available in registry."));
7235
7402
  console.log("");
7236
7403
  return;
7237
7404
  }
7238
7405
  for (const skill of skills) {
7239
- const badge = installed.has(skill.name) ? chalk20.green(" [installed]") : "";
7240
- const version = skill.version ? chalk20.gray(` v${skill.version}`) : "";
7241
- console.log(` ${chalk20.bold.cyan(skill.name)}${version}${badge}`);
7406
+ const badge = installed.has(skill.name) ? chalk21.green(" [installed]") : "";
7407
+ const version = skill.version ? chalk21.gray(` v${skill.version}`) : "";
7408
+ console.log(` ${chalk21.bold.cyan(skill.name)}${version}${badge}`);
7242
7409
  console.log(` ${skill.description}`);
7243
7410
  if (skill.license) {
7244
- console.log(` ${chalk20.gray(`License: ${skill.license}`)}`);
7411
+ console.log(` ${chalk21.gray(`License: ${skill.license}`)}`);
7245
7412
  }
7246
7413
  console.log("");
7247
7414
  }
7248
7415
  } catch (err) {
7249
7416
  const message = err instanceof Error ? err.message : String(err);
7250
- spinner.fail(chalk20.red(`Failed to fetch skills: ${message}`));
7417
+ spinner.fail(chalk21.red(`Failed to fetch skills: ${message}`));
7251
7418
  if (isDebug()) console.error(err instanceof Error ? err.stack : err);
7252
7419
  process.exit(2);
7253
7420
  }
7254
7421
  }
7255
7422
  async function addAction(name, options) {
7256
7423
  if (!validateSkillName(name)) {
7257
- console.log(chalk20.red.bold("Error:"), `Invalid skill name "${name}"`);
7424
+ console.log(chalk21.red.bold("Error:"), `Invalid skill name "${name}"`);
7258
7425
  process.exit(1);
7259
7426
  }
7260
7427
  let targetBase;
@@ -7263,15 +7430,15 @@ async function addAction(name, options) {
7263
7430
  } else {
7264
7431
  const localSkillsDir = resolveSkillsDir("local");
7265
7432
  if (!localSkillsDir) {
7266
- console.log(chalk20.red.bold("Error:"), "No .reygent/ directory found.");
7267
- console.log(chalk20.gray(" Run"), chalk20.cyan("reygent init"), chalk20.gray("first, or use"), chalk20.cyan("--global"));
7433
+ console.log(chalk21.red.bold("Error:"), "No .reygent/ directory found.");
7434
+ console.log(chalk21.gray(" Run"), chalk21.cyan("reygent init"), chalk21.gray("first, or use"), chalk21.cyan("--global"));
7268
7435
  process.exit(1);
7269
7436
  }
7270
7437
  targetBase = localSkillsDir;
7271
7438
  }
7272
7439
  const targetDir = join9(targetBase, name);
7273
7440
  if (existsSync11(targetDir)) {
7274
- console.log(chalk20.red.bold("Error:"), `Skill "${name}" already installed at ${targetDir}`);
7441
+ console.log(chalk21.red.bold("Error:"), `Skill "${name}" already installed at ${targetDir}`);
7275
7442
  process.exit(1);
7276
7443
  }
7277
7444
  const spinner = ora4(`Installing ${name}...`).start();
@@ -7282,9 +7449,9 @@ async function addAction(name, options) {
7282
7449
  const compatible = checkCompatibility(manifest.compatibility, version);
7283
7450
  if (!compatible) {
7284
7451
  spinner.warn(
7285
- chalk20.yellow(`Skill "${name}" requires ${manifest.compatibility}, you have v${version}`)
7452
+ chalk21.yellow(`Skill "${name}" requires ${manifest.compatibility}, you have v${version}`)
7286
7453
  );
7287
- console.log(chalk20.yellow(" Installing anyway \u2014 some features may not work.\n"));
7454
+ console.log(chalk21.yellow(" Installing anyway \u2014 some features may not work.\n"));
7288
7455
  spinner.start(`Downloading ${name}...`);
7289
7456
  }
7290
7457
  spinner.text = `Downloading ${name}...`;
@@ -7296,21 +7463,21 @@ async function addAction(name, options) {
7296
7463
  mkdirSync5(fileDir, { recursive: true });
7297
7464
  writeFileSync3(filePath, file.content, "utf-8");
7298
7465
  }
7299
- spinner.succeed(chalk20.green(`Installed "${name}" (${files.length} files)`));
7466
+ spinner.succeed(chalk21.green(`Installed "${name}" (${files.length} files)`));
7300
7467
  console.log("");
7301
- console.log(chalk20.gray(" Location:"), chalk20.cyan(targetDir));
7302
- console.log(chalk20.gray(" Usage: "), chalk20.cyan(`reygent agent ${name}`));
7468
+ console.log(chalk21.gray(" Location:"), chalk21.cyan(targetDir));
7469
+ console.log(chalk21.gray(" Usage: "), chalk21.cyan(`reygent agent ${name}`));
7303
7470
  console.log("");
7304
7471
  } catch (err) {
7305
7472
  const message = err instanceof Error ? err.message : String(err);
7306
- spinner.fail(chalk20.red(`Failed to install "${name}": ${message}`));
7473
+ spinner.fail(chalk21.red(`Failed to install "${name}": ${message}`));
7307
7474
  if (isDebug()) console.error(err instanceof Error ? err.stack : err);
7308
7475
  process.exit(2);
7309
7476
  }
7310
7477
  }
7311
7478
  async function removeAction(name, options) {
7312
7479
  if (!validateSkillName(name)) {
7313
- console.log(chalk20.red.bold("Error:"), `Invalid skill name "${name}"`);
7480
+ console.log(chalk21.red.bold("Error:"), `Invalid skill name "${name}"`);
7314
7481
  process.exit(1);
7315
7482
  }
7316
7483
  let targetBase;
@@ -7319,22 +7486,22 @@ async function removeAction(name, options) {
7319
7486
  } else {
7320
7487
  const localSkillsDir = resolveSkillsDir("local");
7321
7488
  if (!localSkillsDir) {
7322
- console.log(chalk20.red.bold("Error:"), "No .reygent/ directory found.");
7489
+ console.log(chalk21.red.bold("Error:"), "No .reygent/ directory found.");
7323
7490
  process.exit(1);
7324
7491
  }
7325
7492
  targetBase = localSkillsDir;
7326
7493
  }
7327
7494
  const targetDir = join9(targetBase, name);
7328
7495
  if (!existsSync11(targetDir)) {
7329
- console.log(chalk20.red.bold("Error:"), `Skill "${name}" not found at ${targetDir}`);
7496
+ console.log(chalk21.red.bold("Error:"), `Skill "${name}" not found at ${targetDir}`);
7330
7497
  process.exit(1);
7331
7498
  }
7332
7499
  try {
7333
7500
  rmSync(targetDir, { recursive: true, force: true });
7334
- console.log(chalk20.green(`Removed "${name}" from ${targetDir}`));
7501
+ console.log(chalk21.green(`Removed "${name}" from ${targetDir}`));
7335
7502
  } catch (err) {
7336
7503
  const message = err instanceof Error ? err.message : String(err);
7337
- console.log(chalk20.red.bold("Error:"), `Failed to remove "${name}": ${message}`);
7504
+ console.log(chalk21.red.bold("Error:"), `Failed to remove "${name}": ${message}`);
7338
7505
  if (isDebug()) console.error(err instanceof Error ? err.stack : err);
7339
7506
  process.exit(1);
7340
7507
  }
@@ -7349,7 +7516,7 @@ function registerSkillsCommand(program2) {
7349
7516
  // src/commands/review-work.ts
7350
7517
  import { execFile as execFile3 } from "child_process";
7351
7518
  import { request as httpsRequest2 } from "https";
7352
- import chalk21 from "chalk";
7519
+ import chalk22 from "chalk";
7353
7520
  import ora5 from "ora";
7354
7521
 
7355
7522
  // src/spec-prefix.ts
@@ -7702,7 +7869,7 @@ async function reviewWorkCommand(options) {
7702
7869
  try {
7703
7870
  await exec3("git", ["rev-parse", "--is-inside-work-tree"]);
7704
7871
  } catch {
7705
- console.log(chalk21.red.bold("Error:"), "Not inside a git repository.");
7872
+ console.log(chalk22.red.bold("Error:"), "Not inside a git repository.");
7706
7873
  process.exit(1);
7707
7874
  }
7708
7875
  loadEnvFile();
@@ -7713,9 +7880,9 @@ async function reviewWorkCommand(options) {
7713
7880
  const parsed = parseSpecWithPrefix(options.spec);
7714
7881
  const loaded = await loadSpec(parsed.identifier, parsed.provider);
7715
7882
  spec = { title: loaded.title, content: loaded.content };
7716
- spinner.succeed(chalk21.green(`Spec loaded: ${loaded.title}`));
7883
+ spinner.succeed(chalk22.green(`Spec loaded: ${loaded.title}`));
7717
7884
  } catch (err) {
7718
- spinner.fail(chalk21.red("Failed to load spec"));
7885
+ spinner.fail(chalk22.red("Failed to load spec"));
7719
7886
  throw err;
7720
7887
  }
7721
7888
  }
@@ -7724,14 +7891,14 @@ async function reviewWorkCommand(options) {
7724
7891
  const branch = await getCurrentBranch();
7725
7892
  const defaultBranch = await getDefaultBranch();
7726
7893
  console.log(
7727
- chalk21.gray(` Platform: ${remote.platform}`) + chalk21.gray(` | Branch: ${branch}`) + chalk21.gray(` | Base: ${defaultBranch}`)
7894
+ chalk22.gray(` Platform: ${remote.platform}`) + chalk22.gray(` | Branch: ${branch}`) + chalk22.gray(` | Base: ${defaultBranch}`)
7728
7895
  );
7729
7896
  console.log();
7730
7897
  if (remote.platform === "github") {
7731
7898
  const spinner = ora5("Checking for open PR...").start();
7732
7899
  const prNumber = await detectGitHubPR();
7733
7900
  if (prNumber !== null) {
7734
- spinner.succeed(chalk21.green(`Found PR #${prNumber}`));
7901
+ spinner.succeed(chalk22.green(`Found PR #${prNumber}`));
7735
7902
  const context = {
7736
7903
  spec: spec ? { source: "markdown", title: spec.title, content: spec.content } : { source: "markdown", title: "Review", content: "" },
7737
7904
  prCreate: {
@@ -7745,19 +7912,19 @@ async function reviewWorkCommand(options) {
7745
7912
  console.log();
7746
7913
  const prReviewStatus = createLiveStatus("Running PR review...");
7747
7914
  const { output } = await runPRReview(context, { quiet: true, onActivity: prReviewStatus.onActivity });
7748
- prReviewStatus.succeed(chalk21.green("Review complete"));
7915
+ prReviewStatus.succeed(chalk22.green("Review complete"));
7749
7916
  console.log(formatPRReviewTerminal(output));
7750
7917
  console.log();
7751
7918
  const postSpinner = ora5("Posting review comment to PR...").start();
7752
7919
  try {
7753
7920
  await postPRReviewComment(context, output);
7754
- postSpinner.succeed(chalk21.green(`Review posted to PR #${prNumber}`));
7921
+ postSpinner.succeed(chalk22.green(`Review posted to PR #${prNumber}`));
7755
7922
  } catch (err) {
7756
7923
  const msg = err instanceof Error ? err.message : String(err);
7757
- postSpinner.fail(chalk21.red(`Failed to post comment: ${msg}`));
7924
+ postSpinner.fail(chalk22.red(`Failed to post comment: ${msg}`));
7758
7925
  }
7759
7926
  } else {
7760
- spinner.info(chalk21.yellow("No open PR found for this branch"));
7927
+ spinner.info(chalk22.yellow("No open PR found for this branch"));
7761
7928
  console.log();
7762
7929
  const reviewStatus = createLiveStatus("Running review...");
7763
7930
  let output;
@@ -7766,15 +7933,15 @@ async function reviewWorkCommand(options) {
7766
7933
  } catch (err) {
7767
7934
  if (err instanceof TaskError && err.message.includes("no changes found")) {
7768
7935
  reviewStatus.stop();
7769
- console.log(chalk21.yellow("No changes found against"), chalk21.bold(defaultBranch));
7936
+ console.log(chalk22.yellow("No changes found against"), chalk22.bold(defaultBranch));
7770
7937
  return;
7771
7938
  }
7772
7939
  throw err;
7773
7940
  }
7774
- reviewStatus.succeed(chalk21.green("Review complete"));
7941
+ reviewStatus.succeed(chalk22.green("Review complete"));
7775
7942
  console.log(formatPRReviewTerminal(output));
7776
7943
  console.log();
7777
- console.log(chalk21.gray("No PR found \u2014 review printed to console only."));
7944
+ console.log(chalk22.gray("No PR found \u2014 review printed to console only."));
7778
7945
  }
7779
7946
  } else {
7780
7947
  const spinner = ora5("Checking for open MR...").start();
@@ -7784,16 +7951,16 @@ async function reviewWorkCommand(options) {
7784
7951
  } catch (err) {
7785
7952
  if (isDebug()) {
7786
7953
  const msg = err instanceof Error ? err.message : String(err);
7787
- console.error(chalk21.gray(`[debug] Token resolution failed: ${msg}`));
7954
+ console.error(chalk22.gray(`[debug] Token resolution failed: ${msg}`));
7788
7955
  }
7789
- spinner.info(chalk21.yellow("Could not resolve GitLab token \u2014 skipping MR detection"));
7956
+ spinner.info(chalk22.yellow("Could not resolve GitLab token \u2014 skipping MR detection"));
7790
7957
  token = "";
7791
7958
  }
7792
7959
  const mrIid = token ? await detectGitLabMR(remote, token, branch, options.insecure) : null;
7793
7960
  if (mrIid !== null) {
7794
- spinner.succeed(chalk21.green(`Found MR !${mrIid}`));
7961
+ spinner.succeed(chalk22.green(`Found MR !${mrIid}`));
7795
7962
  } else {
7796
- spinner.info(chalk21.yellow("No open MR found for this branch"));
7963
+ spinner.info(chalk22.yellow("No open MR found for this branch"));
7797
7964
  }
7798
7965
  console.log();
7799
7966
  const glReviewStatus = createLiveStatus("Running review...");
@@ -7803,12 +7970,12 @@ async function reviewWorkCommand(options) {
7803
7970
  } catch (err) {
7804
7971
  if (err instanceof TaskError && err.message.includes("no changes found")) {
7805
7972
  glReviewStatus.stop();
7806
- console.log(chalk21.yellow("No changes found against"), chalk21.bold(defaultBranch));
7973
+ console.log(chalk22.yellow("No changes found against"), chalk22.bold(defaultBranch));
7807
7974
  return;
7808
7975
  }
7809
7976
  throw err;
7810
7977
  }
7811
- glReviewStatus.succeed(chalk21.green("Review complete"));
7978
+ glReviewStatus.succeed(chalk22.green("Review complete"));
7812
7979
  console.log(formatPRReviewTerminal(output));
7813
7980
  console.log();
7814
7981
  if (mrIid !== null && token) {
@@ -7816,13 +7983,13 @@ async function reviewWorkCommand(options) {
7816
7983
  try {
7817
7984
  const body = formatPRReviewOutput(output) + "\n\n---\n*Review by [reygent](https://github.com/andrewevans0102/reygent)*";
7818
7985
  await postGitLabComment(remote, token, mrIid, body, options.insecure);
7819
- postSpinner.succeed(chalk21.green(`Review posted to MR !${mrIid}`));
7986
+ postSpinner.succeed(chalk22.green(`Review posted to MR !${mrIid}`));
7820
7987
  } catch (err) {
7821
7988
  const msg = err instanceof Error ? err.message : String(err);
7822
- postSpinner.fail(chalk21.red(`Failed to post comment: ${msg}`));
7989
+ postSpinner.fail(chalk22.red(`Failed to post comment: ${msg}`));
7823
7990
  }
7824
7991
  } else {
7825
- console.log(chalk21.gray("No MR found \u2014 review printed to console only."));
7992
+ console.log(chalk22.gray("No MR found \u2014 review printed to console only."));
7826
7993
  }
7827
7994
  }
7828
7995
  } catch (err) {
@@ -7830,12 +7997,12 @@ async function reviewWorkCommand(options) {
7830
7997
  process.exit(0);
7831
7998
  }
7832
7999
  if (err instanceof SpecError || err instanceof SpecPrefixError || err instanceof TaskError) {
7833
- console.log(chalk21.red.bold("Error:"), err.message);
8000
+ console.log(chalk22.red.bold("Error:"), err.message);
7834
8001
  if (isDebug()) console.error(err.stack);
7835
8002
  process.exit(1);
7836
8003
  }
7837
8004
  const message = err instanceof Error ? err.message : String(err);
7838
- console.log(chalk21.red.bold("Internal error:"), message);
8005
+ console.log(chalk22.red.bold("Internal error:"), message);
7839
8006
  if (isDebug()) console.error(err instanceof Error ? err.stack : err);
7840
8007
  process.exit(2);
7841
8008
  }
@@ -7844,7 +8011,7 @@ async function reviewWorkCommand(options) {
7844
8011
  // src/commands/review-comments.ts
7845
8012
  import { execFile as execFile4 } from "child_process";
7846
8013
  import { request as httpsRequest3 } from "https";
7847
- import chalk22 from "chalk";
8014
+ import chalk23 from "chalk";
7848
8015
  import { select as select5 } from "@inquirer/prompts";
7849
8016
  var PRIMARY_SECURITY_KEYWORDS = [
7850
8017
  "xss",
@@ -8113,21 +8280,21 @@ async function fetchGitLabComments(remote, token, mrIid, insecure) {
8113
8280
  function displayCommentSummary(comments) {
8114
8281
  const securityCount = comments.filter((c) => c.isSecurity).length;
8115
8282
  const generalCount = comments.length - securityCount;
8116
- console.log(chalk22.bold(` ${comments.length} review comment(s) found`));
8283
+ console.log(chalk23.bold(` ${comments.length} review comment(s) found`));
8117
8284
  if (securityCount > 0) {
8118
8285
  console.log(
8119
- chalk22.yellow(` \u26A0 ${securityCount} security-related`) + chalk22.gray(` | ${generalCount} general`)
8286
+ chalk23.yellow(` \u26A0 ${securityCount} security-related`) + chalk23.gray(` | ${generalCount} general`)
8120
8287
  );
8121
8288
  }
8122
8289
  console.log();
8123
8290
  for (const c of comments) {
8124
- const location = c.path ? chalk22.cyan(` ${c.path}${c.line ? `:${c.line}` : ""}`) : chalk22.gray(" (general)");
8125
- const tag = c.isSecurity ? chalk22.bgYellow.black(" SEC ") + " " : "";
8126
- console.log(` ${tag}${chalk22.bold(c.author)} ${location}`);
8291
+ const location = c.path ? chalk23.cyan(` ${c.path}${c.line ? `:${c.line}` : ""}`) : chalk23.gray(" (general)");
8292
+ const tag = c.isSecurity ? chalk23.bgYellow.black(" SEC ") + " " : "";
8293
+ console.log(` ${tag}${chalk23.bold(c.author)} ${location}`);
8127
8294
  const cols = process.stdout.columns || 80;
8128
8295
  const preview = c.body.length > 200 ? c.body.slice(0, 200) + "..." : c.body;
8129
8296
  for (const line of preview.split("\n")) {
8130
- console.log(chalk22.gray(` ${wrapText(line, 4, cols)}`));
8297
+ console.log(chalk23.gray(` ${wrapText(line, 4, cols)}`));
8131
8298
  }
8132
8299
  console.log();
8133
8300
  }
@@ -8253,23 +8420,23 @@ async function generatePlan(comments, includedDiffs, excludedFiles, feedback) {
8253
8420
  }
8254
8421
  function displayPlan(plan) {
8255
8422
  const cols = process.stdout.columns || 80;
8256
- console.log(chalk22.bold("\n Plan to Address Review Comments\n"));
8257
- console.log(chalk22.bold.blue(" Goals:"));
8423
+ console.log(chalk23.bold("\n Plan to Address Review Comments\n"));
8424
+ console.log(chalk23.bold.blue(" Goals:"));
8258
8425
  for (const g of plan.goals) {
8259
8426
  console.log(` - ${wrapText(g, 6, cols)}`);
8260
8427
  }
8261
8428
  console.log();
8262
- console.log(chalk22.bold.blue(" Tasks:"));
8429
+ console.log(chalk23.bold.blue(" Tasks:"));
8263
8430
  for (const t of plan.tasks) {
8264
8431
  console.log(` - ${wrapText(t, 6, cols)}`);
8265
8432
  }
8266
8433
  console.log();
8267
- console.log(chalk22.bold.blue(" Constraints:"));
8434
+ console.log(chalk23.bold.blue(" Constraints:"));
8268
8435
  for (const c of plan.constraints) {
8269
8436
  console.log(` - ${wrapText(c, 6, cols)}`);
8270
8437
  }
8271
8438
  console.log();
8272
- console.log(chalk22.bold.blue(" Definition of Done:"));
8439
+ console.log(chalk23.bold.blue(" Definition of Done:"));
8273
8440
  for (const d of plan.dod) {
8274
8441
  console.log(` - ${wrapText(d, 6, cols)}`);
8275
8442
  }
@@ -8336,9 +8503,9 @@ async function executeWithDevAgent(comments, plan, autoApprove, onActivity, user
8336
8503
  const parsed = JSON.parse(extractJSON(result.stdout));
8337
8504
  if (parsed.files && parsed.files.length > 0) {
8338
8505
  console.log();
8339
- console.log(chalk22.bold(" Files modified:"));
8506
+ console.log(chalk23.bold(" Files modified:"));
8340
8507
  for (const f of parsed.files) {
8341
- console.log(` - ${chalk22.cyan(f)}`);
8508
+ console.log(` - ${chalk23.cyan(f)}`);
8342
8509
  }
8343
8510
  }
8344
8511
  } catch {
@@ -8350,7 +8517,7 @@ async function reviewCommentsCommand(options) {
8350
8517
  try {
8351
8518
  await exec4("git", ["rev-parse", "--is-inside-work-tree"]);
8352
8519
  } catch {
8353
- console.log(chalk22.red.bold("Error:"), "Not inside a git repository.");
8520
+ console.log(chalk23.red.bold("Error:"), "Not inside a git repository.");
8354
8521
  process.exit(1);
8355
8522
  }
8356
8523
  loadEnvFile();
@@ -8359,7 +8526,7 @@ async function reviewCommentsCommand(options) {
8359
8526
  const branch = await getCurrentBranch2();
8360
8527
  const defaultBranch = await getDefaultBranch2();
8361
8528
  console.log(
8362
- chalk22.gray(` Platform: ${remote.platform}`) + chalk22.gray(` | Branch: ${branch}`) + chalk22.gray(` | Base: ${defaultBranch}`)
8529
+ chalk23.gray(` Platform: ${remote.platform}`) + chalk23.gray(` | Branch: ${branch}`) + chalk23.gray(` | Base: ${defaultBranch}`)
8363
8530
  );
8364
8531
  console.log();
8365
8532
  let comments = [];
@@ -8367,20 +8534,20 @@ async function reviewCommentsCommand(options) {
8367
8534
  const spinner = createLiveStatus("checking for open PR...");
8368
8535
  const prNumber = await detectGitHubPR2();
8369
8536
  if (prNumber === null) {
8370
- spinner.fail(chalk22.red("No open PR found for this branch"));
8537
+ spinner.fail(chalk23.red("No open PR found for this branch"));
8371
8538
  console.log();
8372
- console.log(chalk22.yellow("Cannot pull review comments without a PR or MR."));
8539
+ console.log(chalk23.yellow("Cannot pull review comments without a PR or MR."));
8373
8540
  process.exit(1);
8374
8541
  }
8375
- spinner.succeed(chalk22.green(`Found PR #${prNumber}`));
8542
+ spinner.succeed(chalk23.green(`Found PR #${prNumber}`));
8376
8543
  console.log();
8377
8544
  const commentSpinner = createLiveStatus("fetching review comments...");
8378
8545
  comments = await fetchGitHubComments();
8379
8546
  if (comments.length === 0) {
8380
- commentSpinner.info(chalk22.yellow("No review comments found on this PR"));
8547
+ commentSpinner.info(chalk23.yellow("No review comments found on this PR"));
8381
8548
  return;
8382
8549
  }
8383
- commentSpinner.succeed(chalk22.green(`Fetched ${comments.length} comment(s)`));
8550
+ commentSpinner.succeed(chalk23.green(`Fetched ${comments.length} comment(s)`));
8384
8551
  } else {
8385
8552
  const spinner = createLiveStatus("checking for open MR...");
8386
8553
  let token;
@@ -8389,29 +8556,29 @@ async function reviewCommentsCommand(options) {
8389
8556
  } catch (err) {
8390
8557
  if (isDebug()) {
8391
8558
  const msg = err instanceof Error ? err.message : String(err);
8392
- console.error(chalk22.gray(`[debug] Token resolution failed: ${msg}`));
8559
+ console.error(chalk23.gray(`[debug] Token resolution failed: ${msg}`));
8393
8560
  }
8394
- spinner.fail(chalk22.red("Could not resolve GitLab token"));
8561
+ spinner.fail(chalk23.red("Could not resolve GitLab token"));
8395
8562
  console.log();
8396
- console.log(chalk22.yellow("Cannot pull review comments without a PR or MR."));
8563
+ console.log(chalk23.yellow("Cannot pull review comments without a PR or MR."));
8397
8564
  process.exit(1);
8398
8565
  }
8399
8566
  const mrIid = await detectGitLabMR2(remote, token, branch, options.insecure);
8400
8567
  if (mrIid === null) {
8401
- spinner.fail(chalk22.red("No open MR found for this branch"));
8568
+ spinner.fail(chalk23.red("No open MR found for this branch"));
8402
8569
  console.log();
8403
- console.log(chalk22.yellow("Cannot pull review comments without a PR or MR."));
8570
+ console.log(chalk23.yellow("Cannot pull review comments without a PR or MR."));
8404
8571
  process.exit(1);
8405
8572
  }
8406
- spinner.succeed(chalk22.green(`Found MR !${mrIid}`));
8573
+ spinner.succeed(chalk23.green(`Found MR !${mrIid}`));
8407
8574
  console.log();
8408
8575
  const commentSpinner = createLiveStatus("fetching review comments...");
8409
8576
  comments = await fetchGitLabComments(remote, token, mrIid, options.insecure);
8410
8577
  if (comments.length === 0) {
8411
- commentSpinner.info(chalk22.yellow("No review comments found on this MR"));
8578
+ commentSpinner.info(chalk23.yellow("No review comments found on this MR"));
8412
8579
  return;
8413
8580
  }
8414
- commentSpinner.succeed(chalk22.green(`Fetched ${comments.length} comment(s)`));
8581
+ commentSpinner.succeed(chalk23.green(`Fetched ${comments.length} comment(s)`));
8415
8582
  }
8416
8583
  const classified = classifyComments(comments);
8417
8584
  console.log();
@@ -8421,7 +8588,7 @@ async function reviewCommentsCommand(options) {
8421
8588
  let includedDiffs = [];
8422
8589
  let excludedFiles = [];
8423
8590
  if (!rawDiff.trim()) {
8424
- diffSpinner.warn(chalk22.yellow("No diff found against base branch"));
8591
+ diffSpinner.warn(chalk23.yellow("No diff found against base branch"));
8425
8592
  } else {
8426
8593
  const fileDiffs = splitDiffByFile(rawDiff);
8427
8594
  const reservedTokens = estimateTokens(formatCommentBlock(classified)) + RESERVED_PROMPT_TOKENS;
@@ -8451,16 +8618,16 @@ async function reviewCommentsCommand(options) {
8451
8618
  }
8452
8619
  }
8453
8620
  if (excludedFiles.length > 0) {
8454
- diffSpinner.succeed(chalk22.green(`Diff loaded (${includedDiffs.length} files included, ${excludedFiles.length} excluded for size)`));
8621
+ diffSpinner.succeed(chalk23.green(`Diff loaded (${includedDiffs.length} files included, ${excludedFiles.length} excluded for size)`));
8455
8622
  } else {
8456
- diffSpinner.succeed(chalk22.green("Diff loaded"));
8623
+ diffSpinner.succeed(chalk23.green("Diff loaded"));
8457
8624
  }
8458
8625
  }
8459
8626
  let plan;
8460
8627
  {
8461
8628
  const planSpinner = createLiveStatus("generating plan...");
8462
8629
  plan = await generatePlan(classified, includedDiffs, excludedFiles);
8463
- planSpinner.succeed(chalk22.green("Plan generated"));
8630
+ planSpinner.succeed(chalk23.green("Plan generated"));
8464
8631
  }
8465
8632
  displayPlan(plan);
8466
8633
  let userInstructions;
@@ -8487,7 +8654,7 @@ async function reviewCommentsCommand(options) {
8487
8654
  if (feedback.trim()) {
8488
8655
  const planSpinner = createLiveStatus("regenerating plan...");
8489
8656
  plan = await generatePlan(classified, includedDiffs, excludedFiles, feedback);
8490
- planSpinner.succeed(chalk22.green("Plan regenerated"));
8657
+ planSpinner.succeed(chalk23.green("Plan regenerated"));
8491
8658
  displayPlan(plan);
8492
8659
  }
8493
8660
  } else if (action === "instructions") {
@@ -8499,14 +8666,14 @@ async function reviewCommentsCommand(options) {
8499
8666
  userInstructions = userInstructions ? `${userInstructions}
8500
8667
 
8501
8668
  ${extra.trim()}` : extra.trim();
8502
- console.log(chalk22.green(" Instructions saved. They will be included when executing."));
8669
+ console.log(chalk23.green(" Instructions saved. They will be included when executing."));
8503
8670
  const displayText = userInstructions.length > 200 ? userInstructions.slice(0, 200) + "..." : userInstructions;
8504
- console.log(chalk22.gray(` Current instructions:
8671
+ console.log(chalk23.gray(` Current instructions:
8505
8672
  ${displayText.split("\n").join("\n ")}`));
8506
8673
  console.log();
8507
8674
  }
8508
8675
  } else {
8509
- console.log(chalk22.yellow("\n Rejected. No changes made.\n"));
8676
+ console.log(chalk23.yellow("\n Rejected. No changes made.\n"));
8510
8677
  return;
8511
8678
  }
8512
8679
  }
@@ -8514,25 +8681,19 @@ ${extra.trim()}` : extra.trim();
8514
8681
  console.log();
8515
8682
  const execStatus = createLiveStatus("addressing review comments...");
8516
8683
  await executeWithDevAgent(classified, plan, true, execStatus.onActivity, userInstructions);
8517
- execStatus.succeed(chalk22.green("Dev agent finished"));
8684
+ execStatus.succeed(chalk23.green("Dev agent finished"));
8518
8685
  console.log();
8519
8686
  const pushSpinner = createLiveStatus("committing and pushing...");
8520
8687
  const trace = getChesstrace();
8688
+ const commitMessage = "fix: address PR review comments";
8689
+ const maxRetries = options.retryCommits ?? 3;
8690
+ let committed = false;
8521
8691
  try {
8522
8692
  await exec4("git", ["add", "-A"]);
8523
- await exec4("git", ["commit", "-m", "fix: address PR review comments"]);
8524
- try {
8525
- trace.emit(Events.GIT_COMMIT, { branch, messageSubject: "fix: address PR review comments" });
8526
- } catch {
8527
- }
8528
- await exec4("git", ["push", "origin", branch]);
8529
- try {
8530
- trace.emit(Events.GIT_PUSH, { branch });
8531
- } catch {
8532
- }
8533
- pushSpinner.succeed(chalk22.green("Changes committed and pushed."));
8534
- } catch (pushErr) {
8535
- const msg = pushErr instanceof Error ? pushErr.message : String(pushErr);
8693
+ await exec4("git", ["commit", "-m", commitMessage]);
8694
+ committed = true;
8695
+ } catch (commitErr) {
8696
+ const msg = commitErr instanceof Error ? commitErr.message : String(commitErr);
8536
8697
  if (msg.includes("nothing to commit")) {
8537
8698
  try {
8538
8699
  const ahead = await exec4("git", [
@@ -8546,35 +8707,71 @@ ${extra.trim()}` : extra.trim();
8546
8707
  trace.emit(Events.GIT_PUSH, { branch });
8547
8708
  } catch {
8548
8709
  }
8549
- pushSpinner.succeed(chalk22.green("Changes pushed."));
8710
+ pushSpinner.succeed(chalk23.green("Changes pushed."));
8550
8711
  } else {
8551
- pushSpinner.warn(chalk22.yellow("No changes were made by the dev agent."));
8712
+ pushSpinner.warn(chalk23.yellow("No changes were made by the dev agent."));
8552
8713
  }
8553
8714
  } catch {
8554
- pushSpinner.warn(chalk22.yellow("Nothing to commit or push."));
8715
+ pushSpinner.warn(chalk23.yellow("Nothing to commit or push."));
8555
8716
  }
8556
8717
  } else {
8718
+ let retryCount = 0;
8719
+ while (retryCount < maxRetries) {
8720
+ retryCount++;
8721
+ pushSpinner.text = `pre-commit hook failed, re-staging and retrying (${retryCount}/${maxRetries})...`;
8722
+ try {
8723
+ await exec4("git", ["add", "-A"]);
8724
+ await exec4("git", ["commit", "-m", commitMessage]);
8725
+ committed = true;
8726
+ break;
8727
+ } catch (retryErr) {
8728
+ const retryMsg = retryErr instanceof Error ? retryErr.message : String(retryErr);
8729
+ if (retryCount >= maxRetries) {
8730
+ try {
8731
+ trace.emit(Events.GIT_ERROR, { operation: "commit", error: retryMsg, retriesExhausted: maxRetries });
8732
+ } catch {
8733
+ }
8734
+ pushSpinner.fail(chalk23.red(`Commit failed after ${maxRetries} retries: ${retryMsg}`));
8735
+ }
8736
+ }
8737
+ }
8738
+ }
8739
+ }
8740
+ if (committed) {
8741
+ try {
8742
+ trace.emit(Events.GIT_COMMIT, { branch, messageSubject: commitMessage });
8743
+ } catch {
8744
+ }
8745
+ try {
8746
+ await exec4("git", ["push", "origin", branch]);
8747
+ try {
8748
+ trace.emit(Events.GIT_PUSH, { branch });
8749
+ } catch {
8750
+ }
8751
+ pushSpinner.succeed(chalk23.green("Changes committed and pushed."));
8752
+ } catch (pushErr) {
8753
+ const pushMsg = pushErr instanceof Error ? pushErr.message : String(pushErr);
8557
8754
  try {
8558
- trace.emit(Events.GIT_ERROR, { operation: "commit-push", error: msg });
8755
+ trace.emit(Events.GIT_ERROR, { operation: "push", error: pushMsg });
8559
8756
  } catch {
8560
8757
  }
8561
- pushSpinner.fail(chalk22.red(`Push failed: ${msg}`));
8758
+ pushSpinner.fail(chalk23.red(`Push failed: ${pushMsg}`));
8562
8759
  }
8563
8760
  }
8564
8761
  console.log();
8565
- console.log(chalk22.green.bold(" Done!"), chalk22.gray("Review comments addressed."));
8762
+ console.log(chalk23.green.bold(" Done!"), chalk23.gray("Review comments addressed."));
8566
8763
  console.log();
8567
8764
  } catch (err) {
8568
8765
  if (err instanceof Error && err.name === "ExitPromptError") {
8569
8766
  process.exit(0);
8570
8767
  }
8571
8768
  if (err instanceof TaskError) {
8572
- console.log(chalk22.red.bold("Error:"), err.message);
8769
+ console.log(chalk23.red.bold("Error:"), err.message);
8573
8770
  if (isDebug()) console.error(err.stack);
8574
8771
  process.exit(1);
8575
8772
  }
8576
8773
  const message = err instanceof Error ? err.message : String(err);
8577
- console.log(chalk22.red.bold("Internal error:"), message);
8774
+ console.log(chalk23.red.bold("Internal error:"), message);
8578
8775
  if (isDebug()) console.error(err instanceof Error ? err.stack : err);
8579
8776
  process.exit(2);
8580
8777
  }
@@ -8585,22 +8782,22 @@ ${extra.trim()}` : extra.trim();
8585
8782
  import { existsSync as existsSync12, readFileSync as readFileSync9, writeFileSync as writeFileSync4, mkdirSync as mkdirSync6, lstatSync, renameSync, unlinkSync } from "fs";
8586
8783
  import { join as join10, dirname as dirname5 } from "path";
8587
8784
  import { randomBytes } from "crypto";
8588
- import chalk23 from "chalk";
8785
+ import chalk24 from "chalk";
8589
8786
  import { select as select6, confirm } from "@inquirer/prompts";
8590
8787
  var AGENT_CATEGORIES = [
8591
8788
  {
8592
8789
  label: "Development",
8593
- color: chalk23.blue,
8790
+ color: chalk24.blue,
8594
8791
  roles: ["developer", "general"]
8595
8792
  },
8596
8793
  {
8597
8794
  label: "Testing & Review",
8598
- color: chalk23.magenta,
8795
+ color: chalk24.magenta,
8599
8796
  roles: ["quality-engineer", "security-reviewer", "reviewer"]
8600
8797
  },
8601
8798
  {
8602
8799
  label: "Planning",
8603
- color: chalk23.yellow,
8800
+ color: chalk24.yellow,
8604
8801
  roles: ["planner"]
8605
8802
  }
8606
8803
  ];
@@ -8631,7 +8828,7 @@ function categorizeAgents(agents) {
8631
8828
  if (remaining.length > 0) {
8632
8829
  groups.push({
8633
8830
  label: "Other",
8634
- color: chalk23.gray,
8831
+ color: chalk24.gray,
8635
8832
  agentIndices: remaining
8636
8833
  });
8637
8834
  }
@@ -8639,14 +8836,14 @@ function categorizeAgents(agents) {
8639
8836
  }
8640
8837
  function roleBadge(role) {
8641
8838
  const badges = {
8642
- "developer": chalk23.bgBlue.white,
8643
- "general": chalk23.bgBlue.white,
8644
- "quality-engineer": chalk23.bgMagenta.white,
8645
- "security-reviewer": chalk23.bgRed.white,
8646
- "reviewer": chalk23.bgMagenta.white,
8647
- "planner": chalk23.bgYellow.black
8839
+ "developer": chalk24.bgBlue.white,
8840
+ "general": chalk24.bgBlue.white,
8841
+ "quality-engineer": chalk24.bgMagenta.white,
8842
+ "security-reviewer": chalk24.bgRed.white,
8843
+ "reviewer": chalk24.bgMagenta.white,
8844
+ "planner": chalk24.bgYellow.black
8648
8845
  };
8649
- const colorFn = badges[role] ?? chalk23.bgGray.white;
8846
+ const colorFn = badges[role] ?? chalk24.bgGray.white;
8650
8847
  return colorFn(` ${role} `);
8651
8848
  }
8652
8849
  async function configCommand() {
@@ -8654,7 +8851,7 @@ async function configCommand() {
8654
8851
  await runConfig();
8655
8852
  } catch (err) {
8656
8853
  if (err && typeof err === "object" && "name" in err && err.name === "ExitPromptError") {
8657
- console.log(chalk23.yellow("\nConfiguration cancelled."));
8854
+ console.log(chalk24.yellow("\nConfiguration cancelled."));
8658
8855
  process.exit(0);
8659
8856
  }
8660
8857
  throw err;
@@ -8662,23 +8859,23 @@ async function configCommand() {
8662
8859
  }
8663
8860
  async function runConfig() {
8664
8861
  if (!process.stdin.isTTY) {
8665
- console.log(chalk23.red.bold("Error:"), "config command requires interactive mode.");
8666
- console.log(chalk23.gray(" Edit"), chalk23.cyan(".reygent/config.json"), chalk23.gray("or"), chalk23.cyan("~/.reygent/config.json"), chalk23.gray("directly."));
8862
+ console.log(chalk24.red.bold("Error:"), "config command requires interactive mode.");
8863
+ console.log(chalk24.gray(" Edit"), chalk24.cyan(".reygent/config.json"), chalk24.gray("or"), chalk24.cyan("~/.reygent/config.json"), chalk24.gray("directly."));
8667
8864
  process.exit(1);
8668
8865
  }
8669
8866
  const scope = await select6({
8670
8867
  message: "Configuration scope:",
8671
8868
  choices: [
8672
- { name: `Local ${chalk23.gray("\u2014 .reygent/config.json (this project)")}`, value: "local" },
8673
- { name: `Global ${chalk23.gray("\u2014 ~/.reygent/config.json (all projects)")}`, value: "global" }
8869
+ { name: `Local ${chalk24.gray("\u2014 .reygent/config.json (this project)")}`, value: "local" },
8870
+ { name: `Global ${chalk24.gray("\u2014 ~/.reygent/config.json (all projects)")}`, value: "global" }
8674
8871
  ]
8675
8872
  });
8676
8873
  let configPath;
8677
8874
  if (scope === "local") {
8678
8875
  const configDir = findLocalConfigDir(process.cwd());
8679
8876
  if (!configDir) {
8680
- console.log(chalk23.red.bold("Error:"), "No .reygent/ directory found.");
8681
- console.log(chalk23.gray(" Run"), chalk23.cyan("reygent init"), chalk23.gray("first."));
8877
+ console.log(chalk24.red.bold("Error:"), "No .reygent/ directory found.");
8878
+ console.log(chalk24.gray(" Run"), chalk24.cyan("reygent init"), chalk24.gray("first."));
8682
8879
  console.log("");
8683
8880
  process.exit(1);
8684
8881
  }
@@ -8696,15 +8893,15 @@ async function runConfig() {
8696
8893
  rawConfig = JSON.parse(content);
8697
8894
  } catch (err) {
8698
8895
  if (err instanceof SyntaxError) {
8699
- console.log(chalk23.red.bold("Error:"), `Invalid JSON in ${configPath}`);
8700
- console.log(chalk23.gray(" Parse error:"), err.message);
8896
+ console.log(chalk24.red.bold("Error:"), `Invalid JSON in ${configPath}`);
8897
+ console.log(chalk24.gray(" Parse error:"), err.message);
8701
8898
  process.exit(2);
8702
8899
  }
8703
8900
  if (err && typeof err === "object" && "code" in err && err.code === "EACCES") {
8704
- console.log(chalk23.red.bold("Error:"), `Permission denied: ${configPath}`);
8901
+ console.log(chalk24.red.bold("Error:"), `Permission denied: ${configPath}`);
8705
8902
  process.exit(2);
8706
8903
  }
8707
- console.log(chalk23.red.bold("Error:"), `Failed to read ${configPath}`);
8904
+ console.log(chalk24.red.bold("Error:"), `Failed to read ${configPath}`);
8708
8905
  if (isDebug()) console.error(err);
8709
8906
  process.exit(2);
8710
8907
  }
@@ -8723,15 +8920,15 @@ async function runConfig() {
8723
8920
  }
8724
8921
  const currentProvider = rawConfig.provider ?? "(not set)";
8725
8922
  const currentModel = rawConfig.model ?? "(not set)";
8726
- console.log(chalk23.bold("Current config:"));
8727
- console.log(chalk23.gray(" Scope: "), chalk23.cyan(scope));
8728
- console.log(chalk23.gray(" Provider:"), chalk23.cyan(currentProvider));
8729
- console.log(chalk23.gray(" Model: "), chalk23.cyan(currentModel));
8923
+ console.log(chalk24.bold("Current config:"));
8924
+ console.log(chalk24.gray(" Scope: "), chalk24.cyan(scope));
8925
+ console.log(chalk24.gray(" Provider:"), chalk24.cyan(currentProvider));
8926
+ console.log(chalk24.gray(" Model: "), chalk24.cyan(currentModel));
8730
8927
  console.log("");
8731
8928
  const providerChoices = PROVIDER_NAMES.map((name) => {
8732
8929
  const status = availability[name];
8733
- const badge = status?.available ? chalk23.green("\u2713") : chalk23.red("\u2717");
8734
- const hint = !status?.available && status?.reason ? chalk23.gray(` \u2014 ${status.reason}`) : "";
8930
+ const badge = status?.available ? chalk24.green("\u2713") : chalk24.red("\u2717");
8931
+ const hint = !status?.available && status?.reason ? chalk24.gray(` \u2014 ${status.reason}`) : "";
8735
8932
  return {
8736
8933
  name: `${badge} ${name}${hint}`,
8737
8934
  value: name
@@ -8745,14 +8942,14 @@ async function runConfig() {
8745
8942
  });
8746
8943
  if (!availability[selectedProvider]?.available) {
8747
8944
  const reason = availability[selectedProvider]?.reason ?? "unknown reason";
8748
- console.log(chalk23.yellow("\u26A0"), chalk23.yellow(`Provider ${selectedProvider} is unavailable (${reason})`));
8945
+ console.log(chalk24.yellow("\u26A0"), chalk24.yellow(`Provider ${selectedProvider} is unavailable (${reason})`));
8749
8946
  resetTerminalForInput();
8750
8947
  const proceed = await confirm({
8751
8948
  message: "Continue with this provider anyway?",
8752
8949
  default: false
8753
8950
  });
8754
8951
  if (!proceed) {
8755
- console.log(chalk23.yellow("\nConfiguration cancelled."));
8952
+ console.log(chalk24.yellow("\nConfiguration cancelled."));
8756
8953
  process.exit(0);
8757
8954
  }
8758
8955
  }
@@ -8770,30 +8967,59 @@ async function runConfig() {
8770
8967
  name: `${m.id} \u2014 ${m.label}`,
8771
8968
  value: m.id
8772
8969
  }));
8773
- selectedModel = await select6({
8970
+ modelChoices.push({
8971
+ name: chalk24.gray("Custom model (enter manually)"),
8972
+ value: "__custom__"
8973
+ });
8974
+ const modelSelection = await select6({
8774
8975
  message: "Default model:",
8775
8976
  choices: modelChoices,
8776
8977
  default: rawConfig.model ?? provider.defaultModel
8777
8978
  });
8979
+ if (modelSelection === "__custom__") {
8980
+ resetTerminalForInput();
8981
+ selectedModel = await pasteableInput({
8982
+ message: "Enter model ID:",
8983
+ default: rawConfig.model ?? provider.defaultModel
8984
+ });
8985
+ if (selectedProvider === "claude") {
8986
+ if (!selectedModel.startsWith("claude-") && !selectedModel.includes("projects/")) {
8987
+ console.log(chalk24.yellow("\u26A0"), chalk24.yellow("Model ID doesn't look like Claude format. Expected: claude-{family}-{version} or Vertex AI full resource name."));
8988
+ console.log(chalk24.gray(" Examples: claude-opus-4-6, projects/PROJECT/locations/REGION/publishers/anthropic/models/MODEL"));
8989
+ }
8990
+ } else if (selectedProvider === "gemini") {
8991
+ if (!selectedModel.startsWith("gemini-") && !selectedModel.includes("projects/")) {
8992
+ console.log(chalk24.yellow("\u26A0"), chalk24.yellow("Model ID doesn't look like Gemini format. Expected: gemini-{version}-{variant} or Vertex AI full resource name."));
8993
+ console.log(chalk24.gray(" Examples: gemini-2.5-pro, projects/PROJECT/locations/REGION/publishers/google/models/MODEL"));
8994
+ }
8995
+ } else if (selectedProvider === "codex") {
8996
+ if (!selectedModel.startsWith("gpt-")) {
8997
+ console.log(chalk24.yellow("\u26A0"), chalk24.yellow("Model ID doesn't look like Codex format. Expected: gpt-{version}"));
8998
+ console.log(chalk24.gray(" Examples: gpt-5.4, gpt-6.0"));
8999
+ }
9000
+ }
9001
+ } else {
9002
+ selectedModel = modelSelection;
9003
+ }
8778
9004
  }
8779
9005
  const updatedAgents = [...agents];
8780
9006
  const categorized = categorizeAgents(agents);
8781
9007
  for (const group of categorized) {
8782
9008
  console.log("");
8783
- console.log(group.color(chalk23.bold(`\u2500\u2500 ${group.label} \u2500\u2500`)));
9009
+ console.log(group.color(chalk24.bold(`\u2500\u2500 ${group.label} \u2500\u2500`)));
8784
9010
  for (const agentIndex of group.agentIndices) {
8785
9011
  const agent = updatedAgents[agentIndex];
8786
9012
  const agentProvider = agent.provider ?? selectedProvider;
8787
9013
  const agentModel = agent.model ?? selectedModel;
8788
9014
  console.log("");
8789
- console.log(chalk23.bold(agent.name), roleBadge(agent.role));
8790
- console.log(chalk23.gray(` ${agent.description}`));
9015
+ console.log(chalk24.bold(agent.name), roleBadge(agent.role));
9016
+ console.log(chalk24.gray(` ${agent.description}`));
8791
9017
  console.log(
8792
- chalk23.gray(" Tools:"),
8793
- agent.tools.map((t) => chalk23.cyan(t)).join(chalk23.gray(", "))
9018
+ chalk24.gray(" Tools:"),
9019
+ agent.tools.map((t) => chalk24.cyan(t)).join(chalk24.gray(", "))
8794
9020
  );
8795
- console.log(chalk23.gray(" Provider:"), chalk23.cyan(agentProvider));
8796
- console.log(chalk23.gray(" Model: "), chalk23.cyan(agentModel));
9021
+ console.log(chalk24.gray(" Provider:"), chalk24.cyan(agentProvider));
9022
+ console.log(chalk24.gray(" Model: "), chalk24.cyan(agentModel));
8797
9023
  const hasOverride = agent.provider !== void 0 || agent.model !== void 0;
8798
9024
  resetTerminalForInput();
8799
9025
  const action = await select6({
@@ -8820,7 +9046,7 @@ async function runConfig() {
8820
9046
  });
8821
9047
  if (!availability[agentProviderChoice]?.available) {
8822
9048
  const reason = availability[agentProviderChoice]?.reason ?? "unknown reason";
8823
- console.log(chalk23.yellow("\u26A0"), chalk23.yellow(`Provider ${agentProviderChoice} is unavailable (${reason})`));
9049
+ console.log(chalk24.yellow("\u26A0"), chalk24.yellow(`Provider ${agentProviderChoice} is unavailable (${reason})`));
8824
9050
  resetTerminalForInput();
8825
9051
  const proceed = await confirm({
8826
9052
  message: "Continue with this provider anyway?",
@@ -8844,11 +9070,40 @@ async function runConfig() {
8844
9070
  name: `${m.id} \u2014 ${m.label}`,
8845
9071
  value: m.id
8846
9072
  }));
8847
- agentModelChoice = await select6({
9073
+ agentModelChoices.push({
9074
+ name: chalk24.gray("Custom model (enter manually)"),
9075
+ value: "__custom__"
9076
+ });
9077
+ const agentModelSelection = await select6({
8848
9078
  message: `Model for ${agent.name}:`,
8849
9079
  choices: agentModelChoices,
8850
9080
  default: agent.model ?? agentProviderAdapter.defaultModel
8851
9081
  });
9082
+ if (agentModelSelection === "__custom__") {
9083
+ resetTerminalForInput();
9084
+ agentModelChoice = await pasteableInput({
9085
+ message: `Enter model ID for ${agent.name}:`,
9086
+ default: agent.model ?? agentProviderAdapter.defaultModel
9087
+ });
9088
+ if (agentProviderChoice === "claude") {
9089
+ if (!agentModelChoice.startsWith("claude-") && !agentModelChoice.includes("projects/")) {
9090
+ console.log(chalk24.yellow("\u26A0"), chalk24.yellow("Model ID doesn't look like Claude format. Expected: claude-{family}-{version} or Vertex AI full resource name."));
9091
+ console.log(chalk24.gray(" Examples: claude-opus-4-6, projects/PROJECT/locations/REGION/publishers/anthropic/models/MODEL"));
9092
+ }
9093
+ } else if (agentProviderChoice === "gemini") {
9094
+ if (!agentModelChoice.startsWith("gemini-") && !agentModelChoice.includes("projects/")) {
9095
+ console.log(chalk24.yellow("\u26A0"), chalk24.yellow("Model ID doesn't look like Gemini format. Expected: gemini-{version}-{variant} or Vertex AI full resource name."));
9096
+ console.log(chalk24.gray(" Examples: gemini-2.5-pro, projects/PROJECT/locations/REGION/publishers/google/models/MODEL"));
9097
+ }
9098
+ } else if (agentProviderChoice === "codex") {
9099
+ if (!agentModelChoice.startsWith("gpt-")) {
9100
+ console.log(chalk24.yellow("\u26A0"), chalk24.yellow("Model ID doesn't look like Codex format. Expected: gpt-{version}"));
9101
+ console.log(chalk24.gray(" Examples: gpt-5.4, gpt-6.0"));
9102
+ }
9103
+ }
9104
+ } else {
9105
+ agentModelChoice = agentModelSelection;
9106
+ }
8852
9107
  }
8853
9108
  updatedAgents[agentIndex] = { ...agent, provider: agentProviderChoice, model: agentModelChoice };
8854
9109
  }
@@ -8890,24 +9145,24 @@ async function runConfig() {
8890
9145
  }
8891
9146
  } catch (err) {
8892
9147
  const message = err instanceof Error ? err.message : String(err);
8893
- console.log(chalk23.red.bold("Error:"), `Failed to write config: ${message}`);
9148
+ console.log(chalk24.red.bold("Error:"), `Failed to write config: ${message}`);
8894
9149
  if (isDebug()) console.error(err instanceof Error ? err.stack : err);
8895
9150
  process.exit(2);
8896
9151
  }
8897
9152
  console.log("");
8898
- console.log(chalk23.green.bold("\u2713"), chalk23.bold("Config updated"));
8899
- console.log(chalk23.gray(" Scope: "), chalk23.cyan(scope));
8900
- console.log(chalk23.gray(" File: "), chalk23.gray(configPath));
8901
- console.log(chalk23.gray(" Provider:"), chalk23.cyan(selectedProvider));
8902
- console.log(chalk23.gray(" Model: "), chalk23.cyan(selectedModel));
9153
+ console.log(chalk24.green.bold("\u2713"), chalk24.bold("Config updated"));
9154
+ console.log(chalk24.gray(" Scope: "), chalk24.cyan(scope));
9155
+ console.log(chalk24.gray(" File: "), chalk24.gray(configPath));
9156
+ console.log(chalk24.gray(" Provider:"), chalk24.cyan(selectedProvider));
9157
+ console.log(chalk24.gray(" Model: "), chalk24.cyan(selectedModel));
8903
9158
  const overriddenAgents = updatedAgents.filter((a) => a.provider || a.model);
8904
9159
  if (overriddenAgents.length > 0) {
8905
- console.log(chalk23.gray(" Agent overrides:"));
9160
+ console.log(chalk24.gray(" Agent overrides:"));
8906
9161
  for (const a of overriddenAgents) {
8907
9162
  const parts = [];
8908
9163
  if (a.provider) parts.push(`provider=${a.provider}`);
8909
9164
  if (a.model) parts.push(`model=${a.model}`);
8910
- console.log(chalk23.gray(` ${a.name}:`), chalk23.cyan(parts.join(", ")));
9165
+ console.log(chalk24.gray(` ${a.name}:`), chalk24.cyan(parts.join(", ")));
8911
9166
  }
8912
9167
  }
8913
9168
  console.log("");
@@ -8916,7 +9171,7 @@ async function runConfig() {
8916
9171
  // src/commands/telemetry.ts
8917
9172
  import { statSync as statSync6 } from "fs";
8918
9173
  import { writeFileSync as writeFileSync5 } from "fs";
8919
- import chalk24 from "chalk";
9174
+ import chalk25 from "chalk";
8920
9175
  import ora6 from "ora";
8921
9176
  import Table from "cli-table3";
8922
9177
  import { join as join11 } from "path";
@@ -8967,7 +9222,7 @@ async function statusCommand() {
8967
9222
  const config = loadConfig();
8968
9223
  const telemetryConfig = config.telemetry;
8969
9224
  if (!telemetryConfig) {
8970
- spinner.fail(chalk24.red("Telemetry configuration not found"));
9225
+ spinner.fail(chalk25.red("Telemetry configuration not found"));
8971
9226
  return;
8972
9227
  }
8973
9228
  const backendType = telemetryConfig.backend === "sqlite" ? "local" : "local";
@@ -8977,20 +9232,20 @@ async function statusCommand() {
8977
9232
  const dbPath = backend.getDbPath();
8978
9233
  const dbSize = getDbSize(dbPath);
8979
9234
  await backend.close();
8980
- spinner.succeed(chalk24.green("Telemetry status loaded"));
9235
+ spinner.succeed(chalk25.green("Telemetry status loaded"));
8981
9236
  console.log();
8982
- console.log(chalk24.bold("Telemetry Configuration"));
8983
- console.log(` Enabled: ${telemetryConfig.enabled === void 0 ? chalk24.yellow("unset (will prompt)") : telemetryConfig.enabled ? chalk24.green("yes") : chalk24.red("no")}`);
8984
- console.log(` Level: ${chalk24.cyan(telemetryConfig.level)}`);
8985
- console.log(` Backend: ${chalk24.cyan(telemetryConfig.backend)}`);
8986
- console.log(` Retention: ${chalk24.cyan(`${telemetryConfig.retention} days`)}`);
9237
+ console.log(chalk25.bold("Telemetry Configuration"));
9238
+ console.log(` Enabled: ${telemetryConfig.enabled === void 0 ? chalk25.yellow("unset (will prompt)") : telemetryConfig.enabled ? chalk25.green("yes") : chalk25.red("no")}`);
9239
+ console.log(` Level: ${chalk25.cyan(telemetryConfig.level)}`);
9240
+ console.log(` Backend: ${chalk25.cyan(telemetryConfig.backend)}`);
9241
+ console.log(` Retention: ${chalk25.cyan(`${telemetryConfig.retention} days`)}`);
8987
9242
  console.log();
8988
- console.log(chalk24.bold("Storage"));
8989
- console.log(` Database: ${chalk24.gray(dbPath)}`);
8990
- console.log(` Size: ${chalk24.cyan(formatBytes(dbSize))}`);
8991
- console.log(` Runs: ${chalk24.cyan(runs.length.toString())}`);
9243
+ console.log(chalk25.bold("Storage"));
9244
+ console.log(` Database: ${chalk25.gray(dbPath)}`);
9245
+ console.log(` Size: ${chalk25.cyan(formatBytes(dbSize))}`);
9246
+ console.log(` Runs: ${chalk25.cyan(runs.length.toString())}`);
8992
9247
  } catch (err) {
8993
- spinner.fail(chalk24.red(`Failed to load telemetry status: ${err.message}`));
9248
+ spinner.fail(chalk25.red(`Failed to load telemetry status: ${err.message}`));
8994
9249
  process.exit(1);
8995
9250
  }
8996
9251
  }
@@ -9007,25 +9262,25 @@ async function runsCommand(options) {
9007
9262
  if (options.limit) {
9008
9263
  const parsed = Number.parseInt(options.limit, 10);
9009
9264
  if (isNaN(parsed) || parsed < 1) {
9010
- spinner.fail(chalk24.red(`Invalid limit: ${options.limit}. Must be positive integer.`));
9265
+ spinner.fail(chalk25.red(`Invalid limit: ${options.limit}. Must be positive integer.`));
9011
9266
  process.exit(1);
9012
9267
  }
9013
9268
  limit = parsed;
9014
9269
  }
9015
9270
  const runs = allRuns.slice(0, limit);
9016
- spinner.succeed(chalk24.green(`Loaded ${runs.length} run(s)`));
9271
+ spinner.succeed(chalk25.green(`Loaded ${runs.length} run(s)`));
9017
9272
  if (runs.length === 0) {
9018
- console.log(chalk24.yellow("\nNo telemetry runs found"));
9273
+ console.log(chalk25.yellow("\nNo telemetry runs found"));
9019
9274
  return;
9020
9275
  }
9021
9276
  console.log();
9022
9277
  const table = new Table({
9023
9278
  head: [
9024
- chalk24.cyan("Run ID"),
9025
- chalk24.cyan("Start Time"),
9026
- chalk24.cyan("Duration"),
9027
- chalk24.cyan("Events"),
9028
- chalk24.cyan("Categories")
9279
+ chalk25.cyan("Run ID"),
9280
+ chalk25.cyan("Start Time"),
9281
+ chalk25.cyan("Duration"),
9282
+ chalk25.cyan("Events"),
9283
+ chalk25.cyan("Categories")
9029
9284
  ],
9030
9285
  colWidths: [38, 20, 12, 10, 30]
9031
9286
  });
@@ -9041,13 +9296,13 @@ async function runsCommand(options) {
9041
9296
  }
9042
9297
  console.log(table.toString());
9043
9298
  } catch (err) {
9044
- spinner.fail(chalk24.red(`Failed to load runs: ${err.message}`));
9299
+ spinner.fail(chalk25.red(`Failed to load runs: ${err.message}`));
9045
9300
  process.exit(1);
9046
9301
  }
9047
9302
  }
9048
9303
  async function showCommand(runId) {
9049
9304
  if (!isValidUuid(runId)) {
9050
- console.error(chalk24.red(`Invalid run ID format: ${runId}. Must be valid UUID.`));
9305
+ console.error(chalk25.red(`Invalid run ID format: ${runId}. Must be valid UUID.`));
9051
9306
  process.exit(1);
9052
9307
  }
9053
9308
  const spinner = ora6(`Loading events for run ${runId}...`).start();
@@ -9059,28 +9314,28 @@ async function showCommand(runId) {
9059
9314
  const events = await backend.query({ runId });
9060
9315
  await backend.close();
9061
9316
  if (events.length === 0) {
9062
- spinner.fail(chalk24.yellow(`No events found for run ${runId}`));
9317
+ spinner.fail(chalk25.yellow(`No events found for run ${runId}`));
9063
9318
  return;
9064
9319
  }
9065
- spinner.succeed(chalk24.green(`Loaded ${events.length} event(s) for run ${runId}`));
9320
+ spinner.succeed(chalk25.green(`Loaded ${events.length} event(s) for run ${runId}`));
9066
9321
  console.log();
9067
- console.log(chalk24.bold(`Events for run ${runId}`));
9068
- console.log(chalk24.gray(`Total events: ${events.length}`));
9322
+ console.log(chalk25.bold(`Events for run ${runId}`));
9323
+ console.log(chalk25.gray(`Total events: ${events.length}`));
9069
9324
  console.log();
9070
9325
  for (const event of events) {
9071
9326
  const timestamp = formatTimestamp(event.timestamp);
9072
- const category = chalk24.cyan(`[${event.category}]`);
9073
- const eventName = chalk24.bold(event.event);
9327
+ const category = chalk25.cyan(`[${event.category}]`);
9328
+ const eventName = chalk25.bold(event.event);
9074
9329
  const dataStr = Object.keys(event.data).length > 0 ? JSON.stringify(event.data, null, 2) : "";
9075
- console.log(`${chalk24.gray(timestamp)} ${category} ${eventName}`);
9330
+ console.log(`${chalk25.gray(timestamp)} ${category} ${eventName}`);
9076
9331
  if (dataStr) {
9077
- const grayData = dataStr.split("\n").map((line) => chalk24.gray(line)).join("\n");
9332
+ const grayData = dataStr.split("\n").map((line) => chalk25.gray(line)).join("\n");
9078
9333
  console.log(grayData);
9079
9334
  }
9080
9335
  console.log();
9081
9336
  }
9082
9337
  } catch (err) {
9083
- spinner.fail(chalk24.red(`Failed to load events: ${err.message}`));
9338
+ spinner.fail(chalk25.red(`Failed to load events: ${err.message}`));
9084
9339
  process.exit(1);
9085
9340
  }
9086
9341
  }
@@ -9100,7 +9355,7 @@ function exportCsv(events) {
9100
9355
  }
9101
9356
  async function exportCommand(runId, options) {
9102
9357
  if (!isValidUuid(runId)) {
9103
- console.error(chalk24.red(`Invalid run ID format: ${runId}. Must be valid UUID.`));
9358
+ console.error(chalk25.red(`Invalid run ID format: ${runId}. Must be valid UUID.`));
9104
9359
  process.exit(1);
9105
9360
  }
9106
9361
  const format = options.format ?? "json";
@@ -9113,20 +9368,20 @@ async function exportCommand(runId, options) {
9113
9368
  const events = await backend.query({ runId });
9114
9369
  await backend.close();
9115
9370
  if (events.length === 0) {
9116
- spinner.fail(chalk24.yellow(`No events found for run ${runId}`));
9371
+ spinner.fail(chalk25.yellow(`No events found for run ${runId}`));
9117
9372
  return;
9118
9373
  }
9119
9374
  const data = format === "json" ? exportJson(events) : exportCsv(events);
9120
9375
  if (options.output) {
9121
9376
  writeFileSync5(options.output, data, "utf-8");
9122
- spinner.succeed(chalk24.green(`Exported ${events.length} events to ${options.output}`));
9377
+ spinner.succeed(chalk25.green(`Exported ${events.length} events to ${options.output}`));
9123
9378
  } else {
9124
- spinner.succeed(chalk24.green(`Exported ${events.length} events`));
9379
+ spinner.succeed(chalk25.green(`Exported ${events.length} events`));
9125
9380
  console.log();
9126
9381
  console.log(data);
9127
9382
  }
9128
9383
  } catch (err) {
9129
- spinner.fail(chalk24.red(`Failed to export run: ${err.message}`));
9384
+ spinner.fail(chalk25.red(`Failed to export run: ${err.message}`));
9130
9385
  process.exit(1);
9131
9386
  }
9132
9387
  }
@@ -9142,9 +9397,9 @@ async function pruneCommand(options) {
9142
9397
  const olderThan = Date.now() - days * 24 * 60 * 60 * 1e3;
9143
9398
  const deleted = await backend.prune(olderThan);
9144
9399
  await backend.close();
9145
- spinner.succeed(chalk24.green(`Pruned ${deleted} event(s) older than ${days} days`));
9400
+ spinner.succeed(chalk25.green(`Pruned ${deleted} event(s) older than ${days} days`));
9146
9401
  } catch (err) {
9147
- spinner.fail(chalk24.red(`Failed to prune events: ${err.message}`));
9402
+ spinner.fail(chalk25.red(`Failed to prune events: ${err.message}`));
9148
9403
  process.exit(1);
9149
9404
  }
9150
9405
  }
@@ -9162,9 +9417,9 @@ async function enableCommand() {
9162
9417
  config.telemetry.enabled = true;
9163
9418
  writeFileSync5(configPath, JSON.stringify(config, null, 2), "utf-8");
9164
9419
  const scope = localConfigDir ? "local" : "global";
9165
- spinner.succeed(chalk24.green(`Telemetry enabled (${scope} config)`));
9420
+ spinner.succeed(chalk25.green(`Telemetry enabled (${scope} config)`));
9166
9421
  } catch (err) {
9167
- spinner.fail(chalk24.red(`Failed to enable telemetry: ${err.message}`));
9422
+ spinner.fail(chalk25.red(`Failed to enable telemetry: ${err.message}`));
9168
9423
  process.exit(1);
9169
9424
  }
9170
9425
  }
@@ -9182,9 +9437,9 @@ async function disableCommand() {
9182
9437
  config.telemetry.enabled = false;
9183
9438
  writeFileSync5(configPath, JSON.stringify(config, null, 2), "utf-8");
9184
9439
  const scope = localConfigDir ? "local" : "global";
9185
- spinner.succeed(chalk24.green(`Telemetry disabled (${scope} config)`));
9440
+ spinner.succeed(chalk25.green(`Telemetry disabled (${scope} config)`));
9186
9441
  } catch (err) {
9187
- spinner.fail(chalk24.red(`Failed to disable telemetry: ${err.message}`));
9442
+ spinner.fail(chalk25.red(`Failed to disable telemetry: ${err.message}`));
9188
9443
  process.exit(1);
9189
9444
  }
9190
9445
  }
@@ -9202,7 +9457,7 @@ function registerTelemetryCommand(program2) {
9202
9457
  }
9203
9458
 
9204
9459
  // src/commands/analyze.ts
9205
- import chalk25 from "chalk";
9460
+ import chalk26 from "chalk";
9206
9461
  import ora7 from "ora";
9207
9462
 
9208
9463
  // src/telemetry-path.ts
@@ -9268,8 +9523,8 @@ async function getBackend() {
9268
9523
  }
9269
9524
  function checkTelemetryEnabled(config) {
9270
9525
  if (!config.telemetry?.enabled) {
9271
- console.log(chalk25.yellow("\nTelemetry is disabled. Enable with:"));
9272
- console.log(chalk25.cyan(" reygent telemetry enable\n"));
9526
+ console.log(chalk26.yellow("\nTelemetry is disabled. Enable with:"));
9527
+ console.log(chalk26.cyan(" reygent telemetry enable\n"));
9273
9528
  process.exit(1);
9274
9529
  }
9275
9530
  }
@@ -9285,27 +9540,27 @@ async function analyzeFailures(options) {
9285
9540
  const pipelineEvents = filterEvents(allEvents, { event: Events.PIPELINE_END });
9286
9541
  await backend.close();
9287
9542
  if (errorEvents.length === 0) {
9288
- spinner.succeed(chalk25.green("No failures found"));
9289
- console.log(chalk25.yellow("\nNo error events in telemetry data"));
9543
+ spinner.succeed(chalk26.green("No failures found"));
9544
+ console.log(chalk26.yellow("\nNo error events in telemetry data"));
9290
9545
  return;
9291
9546
  }
9292
9547
  const totalRuns = new Set(pipelineEvents.map((e) => e.runId)).size;
9293
9548
  const days = Math.floor((Date.now() - since) / (24 * 60 * 60 * 1e3));
9294
- spinner.succeed(chalk25.green(`Analyzed ${errorEvents.length} error(s) from ${totalRuns} run(s)`));
9549
+ spinner.succeed(chalk26.green(`Analyzed ${errorEvents.length} error(s) from ${totalRuns} run(s)`));
9295
9550
  console.log();
9296
- console.log(chalk25.bold(`Failure Analysis (last ${days} days, ${totalRuns} runs)`));
9551
+ console.log(chalk26.bold(`Failure Analysis (last ${days} days, ${totalRuns} runs)`));
9297
9552
  console.log();
9298
9553
  const patternGroups = groupBy(errorEvents, (e) => e.event);
9299
9554
  const sortedPatterns = Array.from(patternGroups.entries()).sort((a, b) => b[1].length - a[1].length);
9300
9555
  const limit = options.limit ? Number.parseInt(options.limit, 10) : sortedPatterns.length;
9301
9556
  const topPatterns = sortedPatterns.slice(0, limit);
9302
- console.log(chalk25.bold("Top Failure Patterns:"));
9557
+ console.log(chalk26.bold("Top Failure Patterns:"));
9303
9558
  console.log();
9304
9559
  for (let i = 0; i < topPatterns.length; i++) {
9305
9560
  const [eventName, events] = topPatterns[i];
9306
9561
  const agentGroups = groupBy(events, (e) => e.data.agent || "unknown");
9307
9562
  const mostRecent = events.reduce((a, b) => a.timestamp > b.timestamp ? a : b);
9308
- console.log(chalk25.cyan(`${i + 1}. ${eventName}`) + chalk25.gray(` (${events.length} occurrences)`));
9563
+ console.log(chalk26.cyan(`${i + 1}. ${eventName}`) + chalk26.gray(` (${events.length} occurrences)`));
9309
9564
  const agentSummary = Array.from(agentGroups.entries()).map(([agent, events2]) => `${agent} (${events2.length})`).join(", ");
9310
9565
  console.log(` Agents: ${agentSummary}`);
9311
9566
  const messages = events.map((e) => e.data.message).filter(Boolean);
@@ -9316,7 +9571,7 @@ async function analyzeFailures(options) {
9316
9571
  console.log(` Most recent: run ${mostRecent.runId.substring(0, 8)} (${formatRelativeTime(mostRecent.timestamp)})`);
9317
9572
  console.log();
9318
9573
  }
9319
- console.log(chalk25.bold("Recommendations:"));
9574
+ console.log(chalk26.bold("Recommendations:"));
9320
9575
  const recommendations = [];
9321
9576
  const parseErrors = errorEvents.filter((e) => e.event === Events.ERROR_PARSE);
9322
9577
  if (parseErrors.length > 0) {
@@ -9342,7 +9597,7 @@ async function analyzeFailures(options) {
9342
9597
  }
9343
9598
  }
9344
9599
  if (recommendations.length === 0) {
9345
- console.log(chalk25.gray(" No specific recommendations"));
9600
+ console.log(chalk26.gray(" No specific recommendations"));
9346
9601
  } else {
9347
9602
  for (const rec of recommendations) {
9348
9603
  console.log(rec);
@@ -9356,7 +9611,7 @@ async function analyzeFailures(options) {
9356
9611
  const patterns = analyzeFailurePatterns(analysisBackend, since);
9357
9612
  await analysisBackend.close();
9358
9613
  if (patterns.length === 0) {
9359
- updateSpinner.info(chalk25.yellow("No recurring patterns to add"));
9614
+ updateSpinner.info(chalk26.yellow("No recurring patterns to add"));
9360
9615
  } else {
9361
9616
  let addedCount = 0;
9362
9617
  const limit2 = options.limit ? Number.parseInt(options.limit, 10) : 5;
@@ -9370,13 +9625,13 @@ async function analyzeFailures(options) {
9370
9625
  addedCount++;
9371
9626
  }
9372
9627
  }
9373
- updateSpinner.succeed(chalk25.green(`Added ${addedCount} failure pattern(s) to knowledge base`));
9374
- console.log(chalk25.gray(` See .reygent/knowledge/common-failures.md`));
9628
+ updateSpinner.succeed(chalk26.green(`Added ${addedCount} failure pattern(s) to knowledge base`));
9629
+ console.log(chalk26.gray(` See .reygent/knowledge/common-failures.md`));
9375
9630
  console.log();
9376
9631
  }
9377
9632
  } catch (err) {
9378
9633
  const errMsg = err instanceof Error ? err.message : String(err);
9379
- updateSpinner.fail(chalk25.red(`Failed to update knowledge: ${errMsg}`));
9634
+ updateSpinner.fail(chalk26.red(`Failed to update knowledge: ${errMsg}`));
9380
9635
  if (process.env.REYGENT_DEBUG === "1" || process.env.REYGENT_DEBUG === "telemetry") {
9381
9636
  console.error("[debug:telemetry] analyzeFailures knowledge update error:", err);
9382
9637
  }
@@ -9384,7 +9639,7 @@ async function analyzeFailures(options) {
9384
9639
  }
9385
9640
  } catch (err) {
9386
9641
  const errMsg = err instanceof Error ? err.message : String(err);
9387
- spinner.fail(chalk25.red(`Failed to analyze failures: ${errMsg}`));
9642
+ spinner.fail(chalk26.red(`Failed to analyze failures: ${errMsg}`));
9388
9643
  if (process.env.REYGENT_DEBUG === "1" || process.env.REYGENT_DEBUG === "telemetry") {
9389
9644
  console.error("[debug:telemetry] analyzeFailures error:", err);
9390
9645
  }
@@ -9406,14 +9661,14 @@ async function analyzeSuccess(options) {
9406
9661
  const successfulRuns = pipelineEvents.filter((e) => e.data.success === true);
9407
9662
  const days = Math.floor((Date.now() - since) / (24 * 60 * 60 * 1e3));
9408
9663
  if (successfulRuns.length === 0) {
9409
- spinner.succeed(chalk25.yellow("No successful runs found"));
9664
+ spinner.succeed(chalk26.yellow("No successful runs found"));
9410
9665
  return;
9411
9666
  }
9412
- spinner.succeed(chalk25.green(`Analyzed ${successfulRuns.length} successful run(s)`));
9667
+ spinner.succeed(chalk26.green(`Analyzed ${successfulRuns.length} successful run(s)`));
9413
9668
  console.log();
9414
- console.log(chalk25.bold(`Success Analysis (last ${days} days, ${successfulRuns.length} successful runs)`));
9669
+ console.log(chalk26.bold(`Success Analysis (last ${days} days, ${successfulRuns.length} successful runs)`));
9415
9670
  console.log();
9416
- console.log(chalk25.bold("Agent Performance:"));
9671
+ console.log(chalk26.bold("Agent Performance:"));
9417
9672
  console.log();
9418
9673
  const agentStats = /* @__PURE__ */ new Map();
9419
9674
  for (const spawn4 of agentSpawnEvents) {
@@ -9455,7 +9710,7 @@ async function analyzeSuccess(options) {
9455
9710
  const stageAgents = new Set(stageEvents.map((e) => e.data.agent));
9456
9711
  if (!stageAgents.has(agent)) continue;
9457
9712
  }
9458
- console.log(chalk25.cyan(`${agent}:`));
9713
+ console.log(chalk26.cyan(`${agent}:`));
9459
9714
  console.log(` Runs: ${stats.completions}`);
9460
9715
  console.log(` Success rate: ${formatPercent(successRate)} (${stats.successes} success, ${stats.completions - stats.successes} failures)`);
9461
9716
  console.log(` Avg duration: ${formatDuration3(avgDuration)}`);
@@ -9463,7 +9718,7 @@ async function analyzeSuccess(options) {
9463
9718
  console.log(` Model distribution: ${modelDist}`);
9464
9719
  console.log();
9465
9720
  }
9466
- console.log(chalk25.bold("Recommendations:"));
9721
+ console.log(chalk26.bold("Recommendations:"));
9467
9722
  const recommendations = [];
9468
9723
  const sortedAgents = Array.from(agentStats.entries()).filter(([_, stats]) => stats.completions > 0).map(([agent, stats]) => ({
9469
9724
  agent,
@@ -9477,7 +9732,7 @@ async function analyzeSuccess(options) {
9477
9732
  }
9478
9733
  }
9479
9734
  if (recommendations.length === 0) {
9480
- console.log(chalk25.gray(" No specific recommendations"));
9735
+ console.log(chalk26.gray(" No specific recommendations"));
9481
9736
  } else {
9482
9737
  for (const rec of recommendations) {
9483
9738
  console.log(rec);
@@ -9492,7 +9747,7 @@ async function analyzeSuccess(options) {
9492
9747
  const patterns = analyzeSuccessPatterns(analysisBackend, since, minRate);
9493
9748
  await analysisBackend.close();
9494
9749
  if (patterns.length === 0) {
9495
- updateSpinner.info(chalk25.yellow("No high-success patterns to add"));
9750
+ updateSpinner.info(chalk26.yellow("No high-success patterns to add"));
9496
9751
  } else {
9497
9752
  let addedCount = 0;
9498
9753
  const limit = 5;
@@ -9503,13 +9758,13 @@ async function analyzeSuccess(options) {
9503
9758
  });
9504
9759
  addedCount++;
9505
9760
  }
9506
- updateSpinner.succeed(chalk25.green(`Added ${addedCount} success pattern(s) to knowledge base`));
9507
- console.log(chalk25.gray(` See .reygent/knowledge/success-patterns.md`));
9761
+ updateSpinner.succeed(chalk26.green(`Added ${addedCount} success pattern(s) to knowledge base`));
9762
+ console.log(chalk26.gray(` See .reygent/knowledge/success-patterns.md`));
9508
9763
  console.log();
9509
9764
  }
9510
9765
  } catch (err) {
9511
9766
  const errMsg = err instanceof Error ? err.message : String(err);
9512
- updateSpinner.fail(chalk25.red(`Failed to update knowledge: ${errMsg}`));
9767
+ updateSpinner.fail(chalk26.red(`Failed to update knowledge: ${errMsg}`));
9513
9768
  if (process.env.REYGENT_DEBUG === "1" || process.env.REYGENT_DEBUG === "telemetry") {
9514
9769
  console.error("[debug:telemetry] analyzeSuccess knowledge update error:", err);
9515
9770
  }
@@ -9517,7 +9772,7 @@ async function analyzeSuccess(options) {
9517
9772
  }
9518
9773
  } catch (err) {
9519
9774
  const errMsg = err instanceof Error ? err.message : String(err);
9520
- spinner.fail(chalk25.red(`Failed to analyze success: ${errMsg}`));
9775
+ spinner.fail(chalk26.red(`Failed to analyze success: ${errMsg}`));
9521
9776
  if (process.env.REYGENT_DEBUG === "1" || process.env.REYGENT_DEBUG === "telemetry") {
9522
9777
  console.error("[debug:telemetry] analyzeSuccess error:", err);
9523
9778
  }
@@ -9536,18 +9791,18 @@ async function analyzeCosts(options) {
9536
9791
  const pipelineEvents = filterEvents(allEvents, { event: Events.PIPELINE_END });
9537
9792
  await backend.close();
9538
9793
  if (costEvents.length === 0) {
9539
- spinner.succeed(chalk25.yellow("No cost data found"));
9540
- console.log(chalk25.gray("\nEnable verbose telemetry to track costs:"));
9541
- console.log(chalk25.cyan(" reygent run --telemetry-level verbose\n"));
9794
+ spinner.succeed(chalk26.yellow("No cost data found"));
9795
+ console.log(chalk26.gray("\nEnable verbose telemetry to track costs:"));
9796
+ console.log(chalk26.cyan(" reygent run --telemetry-level verbose\n"));
9542
9797
  return;
9543
9798
  }
9544
9799
  const totalRuns = new Set(pipelineEvents.map((e) => e.runId)).size;
9545
9800
  const successfulRuns = pipelineEvents.filter((e) => e.data.success === true).length;
9546
9801
  const failedRuns = totalRuns - successfulRuns;
9547
9802
  const days = Math.floor((Date.now() - since) / (24 * 60 * 60 * 1e3));
9548
- spinner.succeed(chalk25.green(`Analyzed ${costEvents.length} cost event(s)`));
9803
+ spinner.succeed(chalk26.green(`Analyzed ${costEvents.length} cost event(s)`));
9549
9804
  console.log();
9550
- console.log(chalk25.bold(`Cost Analysis (last ${days} days, ${totalRuns} runs)`));
9805
+ console.log(chalk26.bold(`Cost Analysis (last ${days} days, ${totalRuns} runs)`));
9551
9806
  console.log();
9552
9807
  const totalCost = costEvents.reduce((sum, e) => sum + e.data.costUsd, 0);
9553
9808
  const successRunIds = new Set(
@@ -9555,12 +9810,12 @@ async function analyzeCosts(options) {
9555
9810
  );
9556
9811
  const successCost = costEvents.filter((e) => successRunIds.has(e.runId)).reduce((sum, e) => sum + e.data.costUsd, 0);
9557
9812
  const failedCost = totalCost - successCost;
9558
- console.log(chalk25.bold("Total Spend:"), chalk25.cyan(formatCost2(totalCost)));
9813
+ console.log(chalk26.bold("Total Spend:"), chalk26.cyan(formatCost2(totalCost)));
9559
9814
  console.log(`Successful runs: ${formatCost2(successCost)} (${formatPercent(successCost / totalCost)})`);
9560
9815
  console.log(`Failed runs: ${formatCost2(failedCost)} (${formatPercent(failedCost / totalCost)} - wasted)`);
9561
9816
  console.log();
9562
9817
  if (options.byAgent) {
9563
- console.log(chalk25.bold("Cost by Agent:"));
9818
+ console.log(chalk26.bold("Cost by Agent:"));
9564
9819
  const agentCosts = /* @__PURE__ */ new Map();
9565
9820
  for (const event of costEvents) {
9566
9821
  const agent = event.data.agent || "unknown";
@@ -9578,7 +9833,7 @@ async function analyzeCosts(options) {
9578
9833
  }
9579
9834
  console.log();
9580
9835
  } else {
9581
- console.log(chalk25.bold("Cost by Stage:"));
9836
+ console.log(chalk26.bold("Cost by Stage:"));
9582
9837
  const stageCosts = /* @__PURE__ */ new Map();
9583
9838
  for (const event of costEvents) {
9584
9839
  const stage = event.data.stage ?? "unknown";
@@ -9597,7 +9852,7 @@ async function analyzeCosts(options) {
9597
9852
  console.log();
9598
9853
  }
9599
9854
  if (failedRuns > 0 && options.showRuns) {
9600
- console.log(chalk25.bold("Expensive Failures (top 3):"));
9855
+ console.log(chalk26.bold("Expensive Failures (top 3):"));
9601
9856
  const failedRunIds = new Set(
9602
9857
  pipelineEvents.filter((e) => e.data.success !== true).map((e) => e.runId)
9603
9858
  );
@@ -9622,7 +9877,7 @@ async function analyzeCosts(options) {
9622
9877
  }
9623
9878
  console.log();
9624
9879
  }
9625
- console.log(chalk25.bold("Optimization Opportunities:"));
9880
+ console.log(chalk26.bold("Optimization Opportunities:"));
9626
9881
  const recommendations = [];
9627
9882
  if (failedCost > 0) {
9628
9883
  const wastePercent = failedCost / totalCost * 100;
@@ -9641,7 +9896,7 @@ async function analyzeCosts(options) {
9641
9896
  Potential Savings: ${formatCost2(monthlySavings)}/month (${formatPercent(potentialSavings / totalCost)})`);
9642
9897
  }
9643
9898
  if (recommendations.length === 0) {
9644
- console.log(chalk25.gray(" No specific recommendations"));
9899
+ console.log(chalk26.gray(" No specific recommendations"));
9645
9900
  } else {
9646
9901
  for (const rec of recommendations) {
9647
9902
  console.log(rec);
@@ -9649,7 +9904,7 @@ Potential Savings: ${formatCost2(monthlySavings)}/month (${formatPercent(potenti
9649
9904
  }
9650
9905
  console.log();
9651
9906
  } catch (err) {
9652
- spinner.fail(chalk25.red(`Failed to analyze costs: ${err.message}`));
9907
+ spinner.fail(chalk26.red(`Failed to analyze costs: ${err.message}`));
9653
9908
  process.exit(1);
9654
9909
  }
9655
9910
  }
@@ -9667,13 +9922,13 @@ async function analyzeAgents(options) {
9667
9922
  const costEvents = filterEvents(allEvents, { event: Events.USAGE_COST });
9668
9923
  await backend.close();
9669
9924
  if (agentSpawnEvents.length === 0) {
9670
- spinner.succeed(chalk25.yellow("No agent data found"));
9925
+ spinner.succeed(chalk26.yellow("No agent data found"));
9671
9926
  return;
9672
9927
  }
9673
9928
  const days = Math.floor((Date.now() - since) / (24 * 60 * 60 * 1e3));
9674
- spinner.succeed(chalk25.green(`Analyzed ${agentSpawnEvents.length} agent spawn(s)`));
9929
+ spinner.succeed(chalk26.green(`Analyzed ${agentSpawnEvents.length} agent spawn(s)`));
9675
9930
  console.log();
9676
- console.log(chalk25.bold(`Agent Performance Analysis (last ${days} days)`));
9931
+ console.log(chalk26.bold(`Agent Performance Analysis (last ${days} days)`));
9677
9932
  console.log();
9678
9933
  const agentStats = /* @__PURE__ */ new Map();
9679
9934
  for (const spawn4 of agentSpawnEvents) {
@@ -9727,8 +9982,8 @@ async function analyzeAgents(options) {
9727
9982
  if (options.agent) {
9728
9983
  const requestedStats = agentStats.get(options.agent);
9729
9984
  if (!requestedStats) {
9730
- spinner.warn(chalk25.yellow(`Agent "${options.agent}" not found in telemetry data`));
9731
- console.log(chalk25.gray(`
9985
+ spinner.warn(chalk26.yellow(`Agent "${options.agent}" not found in telemetry data`));
9986
+ console.log(chalk26.gray(`
9732
9987
  Available agents: ${Array.from(agentStats.keys()).join(", ")}`));
9733
9988
  return;
9734
9989
  }
@@ -9740,7 +9995,7 @@ Available agents: ${Array.from(agentStats.keys()).join(", ")}`));
9740
9995
  const successRate = stats.completions > 0 ? stats.successes / stats.completions : 0;
9741
9996
  const avgDuration = stats.completions > 0 ? stats.totalDuration / stats.completions : 0;
9742
9997
  const avgCost = stats.completions > 0 ? stats.totalCost / stats.completions : 0;
9743
- console.log(chalk25.bold.cyan(agent + ":"));
9998
+ console.log(chalk26.bold.cyan(agent + ":"));
9744
9999
  console.log(` Runs: ${stats.completions}`);
9745
10000
  console.log(` Success rate: ${formatPercent(successRate)} (${stats.successes} success, ${stats.failures} failures)`);
9746
10001
  console.log(` Avg duration: ${formatDuration3(avgDuration)}`);
@@ -9790,7 +10045,7 @@ Available agents: ${Array.from(agentStats.keys()).join(", ")}`));
9790
10045
  }
9791
10046
  console.log();
9792
10047
  }
9793
- console.log(chalk25.bold("Recommendations:"));
10048
+ console.log(chalk26.bold("Recommendations:"));
9794
10049
  const recommendations = [];
9795
10050
  for (const [agent, stats] of agentStats) {
9796
10051
  if (stats.completions > 0) {
@@ -9809,7 +10064,7 @@ Available agents: ${Array.from(agentStats.keys()).join(", ")}`));
9809
10064
  recommendations.push(`\u2022 ${sortedBySuccess[0].agent}: Best performer (${formatPercent(sortedBySuccess[0].successRate)} success)`);
9810
10065
  }
9811
10066
  if (recommendations.length === 0) {
9812
- console.log(chalk25.gray(" No specific recommendations"));
10067
+ console.log(chalk26.gray(" No specific recommendations"));
9813
10068
  } else {
9814
10069
  for (const rec of recommendations) {
9815
10070
  console.log(rec);
@@ -9817,7 +10072,7 @@ Available agents: ${Array.from(agentStats.keys()).join(", ")}`));
9817
10072
  }
9818
10073
  console.log();
9819
10074
  } catch (err) {
9820
- spinner.fail(chalk25.red(`Failed to analyze agents: ${err.message}`));
10075
+ spinner.fail(chalk26.red(`Failed to analyze agents: ${err.message}`));
9821
10076
  process.exit(1);
9822
10077
  }
9823
10078
  }
@@ -9830,7 +10085,7 @@ function registerAnalyzeCommand(program2) {
9830
10085
  }
9831
10086
 
9832
10087
  // src/commands/last.ts
9833
- import chalk26 from "chalk";
10088
+ import chalk27 from "chalk";
9834
10089
  import ora8 from "ora";
9835
10090
  import Table2 from "cli-table3";
9836
10091
  function formatTimestamp2(timestamp) {
@@ -9853,8 +10108,8 @@ function formatCost3(usd) {
9853
10108
  }
9854
10109
  function checkTelemetryEnabled2(config) {
9855
10110
  if (!config.telemetry?.enabled) {
9856
- console.log(chalk26.yellow("\nTelemetry disabled. Enable with:"));
9857
- console.log(chalk26.cyan(" reygent telemetry enable\n"));
10111
+ console.log(chalk27.yellow("\nTelemetry disabled. Enable with:"));
10112
+ console.log(chalk27.cyan(" reygent telemetry enable\n"));
9858
10113
  process.exit(1);
9859
10114
  }
9860
10115
  }
@@ -9871,11 +10126,11 @@ function displaySummary(runId, events) {
9871
10126
  const totalCost = costEvents.reduce((sum, e) => sum + e.data.costUsd, 0);
9872
10127
  const agents = [...new Set(agentSpawns.map((e) => e.data.agent))];
9873
10128
  console.log();
9874
- console.log(chalk26.bold("Latest Run Summary"));
10129
+ console.log(chalk27.bold("Latest Run Summary"));
9875
10130
  console.log();
9876
- console.log(` Run ID: ${chalk26.cyan(runId.substring(0, 8))}`);
9877
- console.log(` Status: ${success ? chalk26.green("Success") : chalk26.red("Failed")}`);
9878
- console.log(` Started: ${chalk26.gray(formatTimestamp2(startTime))}`);
10131
+ console.log(` Run ID: ${chalk27.cyan(runId.substring(0, 8))}`);
10132
+ console.log(` Status: ${success ? chalk27.green("Success") : chalk27.red("Failed")}`);
10133
+ console.log(` Started: ${chalk27.gray(formatTimestamp2(startTime))}`);
9879
10134
  console.log(` Duration: ${formatDuration4(duration)}`);
9880
10135
  console.log(` Agents: ${agents.join(", ") || "none"}`);
9881
10136
  if (totalCost > 0) {
@@ -9883,7 +10138,7 @@ function displaySummary(runId, events) {
9883
10138
  }
9884
10139
  if (errorEvents.length > 0) {
9885
10140
  console.log();
9886
- console.log(chalk26.red(` Errors: ${errorEvents.length} error(s)`));
10141
+ console.log(chalk27.red(` Errors: ${errorEvents.length} error(s)`));
9887
10142
  const errorSummary = errorEvents.slice(0, 3).map((e) => {
9888
10143
  const msg = e.data.message || e.event;
9889
10144
  return ` \u2022 ${msg}`;
@@ -9897,14 +10152,14 @@ function displaySummary(runId, events) {
9897
10152
  }
9898
10153
  function displayVerbose(runId, events) {
9899
10154
  console.log();
9900
- console.log(chalk26.bold(`Detailed Event Log (${events.length} events)`));
10155
+ console.log(chalk27.bold(`Detailed Event Log (${events.length} events)`));
9901
10156
  console.log();
9902
10157
  const table = new Table2({
9903
10158
  head: [
9904
- chalk26.cyan("Time"),
9905
- chalk26.cyan("Category"),
9906
- chalk26.cyan("Event"),
9907
- chalk26.cyan("Details")
10159
+ chalk27.cyan("Time"),
10160
+ chalk27.cyan("Category"),
10161
+ chalk27.cyan("Event"),
10162
+ chalk27.cyan("Details")
9908
10163
  ],
9909
10164
  colWidths: [20, 15, 30, 50],
9910
10165
  wordWrap: true
@@ -9913,10 +10168,10 @@ function displayVerbose(runId, events) {
9913
10168
  const timestamp = formatTimestamp2(event.timestamp);
9914
10169
  const details = Object.keys(event.data).length > 0 ? JSON.stringify(event.data).substring(0, 100) : "";
9915
10170
  table.push([
9916
- chalk26.gray(timestamp),
10171
+ chalk27.gray(timestamp),
9917
10172
  event.category,
9918
10173
  event.event,
9919
- chalk26.gray(details)
10174
+ chalk27.gray(details)
9920
10175
  ]);
9921
10176
  }
9922
10177
  console.log(table.toString());
@@ -9926,7 +10181,7 @@ function displayOutput(events) {
9926
10181
  const pipelineEnd = events.find((e) => e.event === Events.PIPELINE_END);
9927
10182
  const agentCompletes = events.filter((e) => e.event === Events.AGENT_COMPLETE);
9928
10183
  console.log();
9929
- console.log(chalk26.bold("Run Output"));
10184
+ console.log(chalk27.bold("Run Output"));
9930
10185
  console.log();
9931
10186
  if (pipelineEnd?.data.output) {
9932
10187
  console.log(pipelineEnd.data.output);
@@ -9935,23 +10190,23 @@ function displayOutput(events) {
9935
10190
  const agent = complete.data.agent;
9936
10191
  const output = complete.data.output;
9937
10192
  if (output) {
9938
- console.log(chalk26.cyan(`[${agent}]`));
10193
+ console.log(chalk27.cyan(`[${agent}]`));
9939
10194
  console.log(output);
9940
10195
  console.log();
9941
10196
  }
9942
10197
  }
9943
10198
  } else {
9944
- console.log(chalk26.yellow("No output captured"));
10199
+ console.log(chalk27.yellow("No output captured"));
9945
10200
  }
9946
10201
  console.log();
9947
10202
  }
9948
10203
  function displayErrors(events) {
9949
10204
  const errorEvents = events.filter((e) => e.category === "error");
9950
10205
  console.log();
9951
- console.log(chalk26.bold(`Errors (${errorEvents.length})`));
10206
+ console.log(chalk27.bold(`Errors (${errorEvents.length})`));
9952
10207
  console.log();
9953
10208
  if (errorEvents.length === 0) {
9954
- console.log(chalk26.green("No errors in this run"));
10209
+ console.log(chalk27.green("No errors in this run"));
9955
10210
  console.log();
9956
10211
  return;
9957
10212
  }
@@ -9959,10 +10214,10 @@ function displayErrors(events) {
9959
10214
  const timestamp = formatTimestamp2(error.timestamp);
9960
10215
  const message = error.data.message || "Unknown error";
9961
10216
  const agent = error.data.agent || "unknown";
9962
- console.log(chalk26.gray(timestamp) + chalk26.red(` [${error.event}]`) + ` ${agent}`);
10217
+ console.log(chalk27.gray(timestamp) + chalk27.red(` [${error.event}]`) + ` ${agent}`);
9963
10218
  console.log(` ${message}`);
9964
10219
  if (error.data.stack) {
9965
- console.log(chalk26.gray(` ${error.data.stack}`));
10220
+ console.log(chalk27.gray(` ${error.data.stack}`));
9966
10221
  }
9967
10222
  console.log();
9968
10223
  }
@@ -9986,8 +10241,8 @@ async function lastCommandImpl(options, testBackend) {
9986
10241
  }
9987
10242
  const runs = await backend.listRuns();
9988
10243
  if (runs.length === 0) {
9989
- spinner.fail(chalk26.yellow("No telemetry runs found"));
9990
- console.log(chalk26.gray("\nRun a reygent command to generate telemetry data"));
10244
+ spinner.fail(chalk27.yellow("No telemetry runs found"));
10245
+ console.log(chalk27.gray("\nRun a reygent command to generate telemetry data"));
9991
10246
  if (!testBackend) {
9992
10247
  await backend.close();
9993
10248
  }
@@ -9998,7 +10253,7 @@ async function lastCommandImpl(options, testBackend) {
9998
10253
  if (!testBackend) {
9999
10254
  await backend.close();
10000
10255
  }
10001
- spinner.succeed(chalk26.green(`Loaded latest run: ${latestRun.runId.substring(0, 8)}`));
10256
+ spinner.succeed(chalk27.green(`Loaded latest run: ${latestRun.runId.substring(0, 8)}`));
10002
10257
  if (options.json) {
10003
10258
  displayJson(latestRun.runId, events);
10004
10259
  } else if (options.output) {
@@ -10011,7 +10266,7 @@ async function lastCommandImpl(options, testBackend) {
10011
10266
  displaySummary(latestRun.runId, events);
10012
10267
  }
10013
10268
  } catch (err) {
10014
- spinner.fail(chalk26.red(`Failed to load latest run: ${err.message}`));
10269
+ spinner.fail(chalk27.red(`Failed to load latest run: ${err.message}`));
10015
10270
  process.exit(1);
10016
10271
  }
10017
10272
  }
@@ -10025,7 +10280,7 @@ function registerLastCommand(program2) {
10025
10280
  // src/commands/knowledge.ts
10026
10281
  import { join as join12 } from "path";
10027
10282
  import { execSync } from "child_process";
10028
- import chalk27 from "chalk";
10283
+ import chalk28 from "chalk";
10029
10284
  import ora9 from "ora";
10030
10285
  import Table3 from "cli-table3";
10031
10286
  import { select as select7, confirm as confirm2 } from "@inquirer/prompts";
@@ -10068,22 +10323,22 @@ function registerKnowledgeCommand(program2) {
10068
10323
  async function listCommand() {
10069
10324
  const knowledgeDir = findKnowledgeDir();
10070
10325
  if (!knowledgeDir) {
10071
- console.log(chalk27.yellow("No .reygent/knowledge/ directory found."));
10326
+ console.log(chalk28.yellow("No .reygent/knowledge/ directory found."));
10072
10327
  console.log(
10073
- chalk27.gray("Run from a project with .reygent/ or create one with:")
10328
+ chalk28.gray("Run from a project with .reygent/ or create one with:")
10074
10329
  );
10075
- console.log(chalk27.cyan(" reygent init"));
10330
+ console.log(chalk28.cyan(" reygent init"));
10076
10331
  return;
10077
10332
  }
10078
10333
  const files = listKnowledgeFiles();
10079
10334
  if (files.length === 0) {
10080
- console.log(chalk27.yellow("No knowledge files found."));
10335
+ console.log(chalk28.yellow("No knowledge files found."));
10081
10336
  return;
10082
10337
  }
10083
- console.log(chalk27.bold("\nKnowledge Files:"));
10338
+ console.log(chalk28.bold("\nKnowledge Files:"));
10084
10339
  console.log();
10085
10340
  const table = new Table3({
10086
- head: [chalk27.cyan("File"), chalk27.cyan("Type")],
10341
+ head: [chalk28.cyan("File"), chalk28.cyan("Type")],
10087
10342
  colWidths: [40, 30]
10088
10343
  });
10089
10344
  for (const file of files) {
@@ -10092,13 +10347,13 @@ async function listCommand() {
10092
10347
  }
10093
10348
  console.log(table.toString());
10094
10349
  console.log();
10095
- console.log(chalk27.gray(`View file: ${chalk27.white("reygent knowledge show <file>")}`));
10096
- console.log(chalk27.gray(`Search: ${chalk27.white("reygent knowledge search <query>")}`));
10350
+ console.log(chalk28.gray(`View file: ${chalk28.white("reygent knowledge show <file>")}`));
10351
+ console.log(chalk28.gray(`Search: ${chalk28.white("reygent knowledge search <query>")}`));
10097
10352
  }
10098
10353
  async function showCommand2(file) {
10099
10354
  const knowledgeDir = findKnowledgeDir();
10100
10355
  if (!knowledgeDir) {
10101
- console.log(chalk27.red("No .reygent/knowledge/ directory found."));
10356
+ console.log(chalk28.red("No .reygent/knowledge/ directory found."));
10102
10357
  process.exit(1);
10103
10358
  }
10104
10359
  const normalizedFile = file.endsWith(".md") ? file : `${file}.md`;
@@ -10106,24 +10361,24 @@ async function showCommand2(file) {
10106
10361
  try {
10107
10362
  const content = readMarkdown(filePath);
10108
10363
  if (content === null) {
10109
- console.log(chalk27.red(`Knowledge file validation failed: ${normalizedFile}`));
10110
- console.log(chalk27.gray("File may contain suspicious content or be malformed."));
10364
+ console.log(chalk28.red(`Knowledge file validation failed: ${normalizedFile}`));
10365
+ console.log(chalk28.gray("File may contain suspicious content or be malformed."));
10111
10366
  process.exit(1);
10112
10367
  }
10113
10368
  if (content === "") {
10114
- console.log(chalk27.yellow(`Knowledge file is empty or not found: ${normalizedFile}`));
10115
- console.log(chalk27.gray("Available files:"));
10369
+ console.log(chalk28.yellow(`Knowledge file is empty or not found: ${normalizedFile}`));
10370
+ console.log(chalk28.gray("Available files:"));
10116
10371
  const files = listKnowledgeFiles();
10117
- files.forEach((f) => console.log(chalk27.gray(` - ${f}`)));
10372
+ files.forEach((f) => console.log(chalk28.gray(` - ${f}`)));
10118
10373
  process.exit(1);
10119
10374
  }
10120
- console.log(chalk27.bold(`
10375
+ console.log(chalk28.bold(`
10121
10376
  ${normalizedFile}
10122
10377
  `));
10123
10378
  console.log(content);
10124
10379
  console.log();
10125
10380
  } catch (err) {
10126
- console.log(chalk27.red(`Failed to read ${normalizedFile}: ${err.message}`));
10381
+ console.log(chalk28.red(`Failed to read ${normalizedFile}: ${err.message}`));
10127
10382
  process.exit(1);
10128
10383
  }
10129
10384
  }
@@ -10132,45 +10387,45 @@ async function searchCommand(query) {
10132
10387
  try {
10133
10388
  const results = searchKnowledge(query);
10134
10389
  if (results.length === 0) {
10135
- spinner.fail(chalk27.yellow("No matches found."));
10390
+ spinner.fail(chalk28.yellow("No matches found."));
10136
10391
  return;
10137
10392
  }
10138
- spinner.succeed(chalk27.green(`Found ${results.length} match(es)`));
10393
+ spinner.succeed(chalk28.green(`Found ${results.length} match(es)`));
10139
10394
  console.log();
10140
10395
  for (const result of results) {
10141
- console.log(chalk27.bold.cyan(`${result.file}`));
10142
- console.log(chalk27.bold(` ${result.entry.title}`));
10143
- console.log(chalk27.gray(` ${result.excerpt}`));
10396
+ console.log(chalk28.bold.cyan(`${result.file}`));
10397
+ console.log(chalk28.bold(` ${result.entry.title}`));
10398
+ console.log(chalk28.gray(` ${result.excerpt}`));
10144
10399
  console.log();
10145
10400
  }
10146
10401
  } catch (err) {
10147
- spinner.fail(chalk27.red(`Search failed: ${err.message}`));
10402
+ spinner.fail(chalk28.red(`Search failed: ${err.message}`));
10148
10403
  process.exit(1);
10149
10404
  }
10150
10405
  }
10151
10406
  async function editCommand(file) {
10152
10407
  const knowledgeDir = findKnowledgeDir();
10153
10408
  if (!knowledgeDir) {
10154
- console.log(chalk27.red("No .reygent/knowledge/ directory found."));
10409
+ console.log(chalk28.red("No .reygent/knowledge/ directory found."));
10155
10410
  process.exit(1);
10156
10411
  }
10157
10412
  const normalizedFile = file.endsWith(".md") ? file : `${file}.md`;
10158
10413
  const filePath = join12(knowledgeDir, normalizedFile);
10159
10414
  const editor = process.env.EDITOR || "vi";
10160
- console.log(chalk27.cyan(`Opening ${normalizedFile} in ${editor}...`));
10415
+ console.log(chalk28.cyan(`Opening ${normalizedFile} in ${editor}...`));
10161
10416
  try {
10162
10417
  execSync(`${editor} "${filePath}"`, { stdio: "inherit" });
10163
- console.log(chalk27.green("File saved."));
10418
+ console.log(chalk28.green("File saved."));
10164
10419
  } catch (err) {
10165
- console.log(chalk27.red(`Failed to open editor: ${err.message}`));
10420
+ console.log(chalk28.red(`Failed to open editor: ${err.message}`));
10166
10421
  process.exit(1);
10167
10422
  }
10168
10423
  }
10169
10424
  async function addFailureCommand(options) {
10170
10425
  const knowledgeDir = findKnowledgeDir();
10171
10426
  if (!knowledgeDir) {
10172
- console.log(chalk27.red("No .reygent/knowledge/ directory found."));
10173
- console.log(chalk27.gray("Run 'reygent init' to create knowledge directory."));
10427
+ console.log(chalk28.red("No .reygent/knowledge/ directory found."));
10428
+ console.log(chalk28.gray("Run 'reygent init' to create knowledge directory."));
10174
10429
  process.exit(1);
10175
10430
  }
10176
10431
  let issue = options.issue;
@@ -10185,7 +10440,7 @@ async function addFailureCommand(options) {
10185
10440
  });
10186
10441
  } catch (err) {
10187
10442
  if (err instanceof InputTimeoutError) {
10188
- console.log(chalk27.red("\n\u2717 Input timed out"));
10443
+ console.log(chalk28.red("\n\u2717 Input timed out"));
10189
10444
  process.exit(1);
10190
10445
  }
10191
10446
  throw err;
@@ -10199,7 +10454,7 @@ async function addFailureCommand(options) {
10199
10454
  });
10200
10455
  } catch (err) {
10201
10456
  if (err instanceof InputTimeoutError) {
10202
- console.log(chalk27.red("\n\u2717 Input timed out"));
10457
+ console.log(chalk28.red("\n\u2717 Input timed out"));
10203
10458
  process.exit(1);
10204
10459
  }
10205
10460
  throw err;
@@ -10224,7 +10479,7 @@ async function addFailureCommand(options) {
10224
10479
  });
10225
10480
  } catch (err) {
10226
10481
  if (err instanceof InputTimeoutError) {
10227
- console.log(chalk27.red("\n\u2717 Input timed out"));
10482
+ console.log(chalk28.red("\n\u2717 Input timed out"));
10228
10483
  process.exit(1);
10229
10484
  }
10230
10485
  throw err;
@@ -10238,15 +10493,15 @@ async function addFailureCommand(options) {
10238
10493
  agent,
10239
10494
  example
10240
10495
  });
10241
- console.log(chalk27.green("\u2713 Failure documented"));
10242
- console.log(chalk27.gray(` File: common-failures.md`));
10243
- console.log(chalk27.gray(` Agent: ${agent}`));
10496
+ console.log(chalk28.green("\u2713 Failure documented"));
10497
+ console.log(chalk28.gray(` File: common-failures.md`));
10498
+ console.log(chalk28.gray(` Agent: ${agent}`));
10244
10499
  }
10245
10500
  async function addPatternCommand(options) {
10246
10501
  const knowledgeDir = findKnowledgeDir();
10247
10502
  if (!knowledgeDir) {
10248
- console.log(chalk27.red("No .reygent/knowledge/ directory found."));
10249
- console.log(chalk27.gray("Run 'reygent init' to create knowledge directory."));
10503
+ console.log(chalk28.red("No .reygent/knowledge/ directory found."));
10504
+ console.log(chalk28.gray("Run 'reygent init' to create knowledge directory."));
10250
10505
  process.exit(1);
10251
10506
  }
10252
10507
  let description = options.description;
@@ -10260,7 +10515,7 @@ async function addPatternCommand(options) {
10260
10515
  });
10261
10516
  } catch (err) {
10262
10517
  if (err instanceof InputTimeoutError) {
10263
- console.log(chalk27.red("\n\u2717 Input timed out"));
10518
+ console.log(chalk28.red("\n\u2717 Input timed out"));
10264
10519
  process.exit(1);
10265
10520
  }
10266
10521
  throw err;
@@ -10278,7 +10533,7 @@ async function addPatternCommand(options) {
10278
10533
  });
10279
10534
  } catch (err) {
10280
10535
  if (err instanceof InputTimeoutError) {
10281
- console.log(chalk27.red("\n\u2717 Input timed out"));
10536
+ console.log(chalk28.red("\n\u2717 Input timed out"));
10282
10537
  process.exit(1);
10283
10538
  }
10284
10539
  throw err;
@@ -10302,7 +10557,7 @@ async function addPatternCommand(options) {
10302
10557
  successRate = parseFloat(rateStr);
10303
10558
  } catch (err) {
10304
10559
  if (err instanceof InputTimeoutError) {
10305
- console.log(chalk27.red("\n\u2717 Input timed out"));
10560
+ console.log(chalk28.red("\n\u2717 Input timed out"));
10306
10561
  process.exit(1);
10307
10562
  }
10308
10563
  throw err;
@@ -10315,13 +10570,13 @@ async function addPatternCommand(options) {
10315
10570
  approach,
10316
10571
  successRate
10317
10572
  });
10318
- console.log(chalk27.green("\u2713 Pattern documented"));
10319
- console.log(chalk27.gray(` File: success-patterns.md`));
10573
+ console.log(chalk28.green("\u2713 Pattern documented"));
10574
+ console.log(chalk28.gray(` File: success-patterns.md`));
10320
10575
  }
10321
10576
  async function statsCommand(options) {
10322
10577
  const knowledgeDir = findKnowledgeDir();
10323
10578
  if (!knowledgeDir) {
10324
- console.log(chalk27.red("No .reygent/knowledge/ directory found."));
10579
+ console.log(chalk28.red("No .reygent/knowledge/ directory found."));
10325
10580
  process.exit(1);
10326
10581
  }
10327
10582
  const spinner = ora9("Calculating knowledge base stats...").start();
@@ -10329,7 +10584,7 @@ async function statsCommand(options) {
10329
10584
  const since = options.since || "30d";
10330
10585
  const match = since.match(/^(\d+)d$/);
10331
10586
  if (!match) {
10332
- spinner.fail(chalk27.red(`Invalid --since format: ${since}. Use format like "30d".`));
10587
+ spinner.fail(chalk28.red(`Invalid --since format: ${since}. Use format like "30d".`));
10333
10588
  process.exit(1);
10334
10589
  }
10335
10590
  const days = Number.parseInt(match[1], 10);
@@ -10343,9 +10598,9 @@ async function statsCommand(options) {
10343
10598
  }, 0);
10344
10599
  const chesstrace = getChesstrace();
10345
10600
  if (!chesstrace) {
10346
- spinner.fail(chalk27.yellow("Telemetry not available. Cannot calculate effectiveness."));
10601
+ spinner.fail(chalk28.yellow("Telemetry not available. Cannot calculate effectiveness."));
10347
10602
  console.log();
10348
- console.log(chalk27.bold("Knowledge Base Stats"));
10603
+ console.log(chalk28.bold("Knowledge Base Stats"));
10349
10604
  console.log();
10350
10605
  console.log(`Files: ${files.length}`);
10351
10606
  console.log(`Total entries: ${totalEntries}`);
@@ -10353,32 +10608,32 @@ async function statsCommand(options) {
10353
10608
  }
10354
10609
  const backend = chesstrace.getBackend();
10355
10610
  const effectiveness = measureKnowledgeEffectiveness(backend, sinceMs);
10356
- spinner.succeed(chalk27.green("Stats calculated"));
10611
+ spinner.succeed(chalk28.green("Stats calculated"));
10357
10612
  console.log();
10358
- console.log(chalk27.bold("Knowledge Base Stats"));
10613
+ console.log(chalk28.bold("Knowledge Base Stats"));
10359
10614
  console.log();
10360
- console.log(chalk27.cyan("Files:"), files.length);
10361
- console.log(chalk27.cyan("Total entries:"), totalEntries);
10615
+ console.log(chalk28.cyan("Files:"), files.length);
10616
+ console.log(chalk28.cyan("Total entries:"), totalEntries);
10362
10617
  console.log();
10363
- console.log(chalk27.bold(`Usage (last ${days} days):`));
10364
- console.log(chalk27.cyan(" Consulted runs:"), effectiveness.consultedRuns);
10365
- console.log(chalk27.cyan(" Baseline runs:"), effectiveness.baselineRuns);
10618
+ console.log(chalk28.bold(`Usage (last ${days} days):`));
10619
+ console.log(chalk28.cyan(" Consulted runs:"), effectiveness.consultedRuns);
10620
+ console.log(chalk28.cyan(" Baseline runs:"), effectiveness.baselineRuns);
10366
10621
  console.log();
10367
10622
  if (effectiveness.consultedRuns > 0 || effectiveness.baselineRuns > 0) {
10368
10623
  const withKnowledgePct = Math.round(effectiveness.withKnowledge * 100);
10369
10624
  const baselinePct = Math.round(effectiveness.baseline * 100);
10370
10625
  const improvementPct = Math.round(effectiveness.improvement * 100);
10371
- console.log(chalk27.bold("Effectiveness:"));
10372
- console.log(chalk27.cyan(" Success rate with knowledge:"), `${withKnowledgePct}%`);
10373
- console.log(chalk27.cyan(" Baseline success rate:"), `${baselinePct}%`);
10374
- const improvementColor = effectiveness.improvement > 0 ? chalk27.green : effectiveness.improvement < 0 ? chalk27.red : chalk27.gray;
10375
- console.log(chalk27.cyan(" Improvement:"), improvementColor(`${improvementPct > 0 ? "+" : ""}${improvementPct}%`));
10626
+ console.log(chalk28.bold("Effectiveness:"));
10627
+ console.log(chalk28.cyan(" Success rate with knowledge:"), `${withKnowledgePct}%`);
10628
+ console.log(chalk28.cyan(" Baseline success rate:"), `${baselinePct}%`);
10629
+ const improvementColor = effectiveness.improvement > 0 ? chalk28.green : effectiveness.improvement < 0 ? chalk28.red : chalk28.gray;
10630
+ console.log(chalk28.cyan(" Improvement:"), improvementColor(`${improvementPct > 0 ? "+" : ""}${improvementPct}%`));
10376
10631
  } else {
10377
- console.log(chalk27.gray("No runs found in time window to measure effectiveness."));
10632
+ console.log(chalk28.gray("No runs found in time window to measure effectiveness."));
10378
10633
  }
10379
10634
  console.log();
10380
10635
  } catch (err) {
10381
- spinner.fail(chalk27.red(`Failed to calculate stats: ${err.message}`));
10636
+ spinner.fail(chalk28.red(`Failed to calculate stats: ${err.message}`));
10382
10637
  process.exit(1);
10383
10638
  }
10384
10639
  }
@@ -10388,7 +10643,7 @@ import { existsSync as existsSync13, readFileSync as readFileSync11, writeFileSy
10388
10643
  import { join as join13, dirname as dirname6 } from "path";
10389
10644
  import { randomBytes as randomBytes2 } from "crypto";
10390
10645
  import { confirm as confirm3 } from "@inquirer/prompts";
10391
- import chalk28 from "chalk";
10646
+ import chalk29 from "chalk";
10392
10647
  function shouldPromptForTelemetry() {
10393
10648
  if (!process.stdin.isTTY) {
10394
10649
  return false;
@@ -10419,16 +10674,16 @@ function shouldPromptForTelemetry() {
10419
10674
  return false;
10420
10675
  } catch (err) {
10421
10676
  if (isDebug()) {
10422
- console.error(chalk28.gray(`Failed to read config at ${configPath}:`), err);
10677
+ console.error(chalk29.gray(`Failed to read config at ${configPath}:`), err);
10423
10678
  }
10424
10679
  return true;
10425
10680
  }
10426
10681
  }
10427
10682
  async function promptForTelemetryOptIn() {
10428
10683
  console.log("");
10429
- console.log(chalk28.bold("First-run telemetry setup"));
10430
- console.log(chalk28.gray("Reygent can collect local usage data to help diagnose issues."));
10431
- console.log(chalk28.gray("Data is stored locally in SQLite and never sent to external servers."));
10684
+ console.log(chalk29.bold("First-run telemetry setup"));
10685
+ console.log(chalk29.gray("Reygent can collect local usage data to help diagnose issues."));
10686
+ console.log(chalk29.gray("Data is stored locally in SQLite and never sent to external servers."));
10432
10687
  console.log("");
10433
10688
  const enabled = await confirm3({
10434
10689
  message: "Enable local telemetry?",
@@ -10437,9 +10692,9 @@ async function promptForTelemetryOptIn() {
10437
10692
  await saveTelemetryChoice(enabled);
10438
10693
  console.log("");
10439
10694
  if (enabled) {
10440
- console.log(chalk28.green("\u2713"), "Local telemetry enabled");
10695
+ console.log(chalk29.green("\u2713"), "Local telemetry enabled");
10441
10696
  } else {
10442
- console.log(chalk28.gray("\u2713"), "Local telemetry disabled");
10697
+ console.log(chalk29.gray("\u2713"), "Local telemetry disabled");
10443
10698
  }
10444
10699
  console.log("");
10445
10700
  }
@@ -10462,7 +10717,7 @@ async function saveTelemetryChoice(enabled) {
10462
10717
  rawConfig = JSON.parse(content);
10463
10718
  } catch (err) {
10464
10719
  if (isDebug()) {
10465
- console.error(chalk28.gray(`Failed to parse config at ${configPath}:`), err);
10720
+ console.error(chalk29.gray(`Failed to parse config at ${configPath}:`), err);
10466
10721
  }
10467
10722
  }
10468
10723
  }
@@ -10491,9 +10746,9 @@ async function saveTelemetryChoice(enabled) {
10491
10746
  }
10492
10747
  } catch (err) {
10493
10748
  const message = err instanceof Error ? err.message : String(err);
10494
- console.log(chalk28.yellow("Warning:"), `Failed to save telemetry config: ${message}`);
10749
+ console.log(chalk29.yellow("Warning:"), `Failed to save telemetry config: ${message}`);
10495
10750
  if (isDebug()) console.error(err instanceof Error ? err.stack : err);
10496
- console.log(chalk28.gray("Command will continue without saving telemetry preference."));
10751
+ console.log(chalk29.gray("Command will continue without saving telemetry preference."));
10497
10752
  }
10498
10753
  }
10499
10754
 
@@ -10504,7 +10759,7 @@ var pkg = JSON.parse(
10504
10759
  );
10505
10760
  var program = new Command();
10506
10761
  program.name("reygent").description("Reygent CLI tool").version(pkg.version).option("--debug", "Show full stack traces on errors (or set REYGENT_DEBUG=1)").option("--model <id>", "Model ID (e.g. claude-sonnet-4-5, gemini-2.5-pro, gpt-5.4)").option("--provider <name>", `AI provider (${PROVIDER_NAMES.join(", ")})`).option("--no-telemetry", "Disable telemetry for this run").option("--telemetry-level <level>", "Override telemetry level (minimal, standard, verbose)").option("--telemetry-verbose", "Shorthand for --telemetry-level verbose").addHelpText("after", `
10507
- ${chalk29.yellow("Disclaimer:")} This software is provided "as is" with no warranty. AI-generated output should be reviewed by a human. See LICENSE for full terms.`);
10762
+ ${chalk30.yellow("Disclaimer:")} This software is provided "as is" with no warranty. AI-generated output should be reviewed by a human. See LICENSE for full terms.`);
10508
10763
  program.command("init").description("Initialize .reygent folder with default agent and skill config").option("--dry-run", "Preview what files would be created without writing anything", false).action(initCommand);
10509
10764
  program.command("generate-spec").description("Generate a full markdown spec from a short description").argument("[description]", "Short description of the feature to spec out").option("--output <file>", "Output file path").option("--skip-clarification", "Skip clarifying questions and generate spec directly", false).action(generateSpecCommand);
10510
10765
  program.command("spec").description("Load a spec from a markdown file, Jira issue, or Linear issue").argument("<source>", "Path to a markdown file, issue key (e.g. PROJ-123), or Linear URL").option("--clarify", "Run planner with clarification loop to evaluate spec", false).option("--source <name>", "Issue source provider (jira, linear, local) \u2014 skips interactive prompt").action(specCommand);
@@ -10512,12 +10767,18 @@ program.command("agent").description("Start an interactive agent session").argum
10512
10767
  program.command("run").description("Run the reygent workflow from spec to reviewed PR").option("--spec <source>", "Path to a markdown file, issue key, or Linear URL (prompts if omitted in interactive mode)").option("--type <type>", "Branch type (feat, fix, chore, refactor, docs, test, style, perf) \u2014 skips interactive prompt").option("--dry-run", "Preview workflow stages without executing", false).option("--security-threshold <level>", "Minimum severity to fail security review (CRITICAL, HIGH, MEDIUM, LOW)", "HIGH").option("--auto-approve", "Auto-approve all file edits and actions without prompting", false).option("--insecure", "Skip SSL certificate verification for API calls", false).option("--skip-clarification", "Skip planner clarification and make assumptions", false).option("--max-retries <count>", "Max retry attempts when gate tests fail", "2").option("--verbose", "Show detailed per-agent token and cost breakdown", false).hook("preAction", (thisCommand) => {
10513
10768
  const opts = thisCommand.opts();
10514
10769
  if (opts.type && !isValidType(opts.type)) {
10515
- console.error(chalk29.red(`Error: Invalid --type "${opts.type}". Must be one of: ${VALID_BRANCH_TYPES.join(", ")} (or feature/bugfix aliases)`));
10770
+ console.error(chalk30.red(`Error: Invalid --type "${opts.type}". Must be one of: ${VALID_BRANCH_TYPES.join(", ")} (or feature/bugfix aliases)`));
10516
10771
  process.exit(1);
10517
10772
  }
10518
10773
  }).action(runCommand);
10519
10774
  program.command("review-work").description("Review current branch and post summary to PR/MR").option("--spec <source>", "Spec source with provider prefix (jira:KEY, linear:ID, markdown:FILE) \u2014 file paths auto-infer markdown:").option("--insecure", "Skip SSL certificate verification for API calls", false).action(reviewWorkCommand);
10520
- program.command("review-comments").description("Fetch PR/MR review comments and address them with an agent").option("--insecure", "Skip SSL certificate verification for API calls", false).option("--auto-approve", "Auto-approve plan and execute without prompting", false).action(reviewCommentsCommand);
10775
+ program.command("review-comments").description("Fetch PR/MR review comments and address them with an agent").option("--insecure", "Skip SSL certificate verification for API calls", false).option("--auto-approve", "Auto-approve plan and execute without prompting", false).option("--retry-commits <count>", "Max retries for pre-commit hook failures (default: 3)", (val) => {
10776
+ const num = parseInt(val, 10);
10777
+ if (isNaN(num) || num < 0 || num > 10) {
10778
+ throw new Error("--retry-commits must be between 0 and 10");
10779
+ }
10780
+ return num;
10781
+ }).action(reviewCommentsCommand);
10521
10782
  program.command("config").description("Configure default provider, model, and per-agent overrides").action(configCommand);
10522
10783
  registerTelemetryCommand(program);
10523
10784
  registerAnalyzeCommand(program);
@@ -10526,8 +10787,8 @@ registerSkillsCommand(program);
10526
10787
  registerKnowledgeCommand(program);
10527
10788
  var isHelpOrVersion = process.argv.includes("--help") || process.argv.includes("-h") || process.argv.includes("--version") || process.argv.includes("-V") || process.argv.length <= 2;
10528
10789
  if (!isHelpOrVersion) {
10529
- console.log(chalk29.bold.cyan(`
10530
- reygent`) + chalk29.gray(` v${pkg.version}`) + "\n");
10790
+ console.log(chalk30.bold.cyan(`
10791
+ reygent`) + chalk30.gray(` v${pkg.version}`) + "\n");
10531
10792
  }
10532
10793
  program.hook("preAction", async () => {
10533
10794
  if (program.opts().debug) {
@@ -10571,7 +10832,7 @@ program.hook("preAction", async () => {
10571
10832
  }
10572
10833
  } catch (err) {
10573
10834
  if (program.opts().debug) {
10574
- console.error(chalk29.gray("Validation error:"), err);
10835
+ console.error(chalk30.gray("Validation error:"), err);
10575
10836
  }
10576
10837
  }
10577
10838
  const noTelemetry = program.opts().telemetry === false;
@@ -10580,11 +10841,11 @@ program.hook("preAction", async () => {
10580
10841
  await promptForTelemetryOptIn();
10581
10842
  } catch (err) {
10582
10843
  if (err && typeof err === "object" && "name" in err && err.name === "ExitPromptError") {
10583
- console.log(chalk29.yellow("\nTelemetry setup cancelled."));
10844
+ console.log(chalk30.yellow("\nTelemetry setup cancelled."));
10584
10845
  process.exit(0);
10585
10846
  }
10586
10847
  if (program.opts().debug) {
10587
- console.error(chalk29.gray("Telemetry prompt failed:"), err);
10848
+ console.error(chalk30.gray("Telemetry prompt failed:"), err);
10588
10849
  }
10589
10850
  }
10590
10851
  }