@kernlang/agon 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
+ ENGINE_COLORS,
4
+ cleanEngineOutput,
5
+ icons,
6
+ parseMarkdownBlocks
7
+ } from "./chunk-WE32YJKT.js";
8
+ import {
9
+ AGON_MODE_NAMES,
3
10
  CORPUS_PATH,
4
11
  FitnessError,
5
12
  RUNS_DIR,
@@ -10,6 +17,7 @@ import {
10
17
  appendUserTurnIfAbsent,
11
18
  applyPatch,
12
19
  assignForgeRoles,
20
+ buildCodebaseMap,
13
21
  buildCritiquePrompt,
14
22
  buildForgePrompt,
15
23
  buildHistoryPrimedPrompt,
@@ -26,6 +34,7 @@ import {
26
34
  createBashTool,
27
35
  createBrainstormTool,
28
36
  createCampfireTool,
37
+ createConquerTool,
29
38
  createDelegateTool,
30
39
  createEditTool,
31
40
  createExitPlanModeTool,
@@ -66,6 +75,7 @@ import {
66
75
  getProjectFileStateCache,
67
76
  getRatings,
68
77
  gitChangedFiles,
78
+ hasProjectBrief,
69
79
  isReadOnlyCommand,
70
80
  listCesarPlans,
71
81
  loadConfig,
@@ -98,7 +108,7 @@ import {
98
108
  worktreeCreate,
99
109
  worktreeDiff,
100
110
  worktreeRemoveBestEffort
101
- } from "./chunk-7PMMOQZ7.js";
111
+ } from "./chunk-C22VTCS6.js";
102
112
 
103
113
  // ../forge/src/generated/forge.ts
104
114
  import { randomUUID as randomUUID2 } from "crypto";
@@ -110,7 +120,7 @@ import { join } from "path";
110
120
  import { mkdirSync, rmSync } from "fs";
111
121
  var HEALTH_CHECK_DISABLE_ENV = "AGON_DISABLE_FORGE_HEALTH_CHECK";
112
122
  var HEALTH_CHECK_DEFAULT_PROMPT = "Reply with just: ok";
113
- async function healthCheckEngine(engineId, registry, adapter, _cwd, timeoutSec, prompt) {
123
+ async function healthCheckEngine(engineId, registry, adapter, _cwd, timeoutSec, prompt, signal) {
114
124
  const start = Date.now();
115
125
  let engine;
116
126
  try {
@@ -143,7 +153,8 @@ async function healthCheckEngine(engineId, registry, adapter, _cwd, timeoutSec,
143
153
  cwd: scratchDir,
144
154
  mode: useAgent ? "agent" : "exec",
145
155
  timeout: Math.max(1, Math.ceil(timeoutSec)),
146
- outputDir: scratchDir
156
+ outputDir: scratchDir,
157
+ signal
147
158
  };
148
159
  dispatchResult = useAgent ? await adapter.dispatchAgent(opts) : await adapter.dispatch(opts);
149
160
  } catch (err) {
@@ -201,7 +212,7 @@ function isApiBackedEngine(engineId, registry) {
201
212
  return false;
202
213
  }
203
214
  }
204
- async function healthCheckEngines(engineIds, registry, adapter, cwd, timeoutSec, prompt, apiTimeoutSec, maxParallelApi) {
215
+ async function healthCheckEngines(engineIds, registry, adapter, cwd, timeoutSec, prompt, apiTimeoutSec, maxParallelApi, signal) {
205
216
  const start = Date.now();
206
217
  if (process.env[HEALTH_CHECK_DISABLE_ENV]) {
207
218
  return { healthy: engineIds.slice(), unhealthy: [], totalMs: Date.now() - start };
@@ -213,10 +224,10 @@ async function healthCheckEngines(engineIds, registry, adapter, cwd, timeoutSec,
213
224
  engineIds.map((id) => {
214
225
  if (isApiBackedEngine(id, registry)) {
215
226
  return apiSem.runWith(
216
- () => healthCheckEngine(id, registry, adapter, cwd, apiTimeout, prompt)
227
+ () => healthCheckEngine(id, registry, adapter, cwd, apiTimeout, prompt, signal)
217
228
  );
218
229
  }
219
- return healthCheckEngine(id, registry, adapter, cwd, timeoutSec, prompt);
230
+ return healthCheckEngine(id, registry, adapter, cwd, timeoutSec, prompt, signal);
220
231
  })
221
232
  );
222
233
  const healthy = [];
@@ -241,6 +252,46 @@ async function healthCheckEngines(engineIds, registry, adapter, cwd, timeoutSec,
241
252
  });
242
253
  return { healthy, unhealthy, totalMs: Date.now() - start };
243
254
  }
255
+ async function preflightHealthFilter(opts) {
256
+ const { engineIds, registry, adapter } = opts;
257
+ const skipped = [];
258
+ const afterQuarantine = [];
259
+ for (const id of engineIds) {
260
+ const health = engineHealth.get(id);
261
+ if (health && (health.status === "auth-failed" || health.status === "unreachable")) {
262
+ skipped.push({ engineId: id, status: health.status, reason: health.reason || "quarantined this session" });
263
+ } else {
264
+ afterQuarantine.push(id);
265
+ }
266
+ }
267
+ const wantProbe = opts.probe === true || !!process.env.AGON_FORCE_HEALTH_PROBE;
268
+ if (!wantProbe || afterQuarantine.length === 0) {
269
+ return { healthy: afterQuarantine, skipped };
270
+ }
271
+ let apiTimeoutSec;
272
+ let maxParallelApi;
273
+ try {
274
+ const cfg = loadConfig(opts.cwd ?? process.cwd());
275
+ apiTimeoutSec = cfg?.forgeHealthCheckApiTimeoutSec;
276
+ maxParallelApi = cfg?.forgeMaxParallelApi;
277
+ } catch {
278
+ }
279
+ const summary = await healthCheckEngines(
280
+ afterQuarantine.slice(),
281
+ registry,
282
+ adapter,
283
+ opts.cwd ?? process.cwd(),
284
+ opts.timeoutSec ?? 5,
285
+ HEALTH_CHECK_DEFAULT_PROMPT,
286
+ apiTimeoutSec,
287
+ maxParallelApi,
288
+ opts.signal
289
+ );
290
+ for (const u of summary.unhealthy) {
291
+ skipped.push({ engineId: u.engineId, status: "health-check-failed", reason: u.reason ?? "probe failed" });
292
+ }
293
+ return { healthy: summary.healthy, skipped };
294
+ }
244
295
 
245
296
  // ../forge/src/generated/stages.ts
246
297
  import { join as join4 } from "path";
@@ -1646,7 +1697,11 @@ async function runForge(options, registry, adapter, onEvent) {
1646
1697
  onEvent?.({ type: "forge:fatal", data: { phase: "preflight", error } });
1647
1698
  return manifest2;
1648
1699
  }
1649
- const enabledEngines = options.engines ?? registry.activeIds(config);
1700
+ const __roster = registry.partitionRoster(options.engines ?? null, config);
1701
+ if (__roster.removed.length > 0) {
1702
+ throw new Error(`Removed engine(s) cannot run: ${__roster.removed.join(", ")}. They were hard-removed via 'agon engine remove'; restore with 'agon engine add <id>' (or /engines restore <id>).`);
1703
+ }
1704
+ const enabledEngines = __roster.active;
1650
1705
  const explicitlyRequested = options.engines != null && options.engines.length > 0;
1651
1706
  const skippedQuarantine = [];
1652
1707
  const droppedEngines = [];
@@ -2395,16 +2450,22 @@ function fallbackParse(output) {
2395
2450
  async function runBrainstorm(opts) {
2396
2451
  const brainstormId = randomUUID3().slice(0, 8);
2397
2452
  seedNewEnginesFromRegistry(opts.registry);
2453
+ const __hc = await preflightHealthFilter({ engineIds: opts.engines, registry: opts.registry, adapter: opts.adapter, signal: opts.signal });
2454
+ for (const s of __hc.skipped) console.warn(`[agon] brainstorm: skipping ${s.engineId} \u2014 ${s.status} (${s.reason})`);
2455
+ const __engines = __hc.healthy;
2456
+ if (__engines.length === 0) {
2457
+ throw new Error(`No healthy engines for brainstorm; all ${__hc.skipped.length} were quarantined this session (${__hc.skipped.map((s) => s.engineId).join(", ")}). Restore with 'agon engine add <id>'.`);
2458
+ }
2398
2459
  const sidechain = createSidechainLogger({
2399
2460
  sessionId: brainstormId,
2400
2461
  sessionType: "brainstorm",
2401
2462
  outputDir: opts.outputDir
2402
2463
  });
2403
- sidechain.log("brainstorm:init", void 0, { question: opts.question, engines: opts.engines });
2464
+ sidechain.log("brainstorm:init", void 0, { question: opts.question, engines: __engines });
2404
2465
  const ranked = await collectRankedDrafts({
2405
2466
  question: opts.question,
2406
2467
  context: opts.context,
2407
- engines: opts.engines,
2468
+ engines: __engines,
2408
2469
  registry: opts.registry,
2409
2470
  adapter: opts.adapter,
2410
2471
  timeout: opts.timeout,
@@ -2749,9 +2810,18 @@ ${snippet}${thinking.length > 800 ? "\u2026" : ""}`;
2749
2810
  });
2750
2811
  }
2751
2812
  async function runTribunal(opts) {
2752
- const { question, engines, rounds, registry, adapter, timeout, outputDir } = opts;
2813
+ const { question, rounds, registry, adapter, timeout, outputDir } = opts;
2753
2814
  const signal = opts.signal;
2754
2815
  const mode = opts.mode ?? "adversarial";
2816
+ const __hc = await preflightHealthFilter({ engineIds: opts.engines, registry, adapter, signal });
2817
+ for (const s of __hc.skipped) console.warn(`[agon] tribunal: skipping ${s.engineId} \u2014 ${s.status} (${s.reason})`);
2818
+ const engines = __hc.healthy;
2819
+ if (engines.length < 2) {
2820
+ if (__hc.skipped.length === 0) {
2821
+ throw new Error(`Tribunal needs at least 2 engines; only ${opts.engines.length} provided. Widen --engines or add one with 'agon engine add <id>'.`);
2822
+ }
2823
+ throw new Error(`Tribunal needs at least 2 healthy engines; ${__hc.skipped.length} were quarantined this session (${__hc.skipped.map((s) => s.engineId).join(", ")}). Restore with 'agon engine add <id>' or widen --engines.`);
2824
+ }
2755
2825
  seedNewEnginesFromRegistry(registry);
2756
2826
  const modeConfig = getModeConfig(mode, engines.length);
2757
2827
  const roles = modeConfig.roles.slice(0, engines.length);
@@ -2898,8 +2968,14 @@ ${p.arguments[p.arguments.length - 1]}`).join("\n\n---\n\n") : void 0;
2898
2968
 
2899
2969
  // ../forge/src/generated/campfire.ts
2900
2970
  async function runCampfire(opts) {
2901
- const { topic, engines, registry, adapter, strategy, timeout, outputDir } = opts;
2971
+ const { topic, registry, adapter, strategy, timeout, outputDir } = opts;
2902
2972
  const cwd = resolveWorkingDir();
2973
+ const __hc = await preflightHealthFilter({ engineIds: opts.engines, registry, adapter, signal: opts.signal });
2974
+ for (const s of __hc.skipped) console.warn(`[agon] campfire: skipping ${s.engineId} \u2014 ${s.status} (${s.reason})`);
2975
+ const engines = __hc.healthy;
2976
+ if (engines.length === 0) {
2977
+ throw new Error(`No healthy engines for campfire; all ${__hc.skipped.length} were quarantined this session (${__hc.skipped.map((s) => s.engineId).join(", ")}). Restore with 'agon engine add <id>'.`);
2978
+ }
2903
2979
  const basePrompt = [
2904
2980
  `## CAMPFIRE`,
2905
2981
  `Topic: ${topic || "open discussion"}`,
@@ -3079,12 +3155,18 @@ async function runNero(opts) {
3079
3155
  const ratings = opts.ratings ?? getRatings();
3080
3156
  const MAX_ATTEMPTS = 2;
3081
3157
  const backoffMs = opts.retryBackoffMs ?? 1200;
3158
+ const __hc = await preflightHealthFilter({ engineIds: opts.engines, registry: opts.registry, adapter: opts.adapter, signal: opts.signal });
3159
+ for (const s of __hc.skipped) opts.onStatus?.(`Nero: skipping ${s.engineId} \u2014 ${s.status} (${s.reason})`);
3160
+ const __engines = __hc.healthy;
3082
3161
  const forced = opts.engine?.trim();
3162
+ if (forced && opts.engines.includes(forced) && !__engines.includes(forced)) {
3163
+ return { ok: false, engineId: forced, reason: "none", scope: null, verdict: "unknown", challengeConfidence: null, challengeText: `Requested Nero critic '${forced}' is quarantined this session (auth-failed/unreachable). Restore with 'agon engine add <id>' or pick another --engine.`, outputDir: opts.outputDir };
3164
+ }
3083
3165
  let ranked;
3084
- if (forced && opts.engines.includes(forced)) {
3166
+ if (forced && __engines.includes(forced)) {
3085
3167
  ranked = [{ engineId: forced, reason: "forced", scope: null }];
3086
3168
  } else {
3087
- ranked = rankNeroCritics(opts.engines, ratings, { exclude: opts.exclude });
3169
+ ranked = rankNeroCritics(__engines, ratings, { exclude: opts.exclude });
3088
3170
  }
3089
3171
  if (ranked.length === 0) {
3090
3172
  return { ok: false, engineId: "", reason: "none", scope: null, verdict: "unknown", challengeConfidence: null, challengeText: "No engine available to play Nero (every candidate is the author under review).", outputDir: opts.outputDir };
@@ -3281,10 +3363,33 @@ function parseCouncilConfidence(text) {
3281
3363
  return n;
3282
3364
  }
3283
3365
  async function runCouncil(opts) {
3284
- const { question, engines, registry, adapter, timeout, outputDir } = opts;
3366
+ const { question, registry, adapter, timeout, outputDir } = opts;
3285
3367
  const signal = opts.signal;
3286
3368
  const cwd = opts.cwd ?? resolveWorkingDir();
3287
3369
  const warnings = [];
3370
+ const __hc = await preflightHealthFilter({ engineIds: opts.engines, registry, adapter, signal });
3371
+ for (const s of __hc.skipped) {
3372
+ warnings.push(`${s.engineId} skipped \u2014 ${s.status} (${s.reason})`);
3373
+ console.warn(`[agon] council: skipping ${s.engineId} \u2014 ${s.status} (${s.reason})`);
3374
+ }
3375
+ const engines = __hc.healthy;
3376
+ const __forcedChair = opts.chairman?.trim();
3377
+ if (__forcedChair && __hc.skipped.some((s) => s.engineId === __forcedChair)) {
3378
+ return {
3379
+ ok: false,
3380
+ question,
3381
+ brief: "",
3382
+ chairmanId: __forcedChair,
3383
+ chairmanReason: "forced",
3384
+ actingChairmanId: "",
3385
+ seats: [],
3386
+ verdict: `Requested chairman '${__forcedChair}' is quarantined this session (auth-failed/unreachable) and cannot chair. Restore with 'agon engine add <id>' or pick another chair.`,
3387
+ confidence: null,
3388
+ degraded: true,
3389
+ warnings: [`Chairman ${__forcedChair} quarantined this session.`],
3390
+ outputDir
3391
+ };
3392
+ }
3288
3393
  if (engines.length < 2) {
3289
3394
  return {
3290
3395
  ok: false,
@@ -3320,6 +3425,13 @@ async function runCouncil(opts) {
3320
3425
  } catch {
3321
3426
  cesarId = "";
3322
3427
  }
3428
+ if (cesarId && !engines.includes(cesarId)) {
3429
+ const __ch = engineHealth.get(cesarId);
3430
+ if (__ch && (__ch.status === "auth-failed" || __ch.status === "unreachable")) {
3431
+ warnings.push(`Configured Cesar chair '${cesarId}' is quarantined this session (${__ch.status}); falling back to ${engines[0]} as chair.`);
3432
+ cesarId = "";
3433
+ }
3434
+ }
3323
3435
  chairmanId = cesarId || engines[0];
3324
3436
  chairmanReason = "cesar";
3325
3437
  degraded = true;
@@ -3580,9 +3692,15 @@ function synthesisRoutingAdvice(prompt) {
3580
3692
  ].join(" ");
3581
3693
  }
3582
3694
  async function runSynthesisModus(opts) {
3583
- const { prompt, engines, registry, adapter, timeout, outputDir } = opts;
3695
+ const { prompt, registry, adapter, timeout, outputDir } = opts;
3584
3696
  const swapRounds = Math.max(0, opts.swaps ?? 1);
3585
3697
  const cwd = resolveWorkingDir();
3698
+ const __hc = await preflightHealthFilter({ engineIds: opts.engines, registry, adapter, signal: opts.signal });
3699
+ for (const s of __hc.skipped) console.warn(`[agon] synthesis: skipping ${s.engineId} \u2014 ${s.status} (${s.reason})`);
3700
+ const engines = __hc.healthy;
3701
+ if (engines.length === 0) {
3702
+ throw new Error(`No healthy engines for synthesis; all ${__hc.skipped.length} were quarantined this session (${__hc.skipped.map((s) => s.engineId).join(", ")}). Restore with 'agon engine add <id>'.`);
3703
+ }
3586
3704
  const drafts = [];
3587
3705
  const draftPromises = engines.map(async (engineId) => {
3588
3706
  const engine = registry.get(engineId);
@@ -4056,7 +4174,11 @@ async function runTeamForge(options, registry, adapter, onEvent) {
4056
4174
  sessionType: "team-forge",
4057
4175
  outputDir: forgeDir
4058
4176
  });
4059
- const enabledEngines = options.engines ?? registry.activeIds(config);
4177
+ const __roster = registry.partitionRoster(options.engines ?? null, config);
4178
+ if (__roster.removed.length > 0) {
4179
+ throw new Error(`Removed engine(s) cannot run: ${__roster.removed.join(", ")}. Restore with 'agon engine add <id>' (or /engines restore <id>).`);
4180
+ }
4181
+ const enabledEngines = __roster.active;
4060
4182
  const available = enabledEngines.filter((id) => {
4061
4183
  try {
4062
4184
  const engine = registry.get(id);
@@ -4311,7 +4433,11 @@ async function runTeamTribunal(options) {
4311
4433
  sessionType: "team-tribunal",
4312
4434
  outputDir: options.outputDir
4313
4435
  });
4314
- const enabledEngines = options.engines ?? options.registry.activeIds(config);
4436
+ const __roster = options.registry.partitionRoster(options.engines ?? null, config);
4437
+ if (__roster.removed.length > 0) {
4438
+ throw new Error(`Removed engine(s) cannot run: ${__roster.removed.join(", ")}. Restore with 'agon engine add <id>' (or /engines restore <id>).`);
4439
+ }
4440
+ const enabledEngines = __roster.active;
4315
4441
  const available = enabledEngines.filter((id) => {
4316
4442
  try {
4317
4443
  const engine = options.registry.get(id);
@@ -4572,7 +4698,11 @@ async function runTeamBrainstorm(options) {
4572
4698
  sessionType: "team-brainstorm",
4573
4699
  outputDir: options.outputDir
4574
4700
  });
4575
- const enabledEngines = options.engines ?? options.registry.activeIds(config);
4701
+ const __roster = options.registry.partitionRoster(options.engines ?? null, config);
4702
+ if (__roster.removed.length > 0) {
4703
+ throw new Error(`Removed engine(s) cannot run: ${__roster.removed.join(", ")}. Restore with 'agon engine add <id>' (or /engines restore <id>).`);
4704
+ }
4705
+ const enabledEngines = __roster.active;
4576
4706
  const available = enabledEngines.filter((id) => {
4577
4707
  try {
4578
4708
  const engine = options.registry.get(id);
@@ -6508,113 +6638,6 @@ Continue. Emit CONQUER_ASK only for a real fork, CONQUER_DONE when finished.`;
6508
6638
  };
6509
6639
  }
6510
6640
 
6511
- // src/generated/signals/icons.ts
6512
- var ROMAN_ICONS = { read: "\u039E", edit: "\u270E", write: "\u2712", bash: "\u03DF", search: "\u2609", find: "\u2295", tool: "\u2692", campfire: "\u2632", brainstorm: "\u2609", tribunal: "\u2696", image: "\u229E", queue: "\u231B", prompt: "\u25BB", winner: "\u2605", success: "\u2714", fail: "\u2718", warning: "\u26A0", header: "\u25B8", nero: "\u2020", dotOn: "\u25C6", dotOff: "\u25C7", play: "\u25B6", refresh: "\u21BB", flag: "\u2691", check: "\u2714", cross: "\u2718", spinner: "\u25D0" };
6513
- var CLASSIC_ICONS = { read: "\u{1F4C4}", edit: "\u270F\uFE0F", write: "\u{1F4DD}", bash: "\u26A1", search: "\u{1F50D}", find: "\u{1F4C2}", tool: "\u{1F527}", campfire: "\u{1F525}", brainstorm: "\u{1F4A1}", tribunal: "\u2696", image: "\u{1F4CE}", queue: "\u23F3", prompt: "\u276F", winner: "\u2605", success: "\u2714", fail: "\u2718", warning: "\u26A0", header: "\u25B8", nero: "\u2694", dotOn: "\u25CF", dotOff: "\u25CB", play: "\u25B6", refresh: "\u21BB", flag: "\u2691", check: "\u2714", cross: "\u2718", spinner: "\u25D0" };
6514
- function icons() {
6515
- const theme = loadConfig().iconTheme ?? "roman";
6516
- return theme === "classic" ? CLASSIC_ICONS : ROMAN_ICONS;
6517
- }
6518
-
6519
- // src/generated/blocks/output-format.ts
6520
- var BOLD = "\x1B[1m";
6521
- var DIM = "\x1B[2m";
6522
- var GREEN = "\x1B[32m";
6523
- var RED = "\x1B[31m";
6524
- var YELLOW = "\x1B[33m";
6525
- var CYAN = "\x1B[36m";
6526
- var RESET = "\x1B[0m";
6527
- var ENGINE_COLORS = { claude: 208, codex: 34, agy: 33, ollama: 255, aider: 141, openrouter: 197, qwen: 45, mistral: 75, opencode: 156, minimax: 124, zai: 124 };
6528
- function bold(text) {
6529
- return `${BOLD}${text}${RESET}`;
6530
- }
6531
- function dim(text) {
6532
- return `${DIM}${text}${RESET}`;
6533
- }
6534
- function green(text) {
6535
- return `${GREEN}${text}${RESET}`;
6536
- }
6537
- function red(text) {
6538
- return `${RED}${text}${RESET}`;
6539
- }
6540
- function yellow(text) {
6541
- return `${YELLOW}${text}${RESET}`;
6542
- }
6543
- function cyan(text) {
6544
- return `${CYAN}${text}${RESET}`;
6545
- }
6546
- function stripAnsi(str) {
6547
- return str.replace(/\x1b\[[0-9;]*m/g, "");
6548
- }
6549
- function visibleLength(str) {
6550
- return stripAnsi(str).length;
6551
- }
6552
- function header(text) {
6553
- const { header: h } = icons();
6554
- console.log(`
6555
- ${BOLD}${CYAN}${h} ${text}${RESET}`);
6556
- }
6557
- function success(text) {
6558
- const { success: s } = icons();
6559
- console.log(`${GREEN}${s}${RESET} ${text}`);
6560
- }
6561
- function fail(text) {
6562
- const { fail: f } = icons();
6563
- console.log(`${RED}${f}${RESET} ${text}`);
6564
- }
6565
- function warn(text) {
6566
- const { warning: w } = icons();
6567
- console.log(`${YELLOW}${w}${RESET} ${text}`);
6568
- }
6569
- function info(text) {
6570
- console.log(`${DIM}${text}${RESET}`);
6571
- }
6572
- function table(headers, rows) {
6573
- const widths = headers.map(
6574
- (h, i) => Math.max(visibleLength(h), ...rows.map((r) => visibleLength(r[i] ?? "")))
6575
- );
6576
- const headerLine = headers.map((h, i) => h.padEnd(widths[i])).join(" ");
6577
- const separator = widths.map((w) => "\u2500".repeat(w)).join("\u2500\u2500");
6578
- console.log(` ${bold(headerLine)}`);
6579
- console.log(` ${dim(separator)}`);
6580
- for (const row of rows) {
6581
- const line = row.map((cell, i) => {
6582
- const pad = widths[i] - visibleLength(cell);
6583
- return cell + " ".repeat(Math.max(0, pad));
6584
- }).join(" ");
6585
- console.log(` ${line}`);
6586
- }
6587
- }
6588
- function shortToolPath(filePath) {
6589
- const home = process.env.HOME;
6590
- const stripped = String(filePath ?? "").replace(`${process.cwd()}/`, "");
6591
- return home ? stripped.replace(home, "~") : stripped;
6592
- }
6593
- function isCesarTelemetryLine(message) {
6594
- const text = String(message ?? "").trim();
6595
- return text.startsWith("Cesar route:") || text.startsWith("What happened:");
6596
- }
6597
- function formatConfidenceToolLabel(parsed, rawInput) {
6598
- const rawValue = parsed?.value ?? parsed?.confidence ?? parsed?.score;
6599
- let value = Number(rawValue);
6600
- if (!Number.isFinite(value)) {
6601
- const text = String(rawInput ?? "");
6602
- const match = text.match(/"value"\s*:\s*(\d{1,3}(?:\.\d+)?)/) || text.match(/(\d{1,3})\s*%/);
6603
- if (match) {
6604
- value = Number(match[1]);
6605
- }
6606
- }
6607
- if (Number.isFinite(value)) {
6608
- const pct = value <= 1 && value > 0 ? Math.round(value * 100) : Math.round(value);
6609
- if (pct >= 0 && pct <= 100) {
6610
- const reasoning = String(parsed?.reasoning ?? parsed?.reason ?? parsed?.thought ?? "").replace(/\s+/g, " ").trim();
6611
- const shortReasoning = reasoning.length > 180 ? `${reasoning.slice(0, 177)}\u2026` : reasoning;
6612
- return shortReasoning ? `${pct}% confidence \xB7 ${shortReasoning}` : `${pct}% confidence`;
6613
- }
6614
- }
6615
- return "confidence";
6616
- }
6617
-
6618
6641
  // src/generated/handlers/engine-filter.ts
6619
6642
  var DEFAULT_EXCLUDED_ORCHESTRATION_ENGINE_PREFIXES = ["qwen", "ollama", "opencode", "open-code"];
6620
6643
  var DEFAULT_EXCLUDED_ORCHESTRATION_ENGINE_EXACT = ["kimi", "minimax", "mistral"];
@@ -6729,6 +6752,7 @@ function createCesarToolRegistry(engineId) {
6729
6752
  toolRegistry.register(createCampfireTool());
6730
6753
  toolRegistry.register(createPipelineTool());
6731
6754
  toolRegistry.register(createGoalTool());
6755
+ toolRegistry.register(createConquerTool());
6732
6756
  toolRegistry.register(createReviewTool());
6733
6757
  toolRegistry.register(createDelegateTool());
6734
6758
  toolRegistry.register(createAgentTool());
@@ -6841,360 +6865,6 @@ async function executeEagerTool(toolName, meta, toolRegistry, toolCtx, dispatch,
6841
6865
  return result;
6842
6866
  }
6843
6867
 
6844
- // src/generated/blocks/markdown.ts
6845
- var FENCE_OPEN = /^```(\w*)\s*$/;
6846
- var FENCE_CLOSE = /^```\s*$/;
6847
- function isTableSeparator(line) {
6848
- return /^\|[\s:_-]+(\|[\s:_-]+)*\|?\s*$/.test(line.trim());
6849
- }
6850
- function isTableRow(line) {
6851
- const t = line.trim();
6852
- return t.startsWith("|") && t.includes("|", 1);
6853
- }
6854
- function parseTableAlignment(sepLine) {
6855
- const cells = sepLine.trim().replace(/^\||\|$/g, "").split("|");
6856
- return cells.map((c) => {
6857
- const t = c.trim();
6858
- if (t.startsWith(":") && t.endsWith(":")) return "center";
6859
- if (t.endsWith(":")) return "right";
6860
- return "left";
6861
- });
6862
- }
6863
- function parseTableCells(line) {
6864
- return line.trim().replace(/^\||\|$/g, "").split("|").map((c) => c.trim());
6865
- }
6866
- function emitProseWithTables(proseLines, segments) {
6867
- let i = 0;
6868
- let buffered = [];
6869
- function flushProse() {
6870
- const text = buffered.join("\n");
6871
- if (text.trim()) {
6872
- segments.push({ type: "prose", text, language: void 0, code: void 0, index: void 0, headers: void 0, rows: void 0, alignments: void 0 });
6873
- }
6874
- buffered = [];
6875
- }
6876
- while (i < proseLines.length) {
6877
- if (isTableRow(proseLines[i]) && i + 1 < proseLines.length && isTableSeparator(proseLines[i + 1])) {
6878
- flushProse();
6879
- const headers = parseTableCells(proseLines[i]);
6880
- const alignments = parseTableAlignment(proseLines[i + 1]);
6881
- const rows = [];
6882
- i += 2;
6883
- while (i < proseLines.length && isTableRow(proseLines[i]) && !isTableSeparator(proseLines[i])) {
6884
- rows.push(parseTableCells(proseLines[i]));
6885
- i++;
6886
- }
6887
- segments.push({ type: "table", text: void 0, language: void 0, code: void 0, index: void 0, headers, rows, alignments });
6888
- continue;
6889
- }
6890
- buffered.push(proseLines[i]);
6891
- i++;
6892
- }
6893
- flushProse();
6894
- }
6895
- var _mdCache = /* @__PURE__ */ new Map();
6896
- var _MD_CACHE_MAX = 500;
6897
- function parseMarkdownBlocks(text) {
6898
- let key;
6899
- if (text.length < 500) {
6900
- key = text;
6901
- } else {
6902
- let hash = 5381;
6903
- for (let i = 0; i < text.length; i++) {
6904
- hash = (hash << 5) + hash + text.charCodeAt(i) | 0;
6905
- }
6906
- key = `h:${hash}:${text.length}`;
6907
- }
6908
- const cached = _mdCache.get(key);
6909
- if (cached) return cached;
6910
- const lines = text.split("\n");
6911
- const segments = [];
6912
- let inCode = false;
6913
- let codeLang = "";
6914
- let codeLines = [];
6915
- let proseLines = [];
6916
- let codeIndex = 0;
6917
- for (const line of lines) {
6918
- const trimmed = line.trimStart();
6919
- if (!inCode) {
6920
- const openMatch = trimmed.match(FENCE_OPEN);
6921
- if (openMatch) {
6922
- emitProseWithTables(proseLines, segments);
6923
- proseLines = [];
6924
- inCode = true;
6925
- codeLang = openMatch[1] ?? "";
6926
- codeLines = [];
6927
- continue;
6928
- }
6929
- proseLines.push(line);
6930
- } else {
6931
- if (FENCE_CLOSE.test(trimmed)) {
6932
- if (codeLines.length > 0) {
6933
- codeIndex++;
6934
- segments.push({ type: "code", language: codeLang, code: codeLines.join("\n"), text: void 0, index: codeIndex, headers: void 0, rows: void 0, alignments: void 0 });
6935
- }
6936
- inCode = false;
6937
- codeLang = "";
6938
- codeLines = [];
6939
- continue;
6940
- }
6941
- codeLines.push(line);
6942
- }
6943
- }
6944
- if (inCode && codeLines.length > 0) {
6945
- codeIndex++;
6946
- segments.push({ type: "code", language: codeLang, code: codeLines.join("\n"), text: void 0, index: codeIndex, headers: void 0, rows: void 0, alignments: void 0 });
6947
- } else if (proseLines.length > 0) {
6948
- emitProseWithTables(proseLines, segments);
6949
- }
6950
- if (_mdCache.size >= _MD_CACHE_MAX) {
6951
- const firstKey = _mdCache.keys().next().value;
6952
- if (firstKey !== void 0) _mdCache.delete(firstKey);
6953
- }
6954
- _mdCache.set(key, segments);
6955
- return segments;
6956
- }
6957
- function truncateCodeLine(line, maxWidth) {
6958
- if (line.length <= maxWidth) {
6959
- return line;
6960
- }
6961
- const overflow = line.length - maxWidth + 1;
6962
- return line.slice(0, maxWidth - 1) + `\u2026+${overflow}`;
6963
- }
6964
- function extractCodexStructured(text) {
6965
- const summaryMatch = text.match(/summary:\s*"([\s\S]*?)"\s*(?:sections\s*\{|$)/);
6966
- const contentMatches = [...text.matchAll(/content:\s*"([\s\S]*?)"\s*\}/g)];
6967
- if (!summaryMatch || contentMatches.length === 0) {
6968
- return null;
6969
- }
6970
- const parts = [summaryMatch[1]];
6971
- const sectionMatches = [...text.matchAll(/\d+:\s*"([^"]+)"\s*\{\s*content:\s*"([\s\S]*?)"\s*\}/g)];
6972
- for (const m of sectionMatches) {
6973
- parts.push(`
6974
- ## ${m[1]}
6975
- ${m[2]}`);
6976
- }
6977
- return parts.join("\n").replace(/\\n/g, "\n").trim();
6978
- }
6979
- function parseStreamJsonLine(trimmed) {
6980
- try {
6981
- const parsed = JSON.parse(trimmed);
6982
- if (!parsed.type) return { action: "keep" };
6983
- if (parsed.type === "assistant" && parsed.message?.content) {
6984
- const content = typeof parsed.message.content === "string" ? parsed.message.content : Array.isArray(parsed.message.content) ? parsed.message.content.filter((b) => b.type === "text").map((b) => b.text).join("\n") : "";
6985
- return content ? { action: "use", content } : { action: "skip" };
6986
- }
6987
- if (parsed.type === "text" && parsed.part?.text) {
6988
- return { action: "use", content: parsed.part.text };
6989
- }
6990
- if (parsed.type === "result") {
6991
- if (parsed.subtype === "error_max_turns" || parsed.is_error) return { action: "skip" };
6992
- if (parsed.result && typeof parsed.result === "string") return { action: "use", content: parsed.result };
6993
- return { action: "skip" };
6994
- }
6995
- const skipTypes = [
6996
- "system",
6997
- "hook_started",
6998
- "hook_response",
6999
- "tool_use",
7000
- "tool_result",
7001
- "user",
7002
- "rate_limit_event",
7003
- "message_start",
7004
- "message_stop",
7005
- "message_delta",
7006
- "content_block_start",
7007
- "content_block_stop",
7008
- "content_block_delta",
7009
- "step_start",
7010
- "step_finish",
7011
- "step-start",
7012
- "step-finish",
7013
- "ping",
7014
- "error",
7015
- "init",
7016
- "session_start",
7017
- "session_end"
7018
- ];
7019
- if (skipTypes.includes(parsed.type)) return { action: "skip" };
7020
- if (parsed.type?.startsWith("hook_")) return { action: "skip" };
7021
- if (parsed.type?.startsWith("step_")) return { action: "skip" };
7022
- if (parsed.subtype === "system") return { action: "skip" };
7023
- if (parsed.sessionID || parsed.session_id || parsed.uuid) return { action: "skip" };
7024
- } catch {
7025
- }
7026
- return { action: "keep" };
7027
- }
7028
- function deduplicateInline(line) {
7029
- const len = line.length;
7030
- if (len < 10) return line;
7031
- for (let half = Math.floor(len / 2); half >= 5; half--) {
7032
- const candidate = line.slice(0, half);
7033
- if (line.slice(half).startsWith(candidate)) {
7034
- return candidate + line.slice(half + candidate.length);
7035
- }
7036
- }
7037
- return line;
7038
- }
7039
- function deduplicateParagraphs(text) {
7040
- const lines = text.split("\n");
7041
- const dedupedLines = lines.map((l) => deduplicateInline(l));
7042
- const joined = dedupedLines.join("\n");
7043
- const paragraphs = joined.split(/\n{2,}/);
7044
- const seen = /* @__PURE__ */ new Set();
7045
- const deduped = [];
7046
- for (const para of paragraphs) {
7047
- const normalized = para.trim().replace(/\s+/g, " ");
7048
- if (!normalized) {
7049
- continue;
7050
- }
7051
- if (seen.has(normalized)) {
7052
- continue;
7053
- }
7054
- seen.add(normalized);
7055
- deduped.push(para.trim());
7056
- }
7057
- return deduped.join("\n\n");
7058
- }
7059
- function stripBuddyThinkingNoise(text) {
7060
- const lines = text.split("\n");
7061
- const result = [];
7062
- for (let i = 0; i < lines.length; i++) {
7063
- const line = lines[i];
7064
- const trimmed = line.trim();
7065
- if (trimmed.startsWith("Command:") && trimmed.includes("/bin/")) continue;
7066
- if (trimmed.startsWith("Chunk ID:")) continue;
7067
- if (trimmed.startsWith("Wall time:")) continue;
7068
- if (trimmed.startsWith("Process exited with code")) continue;
7069
- if (trimmed.startsWith("Original token count:")) continue;
7070
- if (trimmed === "Output:") continue;
7071
- if (i + 1 < lines.length) {
7072
- const next = lines[i + 1].trim();
7073
- if (trimmed.length > 20 && next.startsWith(trimmed)) continue;
7074
- }
7075
- result.push(line);
7076
- }
7077
- return result.join("\n");
7078
- }
7079
- function shortenFilePaths(text) {
7080
- const fenceRe = /^```[\s\S]*?^```/gm;
7081
- const fences = [];
7082
- let fm;
7083
- while ((fm = fenceRe.exec(text)) !== null) {
7084
- fences.push({ start: fm.index, end: fm.index + fm[0].length });
7085
- }
7086
- function insideFence(pos) {
7087
- return fences.some((f) => pos >= f.start && pos < f.end);
7088
- }
7089
- const cwd = process.cwd();
7090
- const home = process.env.HOME ?? "";
7091
- const exts = "tsx|jsx|ts|js|json|kern|md|py|rs|go|yaml|yml|toml|sh|css|html|svelte|vue|rb|java|cpp|c|h";
7092
- const pathRe = new RegExp("(?<!`)(?:~/|/)[A-Za-z0-9._\\-/]+\\.(?:" + exts + ")(?::[0-9]+(?::[0-9]+)?|#L[0-9]+)?(?!`)", "g");
7093
- return text.replace(pathRe, (match, offset) => {
7094
- if (insideFence(offset)) return match;
7095
- if (match.length < 10) return match;
7096
- if (!match.includes("/")) return match;
7097
- let shortened = match;
7098
- if (shortened.startsWith("~/") && home) {
7099
- shortened = home + shortened.slice(1);
7100
- }
7101
- if (shortened.startsWith(cwd + "/")) {
7102
- shortened = shortened.slice(cwd.length + 1);
7103
- } else if (home && shortened.startsWith(home + "/")) {
7104
- shortened = "~/" + shortened.slice(home.length + 1);
7105
- }
7106
- const parts = shortened.split("/");
7107
- if (parts.length > 2) {
7108
- shortened = parts[parts.length - 1];
7109
- }
7110
- return "`" + shortened + "`";
7111
- });
7112
- }
7113
- function addParagraphBreaks(text) {
7114
- const paragraphs = text.split(/\n{2,}/);
7115
- const result = [];
7116
- for (const para of paragraphs) {
7117
- const lines = para.split("\n");
7118
- const isStructured = lines.some((l) => /^(#{1,3}\s|[-*]\s+\w|\d+\.\s+\w|>\s)/.test(l.trimStart()));
7119
- const totalLen = lines.reduce((sum, l) => sum + l.length, 0);
7120
- if (isStructured || totalLen < 250) {
7121
- result.push(para);
7122
- continue;
7123
- }
7124
- const joined = lines.join(" ");
7125
- const sentences = joined.split(/(?<=\.\s)(?=[A-Z])/);
7126
- if (sentences.length <= 2) {
7127
- result.push(para);
7128
- continue;
7129
- }
7130
- const chunks = [];
7131
- let current = "";
7132
- let count = 0;
7133
- for (const sentence of sentences) {
7134
- current += sentence;
7135
- count++;
7136
- if (count >= 3 || current.length > 250) {
7137
- chunks.push(current.trim());
7138
- current = "";
7139
- count = 0;
7140
- }
7141
- }
7142
- if (current.trim()) chunks.push(current.trim());
7143
- result.push(chunks.join("\n\n"));
7144
- }
7145
- return result.join("\n\n");
7146
- }
7147
- var _cleanCache = /* @__PURE__ */ new Map();
7148
- function cleanEngineOutput(raw) {
7149
- const cached = _cleanCache.get(raw);
7150
- if (cached !== void 0) {
7151
- return cached;
7152
- }
7153
- const lines = raw.split("\n");
7154
- const cleaned = [];
7155
- for (const line of lines) {
7156
- const trimmed = line.trim();
7157
- if (cleaned.length === 0 && !trimmed) {
7158
- continue;
7159
- }
7160
- if (trimmed.startsWith("{") && trimmed.includes('"type"')) {
7161
- const result2 = parseStreamJsonLine(trimmed);
7162
- if (result2.action === "skip") {
7163
- continue;
7164
- }
7165
- if (result2.action === "use") {
7166
- cleaned.push(result2.content);
7167
- continue;
7168
- }
7169
- }
7170
- cleaned.push(line);
7171
- }
7172
- let result = cleaned.join("\n").trim();
7173
- const codexResult = extractCodexStructured(result);
7174
- if (codexResult) {
7175
- result = codexResult;
7176
- }
7177
- result = result.replace(/<tool\s+name="[^"]*">[\s\S]*?<\/tool>/g, "");
7178
- result = result.replace(/<tool\s+name="[^"]*">[\s\S]*?<\/invoke>(\s*<\/[a-zA-Z_:]+>)*/g, "");
7179
- result = result.replace(/<tool_result[\s\S]*?<\/tool_result>/g, "");
7180
- result = result.replace(/<\/minimax:tool_call>/g, "");
7181
- result = result.replace(/<parameter\s+name="[^"]*">[^<]*<\/parameter>/g, "");
7182
- result = result.replace(/<tool_calls>[\s\S]*?<\/tool_calls>/gi, "");
7183
- result = result.replace(/<(Read|Write|Edit|Bash|Grep|Glob|LS|ListPlans|Retrieve)\b[\s\S]*?<\/\1>/g, "");
7184
- result = result.replace(/<\/?(file_path|path|pattern|command|query|content|old_string|new_string|start_line|end_line|id)>\s*/g, "");
7185
- result = result.replace(/<think>[\s\S]*?<\/think>\s*/gi, "");
7186
- result = result.replace(/^(I'm checking|I'm looking|I'm reading|I'm searching|I'm inspecting|Let me check|Let me look|Let me read|Let me search|Let me inspect|I've confirmed|I've verified|I've checked|I'll now|I will now|Now I'm|Now let me|First,? I'll|First,? let me|Next,? I'll|Next,? let me)\b[^.\n]*[.\n]\s*/gim, "");
7187
- result = stripBuddyThinkingNoise(result);
7188
- result = deduplicateParagraphs(result);
7189
- result = addParagraphBreaks(result);
7190
- result = shortenFilePaths(result);
7191
- if (_cleanCache.size > 200) {
7192
- _cleanCache.clear();
7193
- }
7194
- _cleanCache.set(raw, result);
7195
- return result;
7196
- }
7197
-
7198
6868
  // src/generated/blocks/code-buffer.ts
7199
6869
  var CodeBlockBuffer = class {
7200
6870
  blocks = [];
@@ -7321,7 +6991,8 @@ function _showNextPermission(actions) {
7321
6991
  choices: [
7322
6992
  { key: "y", label: "Yes", color: "#4ade80" },
7323
6993
  { key: "n", label: "No", color: "#ef4444" },
7324
- { key: "a", label: "Always", color: "#60a5fa" }
6994
+ { key: "a", label: "Always", color: "#60a5fa" },
6995
+ { key: "__other", label: "No, tell Cesar what to do instead", color: "#9ca3af" }
7325
6996
  ],
7326
6997
  resolve: (answer) => {
7327
6998
  _permissionQueue.shift();
@@ -7506,14 +7177,17 @@ function handleOutputEvent(event, state, actions, mode, chatStartTime) {
7506
7177
  case "patch-review":
7507
7178
  actions.setReviewEvent({ winnerId: event.winnerId, patchPath: event.patchPath, patchContent: event.patchContent });
7508
7179
  return;
7509
- case "question":
7180
+ case "question": {
7510
7181
  if (_permissionQueue.length > 0) {
7511
7182
  const qResolve = event.resolve;
7512
7183
  if (qResolve) qResolve("");
7513
7184
  return;
7514
7185
  }
7515
- actions.setQuestionState({ prompt: event.prompt, resolve: event.resolve, choices: event.choices });
7186
+ const _qChoices = event.choices;
7187
+ const _withOther = Array.isArray(_qChoices) && _qChoices.length > 0 && !_qChoices.some((c) => c && c.key === "__other") ? [..._qChoices, { key: "__other", label: "Other", color: "#9ca3af" }] : _qChoices;
7188
+ actions.setQuestionState({ prompt: event.prompt, resolve: event.resolve, choices: _withOther, defaultChoiceKey: event.defaultChoiceKey });
7516
7189
  return;
7190
+ }
7517
7191
  case "permission-ask": {
7518
7192
  if (state.streamingText) {
7519
7193
  actions.flushStream();
@@ -8511,6 +8185,7 @@ function extractDelegation(toolName, args) {
8511
8185
  maxTurns: typeof argsRecord.maxTurns === "number" ? argsRecord.maxTurns : void 0,
8512
8186
  queue: typeof argsRecord.queue === "string" ? argsRecord.queue : void 0,
8513
8187
  gate: typeof argsRecord.gate === "string" ? argsRecord.gate : void 0,
8188
+ builder: typeof argsRecord.builder === "string" ? argsRecord.builder : void 0,
8514
8189
  push: argsRecord.push ?? void 0,
8515
8190
  pr: argsRecord.pr ?? void 0,
8516
8191
  maxHours: typeof argsRecord.maxHours === "number" ? argsRecord.maxHours : void 0,
@@ -8786,6 +8461,25 @@ function summarizeToolPayload(payload) {
8786
8461
  }
8787
8462
  return out;
8788
8463
  }
8464
+ function buildToolErrorDiagnostic(name, args, error) {
8465
+ let inputSnippet;
8466
+ try {
8467
+ const safe = summarizeToolPayload(args);
8468
+ if (safe === void 0) {
8469
+ inputSnippet = "(no input)";
8470
+ } else {
8471
+ const s = JSON.stringify(safe);
8472
+ inputSnippet = s.length > 800 ? s.slice(0, 800) + "\u2026 (truncated)" : s;
8473
+ }
8474
+ } catch {
8475
+ inputSnippet = "(input could not be inspected)";
8476
+ }
8477
+ const rawErr = typeof error === "string" ? error : String(error ?? "Tool execution failed");
8478
+ const errMsg = rawErr.length > 500 ? rawErr.slice(0, 500) + "\u2026 (truncated)" : rawErr;
8479
+ return `Tool ${name} failed.
8480
+ Input (redacted): ${inputSnippet}
8481
+ Error: ${errMsg}`;
8482
+ }
8789
8483
  function appendCesarJsonl(fileName, record, runsDir) {
8790
8484
  const dir = runsDir ?? RUNS_DIR;
8791
8485
  mkdirSync10(dir, { recursive: true });
@@ -8829,6 +8523,27 @@ function recordCesarToolTimeline(record, runsDir) {
8829
8523
  } catch {
8830
8524
  }
8831
8525
  }
8526
+ function recordCesarConfidence(record) {
8527
+ try {
8528
+ const sessionId = typeof record.sessionId === "string" && /^[A-Za-z0-9_-][A-Za-z0-9._-]{0,127}$/.test(record.sessionId) ? record.sessionId : "unknown-session";
8529
+ const value = Number.isFinite(record.value) && record.value >= 0 && record.value <= 100 ? record.value : null;
8530
+ if (value === null) return;
8531
+ let reasoning = typeof record.reasoning === "string" ? record.reasoning.replace(/\s+/g, " ").trim() : void 0;
8532
+ if (reasoning) {
8533
+ if (looksSensitiveString(reasoning)) reasoning = "[redacted]";
8534
+ else if (reasoning.length > 500) reasoning = reasoning.slice(0, 500) + "\u2026 (truncated)";
8535
+ }
8536
+ appendCesarJsonl(`${sessionId}.jsonl`, {
8537
+ kind: "confidence",
8538
+ sessionId,
8539
+ turnId: record.turnId,
8540
+ engineId: record.engineId,
8541
+ value,
8542
+ reasoning
8543
+ }, agonPath("calibration"));
8544
+ } catch {
8545
+ }
8546
+ }
8832
8547
  function readJsonlRecords(filePath) {
8833
8548
  if (!existsSync11(filePath)) {
8834
8549
  return [];
@@ -9064,6 +8779,7 @@ RULE 6 \u2014 AFTER DELEGATION: After calling Forge/Brainstorm/Tribunal/Campfire
9064
8779
  RULE 7 \u2014 NO NARRATION: NEVER narrate your research process. Do not write "Reading the file...", "I'm checking...", "Let me look at...", "I've confirmed...". The user sees your text output \u2014 if you narrate exploration it looks like you have no clue. Instead: call tools SILENTLY, then speak ONLY when you have the answer or decision. Your visible output should be conclusions, answers, and actions \u2014 never a play-by-play of your investigation. If you need to read files or search code, call Read/Grep/Glob directly without announcing it.
9065
8780
 
9066
8781
  RULE 8 \u2014 AUTONOMOUS PLANS: Plan mode is optional, not the default. Stay live unless staged execution is genuinely useful. Switch to planning when the task needs multiple dependent steps, expensive orchestration, resumability, explicit approval, or cost visibility. When you call ProposePlan, decide whether to set autoApprove=true. Set it ONLY when (a) the user clearly described a multi-stage workflow ("plan it, build it, review it"; "investigate then forge it"; "do the whole thing autonomously") AND (b) you have HIGH confidence in the steps after investigation (not before). The runtime applies a layered policy and may still ask the user \u2014 your autoApprove=true is permission, not a guarantee. Default to autoApprove=false (or omit it) whenever you are uncertain or when the plan touches mutating steps and the user did not explicitly invite autonomous execution. selfReview defaults to true for mutating plans \u2014 only set selfReview=false for purely advisory plans (brainstorm/tribunal/research only) where a code-review gate would have nothing to review.
8782
+ RULE 8b \u2014 AUTONOMOUS BUILD TOOLS (Goal / Conquer): These run a build to completion in the BACKGROUND. Goal(intent, queue?, gate?) drives a finite, machine-verifiable task QUEUE (forge \u2192 witness \u2192 review \u2192 commit per task on a goal/* branch). Conquer(task, gate, builder?, engines?) is for an OPEN-ENDED build you'd otherwise babysit: it drives an external builder CLI as the user (builder defaults to codex \u2014 pass builder:"codex" / "claude" / "agy") unattended until the gate passes, convening nero/tribunal/council on forks, then STOPS at a human merge gate (NEVER auto-merges). Fire EITHER ONLY when the user explicitly asks to build it unattended ("conquer this with codex", "build it autonomously") \u2014 NEVER on a vague request; both are long, real-spend, multi-hour runs. Conquer REQUIRES a discriminating gate (the done-spec, e.g. gate:"pnpm test"); if the user did not give one, ASK for the command that proves the build is done before calling. After calling either, STOP and wait \u2014 the background job and the merge gate handle the rest.
9067
8783
 
9068
8784
  RULE 10 \u2014 TURN CLOSURE: End every turn with one clear closing line so the user can tell AT A GLANCE which of three states you are in: done, waiting on them for a decision/info, or handed off. This is non-negotiable: NEVER end a turn with only a recap, a silent stop, or a trailing thought \u2014 that leaves the user wondering "is it my turn? do I have to do something?", which must never happen. Four valid shapes \u2014 pick exactly one:
9069
8785
  a) DONE \u2014 past-tense, concrete, names the file/result. Example: "Fixed: brain.kern lines 787-799, drain timers added before early return, typecheck green." No trailing menu, no "standing by".
@@ -9096,8 +8812,16 @@ function buildCesarSystemPrompt(ctx) {
9096
8812
  const systemParts = [CESAR_SYSTEM_PROMPT];
9097
8813
  if (projectCtx) systemParts.push(`## PROJECT CONTEXT
9098
8814
  ${projectCtx}`);
8815
+ try {
8816
+ const codebaseBrief = buildCodebaseMap(cesarCwd);
8817
+ if (codebaseBrief) systemParts.push(codebaseBrief);
8818
+ } catch (err) {
8819
+ console.warn(`[agon] codebase atlas skipped: ${err instanceof Error ? err.message : String(err)}`);
8820
+ }
9099
8821
  systemParts.push(`## AVAILABLE ENGINES
9100
- ${engineList}`);
8822
+ ${engineList}
8823
+
8824
+ MODES vs ENGINES: the names above are ENGINES \u2014 runnable backends you delegate to (codex, claude, agy, \u2026). MODES are commands/workflows you invoke (run /<name>): ${AGON_MODE_NAMES.join(", ")}. A mode runs ON engines \u2014 never treat a mode name (e.g. "conquer") as an engine id.`);
9101
8825
  if (ctx.explorationMode) {
9102
8826
  systemParts.push(`## OPERATING MODE
9103
8827
  Exploration mode is ON. Stay read-only: inspect files, search, and use read-only shell commands only. Do not call Edit or Write. Do not run non-read-only Bash commands.`);
@@ -9235,6 +8959,7 @@ ${context}`);
9235
8959
  }
9236
8960
  var CESAR_SNAPSHOT_MSG_CHAR_CAP = 4e3;
9237
8961
  var CONFIDENCE_BLOCK_LIMIT = 2;
8962
+ var SEARCH_NUDGE_THRESHOLD = 40;
9238
8963
  function capSnapshotMessageContent(content) {
9239
8964
  if (content.length <= CESAR_SNAPSHOT_MSG_CHAR_CAP) return content;
9240
8965
  return `${content.slice(0, CESAR_SNAPSHOT_MSG_CHAR_CAP)}
@@ -9279,6 +9004,7 @@ function buildOnToolCall(ctx, toolRegistry, config) {
9279
9004
  const toolResultCache = /* @__PURE__ */ new Map();
9280
9005
  const nativeToolErrorRetries = /* @__PURE__ */ new Map();
9281
9006
  const CACHEABLE_TOOLS = /* @__PURE__ */ new Set(["Grep", "Glob"]);
9007
+ const SEARCH_NUDGE_TOOLS = /* @__PURE__ */ new Set(["Read", "Grep", "Glob"]);
9282
9008
  const explorationMode = ctx.explorationMode ?? false;
9283
9009
  const sharedToolCtx = {
9284
9010
  cwd,
@@ -9361,7 +9087,7 @@ ${cleaned}`;
9361
9087
  }
9362
9088
  }
9363
9089
  if (name === "ExitPlanMode") {
9364
- const { handleExitPlanMode } = await import("./plan-mode-DCE7VGQV.js");
9090
+ const { handleExitPlanMode } = await import("./plan-mode-4XRC2ZC7.js");
9365
9091
  return "[DELEGATION_BREAK] " + handleExitPlanMode(String(args.reason ?? ""), ctx.cesar?.planDispatch ?? null, ctx);
9366
9092
  }
9367
9093
  if (name === "ProposePlan") {
@@ -9384,7 +9110,7 @@ ${cleaned}`;
9384
9110
  }
9385
9111
  }
9386
9112
  }
9387
- const { handleProposePlan } = await import("./plan-mode-DCE7VGQV.js");
9113
+ const { handleProposePlan } = await import("./plan-mode-4XRC2ZC7.js");
9388
9114
  const dispatch = ctx.cesar.planDispatch;
9389
9115
  if (!dispatch) {
9390
9116
  return "[PLAN_ERROR] Internal plan display dispatch unavailable. Retry the plan request so Agon can render the approval panel.";
@@ -9412,6 +9138,13 @@ ${cleaned}`;
9412
9138
  ctx.cesar.reportedConfidenceReasoning = reasoning || void 0;
9413
9139
  ctx.cesar.confidenceSatisfied = true;
9414
9140
  ctx.cesar.confidenceBlockCount = 0;
9141
+ recordCesarConfidence({
9142
+ sessionId: String(ctx.chatSession?.id ?? "unknown-session"),
9143
+ turnId: ctx.cesar.turnId,
9144
+ engineId: ctx.cesarSession?.engineId ?? config?.cesarEngine,
9145
+ value,
9146
+ reasoning: reasoning || void 0
9147
+ });
9415
9148
  const blocked = ctx.cesar.blockedOnConfidence;
9416
9149
  ctx.cesar.blockedOnConfidence = null;
9417
9150
  if (blocked) {
@@ -9420,13 +9153,14 @@ ${cleaned}`;
9420
9153
  return value >= 93 ? `Confidence ${value}% recorded. High confidence. Proceed.` : `Confidence ${value}% recorded. Proceed.`;
9421
9154
  }
9422
9155
  }
9423
- const READ_TOOLS = /* @__PURE__ */ new Set(["Read", "Grep", "Glob", "ReportConfidence", "Delegate"]);
9424
- if (!ctx.cesar.confidenceSatisfied && !READ_TOOLS.has(name)) {
9156
+ const CONFIDENCE_INVESTIGATION_TOOLS = /* @__PURE__ */ new Set(["Read", "Grep", "Glob", "ReportConfidence", "Delegate"]);
9157
+ const _isInvestigation = CONFIDENCE_INVESTIGATION_TOOLS.has(name) || name === "Bash" && isReadOnlyCommand(String(args.command ?? ""));
9158
+ if (!ctx.cesar.confidenceSatisfied && !_isInvestigation) {
9425
9159
  const blocks = (ctx.cesar.confidenceBlockCount ?? 0) + 1;
9426
9160
  ctx.cesar.confidenceBlockCount = blocks;
9427
9161
  if (blocks <= CONFIDENCE_BLOCK_LIMIT) {
9428
9162
  ctx.cesar.blockedOnConfidence = { name, args };
9429
- return `[BLOCKED] Report confidence first. Call ReportConfidence(value) before using ${name}. After ReportConfidence succeeds, retry the SAME ${name} call immediately with the same arguments. Read/Grep/Glob are allowed for investigation.`;
9163
+ return `[BLOCKED] Report confidence first. Call ReportConfidence(value) before using ${name}. After ReportConfidence succeeds, retry the SAME ${name} call immediately with the same arguments. Read/Grep/Glob and read-only Bash are allowed for investigation.`;
9430
9164
  }
9431
9165
  ctx.cesar.confidenceSatisfied = true;
9432
9166
  ctx.cesar.blockedOnConfidence = null;
@@ -9452,14 +9186,15 @@ ${cleaned}`;
9452
9186
  );
9453
9187
  let output = result.result.ok ? result.result.content : result.result.error ?? "Tool execution failed";
9454
9188
  if (!result.result.ok) {
9189
+ const diag = buildToolErrorDiagnostic(name, args, result.result.error);
9455
9190
  const retryKey = `${name}:${JSON.stringify(args)}`;
9456
9191
  const used = nativeToolErrorRetries.get(retryKey) ?? 0;
9457
9192
  if (used <= 0) {
9458
9193
  nativeToolErrorRetries.set(retryKey, 1);
9459
- output = `[RETRYABLE_TOOL_ERROR] ${output}
9460
- Retry this ${name} call once with corrected input. Do not narrate before retrying.`;
9194
+ output = `[RETRYABLE_TOOL_ERROR] ${diag}
9195
+ Retry this ${name} call ONCE with corrected input that matches the tool's schema. Do not narrate before retrying.`;
9461
9196
  } else {
9462
- output = `[TOOL_ERROR_FINAL] ${output}
9197
+ output = `[TOOL_ERROR_FINAL] ${diag}
9463
9198
  Repair retry already used for this exact ${name} input in this turn. Stop retrying this call and explain the blocker.`;
9464
9199
  }
9465
9200
  } else {
@@ -9471,6 +9206,16 @@ Repair retry already used for this exact ${name} input in this turn. Stop retryi
9471
9206
  toolResultCache.clear();
9472
9207
  ctx.cesar.blockedOnConfidence = null;
9473
9208
  }
9209
+ if (result.result.ok && SEARCH_NUDGE_TOOLS.has(name)) {
9210
+ const searches = (ctx.cesar.searchToolCount ?? 0) + 1;
9211
+ ctx.cesar.searchToolCount = searches;
9212
+ if (searches >= SEARCH_NUDGE_THRESHOLD && !ctx.cesar.searchNudged) {
9213
+ ctx.cesar.searchNudged = true;
9214
+ output = `${output ?? ""}
9215
+
9216
+ [NOTE] ${searches} read/search calls this turn. A CODEBASE BRIEF mapping where things live (files + top symbols per package) is in your system prompt \u2014 consult it to locate code instead of searching more. If something isn't listed, narrow the query rather than broadening it.`;
9217
+ }
9218
+ }
9474
9219
  return output;
9475
9220
  };
9476
9221
  }
@@ -9945,7 +9690,7 @@ async function commitTurnAndDelegate(pendingDel, input, response, cesarEngineId,
9945
9690
  const reasoning = delResult.userContext ? `${pendingDel.reasoning ?? ""}
9946
9691
 
9947
9692
  User context: ${delResult.userContext}` : pendingDel.reasoning;
9948
- return { mode, delegated: true, responded: true, action, task: pendingDel.task, reasoning, decisionReason: "tool-delegation", scope: pendingDel.scope, fitnessCmd: pendingDel.fitnessCmd, hardened: delResult.hardened ?? pendingDel.hardened, tribunalMode: delResult.tribunalMode ?? pendingDel.tribunalMode, team: delResult.team ?? pendingDel.team, target: pendingDel.target, engineId: pendingDel.engineId, engines: pendingDel.engines, taskKind: pendingDel.taskKind, maxTurns: pendingDel.maxTurns, queue: pendingDel.queue, gate: pendingDel.gate, push: pendingDel.push, pr: pendingDel.pr, maxHours: pendingDel.maxHours, budget: pendingDel.budget, ...telemetry ?? {} };
9693
+ return { mode, delegated: true, responded: true, action, task: pendingDel.task, reasoning, decisionReason: "tool-delegation", scope: pendingDel.scope, fitnessCmd: pendingDel.fitnessCmd, hardened: delResult.hardened ?? pendingDel.hardened, tribunalMode: delResult.tribunalMode ?? pendingDel.tribunalMode, team: delResult.team ?? pendingDel.team, target: pendingDel.target, engineId: pendingDel.engineId, engines: pendingDel.engines, taskKind: pendingDel.taskKind, maxTurns: pendingDel.maxTurns, queue: pendingDel.queue, gate: pendingDel.gate, builder: pendingDel.builder, push: pendingDel.push, pr: pendingDel.pr, maxHours: pendingDel.maxHours, budget: pendingDel.budget, ...telemetry ?? {} };
9949
9694
  }
9950
9695
  return { delegated: false, responded: true, decisionReason: "delegation-cancelled", ...telemetry ?? {} };
9951
9696
  }
@@ -9977,11 +9722,23 @@ User context: ${delResult.userContext}` : suggestion.rest;
9977
9722
  }
9978
9723
  return { delegated: false, responded: true, decisionReason: "suggestion-cancelled", ...telemetry ?? {} };
9979
9724
  }
9725
+ var _noBriefNudged = /* @__PURE__ */ new Set();
9980
9726
  async function handleCesarBrain(input, dispatch, ctx, images) {
9981
9727
  const abort = new AbortController();
9982
9728
  const _turnStart = Date.now();
9983
9729
  const _turnId = createCesarTurnId();
9984
9730
  const _turnCwd = resolveWorkingDir();
9731
+ try {
9732
+ const _sid = String(ctx.chatSession?.id ?? "");
9733
+ if (_sid && !_noBriefNudged.has(_sid)) {
9734
+ if (_noBriefNudged.size > 5e3) _noBriefNudged.clear();
9735
+ _noBriefNudged.add(_sid);
9736
+ if (!hasProjectBrief(_turnCwd)) {
9737
+ dispatch({ type: "warning", message: "No project brief found in this repo. Create AGON.md or .agon/project.md so Cesar has project context from turn 1." });
9738
+ }
9739
+ }
9740
+ } catch {
9741
+ }
9985
9742
  const _toolsUsed = [];
9986
9743
  const _toolUseKeys = /* @__PURE__ */ new Set();
9987
9744
  let _toolEventCount = 0;
@@ -10089,6 +9846,7 @@ async function handleCesarBrain(input, dispatch, ctx, images) {
10089
9846
  console.warn("[cesar:brain] force-clearing stuck busy flag");
10090
9847
  ctx.cesar.busy = false;
10091
9848
  ctx.cesar.queue = null;
9849
+ ctx.cesar.abortSignal = null;
10092
9850
  } else {
10093
9851
  if (_isFollowUp) {
10094
9852
  const elapsed = Math.round((Date.now() - busySince) / 1e3);
@@ -10102,7 +9860,8 @@ async function handleCesarBrain(input, dispatch, ctx, images) {
10102
9860
  } else {
10103
9861
  ctx.cesar.queue = { input, dispatch, images };
10104
9862
  }
10105
- dispatch({ type: "info", message: "Queued \u2014 will send when Cesar finishes." });
9863
+ const _interrupting = ctx.cesar.abortSignal?.aborted === true;
9864
+ dispatch({ type: "info", message: _interrupting ? "Interrupting \u2014 your message is up next\u2026" : "Queued \u2014 will send when Cesar finishes." });
10106
9865
  return { delegated: false, responded: true };
10107
9866
  }
10108
9867
  }
@@ -10114,6 +9873,8 @@ async function handleCesarBrain(input, dispatch, ctx, images) {
10114
9873
  ctx.cesar.confidenceSatisfied = false;
10115
9874
  ctx.cesar.blockedOnConfidence = null;
10116
9875
  ctx.cesar.confidenceBlockCount = 0;
9876
+ ctx.cesar.searchToolCount = 0;
9877
+ ctx.cesar.searchNudged = false;
10117
9878
  ctx.cesar.turnId = _turnId;
10118
9879
  ctx.cesar.planDispatch = dispatch;
10119
9880
  const _brainStartMs = Date.now();
@@ -10146,6 +9907,7 @@ async function handleCesarBrain(input, dispatch, ctx, images) {
10146
9907
  }
10147
9908
  const color = ENGINE_COLORS[cesarEngineId] ?? 124;
10148
9909
  ctx.setActiveAbort(abort);
9910
+ ctx.cesar.abortSignal = abort.signal;
10149
9911
  ctx.cesar.lastDispatch = dispatch;
10150
9912
  dispatch({ type: "confidence-update", value: null });
10151
9913
  dispatch({ type: "spinner-start", message: "Cesar thinking\u2026", color });
@@ -10272,7 +10034,7 @@ async function handleCesarBrain(input, dispatch, ctx, images) {
10272
10034
  const fastPathMode = simpleEditFastPath ? "edit" : answerFastPath ? "answer" : "";
10273
10035
  const fastPathBaseBudget = simpleEditFastPath ? 5 : 3;
10274
10036
  const fastPathMaxBudget = simpleEditFastPath ? 8 : 4;
10275
- const FAST_PATH_BLOCKED_TOOLS = ["Forge", "Brainstorm", "Tribunal", "Campfire", "Pipeline", "Review", "Agent", "Goal", "Delegate", "ProposePlan", "QuickNero"];
10037
+ const FAST_PATH_BLOCKED_TOOLS = ["Forge", "Brainstorm", "Tribunal", "Campfire", "Pipeline", "Review", "Agent", "Goal", "Conquer", "Delegate", "ProposePlan", "QuickNero"];
10276
10038
  if (cesarFastPath && !restoreFastPathMode) {
10277
10039
  const hadPreviousFastPathMode = Object.prototype.hasOwnProperty.call(ctx.cesar, "fastPathMode");
10278
10040
  const previousFastPathMode = ctx.cesar.fastPathMode;
@@ -10521,7 +10283,7 @@ ${enrichedInput}`;
10521
10283
  const toolInput = typeof meta.input === "string" ? meta.input : meta.input ? JSON.stringify(meta.input) : "";
10522
10284
  const toolName = chunk.content || "tool";
10523
10285
  const toolStatus = meta.status ?? "running";
10524
- const STREAM_ORCH = /* @__PURE__ */ new Set(["Forge", "Brainstorm", "Tribunal", "Campfire", "Pipeline", "Review", "Agent", "Goal"]);
10286
+ const STREAM_ORCH = /* @__PURE__ */ new Set(["Forge", "Brainstorm", "Tribunal", "Campfire", "Pipeline", "Review", "Agent", "Goal", "Conquer"]);
10525
10287
  hadToolActivity = true;
10526
10288
  recordToolUse(toolName, ctx.cesar.hasNativeTools ? "native" : "eager", toolInput, toolStatus);
10527
10289
  dispatch({ type: "spinner-update", message: `Cesar: ${toolName}\u2026` });
@@ -10844,6 +10606,13 @@ ${enrichedInput}`;
10844
10606
  ctx.cesar.reportedConfidence = value;
10845
10607
  ctx.cesar.reportedConfidenceReasoning = reasoning || void 0;
10846
10608
  ctx.cesar.confidenceSatisfied = true;
10609
+ recordCesarConfidence({
10610
+ sessionId: String(ctx.chatSession?.id ?? "unknown-session"),
10611
+ turnId: ctx.cesar.turnId ?? _turnId,
10612
+ engineId: cesarEngineId,
10613
+ value,
10614
+ reasoning: reasoning || void 0
10615
+ });
10847
10616
  parsedConfidence = value;
10848
10617
  dispatch({ type: "info", message: confidenceBadge(value) + ` Cesar (via MCP)` });
10849
10618
  dispatch({ type: "confidence-update", value });
@@ -10866,7 +10635,7 @@ ${enrichedInput}`;
10866
10635
  });
10867
10636
  continue;
10868
10637
  }
10869
- const { handleProposePlan } = await import("./plan-mode-DCE7VGQV.js");
10638
+ const { handleProposePlan } = await import("./plan-mode-4XRC2ZC7.js");
10870
10639
  const planDispatch = ctx.cesar.planDispatch ?? dispatch;
10871
10640
  if (planDispatch) {
10872
10641
  try {
@@ -10879,7 +10648,7 @@ ${enrichedInput}`;
10879
10648
  }
10880
10649
  } else if (signal.tool === "ExitPlanMode") {
10881
10650
  recordToolUse("ExitPlanMode", "mcp", JSON.stringify(signal.args ?? {}), "done");
10882
- const { handleExitPlanMode } = await import("./plan-mode-DCE7VGQV.js");
10651
+ const { handleExitPlanMode } = await import("./plan-mode-4XRC2ZC7.js");
10883
10652
  const planDispatch = ctx.cesar.planDispatch ?? dispatch;
10884
10653
  try {
10885
10654
  const exitResult = handleExitPlanMode(String(signal.args?.reason ?? ""), planDispatch, ctx);
@@ -11022,7 +10791,7 @@ ${enrichedInput}`;
11022
10791
  _lastToolInputs[name] = JSON.stringify(inp);
11023
10792
  recordToolUse(name, "xml", _lastToolInputs[name], "running");
11024
10793
  emitXmlToolEvent(name, inp, "running");
11025
- const LOOP_ORCH = /* @__PURE__ */ new Set(["Forge", "Brainstorm", "Tribunal", "Campfire", "Pipeline", "Review", "Agent", "Goal"]);
10794
+ const LOOP_ORCH = /* @__PURE__ */ new Set(["Forge", "Brainstorm", "Tribunal", "Campfire", "Pipeline", "Review", "Agent", "Goal", "Conquer"]);
11026
10795
  if (LOOP_ORCH.has(name)) {
11027
10796
  if (cesarFastPath) {
11028
10797
  return;
@@ -11095,7 +10864,7 @@ ${enrichedInput}`;
11095
10864
  output: "A Cesar plan is already active; nested plans are blocked. Resume or cancel the current plan before proposing another."
11096
10865
  });
11097
10866
  } else {
11098
- const { handleProposePlan } = await import("./plan-mode-DCE7VGQV.js");
10867
+ const { handleProposePlan } = await import("./plan-mode-4XRC2ZC7.js");
11099
10868
  const planDispatch = ctx.cesar.planDispatch ?? dispatch;
11100
10869
  const plan = await handleProposePlan(ppArgs, planDispatch, ctx);
11101
10870
  if (ctx.setActivePlan) ctx.setActivePlan(plan);
@@ -11119,7 +10888,7 @@ ${enrichedInput}`;
11119
10888
  const epArgs = ctx.cesar._exitPlanModeArgs;
11120
10889
  delete ctx.cesar._exitPlanModeArgs;
11121
10890
  try {
11122
- const { handleExitPlanMode } = await import("./plan-mode-DCE7VGQV.js");
10891
+ const { handleExitPlanMode } = await import("./plan-mode-4XRC2ZC7.js");
11123
10892
  const planDispatch = ctx.cesar.planDispatch ?? dispatch;
11124
10893
  const exitResult = handleExitPlanMode(String(epArgs?.reason ?? ""), planDispatch, ctx);
11125
10894
  dispatch({ type: "tool-call", engineId: cesarEngineId, tool: "ExitPlanMode", input: JSON.stringify(epArgs ?? {}), status: "done", output: exitResult });
@@ -11397,7 +11166,7 @@ ${cleanFinalAnswer}` : cleanFinalAnswer;
11397
11166
  }
11398
11167
  }
11399
11168
  const _AUTO_CONT_WRITE_TOOLS = /* @__PURE__ */ new Set(["Edit", "Write", "MultiEdit", "NotebookEdit"]);
11400
- const _AUTO_CONT_LOOP_ORCH = /* @__PURE__ */ new Set(["Forge", "Brainstorm", "Tribunal", "Campfire", "Pipeline", "Review", "Agent", "Goal"]);
11169
+ const _AUTO_CONT_LOOP_ORCH = /* @__PURE__ */ new Set(["Forge", "Brainstorm", "Tribunal", "Campfire", "Pipeline", "Review", "Agent", "Goal", "Conquer"]);
11401
11170
  const _AUTO_CONT_CONTINUE_RE = /\b(?:now i'?ll|next i'?ll|still need|let me also|i'?ll also|then i'?ll|next step|next up)\b/i;
11402
11171
  const _AUTO_CONT_READONLY_DONE_RE = /\b(?:tests? passed|all (?:tests|checks) pass|no matches found|no issues found|no errors|all clean|nothing to (?:do|fix|change)|already (?:correct|fixed|in place|done))\b/i;
11403
11172
  const _detectTurnState = (resp, baselineToolCount) => {
@@ -11461,7 +11230,7 @@ ${cleanFinalAnswer}` : cleanFinalAnswer;
11461
11230
  },
11462
11231
  maxTurns: cesarFastPath ? fastPathMaxBudget : void 0
11463
11232
  });
11464
- const _shouldAutoContinue = (hadToolActivity || ranToolLoop) && !inPlanMode && !ctx.cesar.pendingDelegation && session.alive && !abort.signal.aborted && !_engineErrored && response.trim().length > 0;
11233
+ const _shouldAutoContinue = (hadToolActivity || ranToolLoop) && !inPlanMode && !answerFastPath && !ctx.cesar.pendingDelegation && session.alive && !abort.signal.aborted && !_engineErrored && response.trim().length > 0;
11465
11234
  if (_shouldAutoContinue) {
11466
11235
  const MAX_CONTINUATIONS = 5;
11467
11236
  let _continuations = 0;
@@ -11706,24 +11475,17 @@ ${cleanFinalAnswer}` : cleanFinalAnswer;
11706
11475
  const full = m[3].trim();
11707
11476
  _forkOptions.push({ key, label: full.length > 60 ? full.slice(0, 59) + "\u2026" : full, full });
11708
11477
  }
11709
- const isForkQuestion = /\?\s*$/.test(lastLine) && _forkOptions.length >= 2 && _forkOptions.length <= 6;
11710
- const asksConfirmation = !ranToolLoop && /\?\s*$/.test(lastLine) && /\b(want|shall|should|ready|proceed|go ahead|dispatch|confirm|continue|implement)\b/i.test(lastLine);
11478
+ const _isChatTurn = routingHints.intakeKind === "chat" || routingHints.recommendedFlow === "answer";
11479
+ const isForkQuestion = !_isChatTurn && /\?\s*$/.test(lastLine) && _forkOptions.length >= 2 && _forkOptions.length <= 6;
11480
+ const asksConfirmation = !_isChatTurn && !ranToolLoop && /\?\s*$/.test(lastLine) && /\b(want|shall|should|ready|proceed|go ahead|dispatch|confirm|continue|implement)\b/i.test(lastLine);
11711
11481
  if (isForkQuestion) {
11712
11482
  const _forkColors = ["#4ade80", "#22d3ee", "#fbbf24", "#a78bfa", "#f97316", "#ef4444"];
11713
- const _allNumeric = _forkOptions.every((o) => /^[0-9]$/.test(o.key));
11714
- let _ownKey = _allNumeric ? String(_forkOptions.length + 1) : String.fromCharCode(97 + _forkOptions.length);
11715
- if (_seenForkKeys.has(_ownKey)) _ownKey = "o";
11716
- const _choices = [
11717
- ..._forkOptions.map((o, i) => ({ key: o.key, label: o.label, color: _forkColors[i % _forkColors.length] })),
11718
- { key: _ownKey, label: "\u270E my own idea (type it)", color: "#9ca3af" }
11719
- ];
11483
+ const _choices = _forkOptions.map((o, i) => ({ key: o.key, label: o.label, color: _forkColors[i % _forkColors.length] }));
11720
11484
  const picked = String(await new Promise((resolve4) => {
11721
- dispatch({ type: "question", prompt: `${cesarEngineId} \u2014 pick one, or ${_ownKey.toUpperCase()} to type your own (Esc to decide later):`, choices: _choices, resolve: resolve4 });
11485
+ dispatch({ type: "question", prompt: `${cesarEngineId} \u2014 pick one (Esc to decide later):`, choices: _choices, resolve: resolve4 });
11722
11486
  })).toLowerCase();
11723
11487
  const chosen = _forkOptions.find((o) => o.key === picked);
11724
- if (picked === _ownKey) {
11725
- dispatch({ type: "info", message: "Type your idea below and press Enter \u2014 Cesar has the options in context." });
11726
- } else if (chosen && session.alive && !abort.signal.aborted) {
11488
+ if (chosen && session.alive && !abort.signal.aborted) {
11727
11489
  dispatch({ type: "spinner-start", message: `${cesarEngineId} continuing\u2026`, color });
11728
11490
  let followUp = "";
11729
11491
  const gen = session.send({ message: `Go with option ${chosen.key.toUpperCase()}: ${chosen.full}. Proceed and finish it.`, signal: abort.signal });
@@ -11739,13 +11501,10 @@ ${cleanFinalAnswer}` : cleanFinalAnswer;
11739
11501
  const answer = await new Promise((resolve4) => {
11740
11502
  dispatch({ type: "question", prompt: `${cesarEngineId}: ${lastLine.length > 80 ? lastLine.slice(0, 80) + "\u2026" : lastLine}`, choices: [
11741
11503
  { key: "y", label: "Yes", color: "#4ade80" },
11742
- { key: "n", label: "No", color: "#ef4444" },
11743
- { key: "3", label: "\u270E tell Cesar what to do (type it)", color: "#9ca3af" }
11504
+ { key: "n", label: "No", color: "#ef4444" }
11744
11505
  ], resolve: resolve4 });
11745
11506
  });
11746
- if (answer === "3") {
11747
- dispatch({ type: "info", message: "Type your instruction below and press Enter \u2014 Cesar has the question in context." });
11748
- } else if (answer === "y" && session.alive && !abort.signal.aborted) {
11507
+ if (answer === "y" && session.alive && !abort.signal.aborted) {
11749
11508
  dispatch({ type: "spinner-start", message: `${cesarEngineId} continuing\u2026`, color });
11750
11509
  let followUp = "";
11751
11510
  const gen = session.send({ message: "yes", signal: abort.signal });
@@ -11796,20 +11555,25 @@ ${cleanFinalAnswer}` : cleanFinalAnswer;
11796
11555
  }
11797
11556
  });
11798
11557
  }
11799
- ctx.cesar.busy = false;
11800
- ctx.cesar.busySince = null;
11801
- if (ctx.cesar.turnId === _turnId) ctx.cesar.turnId = void 0;
11558
+ const _ownsTurn = ctx.cesar.turnId === _turnId;
11559
+ const _wasInterrupted = _ownsTurn && ctx.cesar.abortSignal?.aborted === true;
11802
11560
  dispatch({ type: "spinner-stop" });
11803
- ctx.setActiveAbort(null);
11804
- const queued = ctx.cesar.queue;
11805
- if (queued) {
11806
- ctx.cesar.queue = null;
11807
- setTimeout(() => {
11808
- handleCesarBrain(queued.input, queued.dispatch, ctx, queued.images).catch((err) => {
11809
- console.error(`[cesar:queue] drain failed: ${err.message ?? err}`);
11810
- ctx.cesar.busy = false;
11811
- });
11812
- }, 100);
11561
+ if (_ownsTurn) {
11562
+ ctx.cesar.busy = false;
11563
+ ctx.cesar.busySince = null;
11564
+ ctx.cesar.abortSignal = null;
11565
+ ctx.cesar.turnId = void 0;
11566
+ ctx.setActiveAbort(null);
11567
+ const queued = ctx.cesar.queue;
11568
+ if (queued) {
11569
+ ctx.cesar.queue = null;
11570
+ setTimeout(() => {
11571
+ handleCesarBrain(queued.input, queued.dispatch, ctx, queued.images).catch((err) => {
11572
+ console.error(`[cesar:queue] drain failed: ${err.message ?? err}`);
11573
+ ctx.cesar.busy = false;
11574
+ });
11575
+ }, _wasInterrupted ? 0 : 100);
11576
+ }
11813
11577
  }
11814
11578
  }
11815
11579
  }
@@ -11842,23 +11606,6 @@ export {
11842
11606
  runGoalController,
11843
11607
  runSupervisor,
11844
11608
  runConquer,
11845
- icons,
11846
- ENGINE_COLORS,
11847
- bold,
11848
- dim,
11849
- green,
11850
- red,
11851
- yellow,
11852
- cyan,
11853
- header,
11854
- success,
11855
- fail,
11856
- warn,
11857
- info,
11858
- table,
11859
- shortToolPath,
11860
- isCesarTelemetryLine,
11861
- formatConfidenceToolLabel,
11862
11609
  filterDefaultOrchestrationEngines,
11863
11610
  readCesarToolReliability,
11864
11611
  summarizeAllCesarToolReliability,
@@ -11868,9 +11615,6 @@ export {
11868
11615
  deriveRoutingHints,
11869
11616
  buildRoutingContext,
11870
11617
  shouldUseAgentTeam,
11871
- parseMarkdownBlocks,
11872
- truncateCodeLine,
11873
- cleanEngineOutput,
11874
11618
  codeBlockBuffer,
11875
11619
  todosFromPlanSteps,
11876
11620
  getSessionAllowList,
@@ -11888,4 +11632,4 @@ export {
11888
11632
  ensureCesarSession,
11889
11633
  handleCesarBrain
11890
11634
  };
11891
- //# sourceMappingURL=chunk-IA4AR2R4.js.map
11635
+ //# sourceMappingURL=chunk-FCCH7IPJ.js.map