@kernlang/agon 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/{chunk-FCCH7IPJ.js → chunk-3PDYVGRS.js} +107 -24
  2. package/dist/chunk-3PDYVGRS.js.map +1 -0
  3. package/dist/{chunk-ATUT2BUQ.js → chunk-6IF2AV4Y.js} +28 -10
  4. package/dist/chunk-6IF2AV4Y.js.map +1 -0
  5. package/dist/{chunk-4LVYSUMN.js → chunk-7WZ2O5WZ.js} +6 -27
  6. package/dist/chunk-7WZ2O5WZ.js.map +1 -0
  7. package/dist/{chunk-6ANHPXGZ.js → chunk-HSPQEDHX.js} +1 -1
  8. package/dist/{chunk-6ANHPXGZ.js.map → chunk-HSPQEDHX.js.map} +1 -1
  9. package/dist/{chunk-WE32YJKT.js → chunk-NBV37VMW.js} +2 -2
  10. package/dist/{chunk-WE32YJKT.js.map → chunk-NBV37VMW.js.map} +1 -1
  11. package/dist/{chunk-O6YP55RV.js → chunk-PUNBDLQO.js} +141 -96
  12. package/dist/chunk-PUNBDLQO.js.map +1 -0
  13. package/dist/{chunk-C22VTCS6.js → chunk-TMNHJOKU.js} +1193 -226
  14. package/dist/chunk-TMNHJOKU.js.map +1 -0
  15. package/dist/{chunk-5QMVQPHY.js → chunk-XWHC6VAH.js} +3 -2
  16. package/dist/chunk-XWHC6VAH.js.map +1 -0
  17. package/dist/{dispatch-6LQSMMGI.js → dispatch-S3CR5HKX.js} +2 -2
  18. package/dist/engines/codex.json +3 -0
  19. package/dist/{forge-ES4RN7YM.js → forge-GUOEJ5DJ.js} +6 -6
  20. package/dist/index.js +561 -128
  21. package/dist/index.js.map +1 -1
  22. package/dist/plan-mode-35BONR7S.js +17 -0
  23. package/dist/{src-WJGIOESS.js → src-3NWTITZM.js} +55 -3
  24. package/dist/{update-HHN4PJQI.js → update-H3LE4ZSI.js} +6 -6
  25. package/package.json +5 -4
  26. package/dist/chunk-4LVYSUMN.js.map +0 -1
  27. package/dist/chunk-5QMVQPHY.js.map +0 -1
  28. package/dist/chunk-ATUT2BUQ.js.map +0 -1
  29. package/dist/chunk-C22VTCS6.js.map +0 -1
  30. package/dist/chunk-FCCH7IPJ.js.map +0 -1
  31. package/dist/chunk-O6YP55RV.js.map +0 -1
  32. package/dist/plan-mode-4XRC2ZC7.js +0 -17
  33. /package/dist/{dispatch-6LQSMMGI.js.map → dispatch-S3CR5HKX.js.map} +0 -0
  34. /package/dist/{forge-ES4RN7YM.js.map → forge-GUOEJ5DJ.js.map} +0 -0
  35. /package/dist/{plan-mode-4XRC2ZC7.js.map → plan-mode-35BONR7S.js.map} +0 -0
  36. /package/dist/{src-WJGIOESS.js.map → src-3NWTITZM.js.map} +0 -0
  37. /package/dist/{update-HHN4PJQI.js.map → update-H3LE4ZSI.js.map} +0 -0
package/dist/index.js CHANGED
@@ -21,11 +21,12 @@ import {
21
21
  color256toHex,
22
22
  contentWidth,
23
23
  engineColor,
24
+ isLinkedDevInstall,
24
25
  loadDismissedVersion,
25
26
  parseProseToRichLines,
26
27
  saveDismissedVersion,
27
28
  updateCommand
28
- } from "./chunk-ATUT2BUQ.js";
29
+ } from "./chunk-6IF2AV4Y.js";
29
30
  import {
30
31
  buildAgentApprovalCallback,
31
32
  buildConsensus,
@@ -37,10 +38,10 @@ import {
37
38
  runAgentTeam,
38
39
  runReviewCore,
39
40
  selectReviewEngine
40
- } from "./chunk-O6YP55RV.js";
41
+ } from "./chunk-PUNBDLQO.js";
41
42
  import {
42
43
  parsePatchPreview
43
- } from "./chunk-6ANHPXGZ.js";
44
+ } from "./chunk-HSPQEDHX.js";
44
45
  import {
45
46
  buildCheckpoint,
46
47
  createScoreboard,
@@ -52,9 +53,8 @@ import {
52
53
  recordRun,
53
54
  renderScoreboard,
54
55
  scoreboardFailEngine,
55
- scoreboardFinishEngine,
56
- sessionResultStore
57
- } from "./chunk-4LVYSUMN.js";
56
+ scoreboardFinishEngine
57
+ } from "./chunk-7WZ2O5WZ.js";
58
58
  import {
59
59
  buildCesarSystemPrompt,
60
60
  buildOracleCheatPrompt,
@@ -97,6 +97,7 @@ import {
97
97
  runThinkChain,
98
98
  runTribunal,
99
99
  saveCesarConversationSnapshot,
100
+ sessionResultStore,
100
101
  shouldDowngradeCesarToolWork,
101
102
  shouldUseAgentTeam,
102
103
  summarizeAllCesarToolReliability,
@@ -104,7 +105,7 @@ import {
104
105
  synthesisRoutingAdvice,
105
106
  todosFromPlanSteps,
106
107
  yieldToInk
107
- } from "./chunk-FCCH7IPJ.js";
108
+ } from "./chunk-3PDYVGRS.js";
108
109
  import {
109
110
  ENGINE_COLORS,
110
111
  bold,
@@ -126,8 +127,9 @@ import {
126
127
  truncateCodeLine,
127
128
  warn,
128
129
  yellow
129
- } from "./chunk-WE32YJKT.js";
130
+ } from "./chunk-NBV37VMW.js";
130
131
  import {
132
+ AGON_HOME,
131
133
  CommandRegistry,
132
134
  DEFAULT_CONFIG,
133
135
  EngineNotFoundError,
@@ -136,9 +138,11 @@ import {
136
138
  FRICTION_TAGS,
137
139
  RUNS_DIR,
138
140
  StreamParser,
141
+ acquireTurnLease,
139
142
  addWorkspace,
140
143
  agonPath,
141
144
  analyzeFlows,
145
+ appendEvent,
142
146
  appendMessage,
143
147
  appendUserTurnIfAbsent,
144
148
  applyPatch,
@@ -159,17 +163,20 @@ import {
159
163
  classifyDispatchFailure,
160
164
  clearConversation,
161
165
  clearSessionState,
166
+ closeRoom,
162
167
  companionDispatch,
163
168
  configGet,
164
169
  configSet,
165
170
  copyToClipboard,
166
171
  createCesarMemory,
167
172
  createPlan,
173
+ createRoom,
168
174
  createRunDir,
169
175
  createSessionWorktree,
170
176
  createSpeculator,
171
177
  createStreamBridge,
172
178
  currentBranch,
179
+ detectTrigger,
173
180
  diffFileCount,
174
181
  diffLineCount,
175
182
  discoverEngines,
@@ -177,6 +184,7 @@ import {
177
184
  ensureAgonHome,
178
185
  ensureCurrentWorkspace,
179
186
  estimateCost,
187
+ evaluateStop,
180
188
  executePlan,
181
189
  extractImagesFromInput,
182
190
  failPlan,
@@ -195,9 +203,12 @@ import {
195
203
  hooksFailed,
196
204
  initExtensions,
197
205
  installKernStackTraceMapper,
206
+ isRoomClosed,
198
207
  listCesarPlans,
199
208
  listChatSessions,
200
209
  listPlans,
210
+ listPresence,
211
+ listRooms,
201
212
  listSessionWorktrees,
202
213
  listSnapshots,
203
214
  listStoredProviders,
@@ -212,6 +223,7 @@ import {
212
223
  logFlow,
213
224
  mergeStepResult,
214
225
  modelEntryToEngineDef,
226
+ parseMentions,
215
227
  parsePatch,
216
228
  pasteStore,
217
229
  patchSummary,
@@ -220,10 +232,15 @@ import {
220
232
  preflightApply,
221
233
  printRunSummary,
222
234
  pruneSessionWorktrees,
235
+ readActiveLease,
236
+ readEvents,
223
237
  readOnlyDiff,
238
+ recordPresence,
224
239
  registerBuiltinCommands,
225
240
  rehydrateSessionWorktree,
241
+ releaseTurnLease,
226
242
  removeAuthKey,
243
+ removePresence,
227
244
  removeSessionWorktree,
228
245
  removeWorkspace,
229
246
  renderProvenanceJson,
@@ -236,6 +253,7 @@ import {
236
253
  resolveWorkingDir,
237
254
  resumeChatSession,
238
255
  revertSnapshot,
256
+ roomExists,
239
257
  runApiAgentLoop,
240
258
  runHooks,
241
259
  saveCesarPlan,
@@ -246,6 +264,7 @@ import {
246
264
  seedChatSessionFromThread,
247
265
  sessionContext,
248
266
  setAuthKey,
267
+ slugifyRoomId,
249
268
  snapshotWorkspace,
250
269
  spawnStream,
251
270
  spawnWithTimeout,
@@ -259,14 +278,14 @@ import {
259
278
  worktreeRemoveBestEffort,
260
279
  writeProvenanceReport,
261
280
  writeRunStatus
262
- } from "./chunk-C22VTCS6.js";
281
+ } from "./chunk-TMNHJOKU.js";
263
282
  import {
264
283
  apiDispatch,
265
284
  apiStreamDispatch
266
- } from "./chunk-5QMVQPHY.js";
285
+ } from "./chunk-XWHC6VAH.js";
267
286
 
268
287
  // src/index.ts
269
- import { defineCommand as defineCommand30, runMain } from "citty";
288
+ import { defineCommand as defineCommand31, runMain } from "citty";
270
289
 
271
290
  // src/generated/commands/forge.ts
272
291
  import { defineCommand } from "citty";
@@ -2462,11 +2481,337 @@ var historyCommand = defineCommand9({
2462
2481
  }
2463
2482
  });
2464
2483
 
2465
- // src/generated/commands/provenance.ts
2484
+ // src/generated/commands/room.ts
2466
2485
  import { defineCommand as defineCommand10 } from "citty";
2486
+ import { basename as basename2 } from "path";
2487
+ function actorFromArgs(args) {
2488
+ const engine = args.engine || void 0;
2489
+ const callsign = String(args.as || engine || "me").toLowerCase();
2490
+ const cli = engine || "cli";
2491
+ const humanOwner = process.env.USER || process.env.USERNAME || "local";
2492
+ return {
2493
+ actorId: `${cli}:${callsign}`,
2494
+ callsign,
2495
+ kind: "external-cli",
2496
+ engineId: engine,
2497
+ cli,
2498
+ humanOwner
2499
+ };
2500
+ }
2501
+ function renderEvent(ev) {
2502
+ const t = new Date(ev.createdAt);
2503
+ const hh = String(t.getHours()).padStart(2, "0");
2504
+ const mm = String(t.getMinutes()).padStart(2, "0");
2505
+ const stamp = dim(`${hh}:${mm}`);
2506
+ const seq = dim(`#${ev.seq}`);
2507
+ const who = bold(green(ev.actor.callsign));
2508
+ if (ev.kind === "post") {
2509
+ return `${seq} ${stamp} ${who}: ${ev.body}`;
2510
+ }
2511
+ if (ev.kind === "join") return `${seq} ${stamp} ${dim("* " + ev.actor.callsign + " joined")}`;
2512
+ if (ev.kind === "leave" || ev.kind === "room-closed") return `${seq} ${stamp} ${dim("* " + ev.actor.callsign + " left")}`;
2513
+ return `${seq} ${stamp} ${dim("* " + ev.kind + " by " + ev.actor.callsign)}`;
2514
+ }
2515
+ var roomCommand = defineCommand10({
2516
+ meta: {
2517
+ name: "room",
2518
+ description: "Shared multi-party chat room any CLI can join"
2519
+ },
2520
+ args: {
2521
+ action: {
2522
+ type: "positional",
2523
+ description: "create | join | post | read | tail | auto | who | leave | close | list",
2524
+ required: true
2525
+ },
2526
+ room: {
2527
+ type: "positional",
2528
+ description: "Room name or id",
2529
+ required: false
2530
+ },
2531
+ as: { type: "string", description: "Your callsign in the room (e.g. claude, codex)" },
2532
+ text: { type: "string", alias: "m", description: "Message text (post)" },
2533
+ name: { type: "string", alias: "n", description: "Room name (create)" },
2534
+ engine: { type: "string", description: "Engine/CLI id: codex | claude | agy | agon" },
2535
+ since: { type: "string", description: "Only events after this seq (read/tail)", default: "0" },
2536
+ limit: { type: "string", description: "Max events to show (read)", default: "50" },
2537
+ "max-turns": { type: "string", description: "auto: stop after N replies (default 3)", default: "3" },
2538
+ "max-minutes": { type: "string", description: "auto: stop after N minutes (default 10)", default: "10" },
2539
+ "open-floor": { type: "boolean", description: "auto: respond to any post after a quiet gap, not only @mentions" },
2540
+ "until-human": { type: "boolean", description: "auto: stop once a human replies after your turn" },
2541
+ "stop-phrase": { type: "string", description: "auto: stop when a post contains this phrase" },
2542
+ "quiet-ms": { type: "string", description: "auto open-floor: quiet gap before responding (ms, default 4000)", default: "4000" },
2543
+ "poll-ms": { type: "string", description: "auto/tail: poll interval (ms, default 1500)", default: "1500" },
2544
+ "lease-ttl": { type: "string", description: "auto: turn-lease TTL seconds (default 60)", default: "60" },
2545
+ "dry-run": { type: "boolean", description: "auto: post a stub instead of dispatching the engine (test the loop without spending tokens)" }
2546
+ },
2547
+ async run({ args }) {
2548
+ ensureAgonHome();
2549
+ const action = String(args.action);
2550
+ if (action === "list") {
2551
+ const rooms = listRooms();
2552
+ if (rooms.length === 0) {
2553
+ info("No rooms yet. Create one: agon room create --name <name>");
2554
+ return;
2555
+ }
2556
+ header("Rooms");
2557
+ table(["Room", "Name", "Created", "Status"], rooms.map((r) => [
2558
+ bold(r.roomId),
2559
+ r.name,
2560
+ new Date(r.createdAt).toLocaleString(),
2561
+ r.closed ? red("closed") : green("open")
2562
+ ]));
2563
+ return;
2564
+ }
2565
+ const roomName = String(args.room || args.name || "");
2566
+ if (!roomName) {
2567
+ fail(`Usage: agon room ${action} <room> ...`);
2568
+ return;
2569
+ }
2570
+ const roomId = slugifyRoomId(roomName);
2571
+ const actor = actorFromArgs(args);
2572
+ const repoHint = basename2(process.cwd());
2573
+ const since = Math.max(0, parseInt(String(args.since ?? "0"), 10) || 0);
2574
+ const limit = Math.max(0, parseInt(String(args.limit ?? "50"), 10) || 0);
2575
+ switch (action) {
2576
+ case "create": {
2577
+ const meta = createRoom(roomName);
2578
+ success(`Room ${bold(meta.roomId)} ready.`);
2579
+ info(dim(`Join it: agon room join ${meta.roomId} --as <callsign>`));
2580
+ return;
2581
+ }
2582
+ case "join": {
2583
+ if (roomExists(roomId) && isRoomClosed(roomId)) {
2584
+ fail(`Room "${roomId}" is closed.`);
2585
+ return;
2586
+ }
2587
+ createRoom(roomName);
2588
+ recordPresence(roomId, actor, 0, false);
2589
+ appendEvent(roomId, { kind: "join", actor, body: "", mentions: [], replyTo: null, repoHint });
2590
+ success(`${actor.callsign} joined ${bold(roomId)}.`);
2591
+ info(dim(`Post: agon room post ${roomId} --as ${actor.callsign} -m "hello"`));
2592
+ info(dim(`Watch: agon room tail ${roomId}`));
2593
+ return;
2594
+ }
2595
+ case "post": {
2596
+ if (!roomExists(roomId)) {
2597
+ fail(`No room "${roomId}". Create/join it first.`);
2598
+ return;
2599
+ }
2600
+ if (isRoomClosed(roomId)) {
2601
+ fail(`Room "${roomId}" is closed.`);
2602
+ return;
2603
+ }
2604
+ const text = String(args.text ?? "");
2605
+ if (!text.trim()) {
2606
+ fail('Nothing to post. Use -m "your message".');
2607
+ return;
2608
+ }
2609
+ const ev = appendEvent(roomId, { kind: "post", actor, body: text, mentions: parseMentions(text), replyTo: null, repoHint });
2610
+ recordPresence(roomId, actor, ev.seq, false);
2611
+ success(`#${ev.seq} posted to ${bold(roomId)}${ev.mentions.length ? dim(" \xB7 @" + ev.mentions.join(" @")) : ""}`);
2612
+ return;
2613
+ }
2614
+ case "read": {
2615
+ if (!roomExists(roomId)) {
2616
+ fail(`No room "${roomId}".`);
2617
+ return;
2618
+ }
2619
+ const events = readEvents(roomId, since, limit);
2620
+ header(`Room ${roomId}`);
2621
+ if (events.length === 0) {
2622
+ info(dim("(no messages yet)"));
2623
+ return;
2624
+ }
2625
+ for (const ev of events) console.log(renderEvent(ev));
2626
+ return;
2627
+ }
2628
+ case "tail": {
2629
+ if (!roomExists(roomId)) {
2630
+ fail(`No room "${roomId}".`);
2631
+ return;
2632
+ }
2633
+ header(`Room ${roomId} ${dim("(tailing \u2014 Ctrl+C to leave)")}`);
2634
+ let lastSeq = since;
2635
+ for (const ev of readEvents(roomId, since, 50)) {
2636
+ console.log(renderEvent(ev));
2637
+ lastSeq = Math.max(lastSeq, ev.seq);
2638
+ }
2639
+ setInterval(() => {
2640
+ const news = readEvents(roomId, lastSeq, 0);
2641
+ for (const ev of news) {
2642
+ console.log(renderEvent(ev));
2643
+ lastSeq = Math.max(lastSeq, ev.seq);
2644
+ }
2645
+ }, 1e3);
2646
+ await new Promise(() => {
2647
+ });
2648
+ return;
2649
+ }
2650
+ case "auto": {
2651
+ const dryRun = !!args["dry-run"];
2652
+ if (!dryRun && !actor.engineId) {
2653
+ fail("auto needs --engine <id> (or --dry-run to test the loop without an engine).");
2654
+ return;
2655
+ }
2656
+ createRoom(roomName);
2657
+ if (isRoomClosed(roomId)) {
2658
+ fail(`Room "${roomId}" is closed.`);
2659
+ return;
2660
+ }
2661
+ const registry = new EngineRegistry();
2662
+ registry.load(resolveBuiltinEnginesDir());
2663
+ const adapter = createCliAdapter(registry);
2664
+ const dispatchTimeoutSec = 120;
2665
+ let engine = null;
2666
+ if (!dryRun) {
2667
+ try {
2668
+ engine = registry.get(actor.engineId);
2669
+ } catch {
2670
+ fail(`Unknown engine "${actor.engineId}". Run: agon engine list`);
2671
+ return;
2672
+ }
2673
+ }
2674
+ const autoCfg = {
2675
+ callsign: actor.callsign,
2676
+ openFloor: !!args["open-floor"],
2677
+ quietMs: Math.max(0, parseInt(String(args["quiet-ms"] ?? "4000"), 10) || 4e3),
2678
+ maxTurns: Math.min(100, Math.max(1, parseInt(String(args["max-turns"] ?? "3"), 10) || 3)),
2679
+ maxWallMs: Math.min(1440, Math.max(1, parseInt(String(args["max-minutes"] ?? "10"), 10) || 10)) * 6e4,
2680
+ stopPhrase: String(args["stop-phrase"] ?? ""),
2681
+ untilHuman: !!args["until-human"]
2682
+ };
2683
+ const leaseTtlMs = Math.max(Math.max(5, parseInt(String(args["lease-ttl"] ?? "60"), 10) || 60), dispatchTimeoutSec + 15) * 1e3;
2684
+ const pollMs = Math.max(250, parseInt(String(args["poll-ms"] ?? "1500"), 10) || 1500);
2685
+ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
2686
+ let cleanedUp = false;
2687
+ const cleanup = () => {
2688
+ if (cleanedUp) return;
2689
+ cleanedUp = true;
2690
+ try {
2691
+ appendEvent(roomId, { kind: "leave", actor, body: "", mentions: [], replyTo: null, repoHint, auto: true });
2692
+ } catch {
2693
+ }
2694
+ try {
2695
+ removePresence(roomId, actor.callsign);
2696
+ } catch {
2697
+ }
2698
+ };
2699
+ const onSigint = () => {
2700
+ cleanup();
2701
+ process.exit(0);
2702
+ };
2703
+ process.once("SIGINT", onSigint);
2704
+ try {
2705
+ recordPresence(roomId, actor, 0, true);
2706
+ appendEvent(roomId, { kind: "join", actor, body: "", mentions: [], replyTo: null, repoHint, auto: true });
2707
+ header(`Auto ${bold(actor.callsign)} in ${bold(roomId)} ${dim("(" + (autoCfg.openFloor ? "open-floor" : "mention-only") + ", \u2264" + autoCfg.maxTurns + " turns / " + autoCfg.maxWallMs / 6e4 + "m" + (dryRun ? ", dry-run" : ", " + actor.engineId) + " \u2014 Ctrl+C to stop)")}`);
2708
+ const st = { turns: 0, startedAtMs: Date.now(), lastSelfSeq: 0 };
2709
+ let lastHandledSeq = 0;
2710
+ for (; ; ) {
2711
+ if (isRoomClosed(roomId)) {
2712
+ info(dim("auto stopped: room closed"));
2713
+ break;
2714
+ }
2715
+ const events = readEvents(roomId, 0, 0);
2716
+ const stop = evaluateStop(st, autoCfg, events);
2717
+ if (stop.stop) {
2718
+ info(dim(`auto stopped: ${stop.reason}`));
2719
+ break;
2720
+ }
2721
+ const trig = detectTrigger(events, actor.callsign, autoCfg.openFloor, autoCfg.quietMs);
2722
+ if (!trig.trigger || trig.triggerSeq <= lastHandledSeq) {
2723
+ await sleep(pollMs);
2724
+ continue;
2725
+ }
2726
+ const lease = acquireTurnLease(roomId, actor.callsign, trig.triggerSeq, leaseTtlMs);
2727
+ if (!lease) {
2728
+ await sleep(pollMs);
2729
+ continue;
2730
+ }
2731
+ try {
2732
+ let reply = "";
2733
+ if (dryRun) {
2734
+ reply = `(dry-run) ${actor.callsign} acks #${trig.triggerSeq}`;
2735
+ } else {
2736
+ const transcript = events.filter((e) => e.kind === "post").slice(-20).map((e) => `${e.actor.callsign}: ${e.body}`).join("\n");
2737
+ const prompt2 = `You are "${actor.callsign}" in a multi-agent chat room. Reply concisely (1-3 sentences) to the latest message; do not repeat earlier points. Transcript:
2738
+ ${transcript}`;
2739
+ const { path: outputDir } = createRunDir({ mode: "room-auto", announce: false });
2740
+ const result = await adapter.dispatch({ engine, prompt: prompt2, cwd: process.cwd(), mode: "exec", timeout: dispatchTimeoutSec, outputDir });
2741
+ reply = (result.stdout || "").trim();
2742
+ }
2743
+ const held = readActiveLease(roomId);
2744
+ if (reply && held && held.leaseId === lease.leaseId) {
2745
+ const posted = appendEvent(roomId, { kind: "post", actor, body: reply, mentions: parseMentions(reply), replyTo: null, repoHint, auto: true });
2746
+ recordPresence(roomId, actor, posted.seq, true);
2747
+ st.lastSelfSeq = posted.seq;
2748
+ console.log(renderEvent(posted));
2749
+ } else if (reply) {
2750
+ info(dim("auto: lost the floor during dispatch \u2014 dropping this reply (one-poster guarantee)"));
2751
+ }
2752
+ } finally {
2753
+ releaseTurnLease(roomId, lease.leaseId);
2754
+ }
2755
+ lastHandledSeq = trig.triggerSeq;
2756
+ st.turns += 1;
2757
+ await sleep(pollMs);
2758
+ }
2759
+ } finally {
2760
+ process.removeListener("SIGINT", onSigint);
2761
+ cleanup();
2762
+ }
2763
+ return;
2764
+ }
2765
+ case "who": {
2766
+ if (!roomExists(roomId)) {
2767
+ fail(`No room "${roomId}".`);
2768
+ return;
2769
+ }
2770
+ const present = listPresence(roomId);
2771
+ if (present.length === 0) {
2772
+ info(dim("Nobody here yet."));
2773
+ return;
2774
+ }
2775
+ header(`Who's in ${roomId}`);
2776
+ table(["Callsign", "Status", "CLI", "Last seen"], present.map((p) => [
2777
+ bold(p.callsign),
2778
+ p.status === "here" ? green("here") : p.status === "stale" ? dim("stale") : red("left"),
2779
+ p.cli,
2780
+ new Date(p.lastSeenAt).toLocaleTimeString()
2781
+ ]));
2782
+ return;
2783
+ }
2784
+ case "leave": {
2785
+ if (!roomExists(roomId)) {
2786
+ fail(`No room "${roomId}".`);
2787
+ return;
2788
+ }
2789
+ appendEvent(roomId, { kind: "leave", actor, body: "", mentions: [], replyTo: null, repoHint });
2790
+ removePresence(roomId, actor.callsign);
2791
+ success(`${actor.callsign} left ${bold(roomId)}.`);
2792
+ return;
2793
+ }
2794
+ case "close": {
2795
+ if (!roomExists(roomId)) {
2796
+ fail(`No room "${roomId}".`);
2797
+ return;
2798
+ }
2799
+ appendEvent(roomId, { kind: "room-closed", actor, body: "", mentions: [], replyTo: null, repoHint });
2800
+ closeRoom(roomId);
2801
+ success(`Room ${bold(roomId)} closed.`);
2802
+ return;
2803
+ }
2804
+ default:
2805
+ fail(`Unknown action "${action}". Use: create | join | post | read | tail | auto | who | leave | close | list`);
2806
+ }
2807
+ }
2808
+ });
2809
+
2810
+ // src/generated/commands/provenance.ts
2811
+ import { defineCommand as defineCommand11 } from "citty";
2467
2812
  import { readdirSync as readdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
2468
2813
  import { join as join8 } from "path";
2469
- var provenanceCommand = defineCommand10({
2814
+ var provenanceCommand = defineCommand11({
2470
2815
  meta: {
2471
2816
  name: "provenance",
2472
2817
  description: "AI-contribution / transparency report for a forge run"
@@ -2571,9 +2916,9 @@ ${js}
2571
2916
  });
2572
2917
 
2573
2918
  // src/generated/commands/engine.ts
2574
- import { defineCommand as defineCommand11 } from "citty";
2919
+ import { defineCommand as defineCommand12 } from "citty";
2575
2920
  import "path";
2576
- var engineCommand = defineCommand11({
2921
+ var engineCommand = defineCommand12({
2577
2922
  meta: {
2578
2923
  name: "engine",
2579
2924
  description: "Manage AI engines"
@@ -2730,11 +3075,11 @@ var engineCommand = defineCommand11({
2730
3075
  });
2731
3076
 
2732
3077
  // src/generated/commands/doctor.ts
2733
- import { defineCommand as defineCommand12 } from "citty";
3078
+ import { defineCommand as defineCommand13 } from "citty";
2734
3079
  import { spawnSync } from "child_process";
2735
3080
  import { mkdtempSync, rmSync, writeFileSync as writeFileSync3, existsSync as existsSync3 } from "fs";
2736
3081
  import { tmpdir, homedir as homedir2 } from "os";
2737
- import { join as join10, basename as basename2 } from "path";
3082
+ import { join as join10, basename as basename3 } from "path";
2738
3083
  import "url";
2739
3084
  function shellQuoteForDoctor(value) {
2740
3085
  const s = String(value ?? "");
@@ -2814,14 +3159,14 @@ function diagnoseEngineIsolation(engine, cleanConfigDir) {
2814
3159
  const hints = engine.isolationHints;
2815
3160
  if (!hints?.configEnv) return null;
2816
3161
  const marker = hints.authMarker?.trim();
2817
- if (marker && existsSync3(join10(cleanConfigDir, basename2(marker)))) {
3162
+ if (marker && existsSync3(join10(cleanConfigDir, basename3(marker)))) {
2818
3163
  return { id: engine.id, authed: true, detail: `clean dispatch authenticated (${cleanConfigDir})` };
2819
3164
  }
2820
3165
  if (!marker) {
2821
3166
  return { id: engine.id, authed: true, detail: `no auth marker required (${cleanConfigDir})` };
2822
3167
  }
2823
3168
  const authFiles = hints.authFiles ?? [];
2824
- const markerSource = authFiles.find((rel) => basename2(rel) === basename2(marker));
3169
+ const markerSource = authFiles.find((rel) => basename3(rel) === basename3(marker));
2825
3170
  if (markerSource) {
2826
3171
  const realHome = process.env[hints.configEnv] || (hints.personalPaths?.[0] ?? "").replace(/^~(?=$|\/)/, homedir2());
2827
3172
  if (!!realHome && existsSync3(join10(realHome, markerSource))) {
@@ -3047,7 +3392,7 @@ async function runReviewDoctor(registry, config, adapter, engineIds, timeoutSec)
3047
3392
  summary: `${rows.length - failing - warned} ok, ${warned} warn, ${failing} fail`
3048
3393
  };
3049
3394
  }
3050
- var doctorCommand = defineCommand12({
3395
+ var doctorCommand = defineCommand13({
3051
3396
  meta: {
3052
3397
  name: "doctor",
3053
3398
  description: "Diagnose Agon engine and worktree health"
@@ -3194,10 +3539,10 @@ var doctorCommand = defineCommand12({
3194
3539
  });
3195
3540
 
3196
3541
  // src/generated/commands/last.ts
3197
- import { defineCommand as defineCommand13 } from "citty";
3542
+ import { defineCommand as defineCommand14 } from "citty";
3198
3543
  import { readFileSync as readFileSync4, existsSync as existsSync4 } from "fs";
3199
3544
  import { join as join11 } from "path";
3200
- var lastCommand = defineCommand13({
3545
+ var lastCommand = defineCommand14({
3201
3546
  meta: {
3202
3547
  name: "last",
3203
3548
  description: "Print the path of the most recent run directory (orchestrators: composes with cat/jq)"
@@ -3258,15 +3603,15 @@ var lastCommand = defineCommand13({
3258
3603
  });
3259
3604
 
3260
3605
  // src/generated/commands/models.ts
3261
- import { defineCommand as defineCommand14 } from "citty";
3606
+ import { defineCommand as defineCommand15 } from "citty";
3262
3607
  import "path";
3263
- var modelsCommand = defineCommand14({
3608
+ var modelsCommand = defineCommand15({
3264
3609
  meta: {
3265
3610
  name: "models",
3266
3611
  description: "Manage engine\u2192model mappings"
3267
3612
  },
3268
3613
  subCommands: {
3269
- list: defineCommand14({
3614
+ list: defineCommand15({
3270
3615
  meta: { name: "list", description: "List engine model mappings and activation mode" },
3271
3616
  async run(ctx) {
3272
3617
  const config = loadConfig();
@@ -3309,7 +3654,7 @@ var modelsCommand = defineCommand14({
3309
3654
  }
3310
3655
  }
3311
3656
  }),
3312
- enable: defineCommand14({
3657
+ enable: defineCommand15({
3313
3658
  meta: { name: "enable", description: "Activate an engine for routing/fallback" },
3314
3659
  args: {
3315
3660
  engine: { type: "positional", required: true, description: "Engine ID" }
@@ -3344,7 +3689,7 @@ var modelsCommand = defineCommand14({
3344
3689
  success(`Activated ${canonical}`);
3345
3690
  }
3346
3691
  }),
3347
- add: defineCommand14({
3692
+ add: defineCommand15({
3348
3693
  meta: { name: "add", description: "Alias for enable" },
3349
3694
  args: {
3350
3695
  engine: { type: "positional", required: true, description: "Engine ID" }
@@ -3379,7 +3724,7 @@ var modelsCommand = defineCommand14({
3379
3724
  success(`Activated ${canonical}`);
3380
3725
  }
3381
3726
  }),
3382
- disable: defineCommand14({
3727
+ disable: defineCommand15({
3383
3728
  meta: { name: "disable", description: "Remove an engine from routing/fallback" },
3384
3729
  args: {
3385
3730
  engine: { type: "positional", required: true, description: "Engine ID" }
@@ -3401,7 +3746,7 @@ var modelsCommand = defineCommand14({
3401
3746
  success(`Hid ${engine} (soft \u2014 explicit -e still works)`);
3402
3747
  }
3403
3748
  }),
3404
- hide: defineCommand14({
3749
+ hide: defineCommand15({
3405
3750
  meta: { name: "hide", description: "Alias for disable" },
3406
3751
  args: {
3407
3752
  engine: { type: "positional", required: true, description: "Engine ID" }
@@ -3423,14 +3768,14 @@ var modelsCommand = defineCommand14({
3423
3768
  success(`Hid ${engine} (soft \u2014 explicit -e still works)`);
3424
3769
  }
3425
3770
  }),
3426
- auto: defineCommand14({
3771
+ auto: defineCommand15({
3427
3772
  meta: { name: "auto", description: "Use every non-removed available engine automatically" },
3428
3773
  async run(ctx) {
3429
3774
  configSet("engineActivationMode", "auto");
3430
3775
  success("Engine activation mode set to auto; removed engines stay removed");
3431
3776
  }
3432
3777
  }),
3433
- set: defineCommand14({
3778
+ set: defineCommand15({
3434
3779
  meta: { name: "set", description: "Set model for an engine" },
3435
3780
  args: {
3436
3781
  engine: { type: "positional", required: true, description: "Engine ID (e.g., claude)" },
@@ -3445,7 +3790,7 @@ var modelsCommand = defineCommand14({
3445
3790
  success(`Set ${engine} \u2192 ${model}`);
3446
3791
  }
3447
3792
  }),
3448
- remove: defineCommand14({
3793
+ remove: defineCommand15({
3449
3794
  meta: { name: "remove", description: "Remove model mapping" },
3450
3795
  args: {
3451
3796
  engine: { type: "positional", required: true, description: "Engine ID" }
@@ -3463,8 +3808,8 @@ var modelsCommand = defineCommand14({
3463
3808
  });
3464
3809
 
3465
3810
  // src/commands/config.ts
3466
- import { defineCommand as defineCommand15 } from "citty";
3467
- var configCommand = defineCommand15({
3811
+ import { defineCommand as defineCommand16 } from "citty";
3812
+ var configCommand = defineCommand16({
3468
3813
  meta: {
3469
3814
  name: "config",
3470
3815
  description: "View and modify Agon configuration"
@@ -3556,7 +3901,7 @@ var configCommand = defineCommand15({
3556
3901
  });
3557
3902
 
3558
3903
  // src/commands/provider.ts
3559
- import { defineCommand as defineCommand16 } from "citty";
3904
+ import { defineCommand as defineCommand17 } from "citty";
3560
3905
  import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync6, unlinkSync as unlinkSync2, readdirSync as readdirSync3, readFileSync as readFileSync5, existsSync as existsSync5 } from "fs";
3561
3906
  import { join as join13 } from "path";
3562
3907
  import { homedir as homedir3 } from "os";
@@ -3659,7 +4004,7 @@ async function interactiveAdd() {
3659
4004
  return;
3660
4005
  }
3661
4006
  }
3662
- var providerCommand = defineCommand16({
4007
+ var providerCommand = defineCommand17({
3663
4008
  meta: {
3664
4009
  name: "provider",
3665
4010
  description: "Add, remove, or list API providers; connect/disconnect and manage API keys"
@@ -3918,7 +4263,7 @@ var providerCommand = defineCommand16({
3918
4263
  });
3919
4264
 
3920
4265
  // src/commands/review.ts
3921
- import { defineCommand as defineCommand17 } from "citty";
4266
+ import { defineCommand as defineCommand18 } from "citty";
3922
4267
  import { writeFileSync as writeFileSync5 } from "fs";
3923
4268
  import { join as join14 } from "path";
3924
4269
  var PASTE_PLACEHOLDER_RE = /\[Pasted text(?:\s*#\d+)?\s*\+\d+\s*lines?\]/i;
@@ -3935,7 +4280,7 @@ function formatSeverityCounts(c) {
3935
4280
  if (c.nit) parts.push(`${c.nit} ${c.nit === 1 ? "nit" : "nits"}`);
3936
4281
  return parts.join(", ");
3937
4282
  }
3938
- var reviewCommand = defineCommand17({
4283
+ var reviewCommand = defineCommand18({
3939
4284
  meta: {
3940
4285
  name: "review",
3941
4286
  description: "Run a non-interactive AI review of a diff target"
@@ -4062,24 +4407,24 @@ ${body.join("\n")}`);
4062
4407
  return { id: engineId, status: "timeout", durationMs: Date.now() - engineStart, detail: `exceeded ${timeoutSec}s per-engine timeout`, outputPath };
4063
4408
  }
4064
4409
  if (isPastePlaceholderOnly(rawResponse)) {
4065
- flush([rawResponse, "\u26A0 captured a paste placeholder, not a review (prompt likely never submitted)."]);
4410
+ flush(["\u26A0 captured a paste placeholder, not a review (prompt likely never submitted)."]);
4066
4411
  return { id: engineId, status: "parse-failure", durationMs: Date.now() - engineStart, detail: "captured paste placeholder \u2014 prompt never submitted", outputPath };
4067
4412
  }
4068
4413
  if (result.parseFailed && result.unstructured) {
4069
- flush([rawResponse, "review complete (unstructured \u2014 no machine verdict, but the review above is valid)."]);
4414
+ flush([`${bold(engineId)}: unstructured (no machine verdict \u2014 full review in ${outputPath})`]);
4070
4415
  return { id: engineId, status: "unstructured", durationMs: Date.now() - engineStart, detail: "unstructured review (no machine-parseable findings block)", outputPath };
4071
4416
  }
4072
4417
  if (result.parseFailed) {
4073
- flush([rawResponse, "\u26A0 returned no usable review output."]);
4418
+ flush(["\u26A0 returned no usable review output."]);
4074
4419
  return { id: engineId, status: "parse-failure", durationMs: Date.now() - engineStart, detail: "empty or unusable response", outputPath };
4075
4420
  }
4076
4421
  const counts = formatSeverityCounts(result.severityCounts);
4077
4422
  captureFindings(engineId, rawResponse);
4078
4423
  if (result.blocking) {
4079
- flush([rawResponse, `\u26A0 ${bold(engineId)}: blocking, ${counts}`]);
4424
+ flush([`\u26A0 ${bold(engineId)}: blocking, ${counts}`]);
4080
4425
  return { id: engineId, status: "blocking", durationMs: Date.now() - engineStart, detail: `blocking, ${counts}`, outputPath };
4081
4426
  }
4082
- flush([rawResponse, `${bold(engineId)}: ok, ${counts}`]);
4427
+ flush([`${bold(engineId)}: ok, ${counts}`]);
4083
4428
  return { id: engineId, status: "ok", durationMs: Date.now() - engineStart, detail: `ok, ${counts}`, outputPath };
4084
4429
  } catch (err) {
4085
4430
  const message = err instanceof Error ? err.message : String(err);
@@ -4144,12 +4489,13 @@ ${body.join("\n")}`);
4144
4489
  if (consensus.speculative.length) lines.push(` SPECULATIVE: ${consensus.speculative.length} low-confidence finding(s) \u2014 likely noise.`);
4145
4490
  if (consensus.nits.length) lines.push(` NITS: ${consensus.nits.length}.`);
4146
4491
  console.log(lines.join("\n"));
4492
+ if (!quiet) info(`Full per-engine reviews: ${outputDir}`);
4147
4493
  }
4148
4494
  });
4149
4495
 
4150
4496
  // src/generated/commands/call.ts
4151
4497
  import { spawn } from "child_process";
4152
- import { defineCommand as defineCommand18 } from "citty";
4498
+ import { defineCommand as defineCommand19 } from "citty";
4153
4499
  function textFlag(flag, value) {
4154
4500
  const text = value?.trim();
4155
4501
  return text ? [flag, text] : [];
@@ -4359,7 +4705,7 @@ async function runCommand(command, args, cwd, jsonl) {
4359
4705
  });
4360
4706
  });
4361
4707
  }
4362
- var callCommand = defineCommand18({
4708
+ var callCommand = defineCommand19({
4363
4709
  meta: {
4364
4710
  name: "call",
4365
4711
  description: "Live bridge for external CLIs to run Agon modes"
@@ -4534,7 +4880,7 @@ var callCommand = defineCommand18({
4534
4880
  });
4535
4881
 
4536
4882
  // src/generated/commands/agent-guide.ts
4537
- import { defineCommand as defineCommand19 } from "citty";
4883
+ import { defineCommand as defineCommand20 } from "citty";
4538
4884
 
4539
4885
  // src/generated/commands/agent-guide-text.ts
4540
4886
  function agentGuideMarkdown() {
@@ -4557,6 +4903,16 @@ function agentGuideMarkdown() {
4557
4903
  '- `agon goal "<intent>" --queue <dir|.jsonl> --gate "<test cmd>"` \u2014 autonomous controller: drives a task queue to completion unattended, looping build -> witness -> gate -> review (panel + judge) -> fix -> commit per task on a goal/ branch. Bound it with `--max-hours`/`--budget`; `--push` pushes each task. Long-running (designed for 8-24h).',
4558
4904
  '- `agon conquer "<task>" --gate "<test cmd>"` \u2014 supervised-autonomous BUILD of an OPEN-ENDED task. Cesar drives a pluggable builder CLI (codex/claude/agy) in agent mode turn by turn; when the builder hits a fork it asks and Cesar convenes the cheapest sufficient consult (nero/tribunal/brainstorm/council) and feeds back a compact verdict; when it claims done, a layered done-oracle runs (the `--gate` command + diff acceptance-drift + a nero falsification round) and it STOPS at a HUMAN merge gate \u2014 it never auto-merges to main. The open-ended sibling to `goal`: use `conquer` when you CANNOT write a clean discriminating oracle up front (build a whole tool), `goal` when you can. `--push` needs a clean tree; bound it with `--max-turns`/`--max-hours`.',
4559
4905
  "",
4906
+ "## Collaborate with other agents \u2014 rooms",
4907
+ "Agon hosts shared chat ROOMS so multiple live CLIs (you, other Codex/Claude/agy sessions, agon engines) coordinate over one persistent transcript. Human-mediated: you post when prompted, and read what others said. Use a room to hand off work, ask another agent for help, or coordinate parallel work in the same repo.",
4908
+ "- `agon room join <room> --as <callsign> --engine <codex|claude|agy>` \u2014 join a room (creates it if new)",
4909
+ '- `agon room post <room> --as <callsign> -m "message"` \u2014 post a message; use `@callsign` to mention someone',
4910
+ "- `agon room read <room> [--since <seq>]` \u2014 read the shared transcript",
4911
+ "- `agon room tail <room>` \u2014 follow the room live (Ctrl+C to leave)",
4912
+ "- `agon room who <room>` \u2014 see who is present",
4913
+ "- `agon room leave <room> --as <callsign>` \u2014 leave (clears your presence immediately)",
4914
+ "- `agon room auto <room> --as <callsign> --engine <id> [--open-floor] [--max-turns N] [--max-minutes N] [--until-human]` \u2014 AUTONOMOUS: watch the room and auto-reply on your turn until a stop condition. Safe by default: mention-only, \u22643 turns / 10 min, one-poster-at-a-time turn lease, and a ping-pong halt if two auto-agents loop. Use `--dry-run` to test the loop without spending tokens.",
4915
+ "",
4560
4916
  "## Setting up forge & goal \u2014 the test/gate IS the spec",
4561
4917
  "These two modes only optimize to make your test (`-t` for forge) or gate/verify (for goal) pass. That command IS the specification \u2014 not the prose task. A check that a wrong implementation can still pass will ship a wrong implementation, and often dead-loops the run. Before launching:",
4562
4918
  "- Discriminate: every check must FAIL a plausibly-wrong impl, not just pass the intended one. Use distinct/edge args (atan2(3,4) not atan2(0,1); `5.5 % 2` to catch int() truncation; cbrt(-27) to reject pow(x,1/3), since pow returns NaN on a negative base).",
@@ -4679,7 +5035,7 @@ function codexSkillOpenAiYaml() {
4679
5035
  }
4680
5036
 
4681
5037
  // src/generated/commands/agent-guide.ts
4682
- var agentGuideCommand = defineCommand19({
5038
+ var agentGuideCommand = defineCommand20({
4683
5039
  meta: {
4684
5040
  name: "agent-guide",
4685
5041
  description: "Print how to call agon \u2014 a compact overview for any external engine (Codex, Antigravity, Claude, OpenCode)"
@@ -4708,7 +5064,17 @@ var agentGuideCommand = defineCommand19({
4708
5064
  ],
4709
5065
  flags: ["--engines claude,codex,agy", "--timeout <sec>"],
4710
5066
  machineReadable: 'agon call <mode> "<input>" [flags] --jsonl',
4711
- results: { lastDir: "agon last", summary: 'cat "$(agon last)/summary.json"', status: "agon last --status" }
5067
+ results: { lastDir: "agon last", summary: 'cat "$(agon last)/summary.json"', status: "agon last --status" },
5068
+ rooms: {
5069
+ about: "Shared multi-party chat rooms \u2014 coordinate with other live CLIs/sessions over one persistent transcript (human-mediated: post when prompted).",
5070
+ join: "agon room join <room> --as <callsign> --engine <codex|claude|agy>",
5071
+ post: 'agon room post <room> --as <callsign> -m "<message>" (use @callsign to mention)',
5072
+ read: "agon room read <room> [--since <seq>]",
5073
+ tail: "agon room tail <room>",
5074
+ who: "agon room who <room>",
5075
+ leave: "agon room leave <room> --as <callsign>",
5076
+ auto: "agon room auto <room> --as <callsign> --engine <id> [--open-floor] [--max-turns N] [--until-human] [--dry-run] \u2014 autonomous reply loop, safe by default (mention-only, \u22643 turns/10min, turn-lease, ping-pong halt)"
5077
+ }
4712
5078
  }, null, 2) + "\n");
4713
5079
  return;
4714
5080
  }
@@ -4717,11 +5083,11 @@ var agentGuideCommand = defineCommand19({
4717
5083
  });
4718
5084
 
4719
5085
  // src/generated/commands/install-agent-prompts.ts
4720
- import { defineCommand as defineCommand20 } from "citty";
5086
+ import { defineCommand as defineCommand21 } from "citty";
4721
5087
  import { existsSync as existsSync6, mkdirSync as mkdirSync7, writeFileSync as writeFileSync6 } from "fs";
4722
5088
  import { homedir as homedir4 } from "os";
4723
5089
  import { join as join15, dirname as dirname5 } from "path";
4724
- var installAgentPromptsCommand = defineCommand20({
5090
+ var installAgentPromptsCommand = defineCommand21({
4725
5091
  meta: {
4726
5092
  name: "install-agent-prompts",
4727
5093
  description: "Install lightweight Agon prompts/skills into other CLIs (Codex, Antigravity, Claude Code) \u2014 no MCP, no always-on tokens"
@@ -4825,7 +5191,7 @@ var installAgentPromptsCommand = defineCommand20({
4825
5191
  });
4826
5192
 
4827
5193
  // src/generated/commands/goal.ts
4828
- import { defineCommand as defineCommand21 } from "citty";
5194
+ import { defineCommand as defineCommand22 } from "citty";
4829
5195
  import { readFileSync as readFileSync6, readdirSync as readdirSync4, existsSync as existsSync7, statSync as statSync2, writeFileSync as writeFileSync7 } from "fs";
4830
5196
  import { resolve } from "path";
4831
5197
  var goalCommand = (() => {
@@ -4867,7 +5233,7 @@ var goalCommand = (() => {
4867
5233
  }
4868
5234
  throw new Error(`unsupported queue ${queuePath} \u2014 expected a directory or a .jsonl/.json file`);
4869
5235
  };
4870
- return defineCommand21({
5236
+ return defineCommand22({
4871
5237
  meta: {
4872
5238
  name: "goal",
4873
5239
  description: "Autonomously drive a task queue (e.g. .kern-gaps/) to completion. Per task: forge implements, the diff is witnessed + mutation-witnessed, the frozen gate runs, ALL engines review and a judge decides, blockers get one fix pass, then one commit lands on the goal branch (never main) \u2014 and is pushed with --push. Bound it with --max-hours and/or --budget, or neither (free)."
@@ -5499,8 +5865,8 @@ judge ${judge} errored (${e instanceof Error ? e.message : String(e)}); ${consen
5499
5865
  })();
5500
5866
 
5501
5867
  // src/generated/commands/synthesis.ts
5502
- import { defineCommand as defineCommand22 } from "citty";
5503
- var synthesisCommand = defineCommand22({
5868
+ import { defineCommand as defineCommand23 } from "citty";
5869
+ var synthesisCommand = defineCommand23({
5504
5870
  meta: {
5505
5871
  name: "synthesis",
5506
5872
  description: "Competitive cross-pollination - engines draft, swap, improve, judge picks the best evolved artifact"
@@ -5644,7 +6010,7 @@ var synthesisCommand = defineCommand22({
5644
6010
  });
5645
6011
 
5646
6012
  // src/generated/commands/ask.ts
5647
- import { defineCommand as defineCommand23 } from "citty";
6013
+ import { defineCommand as defineCommand24 } from "citty";
5648
6014
  function resolveAskInputs(rawEngine, rawPrompt, extras, activeEngines) {
5649
6015
  const extra = (extras || []).filter(Boolean).join(" ").trim();
5650
6016
  if (rawPrompt === void 0 || rawPrompt === null) {
@@ -5660,7 +6026,7 @@ function resolveAskInputs(rawEngine, rawPrompt, extras, activeEngines) {
5660
6026
  if (!engineId) return { engineId: "", prompt: prompt2, error: "no-engine" };
5661
6027
  return { engineId, prompt: prompt2, error: null };
5662
6028
  }
5663
- var askCommand = defineCommand23({
6029
+ var askCommand = defineCommand24({
5664
6030
  meta: {
5665
6031
  name: "ask",
5666
6032
  description: 'Ask one engine a single question \u2014 fast raw answer, no competition. `agon ask codex "..."`, or `agon ask "..."` for the default engine.'
@@ -5771,11 +6137,11 @@ var askCommand = defineCommand23({
5771
6137
  });
5772
6138
 
5773
6139
  // src/generated/commands/think.ts
5774
- import { defineCommand as defineCommand24 } from "citty";
6140
+ import { defineCommand as defineCommand25 } from "citty";
5775
6141
  function thoughtGlyph(kind) {
5776
6142
  return kind === "critique" ? "\u{1F50D}" : kind === "revision" ? "\u270F\uFE0F" : kind === "question" ? "\u2753" : kind === "decision" ? "\u2705" : kind === "hypothesis" ? "\u{1F52C}" : kind === "decompose" ? "\u{1F9E9}" : "\u{1F4AD}";
5777
6143
  }
5778
- var thinkCommand = defineCommand24({
6144
+ var thinkCommand = defineCommand25({
5779
6145
  meta: {
5780
6146
  name: "think",
5781
6147
  description: 'Sequential thinking \u2014 decompose a problem into structured thoughts before acting. `agon think "..." --strategy reflexion`. Opt-in; surfaces open questions and a goal handoff.'
@@ -5975,11 +6341,11 @@ var thinkCommand = defineCommand24({
5975
6341
  });
5976
6342
 
5977
6343
  // src/generated/commands/nero.ts
5978
- import { defineCommand as defineCommand25 } from "citty";
6344
+ import { defineCommand as defineCommand26 } from "citty";
5979
6345
  function verdictGlyph(verdict) {
5980
6346
  return verdict === "flawed" ? "\u{1F534}" : verdict === "proceed-with-caution" ? "\u{1F7E1}" : verdict === "sound" ? "\u{1F7E2}" : "\u26AA";
5981
6347
  }
5982
- var neroCommand = defineCommand25({
6348
+ var neroCommand = defineCommand26({
5983
6349
  meta: {
5984
6350
  name: "nero",
5985
6351
  description: 'Adversarial self-challenge \u2014 the top-rated critic attacks a decision and returns concrete failure scenarios + a verdict. `agon nero "<decision>" --reasoning "..."`. Agon\'s /evil-twin for external CLIs.'
@@ -6128,7 +6494,7 @@ var neroCommand = defineCommand25({
6128
6494
  process.exitCode = 1;
6129
6495
  return;
6130
6496
  }
6131
- const pick = result.reason === "forced" ? `forced` : result.reason === "random" ? `random \u2014 no Elo yet` : `top-rated via ${result.scope}`;
6497
+ const pick = result.reason === "forced" ? `forced` : result.reason === "random" ? `random \u2014 no rating yet` : `top-rated via ${result.scope}`;
6132
6498
  if (quiet) {
6133
6499
  console.log(`${verdictGlyph(result.verdict)} ${result.verdict.toUpperCase()} \u2014 ${result.engineId} (${pick})${result.challengeConfidence != null ? ` \xB7 Nero ${result.challengeConfidence}%` : ""}`);
6134
6500
  } else {
@@ -6145,15 +6511,15 @@ var neroCommand = defineCommand25({
6145
6511
  });
6146
6512
 
6147
6513
  // src/generated/commands/council.ts
6148
- import { defineCommand as defineCommand26 } from "citty";
6514
+ import { defineCommand as defineCommand27 } from "citty";
6149
6515
  function chairmanPickLabel(reason) {
6150
6516
  if (reason === "forced") return "forced";
6151
6517
  if (reason === "cesar") return "cesar-chaired (2-engine council)";
6152
- if (reason === "random") return "random \u2014 no Elo yet";
6518
+ if (reason === "random") return "random \u2014 no rating yet";
6153
6519
  if (reason === "top-rated") return "top-rated";
6154
6520
  return reason;
6155
6521
  }
6156
- var councilCommand = defineCommand26({
6522
+ var councilCommand = defineCommand27({
6157
6523
  meta: {
6158
6524
  name: "council",
6159
6525
  description: 'Roundtable of ALL active engines \u2014 each takes a role, the top-rated engine chairs. `agon council "<decision>"`. Agon\'s stronger LLM-Council: real heterogeneous models, decision brief, directed critique, a chairman verdict with confidence + kill-switch.'
@@ -6338,8 +6704,8 @@ var councilCommand = defineCommand26({
6338
6704
  });
6339
6705
 
6340
6706
  // src/generated/commands/conquer.ts
6341
- import { defineCommand as defineCommand27 } from "citty";
6342
- var conquerCommand = defineCommand27({
6707
+ import { defineCommand as defineCommand28 } from "citty";
6708
+ var conquerCommand = defineCommand28({
6343
6709
  meta: {
6344
6710
  name: "conquer",
6345
6711
  description: 'Supervised-autonomous build: Cesar drives an external builder CLI (codex/claude/agy) unattended toward a task, convening nero/tribunal/council on forks, and stops at a human merge gate. `agon conquer "<task>" --gate "<test cmd>"`.'
@@ -6502,9 +6868,9 @@ var conquerCommand = defineCommand27({
6502
6868
  });
6503
6869
 
6504
6870
  // src/generated/commands/worktree.ts
6505
- import { defineCommand as defineCommand28 } from "citty";
6871
+ import { defineCommand as defineCommand29 } from "citty";
6506
6872
  import { execFileSync } from "child_process";
6507
- var worktreeCommand = defineCommand28({
6873
+ var worktreeCommand = defineCommand29({
6508
6874
  meta: {
6509
6875
  name: "worktree",
6510
6876
  description: "Isolated per-session git worktrees (new/list/rm/prune/rehydrate)"
@@ -6682,10 +7048,10 @@ var worktreeCommand = defineCommand28({
6682
7048
  });
6683
7049
 
6684
7050
  // src/generated/commands/login.ts
6685
- import { defineCommand as defineCommand29 } from "citty";
7051
+ import { defineCommand as defineCommand30 } from "citty";
6686
7052
  import { spawnSync as spawnSync2 } from "child_process";
6687
7053
  import { mkdirSync as mkdirSync8, existsSync as existsSync8, chmodSync as chmodSync2 } from "fs";
6688
- import { join as join16, basename as basename3 } from "path";
7054
+ import { join as join16, basename as basename4 } from "path";
6689
7055
  function planEngineLogin(engine, cleanConfigDir) {
6690
7056
  const hints = engine.isolationHints;
6691
7057
  if (!hints?.configEnv) {
@@ -6703,7 +7069,7 @@ function planEngineLogin(engine, cleanConfigDir) {
6703
7069
  authMarker: hints.authMarker
6704
7070
  };
6705
7071
  }
6706
- var loginCommand = defineCommand29({
7072
+ var loginCommand = defineCommand30({
6707
7073
  meta: {
6708
7074
  name: "login",
6709
7075
  description: "Log an engine's CLI into its clean workspace-pure config dir so dispatches stay authenticated without inheriting your personal Claude Code setup"
@@ -6754,7 +7120,7 @@ var loginCommand = defineCommand29({
6754
7120
  return;
6755
7121
  }
6756
7122
  const marker = plan.authMarker?.trim();
6757
- const markerPath = marker ? join16(plan.cleanConfigDir, basename3(marker)) : "";
7123
+ const markerPath = marker ? join16(plan.cleanConfigDir, basename4(marker)) : "";
6758
7124
  const alreadyAuthed = !!markerPath && existsSync8(markerPath);
6759
7125
  if (alreadyAuthed && !args.force) {
6760
7126
  success(`${engine.id} is already logged in for clean dispatch \u2014 workspace-pure isolation is active.`);
@@ -6799,7 +7165,7 @@ import { Box as Box9, Static, Text as Text9, render } from "ink";
6799
7165
  import { ScrollBox, AlternateScreen } from "@kernlang/terminal/runtime";
6800
7166
 
6801
7167
  // src/generated/signals/intent.ts
6802
- var SLASH_COMMANDS = [{ cmd: "/forge", desc: "<task> test with <cmd> [--hardened] \u2014 competitive code generation" }, { cmd: "/brainstorm", desc: "<question> \u2014 confidence-bidding answers" }, { cmd: "/tribunal", desc: "[mode] <question> \u2014 debate (adversarial|socratic|red-team|steelman|synthesis|postmortem)" }, { cmd: "/campfire", desc: "<topic> \u2014 think together, no competition" }, { cmd: "/think", desc: "<problem> [--strategy reflexion] [--steps 8] \u2014 sequential thinking, one engine" }, { cmd: "/council", desc: "<decision> \u2014 roundtable: every engine a role, top-rated chairs" }, { cmd: "/synthesis", desc: "<task> [--swaps 2] \u2014 engines draft, swap, improve; judge picks winner" }, { cmd: "/workspace", desc: "add|remove|list|switch \u2014 manage project repos" }, { cmd: "/ws", desc: " \u2014 list workspaces (shortcut)" }, { cmd: "/cesar", desc: "<engine> \u2014 set Cesar brain engine (e.g. /cesar codex)" }, { cmd: "/models", desc: " \u2014 browse & add provider models + CLI models" }, { cmd: "/tokens", desc: " \u2014 show token usage & costs" }, { cmd: "/engines", desc: " \u2014 select active engines" }, { cmd: "/leaderboard", desc: " \u2014 ELO rankings" }, { cmd: "/cesar-report", desc: " \u2014 Cesar routing calibration report" }, { cmd: "/cesar-hints", desc: "<task> \u2014 inspect Cesar routing hints for a prompt" }, { cmd: "/history", desc: "[id] \u2014 past forge runs" }, { cmd: "/config", desc: "[list|get|set] \u2014 settings" }, { cmd: "/plan", desc: "<task> or no args \u2014 plan mode or show plan" }, { cmd: "/auto", desc: "[on|off|toggle|status] or <task> \u2014 autonomous mode control" }, { cmd: "/plans", desc: " \u2014 list recent plans" }, { cmd: "/approve", desc: " \u2014 approve current plan" }, { cmd: "/retry", desc: " \u2014 retry failed plan step" }, { cmd: "/cancel", desc: " \u2014 cancel current plan" }, { cmd: "/apply", desc: "[path] [--force] \u2014 apply winning forge patch" }, { cmd: "/cp", desc: "[N] \u2014 copy code block N to clipboard" }, { cmd: "/img", desc: "<path> \u2014 attach image to next prompt" }, { cmd: "/flow", desc: " \u2014 log this session" }, { cmd: "/flows", desc: " \u2014 flow analytics dashboard" }, { cmd: "/chats", desc: "[id|resume <id>] \u2014 chat history or resume session" }, { cmd: "/build", desc: "<task> \u2014 agent builds in cwd (reads/edits/tests)" }, { cmd: "/goal", desc: '<intent> --queue <dir> --gate "<cmd>" [--push] \u2014 autonomous queue: build\u2192review(all)\u2192judge\u2192fix\u2192commit\u2192push per task (background job)' }, { cmd: "/conquer", desc: '<task> --gate "<cmd>" [--builder X] [-e a,b] \u2014 supervised-autonomous build: Cesar drives a builder CLI, convenes nero/tribunal/council on forks, stops at a human merge gate (background job)' }, { cmd: "/agent", desc: "<task> \u2014 autonomous agent loop (solo or shadow, auto-routed)" }, { cmd: "/agent-solo", desc: "<task> \u2014 force solo agent mode, no shadow worker" }, { cmd: "/speculate", desc: "<task> \u2014 parallel speculation: N engines race in worktrees, winner applied" }, { cmd: "/team-forge", desc: "[2v2|3v3] <task> test with <cmd> \u2014 team code competition" }, { cmd: "/team-tribunal", desc: "[2v2|3v3] [mode] <question> \u2014 team debate" }, { cmd: "/team-brainstorm", desc: "[2v2|3v3] <question> \u2014 team ideation" }, { cmd: "/pipeline", desc: "<task> [test with <cmd>] \u2014 build\u2192review\u2192fix loop" }, { cmd: "/review", desc: "[with <engine>] [<target>] \u2014 code review (uncommitted|branch:NAME|commit:SHA)" }, { cmd: "/provider", desc: "add|remove|list|key \u2014 providers & keys (key set/clear/list)" }, { cmd: "/run", desc: "<cmd> \u2014 run shell command inline" }, { cmd: "/commit", desc: "[message] \u2014 stage & commit with auto-generated message" }, { cmd: "/status", desc: " \u2014 live engine telemetry snapshot" }, { cmd: "/doctor", desc: "[engines|harness] \u2014 diagnose engines, worktree, or Cesar harness" }, { cmd: "/harness-replay", desc: "[turnId] \u2014 replay Cesar tool timeline + approval ledger" }, { cmd: "/undo", desc: " \u2014 revert last patch or Cesar checkpoint" }, { cmd: "/checkpoints", desc: " \u2014 list recent file checkpoints" }, { cmd: "/jobs", desc: " \u2014 list running/completed jobs" }, { cmd: "/focus", desc: "<id> \u2014 switch to background job output" }, { cmd: "/explore", desc: " \u2014 toggle exploration mode (read-only)" }, { cmd: "/nero", desc: "[<decision>] \u2014 toggle Nero mode, or challenge a decision (top-rated critic)" }, { cmd: "/btw", desc: "<question> \u2014 ask something while engines work (side-channel)" }, { cmd: "/compact", desc: " \u2014 shrink Cesar context without clearing transcript" }, { cmd: "/mcp", desc: "connect <name|url> | disconnect <name> | list \u2014 manage session MCP servers" }, { cmd: "/init", desc: " \u2014 create AGON.md config wizard" }, { cmd: "/create-skill", desc: "<name> \u2014 scaffold a new skill (.agon/skills/)" }, { cmd: "/clear", desc: " \u2014 reset session (saves chat, clears brain)" }, { cmd: "/clean", desc: " \u2014 alias for /clear" }, { cmd: "/extensions", desc: " \u2014 list installed extensions" }, { cmd: "/help", desc: " \u2014 show this help" }, { cmd: "/exit", desc: " \u2014 quit" }];
7168
+ var SLASH_COMMANDS = [{ cmd: "/forge", desc: "<task> test with <cmd> [--hardened] \u2014 competitive code generation" }, { cmd: "/brainstorm", desc: "<question> \u2014 confidence-bidding answers" }, { cmd: "/tribunal", desc: "[mode] <question> \u2014 debate (adversarial|socratic|red-team|steelman|synthesis|postmortem)" }, { cmd: "/campfire", desc: "<topic> \u2014 think together, no competition" }, { cmd: "/think", desc: "<problem> [--strategy reflexion] [--steps 8] \u2014 sequential thinking, one engine" }, { cmd: "/council", desc: "<decision> \u2014 roundtable: every engine a role, top-rated chairs" }, { cmd: "/synthesis", desc: "<task> [--swaps 2] \u2014 engines draft, swap, improve; judge picks winner" }, { cmd: "/workspace", desc: "add|remove|list|switch \u2014 manage project repos" }, { cmd: "/ws", desc: " \u2014 list workspaces (shortcut)" }, { cmd: "/cesar", desc: "<engine> \u2014 set Cesar brain engine (e.g. /cesar codex)" }, { cmd: "/models", desc: " \u2014 browse & add provider models + CLI models" }, { cmd: "/tokens", desc: " \u2014 show token usage & costs" }, { cmd: "/engines", desc: " \u2014 select active engines" }, { cmd: "/leaderboard", desc: " \u2014 Glicko rankings" }, { cmd: "/cesar-report", desc: " \u2014 Cesar routing calibration report" }, { cmd: "/cesar-hints", desc: "<task> \u2014 inspect Cesar routing hints for a prompt" }, { cmd: "/history", desc: "[id] \u2014 past forge runs" }, { cmd: "/config", desc: "[list|get|set] \u2014 settings" }, { cmd: "/plan", desc: "<task> or no args \u2014 plan mode or show plan" }, { cmd: "/auto", desc: "[on|off|toggle|status] or <task> \u2014 autonomous mode control" }, { cmd: "/plans", desc: " \u2014 list recent plans" }, { cmd: "/approve", desc: " \u2014 approve current plan" }, { cmd: "/retry", desc: " \u2014 retry failed plan step" }, { cmd: "/cancel", desc: " \u2014 cancel current plan" }, { cmd: "/apply", desc: "[path] [--force] \u2014 apply winning forge patch" }, { cmd: "/cp", desc: "[N] \u2014 copy code block N to clipboard" }, { cmd: "/img", desc: "<path> \u2014 attach image to next prompt" }, { cmd: "/flow", desc: " \u2014 log this session" }, { cmd: "/flows", desc: " \u2014 flow analytics dashboard" }, { cmd: "/chats", desc: "[id|resume <id>] \u2014 chat history or resume session" }, { cmd: "/build", desc: "<task> \u2014 agent builds in cwd (reads/edits/tests)" }, { cmd: "/goal", desc: '<intent> --queue <dir> --gate "<cmd>" [--push] \u2014 autonomous queue: build\u2192review(all)\u2192judge\u2192fix\u2192commit\u2192push per task (background job)' }, { cmd: "/conquer", desc: '<task> --gate "<cmd>" [--builder X] [-e a,b] \u2014 supervised-autonomous build: Cesar drives a builder CLI, convenes nero/tribunal/council on forks, stops at a human merge gate (background job)' }, { cmd: "/agent", desc: "<task> \u2014 autonomous agent loop (solo or shadow, auto-routed)" }, { cmd: "/agent-solo", desc: "<task> \u2014 force solo agent mode, no shadow worker" }, { cmd: "/speculate", desc: "<task> \u2014 parallel speculation: N engines race in worktrees, winner applied" }, { cmd: "/team-forge", desc: "[2v2|3v3] <task> test with <cmd> \u2014 team code competition" }, { cmd: "/team-tribunal", desc: "[2v2|3v3] [mode] <question> \u2014 team debate" }, { cmd: "/team-brainstorm", desc: "[2v2|3v3] <question> \u2014 team ideation" }, { cmd: "/pipeline", desc: "<task> [test with <cmd>] \u2014 build\u2192review\u2192fix loop" }, { cmd: "/review", desc: "[with <engine>] [<target>] \u2014 code review (uncommitted|branch:NAME|commit:SHA)" }, { cmd: "/provider", desc: "add|remove|list|key \u2014 providers & keys (key set/clear/list)" }, { cmd: "/run", desc: "<cmd> \u2014 run shell command inline" }, { cmd: "/commit", desc: "[message] \u2014 stage & commit with auto-generated message" }, { cmd: "/status", desc: " \u2014 live engine telemetry snapshot" }, { cmd: "/doctor", desc: "[engines|harness] \u2014 diagnose engines, worktree, or Cesar harness" }, { cmd: "/harness-replay", desc: "[turnId] \u2014 replay Cesar tool timeline + approval ledger" }, { cmd: "/undo", desc: " \u2014 revert last patch or Cesar checkpoint" }, { cmd: "/checkpoints", desc: " \u2014 list recent file checkpoints" }, { cmd: "/jobs", desc: " \u2014 list running/completed jobs" }, { cmd: "/focus", desc: "<id> \u2014 switch to background job output" }, { cmd: "/explore", desc: " \u2014 toggle exploration mode (read-only)" }, { cmd: "/nero", desc: "[<decision>] \u2014 toggle Nero mode, or challenge a decision (top-rated critic)" }, { cmd: "/btw", desc: "<question> \u2014 ask something while engines work (side-channel)" }, { cmd: "/compact", desc: " \u2014 shrink Cesar context without clearing transcript" }, { cmd: "/mcp", desc: "connect <name|url> | disconnect <name> | list \u2014 manage session MCP servers" }, { cmd: "/init", desc: " \u2014 create AGON.md config wizard" }, { cmd: "/create-skill", desc: "<name> \u2014 scaffold a new skill (.agon/skills/)" }, { cmd: "/clear", desc: " \u2014 reset session (saves chat, clears brain)" }, { cmd: "/clean", desc: " \u2014 alias for /clear" }, { cmd: "/extensions", desc: " \u2014 list installed extensions" }, { cmd: "/help", desc: " \u2014 show this help" }, { cmd: "/exit", desc: " \u2014 quit" }];
6803
7169
  var FITNESS_PATTERN = /\b(?:test with|test:|--test|fitness:)\s+(.+)/i;
6804
7170
  var LEADERBOARD_KEYWORDS = /\b(leaderboard|elo|rankings?)\b/i;
6805
7171
  var HISTORY_KEYWORDS = /\b(history|last runs?|recent)\b/i;
@@ -7423,8 +7789,11 @@ function recordPastePlaceholder(hashMap, placeholder, fullHash) {
7423
7789
  hashes.push(fullHash);
7424
7790
  hashMap.set(placeholder, JSON.stringify(hashes));
7425
7791
  }
7792
+ function sanitizeInlinePaste(text) {
7793
+ return text.replace(/\x1b\[[0-?]*[ -\/]*[@-~]/g, "").replace(/\x1b\][^\x07\x1b]*(?:\x07|\x1b\\)/g, "").replace(/[\x00-\x08\x0b-\x1f\x7f]/g, "");
7794
+ }
7426
7795
  function processPasteContent(raw) {
7427
- const normalized = raw.replace(/\r\n/g, "\n");
7796
+ const normalized = raw.replace(/\r\n?/g, "\n");
7428
7797
  const content = normalized.trimEnd();
7429
7798
  if (!content) {
7430
7799
  return { type: "empty" };
@@ -7440,7 +7809,7 @@ function processPasteContent(raw) {
7440
7809
  } catch (e) {
7441
7810
  }
7442
7811
  }
7443
- return { type: "direct", content: normalized };
7812
+ return { type: "direct", content: sanitizeInlinePaste(normalized) };
7444
7813
  }
7445
7814
  function expandPastePlaceholders(input, hashMap) {
7446
7815
  const takeHash = (key) => {
@@ -7796,20 +8165,21 @@ function buildPlanCallbacks(initialPlan, cb) {
7796
8165
  },
7797
8166
  onStepDone: (stepId, result) => {
7798
8167
  const step = currentPlan.steps.find((s) => s.id === stepId);
7799
- const icon = result.status === "success" ? "\u2713" : "\u2717";
7800
- const msgType = result.status === "success" ? "success" : "error";
8168
+ const isPausedResult = result.status === "paused";
8169
+ const icon = result.status === "success" ? "\u2713" : isPausedResult ? "\u23F8" : "\u2717";
8170
+ const msgType = result.status === "success" ? "success" : isPausedResult ? "warning" : "error";
7801
8171
  cb.dispatch({ type: "spinner-stop" });
7802
8172
  cb.dispatch({
7803
8173
  type: "tool-call",
7804
8174
  engineId: "cesar",
7805
8175
  tool: "PlanStep",
7806
8176
  input: JSON.stringify(buildPlanStepToolInput(stepId)),
7807
- status: result.status === "success" ? "done" : "error",
8177
+ status: result.status === "success" || isPausedResult ? "done" : "error",
7808
8178
  output: result.output ? result.output.slice(0, 4e3) : "",
7809
- error: result.error
8179
+ error: isPausedResult ? void 0 : result.error
7810
8180
  });
7811
8181
  cb.dispatch({ type: msgType, message: `${icon} ${step?.description ?? stepId} \u2014 ${result.status}${result.error ? ": " + result.error : ""} (${(result.durationMs / 1e3).toFixed(1)}s, $${result.actualCostUsd.toFixed(4)})` });
7812
- cb.dispatch({ type: "todos-update", id: stepId, state: result.status === "success" ? "done" : "failed", note: result.error ? result.error.slice(0, 80) : void 0 });
8182
+ cb.dispatch({ type: "todos-update", id: stepId, state: result.status === "success" ? "done" : isPausedResult ? "pending" : "failed", note: result.error ? result.error.slice(0, 80) : void 0 });
7813
8183
  },
7814
8184
  onPlanUpdate: (updated) => {
7815
8185
  const previousState = currentPlan.state;
@@ -9512,7 +9882,7 @@ async function handlePlanShow(dispatch, ctx, planId) {
9512
9882
  savePlan(approved);
9513
9883
  dispatch({ type: "success", message: "Plan approved." });
9514
9884
  if (approved.action.type === "forge") {
9515
- const { handleForge: handleForge2 } = await import("./forge-ES4RN7YM.js");
9885
+ const { handleForge: handleForge2 } = await import("./forge-GUOEJ5DJ.js");
9516
9886
  await handleForge2(approved.action.task, approved.action.fitnessCmd ?? null, dispatch, ctx, approved, approved.action.hardened);
9517
9887
  } else {
9518
9888
  dispatch({ type: "info", message: "Run the build again to execute." });
@@ -9538,7 +9908,7 @@ async function handleApprove(dispatch, ctx) {
9538
9908
  savePlan(plan);
9539
9909
  dispatch({ type: "success", message: "Plan approved." });
9540
9910
  if (plan.action.type === "forge") {
9541
- const { handleForge: handleForge2 } = await import("./forge-ES4RN7YM.js");
9911
+ const { handleForge: handleForge2 } = await import("./forge-GUOEJ5DJ.js");
9542
9912
  await handleForge2(plan.action.task, plan.action.fitnessCmd ?? null, dispatch, ctx, plan, plan.action.hardened);
9543
9913
  } else {
9544
9914
  dispatch({ type: "info", message: "Run the build again to execute." });
@@ -9566,7 +9936,7 @@ async function handleRetry(dispatch, ctx) {
9566
9936
  plan = startPlan(plan);
9567
9937
  ctx.setCurrentPlan(plan);
9568
9938
  savePlan(plan);
9569
- const { handleForge: handleForge2 } = await import("./forge-ES4RN7YM.js");
9939
+ const { handleForge: handleForge2 } = await import("./forge-GUOEJ5DJ.js");
9570
9940
  await handleForge2(plan.action.task, plan.action.fitnessCmd ?? null, dispatch, ctx, plan, plan.action.hardened);
9571
9941
  } else {
9572
9942
  dispatch({ type: "info", message: "Plan reset to approved. Run the build again to execute." });
@@ -10894,7 +11264,7 @@ async function handleNeroChallenge(decision, dispatch, ctx, opts) {
10894
11264
  dispatch({ type: "error", message: `Nero produced no usable challenge${result.challengeText ? `: ${result.challengeText}` : "."}` });
10895
11265
  return;
10896
11266
  }
10897
- const pick = result.reason === "forced" ? "forced" : result.reason === "random" ? "random \u2014 no Elo yet" : `top-rated via ${result.scope}`;
11267
+ const pick = result.reason === "forced" ? "forced" : result.reason === "random" ? "random \u2014 no rating yet" : `top-rated via ${result.scope}`;
10898
11268
  dispatch({ type: "info", message: `Critic: ${result.engineId} (${pick})` });
10899
11269
  dispatch({ type: "engine-block", engineId: result.engineId, color: 196, content: result.challengeText });
10900
11270
  const verdictLine = `${verdictGlyph2(result.verdict)} VERDICT: ${result.verdict.toUpperCase()}${result.challengeConfidence != null ? ` \xB7 Nero is ${result.challengeConfidence}% sure the original is correct` : ""}`;
@@ -12537,11 +12907,11 @@ async function runCesarBrainFallback(input, cb, crashDel, priorDeterministic) {
12537
12907
  }
12538
12908
  if (!usingApiBackend) try {
12539
12909
  const cesarEngine = cesarEngineDef ?? cb.ctx.registry.get(cesarId);
12540
- const { join: join46 } = await import("path");
12541
- const { mkdirSync: mkdirSync29 } = await import("fs");
12542
- const { resolveWorkingDir: resolveWorkingDir3, RUNS_DIR: RUNS_DIR3, appendMessage: appendMessage3 } = await import("./src-WJGIOESS.js");
12543
- const outDir = join46(RUNS_DIR3, `cesar-fallback-${Date.now()}`);
12544
- mkdirSync29(outDir, { recursive: true });
12910
+ const { join: join47 } = await import("path");
12911
+ const { mkdirSync: mkdirSync30 } = await import("fs");
12912
+ const { resolveWorkingDir: resolveWorkingDir3, RUNS_DIR: RUNS_DIR3, appendMessage: appendMessage3 } = await import("./src-3NWTITZM.js");
12913
+ const outDir = join47(RUNS_DIR3, `cesar-fallback-${Date.now()}`);
12914
+ mkdirSync30(outDir, { recursive: true });
12545
12915
  if (!_silentMode) cb.dispatch({ type: "warning", message: formatCesarRecoveryStatus("retry", cesarId, `log: ${outDir}`) });
12546
12916
  const primedPrompt = buildHistoryPrimedPrompt(cb.ctx.chatSession, input);
12547
12917
  const freshResult = await cb.ctx.adapter.dispatch({
@@ -12720,12 +13090,12 @@ ${historyContext}
12720
13090
  ` : ""}## USER MESSAGE
12721
13091
  ${input}`;
12722
13092
  try {
12723
- const { resolveWorkingDir: resolveWorkingDir3, RUNS_DIR: RUNS_DIR3, appendMessage: appendMessage3 } = await import("./src-WJGIOESS.js");
12724
- const { join: join46 } = await import("path");
12725
- const { mkdirSync: mkdirSync29 } = await import("fs");
13093
+ const { resolveWorkingDir: resolveWorkingDir3, RUNS_DIR: RUNS_DIR3, appendMessage: appendMessage3 } = await import("./src-3NWTITZM.js");
13094
+ const { join: join47 } = await import("path");
13095
+ const { mkdirSync: mkdirSync30 } = await import("fs");
12726
13096
  const actingEngine = cb.ctx.registry.get(actingCesar);
12727
- const outDir = join46(RUNS_DIR3, `acting-cesar-${Date.now()}`);
12728
- mkdirSync29(outDir, { recursive: true });
13097
+ const outDir = join47(RUNS_DIR3, `acting-cesar-${Date.now()}`);
13098
+ mkdirSync30(outDir, { recursive: true });
12729
13099
  if (!_silentMode) cb.dispatch({ type: "info", message: formatCesarRecoveryStatus("acting", actingCesar, `log: ${outDir}`) });
12730
13100
  const actingResult = await cb.ctx.adapter.dispatch({
12731
13101
  engine: actingEngine,
@@ -13652,7 +14022,7 @@ async function dispatchSessionInfoIntent(intent, input, cb) {
13652
14022
  cb.setModelPickerTitle?.("Select model");
13653
14023
  cb.setModelPickerLoading(true);
13654
14024
  cb.setModelPickerOpen(true);
13655
- import("./src-WJGIOESS.js").then(({ fetchModelsRegistry: fetchModelsRegistry2, buildModelEntries: buildModelEntries2, buildCliGroupsImmediate, refreshCliGroup, refreshCliGroupVersion }) => {
14025
+ import("./src-3NWTITZM.js").then(({ fetchModelsRegistry: fetchModelsRegistry2, buildModelEntries: buildModelEntries2, buildCliGroupsImmediate, refreshCliGroup, refreshCliGroupVersion }) => {
13656
14026
  let cliGroups = buildCliGroupsImmediate();
13657
14027
  cb.setModelPickerCliGroups?.(cliGroups);
13658
14028
  for (const g of cliGroups) {
@@ -13710,7 +14080,7 @@ async function dispatchSessionInfoIntent(intent, input, cb) {
13710
14080
  await handlePlanShow(cb.dispatch, cb.ctx, intent.planId);
13711
14081
  break;
13712
14082
  case "plan-task": {
13713
- const { createCesarPlan } = await import("./src-WJGIOESS.js");
14083
+ const { createCesarPlan } = await import("./src-3NWTITZM.js");
13714
14084
  const cesarPlan = createCesarPlan(intent.task, []);
13715
14085
  cb.setActivePlan(cesarPlan);
13716
14086
  if (!cb.ctx.cesar) {
@@ -14018,7 +14388,7 @@ async function dispatchMetaIntent(intent, input, cb) {
14018
14388
  }
14019
14389
 
14020
14390
  // src/generated/signals/dispatch/intent-init.ts
14021
- import { join as join41, basename as basename4 } from "path";
14391
+ import { join as join41, basename as basename5 } from "path";
14022
14392
  import "fs";
14023
14393
  async function dispatchInitIntent(intent, input, cb) {
14024
14394
  switch (intent.type) {
@@ -14050,14 +14420,14 @@ async function dispatchInitIntent(intent, input, cb) {
14050
14420
  }
14051
14421
  const target = targets[0];
14052
14422
  const targetPath = target.path;
14053
- const { existsSync: existsSync15, mkdirSync: mkdirSync29, writeFileSync: writeFileSync14 } = await import("fs");
14423
+ const { existsSync: existsSync15, mkdirSync: mkdirSync30, writeFileSync: writeFileSync14 } = await import("fs");
14054
14424
  if (existsSync15(targetPath)) {
14055
14425
  cb.dispatch({ type: "warning", message: `AGON.md already exists: ${targetPath}` });
14056
14426
  cb.dispatch({ type: "info", message: "Edit it directly or delete it first to regenerate." });
14057
14427
  break;
14058
14428
  }
14059
- const { dirname: dirname9 } = await import("path");
14060
- mkdirSync29(dirname9(targetPath), { recursive: true });
14429
+ const { dirname: dirname10 } = await import("path");
14430
+ mkdirSync30(dirname10(targetPath), { recursive: true });
14061
14431
  const cwd = resolveWorkingDir();
14062
14432
  const shellVar = process.env.SHELL ?? "/bin/zsh";
14063
14433
  const isZsh = shellVar.includes("zsh");
@@ -14143,7 +14513,7 @@ async function dispatchInitIntent(intent, input, cb) {
14143
14513
  ].join("\n");
14144
14514
  } else {
14145
14515
  const { readFileSync: readSync, existsSync: existsSync22, readdirSync: readdirSync9 } = await import("fs");
14146
- let projectName = basename4(cwd);
14516
+ let projectName = basename5(cwd);
14147
14517
  let projectDesc = "";
14148
14518
  try {
14149
14519
  const pkg = JSON.parse(readSync(join41(cwd, "package.json"), "utf-8"));
@@ -14353,12 +14723,12 @@ async function dispatchSkillsUiIntent(intent, input, cb) {
14353
14723
  const trigger = `/${slug}`;
14354
14724
  const skillDir = join42(resolveWorkingDir(), ".agon", "skills");
14355
14725
  const skillPath = join42(skillDir, `${slug}.md`);
14356
- const { mkdirSync: mkdirSync29, existsSync: existsSync15, writeFileSync: writeFileSync14 } = await import("fs");
14726
+ const { mkdirSync: mkdirSync30, existsSync: existsSync15, writeFileSync: writeFileSync14 } = await import("fs");
14357
14727
  if (existsSync15(skillPath)) {
14358
14728
  cb.dispatch({ type: "warning", message: `Skill already exists: ${skillPath}` });
14359
14729
  break;
14360
14730
  }
14361
- mkdirSync29(skillDir, { recursive: true });
14731
+ mkdirSync30(skillDir, { recursive: true });
14362
14732
  const template = [
14363
14733
  "---",
14364
14734
  `name: ${skillName}`,
@@ -15114,10 +15484,9 @@ function resolveKeyboardInput(ctx) {
15114
15484
  if (key.escape) return { type: "cancelChoice" };
15115
15485
  return { type: "swallow" };
15116
15486
  }
15117
- if (ctx.updateInfo && ctx.updateInfo.latestVersion && ctx.inputValue === "" && !ctx.textInputActive && !ctx.questionState && !ctx.modelPickerOpen && !ctx.cesarPickerOpen && !ctx.toolDetailOpen && !ctx.slashPickerOpen && !ctx.enginePickerOpen && !ctx.reviewEventOpen && !hasCtrlSignal && (input === "u" || input === "U" || input === "l" || input === "L" || input === "x" || input === "X")) {
15118
- const lower = input.toLowerCase();
15119
- if (lower === "u") return { type: "updateBanner", action: "update" };
15120
- if (lower === "l") return { type: "updateBanner", action: "changelog" };
15487
+ if (ctx.updateInfo && ctx.updateInfo.latestVersion && ctx.inputValue === "" && !ctx.questionState && !ctx.modelPickerOpen && !ctx.cesarPickerOpen && !ctx.toolDetailOpen && !ctx.slashPickerOpen && !ctx.enginePickerOpen && !ctx.reviewEventOpen && !hasCtrlSignal && (input === "u" || input === "l" || input === "x")) {
15488
+ if (input === "u") return { type: "updateBanner", action: "update" };
15489
+ if (input === "l") return { type: "updateBanner", action: "changelog" };
15121
15490
  return { type: "updateBanner", action: "dismiss" };
15122
15491
  }
15123
15492
  if (ctx.textInputActive && hasCtrlSignal && delegatedCtrlShortcuts.has(normalizedCtrlInput)) {
@@ -15226,7 +15595,6 @@ var MAX_LIVE_BLOCKS = 500;
15226
15595
  var ARCHIVE_BATCH = 100;
15227
15596
  function makeBlockArchivePath(sessionStartTime) {
15228
15597
  const dir = join43(RUNS_DIR, `live-${sessionStartTime}`);
15229
- mkdirSync27(dir, { recursive: true });
15230
15598
  return join43(dir, "transcript.ndjson");
15231
15599
  }
15232
15600
  function archiveBlocks(archivePath, blocks) {
@@ -15249,6 +15617,25 @@ function appendBlockWithCap(prev, block, archivePath) {
15249
15617
  return next.slice(overflow);
15250
15618
  }
15251
15619
 
15620
+ // src/generated/signals/input-perf.ts
15621
+ import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync28 } from "fs";
15622
+ import { join as join44, dirname as dirname8 } from "path";
15623
+ var PERF_ENABLED = process.env.AGON_PERF === "1";
15624
+ var PERF_PATH = join44(AGON_HOME, "perf", "input-latency.ndjson");
15625
+ function perfNow() {
15626
+ return PERF_ENABLED ? performance.now() : 0;
15627
+ }
15628
+ function recordKeystrokeLatency(t0, blocks, archive, live, inputLen) {
15629
+ if (!PERF_ENABLED || !t0) return;
15630
+ try {
15631
+ const dtMs = Math.round((performance.now() - t0) * 100) / 100;
15632
+ const line = JSON.stringify({ ts: Date.now(), dtMs, blocks, archive, live, inputLen }) + "\n";
15633
+ mkdirSync28(dirname8(PERF_PATH), { recursive: true });
15634
+ appendFileSync3(PERF_PATH, line);
15635
+ } catch {
15636
+ }
15637
+ }
15638
+
15252
15639
  // src/generated/blocks/review.ts
15253
15640
  import { spawnSync as spawnSync4 } from "child_process";
15254
15641
  function handleReviewAction(action, review, dispatch) {
@@ -17059,13 +17446,14 @@ function useStableInput(inputHandler, options = {}) {
17059
17446
 
17060
17447
  // src/generated/blocks/prompt-input.tsx
17061
17448
  import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
17062
- var PromptTextInput = React4.memo(function PromptTextInput2({ value, placeholder, focus, showCursor, highlightPastedText, ghostText, width, maxVisibleLines, onChange, onSubmit, onCtrlShortcut, onPaste }) {
17449
+ var PromptTextInput = React4.memo(function PromptTextInput2({ value, placeholder, focus, showCursor, highlightPastedText, ghostText, width, maxVisibleLines, onChange, onSubmit, onCtrlShortcut, onPaste, reservedPlainKeys }) {
17063
17450
  const originalValue = value;
17064
17451
  const resolvedPlaceholder = placeholder ?? "";
17065
17452
  const resolvedFocus = focus ?? true;
17066
17453
  const resolvedShowCursor = showCursor ?? true;
17067
17454
  const resolvedHighlightPastedText = highlightPastedText ?? true;
17068
17455
  const resolvedMaxVisibleLines = maxVisibleLines ?? 6;
17456
+ const resolvedReservedPlainKeys = reservedPlainKeys ?? [];
17069
17457
  const [bufferedValue, setBufferedValue] = useState3(originalValue);
17070
17458
  const [state, setState] = useState3({
17071
17459
  cursorOffset: originalValue.length,
@@ -17163,6 +17551,9 @@ var PromptTextInput = React4.memo(function PromptTextInput2({ value, placeholder
17163
17551
  onCtrlShortcut?.(normalizedCtrlInput);
17164
17552
  return;
17165
17553
  }
17554
+ if (shouldDeferReservedPlainKey(input, hasCtrlSignal, hasSpecialKeySignal, value, resolvedReservedPlainKeys)) {
17555
+ return;
17556
+ }
17166
17557
  if (key.upArrow || key.downArrow || key.pageUp || key.pageDown || key.tab || isShiftTab) return;
17167
17558
  if (hasCtrlSignal && !isSupportedCtrlEditShortcut) return;
17168
17559
  if (key.meta && !isWordLeft && !isWordRight && !isDeleteWordBackward) return;
@@ -17437,6 +17828,9 @@ function pluralizeLines(count) {
17437
17828
  function isDelegatedCtrlShortcut(input) {
17438
17829
  return ["b", "c", "e", "g", "i", "j", "l", "r", "t", "y"].includes(input);
17439
17830
  }
17831
+ function shouldDeferReservedPlainKey(input, hasCtrlSignal, hasSpecialKeySignal, value, reservedPlainKeys) {
17832
+ return reservedPlainKeys.length > 0 && !hasCtrlSignal && !hasSpecialKeySignal && input.length === 1 && value === "" && reservedPlainKeys.includes(input);
17833
+ }
17440
17834
  function shouldAdoptPromptValue(originalValue, pendingEchoValue) {
17441
17835
  if (pendingEchoValue === null) {
17442
17836
  return true;
@@ -17455,7 +17849,7 @@ function shouldAdoptPromptValue(originalValue, pendingEchoValue) {
17455
17849
 
17456
17850
  // src/generated/blocks/composer.tsx
17457
17851
  import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
17458
- var ComposerView = React5.memo(function ComposerView2({ mode, replState, planModeQueued, autoModeQueued, activePlanState, slashPickerOpen, inputValue, handleInputChange, handlePasteInput, handleSubmit, allSlashCommands, availableEngines, onSlashSelect, onSlashCancel, questionState, questionAnswer, selectedChoiceIndex, questionOtherActive, onQuestionAnswerChange, onQuestionAnswerSubmit, onCtrlShortcut, termWidth, termHeight }) {
17852
+ var ComposerView = React5.memo(function ComposerView2({ mode, replState, planModeQueued, autoModeQueued, activePlanState, slashPickerOpen, inputValue, handleInputChange, handlePasteInput, handleSubmit, allSlashCommands, availableEngines, onSlashSelect, onSlashCancel, questionState, questionAnswer, selectedChoiceIndex, questionOtherActive, onQuestionAnswerChange, onQuestionAnswerSubmit, onCtrlShortcut, updateBannerActive, termWidth, termHeight }) {
17459
17853
  const placeholder = replState === "idle" ? mode === "chat" ? "" : mode === "campfire" ? "What should we think about?" : mode === "brainstorm" ? "What question for the engines?" : "What should they debate?" : "";
17460
17854
  const ghost = getGhostCompletion(inputValue, allSlashCommands, availableEngines);
17461
17855
  const promptWidth = Math.max(12, termWidth - (mode === "chat" ? 10 : 22));
@@ -17504,6 +17898,7 @@ var ComposerView = React5.memo(function ComposerView2({ mode, replState, planMod
17504
17898
  onPaste: handlePasteInput,
17505
17899
  onSubmit: handleSubmit,
17506
17900
  onCtrlShortcut,
17901
+ reservedPlainKeys: updateBannerActive ? UPDATE_BANNER_KEYS : void 0,
17507
17902
  placeholder,
17508
17903
  focus: true,
17509
17904
  showCursor: true,
@@ -17540,6 +17935,7 @@ var ComposerView = React5.memo(function ComposerView2({ mode, replState, planMod
17540
17935
  onPaste: void 0,
17541
17936
  onSubmit: onQuestionAnswerSubmit,
17542
17937
  onCtrlShortcut,
17938
+ reservedPlainKeys: void 0,
17543
17939
  placeholder: "type your instruction, Enter to send",
17544
17940
  focus: true,
17545
17941
  showCursor: true,
@@ -17591,6 +17987,7 @@ var ComposerView = React5.memo(function ComposerView2({ mode, replState, planMod
17591
17987
  onPaste: void 0,
17592
17988
  onSubmit: onQuestionAnswerSubmit,
17593
17989
  onCtrlShortcut,
17990
+ reservedPlainKeys: void 0,
17594
17991
  placeholder: "type your answer, Enter to send",
17595
17992
  focus: true,
17596
17993
  showCursor: true,
@@ -17613,6 +18010,7 @@ var ComposerView = React5.memo(function ComposerView2({ mode, replState, planMod
17613
18010
  onPaste: void 0,
17614
18011
  onSubmit: onQuestionAnswerSubmit,
17615
18012
  onCtrlShortcut,
18013
+ reservedPlainKeys: void 0,
17616
18014
  placeholder: "",
17617
18015
  focus: true,
17618
18016
  showCursor: true,
@@ -17625,6 +18023,7 @@ var ComposerView = React5.memo(function ComposerView2({ mode, replState, planMod
17625
18023
  ] }) }))
17626
18024
  ] });
17627
18025
  });
18026
+ var UPDATE_BANNER_KEYS = ["u", "l", "x"];
17628
18027
 
17629
18028
  // src/generated/surfaces/agent.tsx
17630
18029
  import React6 from "react";
@@ -18280,9 +18679,9 @@ function formatRelativeTime(ms) {
18280
18679
  }
18281
18680
 
18282
18681
  // src/generated/surfaces/app.tsx
18283
- import { join as join45 } from "path";
18682
+ import { join as join46 } from "path";
18284
18683
  import "url";
18285
- import { writeFileSync as writeFileSync13, mkdirSync as mkdirSync28, unlinkSync as unlinkSync4, statSync as statSync4 } from "fs";
18684
+ import { writeFileSync as writeFileSync13, mkdirSync as mkdirSync29, unlinkSync as unlinkSync4, statSync as statSync4 } from "fs";
18286
18685
  import { tmpdir as tmpdir3 } from "os";
18287
18686
  import { spawnSync as spawnSync6 } from "child_process";
18288
18687
 
@@ -18483,9 +18882,31 @@ function formatNero(r, idx) {
18483
18882
  }
18484
18883
  return lines.join("\n");
18485
18884
  }
18885
+ function formatReview(r, idx) {
18886
+ const data = r.data;
18887
+ const lines = [];
18888
+ const accent = data.blocking ? RED : YELLOW;
18889
+ lines.push(`${BOLD}${accent}${RULE}${RESET}`);
18890
+ lines.push(`${BOLD} REVIEW #${idx} ${DIM}\xB7 ${formatTime(r.timestamp)} \xB7 ${RESET}${BOLD}${data.label}${RESET}`);
18891
+ lines.push(`${DIM} Engines: ${r.engines.join(", ")}${data.blocking ? ` \xB7 ${RESET}${RED}${BOLD}BLOCKING${RESET}` : ""}${RESET}`);
18892
+ lines.push(`${BOLD}${accent}${RULE}${RESET}`);
18893
+ lines.push("");
18894
+ if (data.consensusSummary) {
18895
+ lines.push(`${BOLD}\u2500\u2500 Consensus \u2500\u2500${RESET}`);
18896
+ lines.push(data.consensusSummary);
18897
+ lines.push("");
18898
+ }
18899
+ for (const rev of data.reviews) {
18900
+ const statusTag = rev.status === "ok" ? "" : `${DIM} [${rev.status}]${RESET}`;
18901
+ lines.push(`${BOLD}\u2500\u2500 ${rev.engineId}${statusTag} \u2500\u2500${RESET}`);
18902
+ lines.push(rev.reviewOutput);
18903
+ lines.push("");
18904
+ }
18905
+ return lines.join("\n");
18906
+ }
18486
18907
  function formatSessionResults(results) {
18487
18908
  if (results.length === 0) {
18488
- return `${DIM}No results in this session yet. Run /brainstorm, /campfire, /tribunal, /forge, /think, /council, /synthesis, or /nero first.${RESET}
18909
+ return `${DIM}No results in this session yet. Run /brainstorm, /campfire, /tribunal, /forge, /think, /council, /synthesis, /nero, or /review first.${RESET}
18489
18910
  `;
18490
18911
  }
18491
18912
  const sections = [];
@@ -18519,17 +18940,20 @@ function formatSessionResults(results) {
18519
18940
  case "nero":
18520
18941
  sections.push(formatNero(r, idx));
18521
18942
  break;
18943
+ case "review":
18944
+ sections.push(formatReview(r, idx));
18945
+ break;
18522
18946
  }
18523
18947
  }
18524
18948
  return sections.join("\n");
18525
18949
  }
18526
18950
 
18527
18951
  // src/generated/surfaces/app-composer.ts
18528
- import { join as join44 } from "path";
18952
+ import { join as join45 } from "path";
18529
18953
  import { readFileSync as readFileSync14, writeFileSync as writeFileSync12 } from "fs";
18530
18954
  var COMPOSER_HISTORY_LIMIT = 200;
18531
18955
  function composerHistoryPath() {
18532
- return join44(getAgonHome(), "composer-history.json");
18956
+ return join45(getAgonHome(), "composer-history.json");
18533
18957
  }
18534
18958
  function loadComposerInputHistory() {
18535
18959
  try {
@@ -20046,7 +20470,7 @@ function buildTranscriptRows(blocks, mode, toolOutputExpanded, thinkingExpanded)
20046
20470
  { text: " " },
20047
20471
  { text: "\u265B ", color: "#fbbf24" },
20048
20472
  { text: event.eloTop.id, color: engineColor(event.eloTop.id), bold: true },
20049
- { text: ` ${event.eloTop.rating} ELO`, dimColor: true }
20473
+ { text: ` ${event.eloTop.rating} Glicko`, dimColor: true }
20050
20474
  ]);
20051
20475
  }
20052
20476
  [
@@ -21015,6 +21439,7 @@ function App() {
21015
21439
  const modeRef = useRef4("chat");
21016
21440
  const inputEpochRef = useRef4(0);
21017
21441
  const inputValueRef = useRef4("");
21442
+ const keyT0Ref = useRef4(0);
21018
21443
  const ctrlKeyHandledRef = useRef4(false);
21019
21444
  const pendingPasteTransformRef = useRef4(false);
21020
21445
  const pasteHashesRef = useRef4(/* @__PURE__ */ new Map());
@@ -21459,6 +21884,7 @@ function App() {
21459
21884
  return replacement;
21460
21885
  }, []);
21461
21886
  const handleInputChange = useCallback((value) => {
21887
+ keyT0Ref.current = perfNow();
21462
21888
  if (questionState && questionState.choices) {
21463
21889
  return;
21464
21890
  }
@@ -21552,7 +21978,7 @@ function App() {
21552
21978
  ${streamCtx ? "Recent live output from the running task:\n" + streamCtx + "\n\n" : ""}${transcriptCtx ? "Recent transcript context:\n" + transcriptCtx + "\n\n" : ""}Answer directly and briefly. Do not take over, cancel, or modify the main task.`;
21553
21979
  const btwNow = Date.now();
21554
21980
  const convId = btwPanel?.id ?? `btw-${btwNow}`;
21555
- const btwOutputDir = join45(RUNS_DIR, `${convId}-${btwNow}`);
21981
+ const btwOutputDir = join46(RUNS_DIR, `${convId}-${btwNow}`);
21556
21982
  try {
21557
21983
  btwAbortRef.current?.abort();
21558
21984
  } catch {
@@ -21565,7 +21991,7 @@ function App() {
21565
21991
  return { ...base, id: base.id ?? convId, engineId: cesarId, status: "running", error: "", messages, startedAt: btwNow };
21566
21992
  });
21567
21993
  try {
21568
- mkdirSync28(btwOutputDir, { recursive: true });
21994
+ mkdirSync29(btwOutputDir, { recursive: true });
21569
21995
  } catch {
21570
21996
  }
21571
21997
  ctx.adapter.dispatch({
@@ -21809,7 +22235,7 @@ function App() {
21809
22235
  setEnginePickerOpen(false);
21810
22236
  setModelPickerOpen(true);
21811
22237
  setModelPickerCliGroups([]);
21812
- import("./src-WJGIOESS.js").then(({ fetchModelsRegistry: fetchModelsRegistry2, buildModelEntries: buildModelEntries2, buildCliGroupsImmediate, refreshCliGroup, refreshCliGroupVersion }) => {
22238
+ import("./src-3NWTITZM.js").then(({ fetchModelsRegistry: fetchModelsRegistry2, buildModelEntries: buildModelEntries2, buildCliGroupsImmediate, refreshCliGroup, refreshCliGroupVersion }) => {
21813
22239
  let cliGroups = buildCliGroupsImmediate();
21814
22240
  setModelPickerCliGroups(cliGroups);
21815
22241
  for (const g of cliGroups) {
@@ -21861,14 +22287,14 @@ function App() {
21861
22287
  return;
21862
22288
  }
21863
22289
  content = formatChatTranscript(chatSession);
21864
- tmpFile = join45(tmpdir3(), `agon-chat-${Date.now()}.txt`);
22290
+ tmpFile = join46(tmpdir3(), `agon-chat-${Date.now()}.txt`);
21865
22291
  } else {
21866
22292
  if (!sessionResultStore.hasResults()) {
21867
22293
  dispatch({ type: "info", message: "No results yet \u2014 run /brainstorm, /campfire, /tribunal, or /forge first" });
21868
22294
  return;
21869
22295
  }
21870
22296
  content = formatSessionResults(sessionResultStore.getResults());
21871
- tmpFile = join45(tmpdir3(), `agon-results-${Date.now()}.txt`);
22297
+ tmpFile = join46(tmpdir3(), `agon-results-${Date.now()}.txt`);
21872
22298
  }
21873
22299
  try {
21874
22300
  writeFileSync13(tmpFile, content, "utf-8");
@@ -21970,7 +22396,7 @@ function App() {
21970
22396
  if (ans === "later") return;
21971
22397
  if (ans === "update") {
21972
22398
  setUpdateInfo(null);
21973
- import("./update-HHN4PJQI.js").then((m) => m.runUpdate(latest)).catch((err) => {
22399
+ import("./update-H3LE4ZSI.js").then((m) => m.runUpdate(latest)).catch((err) => {
21974
22400
  console.error("[agon] failed to launch update:", err && err.message ? err.message : String(err));
21975
22401
  });
21976
22402
  return;
@@ -22485,6 +22911,7 @@ function App() {
22485
22911
  lastReviewResultRef.current = lastReviewResult;
22486
22912
  }, [lastReviewResult]);
22487
22913
  useEffect6(() => {
22914
+ if (isLinkedDevInstall()) return;
22488
22915
  const startedAt = Date.now();
22489
22916
  const elapsed = () => Date.now() - startedAt;
22490
22917
  const boot = setTimeout(async () => {
@@ -22731,6 +23158,10 @@ function App() {
22731
23158
  useEffect6(() => {
22732
23159
  inputValueRef.current = inputValue;
22733
23160
  }, [inputValue]);
23161
+ useEffect6(() => {
23162
+ recordKeystrokeLatency(keyT0Ref.current, outputBlocks.length, effectiveNativeArchiveCount, nativeLiveBlocks.length, inputValue.length);
23163
+ keyT0Ref.current = 0;
23164
+ }, [inputValue]);
22734
23165
  useEffect6(() => {
22735
23166
  if (questionState && Array.isArray(questionState.choices) && questionState.choices.length > 0) {
22736
23167
  const dk = questionState.defaultChoiceKey;
@@ -22889,7 +23320,7 @@ function App() {
22889
23320
  _keyEnv = registry.get(engineId)?.api?.apiKeyEnv;
22890
23321
  } catch (_e) {
22891
23322
  }
22892
- const engPath = join45(getAgonHome(), "engines", `${engineId}.json`);
23323
+ const engPath = join46(getAgonHome(), "engines", `${engineId}.json`);
22893
23324
  try {
22894
23325
  unlinkSync4(engPath);
22895
23326
  } catch (_e) {
@@ -22984,9 +23415,9 @@ function App() {
22984
23415
  setModelPickerOpen(false);
22985
23416
  void (async () => {
22986
23417
  const def = modelEntryToEngineDef(entry);
22987
- const dir = join45(getAgonHome(), "engines");
22988
- mkdirSync28(dir, { recursive: true });
22989
- writeFileSync13(join45(dir, `${def.id}.json`), JSON.stringify(def, null, 2) + "\n");
23418
+ const dir = join46(getAgonHome(), "engines");
23419
+ mkdirSync29(dir, { recursive: true });
23420
+ writeFileSync13(join46(dir, `${def.id}.json`), JSON.stringify(def, null, 2) + "\n");
22990
23421
  registry.register(def);
22991
23422
  const envVar = def.api?.apiKeyEnv;
22992
23423
  if (envVar && !getAuthKey(envVar)) {
@@ -23136,6 +23567,7 @@ function App() {
23136
23567
  questionOtherActive,
23137
23568
  onQuestionAnswerChange: setQuestionAnswer,
23138
23569
  onQuestionAnswerSubmit: handleQuestionAnswer,
23570
+ updateBannerActive: !!(updateInfo && updateInfo.latestVersion) && !questionState && !modelPickerOpen && !cesarPickerOpen && !slashPickerOpen && !enginePickerOpen && !toolDetailEvent && !reviewEvent,
23139
23571
  termWidth,
23140
23572
  termHeight,
23141
23573
  onCtrlShortcut: handleComposerCtrlShortcut
@@ -23467,10 +23899,10 @@ consumeIsolationFlags();
23467
23899
  consumeContinueFlag();
23468
23900
  guardAgainstRecursiveDispatch();
23469
23901
  maybeNotifyIsolationMigration();
23470
- var main = defineCommand30({
23902
+ var main = defineCommand31({
23471
23903
  meta: {
23472
23904
  name: "agon",
23473
- version: "0.1.4",
23905
+ version: "0.1.6",
23474
23906
  description: "Any AI can join. They compete. You ship."
23475
23907
  },
23476
23908
  subCommands: {
@@ -23483,6 +23915,7 @@ var main = defineCommand30({
23483
23915
  "team-tribunal": teamTribunalCommand,
23484
23916
  leaderboard: leaderboardCommand,
23485
23917
  history: historyCommand,
23918
+ room: roomCommand,
23486
23919
  provenance: provenanceCommand,
23487
23920
  engine: engineCommand,
23488
23921
  doctor: doctorCommand,