@wrongstack/cli 0.306.4 → 0.307.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/dist/{auth-L3WGSGDX.js → auth-TVOOHL4Q.js} +45 -106
  2. package/dist/boot/short-circuit-flags.d.ts +2 -2
  3. package/dist/chimera-cascade-evidence.d.ts +1 -1
  4. package/dist/chimera-reviewer-policy.d.ts +1 -1
  5. package/dist/chunk-2VMJ3E5Z.js +71 -0
  6. package/dist/{chunk-RHLQT3EV.js → chunk-CB35UVXO.js} +1636 -1528
  7. package/dist/{chunk-YKBRFSGL.js → chunk-DOJLAULS.js} +28 -28
  8. package/dist/{chunk-KXN5HZDL.js → chunk-PKHGLWUJ.js} +24 -6
  9. package/dist/{chunk-HITHEXE3.js → chunk-TOG7OMKJ.js} +2 -2
  10. package/dist/{chunk-ARWGQUB3.js → chunk-XSG33WHN.js} +15 -5
  11. package/dist/{cli-main-4TZCCZR6.js → cli-main-DD3I7KOO.js} +29198 -28411
  12. package/dist/cli-main.d.ts +0 -20
  13. package/dist/{execution-547PM3NI.js → execution-4ASWJ7EY.js} +309 -273
  14. package/dist/fleet/host-learning-scheduler.d.ts +27 -0
  15. package/dist/fleet/host-shadow-manager.d.ts +64 -0
  16. package/dist/fleet/host.d.ts +5 -140
  17. package/dist/{hq-ZK6PGN3W.js → hq-PA6RH2UW.js} +2 -2
  18. package/dist/hq-server/mailbox-gateway-manager.d.ts +32 -0
  19. package/dist/hq-server/routes/auth/bootstrap-routes.d.ts +5 -0
  20. package/dist/hq-server/routes/auth/common.d.ts +11 -0
  21. package/dist/hq-server/routes/auth/password-routes.d.ts +9 -0
  22. package/dist/hq-server/routes/auth/session-audit-routes.d.ts +6 -0
  23. package/dist/hq-server/routes/auth/totp-routes.d.ts +9 -0
  24. package/dist/hq-server/routes/auth-handlers.d.ts +5 -132
  25. package/dist/hq-server/routes/command-handlers.d.ts +7 -0
  26. package/dist/hq-server/routes/data-handlers.d.ts +8 -0
  27. package/dist/hq-server/routes/mailbox-handlers.d.ts +22 -0
  28. package/dist/hq-server/routes.d.ts +3 -3
  29. package/dist/hq-server/server-lifecycle.d.ts +37 -0
  30. package/dist/hq-server/snapshot.d.ts +6 -5
  31. package/dist/hq-server/types.d.ts +4 -0
  32. package/dist/hq-server/upgrade-handler.d.ts +34 -0
  33. package/dist/hq-server/ws-client-events.d.ts +25 -0
  34. package/dist/hq-server/ws-leader.d.ts +47 -0
  35. package/dist/hq-server/ws-resume.d.ts +27 -0
  36. package/dist/hq-server/ws.d.ts +4 -71
  37. package/dist/{hq-server-IVZLVCFV.js → hq-server-PBRU275L.js} +2 -2
  38. package/dist/hq-server.d.ts +0 -38
  39. package/dist/index.js +1267 -122
  40. package/dist/{mcp-W7HHN7IA.js → mcp-CMLFHRG2.js} +14 -7
  41. package/dist/mcp-serve.d.ts +12 -1
  42. package/dist/{modeldiag-6VS5KDP5.js → modeldiag-ICMPHT5L.js} +868 -831
  43. package/dist/{providers-models-HQN3AT3K.js → providers-models-4FAKM2WO.js} +4 -4
  44. package/dist/repl-eternal-loop.d.ts +8 -0
  45. package/dist/repl-goal-banner.d.ts +21 -0
  46. package/dist/slash-commands/brain-council.d.ts +36 -0
  47. package/dist/slash-commands/brain-status.d.ts +12 -0
  48. package/dist/slash-commands/kanban-board-handlers.d.ts +13 -0
  49. package/dist/slash-commands/kanban-lifecycle-diagnostics.d.ts +16 -0
  50. package/dist/slash-commands/kanban-task-subcommands.d.ts +8 -0
  51. package/dist/slash-commands/memory-audience.d.ts +14 -0
  52. package/dist/slash-commands/memory-gather.d.ts +9 -0
  53. package/dist/slash-commands/memory-stats.d.ts +5 -0
  54. package/dist/slash-commands/settings-mutations.d.ts +6 -0
  55. package/dist/slash-commands/settings-view.d.ts +5 -0
  56. package/dist/subcommands/handlers/modeldiag-bench.d.ts +10 -0
  57. package/dist/subcommands/handlers/modeldiag-eval.d.ts +27 -0
  58. package/dist/subcommands/handlers/modeldiag-test.d.ts +8 -0
  59. package/dist/{version-help-ASKQYXDJ.js → version-help-TFD6VPF3.js} +2 -2
  60. package/dist/vibe-protocol-wiring.d.ts +2 -0
  61. package/dist/webui-server/credential-watcher.d.ts +15 -0
  62. package/dist/webui-server/domain-handlers.d.ts +21 -0
  63. package/dist/webui-server/route-contexts.d.ts +41 -0
  64. package/dist/{webui-server-FTG7JAZU.js → webui-server-IPHGJGXE.js} +515 -437
  65. package/dist/wiring/cli-execute-builder.d.ts +88 -0
  66. package/dist/wiring/cli-heap-watchdog.d.ts +33 -0
  67. package/dist/wiring/cli-prompt-and-tools-setup.d.ts +25 -0
  68. package/dist/wiring/cli-slash-commands-setup.d.ts +79 -0
  69. package/dist/wiring/heap-watchdog-setup.d.ts +53 -0
  70. package/dist/wiring/metrics.d.ts +1 -0
  71. package/dist/wiring/prompt-journal-recorder.d.ts +45 -0
  72. package/dist/wiring/replay-governance-setup.d.ts +31 -0
  73. package/package.json +27 -27
@@ -29,27 +29,27 @@ import {
29
29
  import {
30
30
  theme
31
31
  } from "./chunk-QD544J2B.js";
32
- import {
33
- fmtTok
34
- } from "./chunk-TYO2OVAD.js";
35
32
  import {
36
33
  WEBUI_SESSION_CHILD_CAPABILITIES,
37
34
  writeWebuiSessionChildError,
38
35
  writeWebuiSessionChildReady
39
36
  } from "./chunk-3JPTNADJ.js";
40
37
  import {
41
- CLI_VERSION
42
- } from "./chunk-XJXDOF63.js";
38
+ fmtTok
39
+ } from "./chunk-TYO2OVAD.js";
43
40
  import {
44
41
  terminalLink,
45
42
  terminalText
46
43
  } from "./chunk-KE7E7DPX.js";
47
44
  import {
48
- resolveActiveApiKey
49
- } from "./chunk-SZ42FYPT.js";
45
+ CLI_VERSION
46
+ } from "./chunk-XJXDOF63.js";
50
47
  import {
51
48
  activeProfileConfigPath
52
49
  } from "./chunk-YMXXOOFN.js";
50
+ import {
51
+ resolveActiveApiKey
52
+ } from "./chunk-SZ42FYPT.js";
53
53
  import "./chunk-7OCVIDC7.js";
54
54
 
55
55
  // src/execution.ts
@@ -205,7 +205,7 @@ async function runWebUIDispatch(ctx) {
205
205
  const isSimpleUi = !isSessionChild && flags["simpleui"] === true;
206
206
  agent.disableInteractiveConfirmation();
207
207
  renderer.setSilent(true);
208
- const { runWebUI } = await import("./webui-server-FTG7JAZU.js");
208
+ const { runWebUI } = await import("./webui-server-IPHGJGXE.js");
209
209
  const flagValue = (names) => {
210
210
  for (const name of names) {
211
211
  if (!Object.hasOwn(flags, name)) continue;
@@ -1318,7 +1318,7 @@ async function resumeSession(ctx, sessionId) {
1318
1318
  throw err;
1319
1319
  }
1320
1320
  writerSwapped = true;
1321
- state.sessionRef && (state.sessionRef.current = resumed.writer);
1321
+ if (state.sessionRef) state.sessionRef.current = resumed.writer;
1322
1322
  await agent.ctx.flushConversationJournal().catch((err) => {
1323
1323
  console.error(
1324
1324
  JSON.stringify({
@@ -1358,30 +1358,31 @@ async function resumeSession(ctx, sessionId) {
1358
1358
  const targetProviderId = typeof meta.provider === "string" && meta.provider.length > 0 ? meta.provider : currentProviderId;
1359
1359
  const targetModel = typeof meta.model === "string" && meta.model.length > 0 ? meta.model : agent.ctx.model;
1360
1360
  if (switchProviderAndModel && targetProviderId && (targetProviderId !== currentProviderId || targetModel !== agent.ctx.model)) {
1361
- await Promise.resolve(switchProviderAndModel(targetProviderId, targetModel)).catch(
1362
- (err) => {
1363
- console.error(
1364
- JSON.stringify({
1365
- level: "error",
1366
- event: "execution.resume_model_restore_failed",
1367
- provider: targetProviderId,
1368
- model: targetModel,
1369
- message: err instanceof Error ? err.message : String(err),
1370
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
1371
- })
1372
- );
1373
- }
1374
- );
1361
+ try {
1362
+ await Promise.resolve(switchProviderAndModel(targetProviderId, targetModel));
1363
+ } catch (err) {
1364
+ console.error(
1365
+ JSON.stringify({
1366
+ level: "error",
1367
+ event: "execution.resume_model_restore_failed",
1368
+ provider: targetProviderId,
1369
+ model: targetModel,
1370
+ message: err instanceof Error ? err.message : String(err),
1371
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
1372
+ })
1373
+ );
1374
+ }
1375
1375
  } else if (targetModel !== agent.ctx.model) {
1376
1376
  agent.ctx.model = targetModel;
1377
1377
  }
1378
- let oldWriterFinalize;
1378
+ let finalizeOldWriter;
1379
1379
  if (oldWriter && oldWriter !== resumed.writer) {
1380
+ const staleWriter = oldWriter;
1380
1381
  const endedUsage = tokenCounter.total();
1381
- oldWriterFinalize = void (async () => {
1382
+ finalizeOldWriter = async () => {
1382
1383
  let appendOk = false;
1383
1384
  try {
1384
- await oldWriter.append({
1385
+ await staleWriter.append({
1385
1386
  type: "session_end",
1386
1387
  ts: (/* @__PURE__ */ new Date()).toISOString(),
1387
1388
  usage: endedUsage
@@ -1399,7 +1400,7 @@ async function resumeSession(ctx, sessionId) {
1399
1400
  }
1400
1401
  if (appendOk) {
1401
1402
  try {
1402
- await oldWriter.close();
1403
+ await staleWriter.close();
1403
1404
  } catch (err) {
1404
1405
  console.error(
1405
1406
  JSON.stringify({
@@ -1411,7 +1412,7 @@ async function resumeSession(ctx, sessionId) {
1411
1412
  );
1412
1413
  }
1413
1414
  }
1414
- })();
1415
+ };
1415
1416
  }
1416
1417
  tokenCounter.reset();
1417
1418
  tokenCounter.account(resumed.data.usage, targetModel, targetProviderId);
@@ -1424,7 +1425,7 @@ async function resumeSession(ctx, sessionId) {
1424
1425
  sessionId: resumed.writer.id,
1425
1426
  contextSnapshot: { tokens, maxContext }
1426
1427
  };
1427
- void oldWriterFinalize;
1428
+ if (finalizeOldWriter) void finalizeOldWriter();
1428
1429
  return result;
1429
1430
  } catch (err) {
1430
1431
  if (!identityClaimed) await resumeClaim?.cancel().catch(() => void 0);
@@ -2181,8 +2182,12 @@ var CHIMERA_REVIEW_READ_ONLY_TOOLS = Object.freeze([
2181
2182
  "grep",
2182
2183
  "glob",
2183
2184
  "tree",
2185
+ "codebase-stats",
2184
2186
  "codebase-search",
2185
- "codebase-stats"
2187
+ "codebase-skeleton",
2188
+ "codebase-repo-map",
2189
+ "codebase-incoming-calls",
2190
+ "codebase-outgoing-calls"
2186
2191
  ]);
2187
2192
  function applyChimeraReviewerReadOnlyPolicy(config) {
2188
2193
  return {
@@ -2750,18 +2755,26 @@ import { emitReviewIfChanged } from "@wrongstack/core/plugin";
2750
2755
 
2751
2756
  // src/chimera-cascade-evidence.ts
2752
2757
  import { spawn as spawn2 } from "node:child_process";
2753
- var JSON_BLOCK_RE = /```json\s*([\s\S]*?)```/gi;
2758
+ var JSON_BLOCK_RE = /```(?:json)?\s*([\s\S]*?)```/gi;
2759
+ function tryParseJson(raw) {
2760
+ try {
2761
+ return JSON.parse(raw);
2762
+ } catch {
2763
+ try {
2764
+ const cleaned = raw.replace(/,\s*([}\]])/g, "$1");
2765
+ return JSON.parse(cleaned);
2766
+ } catch {
2767
+ return null;
2768
+ }
2769
+ }
2770
+ }
2754
2771
  function extractCascadeEvidence(text) {
2755
2772
  if (!text) return null;
2756
2773
  for (const match of text.matchAll(JSON_BLOCK_RE)) {
2757
2774
  const body = match[1]?.trim();
2758
2775
  if (!body) continue;
2759
- let parsed;
2760
- try {
2761
- parsed = JSON.parse(body);
2762
- } catch {
2763
- continue;
2764
- }
2776
+ const parsed = tryParseJson(body);
2777
+ if (!parsed) continue;
2765
2778
  const evidence = parseEvidenceObject(parsed);
2766
2779
  if (evidence) return evidence;
2767
2780
  }
@@ -2822,7 +2835,7 @@ function isSafeCascadeCommand(command) {
2822
2835
  const tokens = command.trim().split(/\s+/);
2823
2836
  if (tokens.length === 0) return false;
2824
2837
  if (!SAFE_EXECUTABLES.has(tokens[0])) return false;
2825
- return tokens.every((token) => /^[A-Za-z0-9@/._:=~+*?\[\]-]+$/.test(token));
2838
+ return tokens.every((token) => /^[A-Za-z0-9@/._:=~+*?[\]-]+$/.test(token));
2826
2839
  }
2827
2840
  var runCascadeVerificationCommand = (command, cwd, timeoutMs) => {
2828
2841
  if (!isSafeCascadeCommand(command)) {
@@ -3656,6 +3669,10 @@ function installChimeraReviewHandler({
3656
3669
  const inScopeCited = citedFindings.filter((finding) => {
3657
3670
  const citedKey = normalizeFileKeyForCitation(finding.location.file, p.cwd);
3658
3671
  if (citedPaths.has(citedKey)) return true;
3672
+ const suffixMatches = [...citedPaths].filter(
3673
+ (cp) => cp.endsWith(`/${citedKey}`) || cp === citedKey
3674
+ );
3675
+ if (suffixMatches.length === 1) return true;
3659
3676
  const basename7 = path11.basename(finding.location.file).toLowerCase();
3660
3677
  const bucket = changedBasenameIndex.get(basename7);
3661
3678
  return !!(bucket && bucket.length === 1);
@@ -3672,7 +3689,7 @@ function installChimeraReviewHandler({
3672
3689
  const failedVerificationCount = inScopeCited.filter(
3673
3690
  (finding) => finding.verification?.status === "failed"
3674
3691
  ).length;
3675
- const effectiveHasFindings = reviewHasFindings && actionableFindings.length > 0;
3692
+ const effectiveHasFindings = reviewHasFindings && (actionableFindings.length > 0 || unverifiedInScope.length > 0);
3676
3693
  const verifiedCount = actionableFindings.length;
3677
3694
  const unverifiedCount = unverifiedInScope.length;
3678
3695
  const hallucinationNote = droppedCitations.length > 0 ? `
@@ -3958,13 +3975,11 @@ async function predictNextTasks(input, opts) {
3958
3975
 
3959
3976
  // src/repl.ts
3960
3977
  import { detectContinueIntent, InputBuilder, resolveContinuation } from "@wrongstack/core/agent";
3961
- import { goalFilePath, loadGoal, summarizeUsage } from "@wrongstack/core/goal";
3962
3978
  import {
3963
- color as color9,
3979
+ color as color11,
3964
3980
  estimateRequestTokensCalibrated as estimateRequestTokensCalibrated2,
3965
- expectDefined,
3966
3981
  hasOpenTodos as hasOpenTodos2,
3967
- toErrorMessage
3982
+ toErrorMessage as toErrorMessage3
3968
3983
  } from "@wrongstack/core/utils";
3969
3984
  import { readClipboardImage, routeImagesForModel } from "@wrongstack/runtime";
3970
3985
  import { createAutoProceedLoopGuard } from "@wrongstack/tools/auto-proceed-loop-guard";
@@ -4190,11 +4205,210 @@ function registerReplClient(opts) {
4190
4205
  };
4191
4206
  }
4192
4207
 
4208
+ // src/repl-eternal-loop.ts
4209
+ import { goalFilePath as goalFilePath2, summarizeUsage } from "@wrongstack/core/goal";
4210
+ import { color as color8, toErrorMessage as toErrorMessage2 } from "@wrongstack/core/utils";
4211
+
4212
+ // src/repl-goal-banner.ts
4213
+ import { goalFilePath, loadGoal } from "@wrongstack/core/goal";
4214
+ import { color as color7, expectDefined, toErrorMessage } from "@wrongstack/core/utils";
4215
+ async function loadGoalSafe(opts) {
4216
+ if (!opts.projectRoot) return null;
4217
+ try {
4218
+ return await loadGoal(goalFilePath(opts.projectRoot));
4219
+ } catch {
4220
+ return null;
4221
+ }
4222
+ }
4223
+ async function renderGoalBanner(opts) {
4224
+ const goal = await loadGoalSafe(opts);
4225
+ if (!goal) return;
4226
+ const summary = goal.goal.length > 80 ? `${goal.goal.slice(0, 77)}\u2026` : goal.goal;
4227
+ const stateColor = goal.goalState === "active" ? color7.green : goal.goalState === "paused" ? color7.amber : goal.goalState === "completed" ? color7.green : color7.dim;
4228
+ opts.renderer.write(
4229
+ color7.dim("Goal: ") + stateColor(summary) + color7.dim(` [${goal.goalState}] (iter ${goal.iterations})`) + "\n"
4230
+ );
4231
+ if (goal.journal.length > 0) {
4232
+ const lastEntry = expectDefined(goal.journal[goal.journal.length - 1]);
4233
+ const statusIcon = lastEntry.status === "success" ? "\u2713" : lastEntry.status === "failure" ? "\u2717" : lastEntry.status === "aborted" ? "\u2298" : lastEntry.status === "skipped" ? "\u229D" : "\xB7";
4234
+ opts.renderer.write(
4235
+ color7.dim(` Last: ${statusIcon} ${lastEntry.task} (${lastEntry.status})`) + "\n"
4236
+ );
4237
+ }
4238
+ if (goal.engineState === "running") {
4239
+ opts.renderer.write(
4240
+ color7.amber(" \u21BA Eternal engine was running when last session ended.") + "\n"
4241
+ );
4242
+ try {
4243
+ const answer = (await opts.reader.readLine(color7.dim(" Resume eternal mode? [y/N] "))).trim().toLowerCase();
4244
+ if (answer === "y" || answer === "yes") {
4245
+ try {
4246
+ await opts.slashRegistry.dispatch("/autonomy eternal", opts.agent.ctx);
4247
+ } catch (err) {
4248
+ opts.renderer.writeError(`Auto-resume failed: ${toErrorMessage(err)}`);
4249
+ }
4250
+ } else {
4251
+ opts.renderer.write(
4252
+ color7.dim(" Not resuming. Use `/autonomy eternal` later to continue.") + "\n"
4253
+ );
4254
+ }
4255
+ } catch {
4256
+ opts.renderer.write(color7.dim(" Use `/autonomy eternal` to resume.") + "\n");
4257
+ }
4258
+ } else if (goal.goalState === "paused") {
4259
+ opts.renderer.write(color7.amber(" \u23F8 Goal is paused. Use `/goal resume` to continue.") + "\n");
4260
+ } else if (goal.goalState === "completed") {
4261
+ opts.renderer.write(
4262
+ color7.green(" \u2713 Goal completed! Use `/goal clear` to set a new goal.") + "\n"
4263
+ );
4264
+ } else if (goal.goalState === "abandoned") {
4265
+ opts.renderer.write(color7.dim(" Use `/goal clear` to set a new goal.") + "\n");
4266
+ }
4267
+ opts.renderer.write("\n");
4268
+ }
4269
+
4270
+ // src/repl-eternal-loop.ts
4271
+ async function runReplEternalLoop(opts, onInterruptsReset) {
4272
+ const autonomy = opts.getAutonomy?.();
4273
+ if (autonomy === "eternal") {
4274
+ const engine = opts.getEternalEngine?.();
4275
+ if (!engine) {
4276
+ opts.renderer.writeWarning("Eternal mode set but no engine wired \u2014 falling back to off.");
4277
+ return false;
4278
+ }
4279
+ const beforeGoal = await loadGoalSafe(opts);
4280
+ const beforeIter = beforeGoal?.iterations ?? 0;
4281
+ opts.renderer.write(color8.dim(`
4282
+ \u21B3 [eternal #${beforeIter + 1}] running iteration\u2026
4283
+ `));
4284
+ onInterruptsReset();
4285
+ try {
4286
+ const ok = await engine.runOneIteration();
4287
+ const afterGoal = await loadGoalSafe(opts);
4288
+ const last = afterGoal?.journal[afterGoal.journal.length - 1];
4289
+ if (!ok && !last) {
4290
+ opts.renderer.write(color8.dim(" \u21B3 [eternal] iteration produced no progress.\n"));
4291
+ } else if (last) {
4292
+ const mark = last.status === "success" ? color8.green("\u2713") : last.status === "failure" ? color8.red("\u2717") : color8.amber("\u2298");
4293
+ const tail = last.note ? color8.dim(` \u2014 ${last.note.slice(0, 80)}`) : "";
4294
+ opts.renderer.write(
4295
+ ` ${mark} ${color8.dim(`#${last.iteration}`)} ${color8.dim(`[${last.source}]`)} ${last.task}${tail}
4296
+ `
4297
+ );
4298
+ }
4299
+ if (engine.currentState === "stopped") {
4300
+ const goal = await loadGoalSafe(opts);
4301
+ if (goal?.goalState === "completed") {
4302
+ const u = goal.journal.length > 0 ? summarizeUsage(goal) : null;
4303
+ const costLine = u && u.iterationsWithUsage > 0 ? color8.dim(
4304
+ ` \u2014 ${u.totalCostUsd.toFixed(4)} \xB7 ${u.totalInputTokens} in / ${u.totalOutputTokens} out \xB7 ${goal.iterations} iterations`
4305
+ ) : goal.iterations > 0 ? color8.dim(` \u2014 ${goal.iterations} iterations`) : "";
4306
+ opts.renderer.write(
4307
+ color8.green(`
4308
+ \u{1F3AF} Goal completed!${costLine}
4309
+
4310
+ `) + color8.dim(" Goal cleared. Use /goal set <mission> to create a new goal.\n")
4311
+ );
4312
+ if (opts.projectRoot) {
4313
+ try {
4314
+ const { unlink } = await import("node:fs/promises");
4315
+ await unlink(goalFilePath2(opts.projectRoot));
4316
+ } catch {
4317
+ }
4318
+ }
4319
+ }
4320
+ opts.onAutonomy?.("auto");
4321
+ return true;
4322
+ }
4323
+ } catch (err) {
4324
+ opts.renderer.writeError(`[eternal] ${toErrorMessage2(err)}`);
4325
+ }
4326
+ await new Promise((resolve3) => setTimeout(resolve3, 250));
4327
+ return true;
4328
+ }
4329
+ if (autonomy === "eternal-parallel") {
4330
+ const engine = opts.getParallelEngine?.();
4331
+ if (!engine) {
4332
+ opts.renderer.writeWarning(
4333
+ "Parallel mode set but no engine wired \u2014 falling back to off."
4334
+ );
4335
+ return false;
4336
+ }
4337
+ const beforeGoal = await loadGoalSafe(opts);
4338
+ const beforeIter = beforeGoal?.iterations ?? 0;
4339
+ const coord = engine.getCoordinator();
4340
+ if (coord) {
4341
+ const stats = coord.getStats();
4342
+ opts.renderer.write(
4343
+ color8.dim(
4344
+ ` \u250C\u2500 Fleet: ${stats.running} running, ${stats.idle} idle, ${stats.pending} pending, ${stats.completed} done`
4345
+ ) + "\n"
4346
+ );
4347
+ }
4348
+ opts.renderer.write(
4349
+ color8.magenta(` \u21B3 [parallel #${beforeIter + 1}] launching fan-out\u2026
4350
+ `)
4351
+ );
4352
+ onInterruptsReset();
4353
+ try {
4354
+ await engine.runOneIteration();
4355
+ const afterGoal = await loadGoalSafe(opts);
4356
+ const last = afterGoal?.journal[afterGoal.journal.length - 1];
4357
+ if (coord) {
4358
+ const stats = coord.getStats();
4359
+ opts.renderer.write(
4360
+ color8.dim(
4361
+ ` \u2514\u2500 Fleet: ${stats.running} running, ${stats.idle} idle, ${stats.completed} done
4362
+ `
4363
+ )
4364
+ );
4365
+ }
4366
+ if (last) {
4367
+ const mark = last.status === "success" ? color8.green("\u2713") : last.status === "failure" ? color8.red("\u2717") : color8.amber("\u2298");
4368
+ const tail = last.note ? color8.dim(` \u2014 ${last.note.slice(0, 80)}`) : "";
4369
+ opts.renderer.write(
4370
+ ` ${mark} ${color8.dim(`#${last.iteration}`)} ${color8.dim(`[${last.source}]`)} ${last.task}${tail}
4371
+ `
4372
+ );
4373
+ }
4374
+ if (engine.currentState === "stopped") {
4375
+ const goal = await loadGoalSafe(opts);
4376
+ if (goal?.goalState === "completed") {
4377
+ const u = goal.journal.length > 0 ? summarizeUsage(goal) : null;
4378
+ const costLine = u && u.iterationsWithUsage > 0 ? color8.dim(
4379
+ ` \u2014 ${u.totalCostUsd.toFixed(4)} \xB7 ${u.totalInputTokens} in / ${u.totalOutputTokens} out \xB7 ${goal.iterations} iterations`
4380
+ ) : goal.iterations > 0 ? color8.dim(` \u2014 ${goal.iterations} iterations`) : "";
4381
+ opts.renderer.write(
4382
+ color8.green(`
4383
+ \u{1F3AF} Goal completed!${costLine}
4384
+
4385
+ `) + color8.dim(" Goal cleared. Use /goal set <mission> to create a new goal.\n")
4386
+ );
4387
+ if (opts.projectRoot) {
4388
+ try {
4389
+ const { unlink } = await import("node:fs/promises");
4390
+ await unlink(goalFilePath2(opts.projectRoot));
4391
+ } catch {
4392
+ }
4393
+ }
4394
+ }
4395
+ opts.onAutonomy?.("auto");
4396
+ return true;
4397
+ }
4398
+ } catch (err) {
4399
+ opts.renderer.writeError(`[parallel] ${toErrorMessage2(err)}`);
4400
+ }
4401
+ await new Promise((resolve3) => setTimeout(resolve3, 250));
4402
+ return true;
4403
+ }
4404
+ return false;
4405
+ }
4406
+
4193
4407
  // src/repl-input.ts
4194
- import { color as color7 } from "@wrongstack/core/utils";
4408
+ import { color as color9 } from "@wrongstack/core/utils";
4195
4409
  async function readPossiblyMultiline(opts) {
4196
4410
  const firstPrompt = theme.primary("\u203A ");
4197
- const contPrompt = color7.dim("\xB7 ");
4411
+ const contPrompt = color9.dim("\xB7 ");
4198
4412
  const first = await opts.reader.readLine(firstPrompt);
4199
4413
  if (first.trim() === '"""') {
4200
4414
  const parts = [];
@@ -4219,7 +4433,7 @@ async function readPossiblyMultiline(opts) {
4219
4433
  }
4220
4434
 
4221
4435
  // src/repl-rendering.ts
4222
- import { color as color8 } from "@wrongstack/core/utils";
4436
+ import { color as color10 } from "@wrongstack/core/utils";
4223
4437
  var FILLED = "\u2588";
4224
4438
  var EMPTY = "\u2591";
4225
4439
  function renderContextChip(used, max) {
@@ -4236,13 +4450,13 @@ function renderProgress(ratio, width) {
4236
4450
  }
4237
4451
  function printBanner(renderer, projectName) {
4238
4452
  const lines = [
4239
- theme.primary(theme.bold("WrongStack")) + color8.dim(` v${CLI_VERSION}`),
4240
- color8.dim("Built on the wrong stack. Shipped anyway.")
4453
+ theme.primary(theme.bold("WrongStack")) + color10.dim(` v${CLI_VERSION}`),
4454
+ color10.dim("Built on the wrong stack. Shipped anyway.")
4241
4455
  ];
4242
4456
  if (projectName && projectName.length > 0) {
4243
- lines.push(color8.dim("Project: ") + theme.bold(projectName));
4457
+ lines.push(color10.dim("Project: ") + theme.bold(projectName));
4244
4458
  }
4245
- lines.push(color8.dim("Type /help for commands, /exit or q to quit."), "");
4459
+ lines.push(color10.dim("Type /help for commands, /exit or q to quit."), "");
4246
4460
  renderer.write(`${lines.join("\n")}
4247
4461
  `);
4248
4462
  }
@@ -4311,144 +4525,21 @@ async function runRepl(opts) {
4311
4525
  try {
4312
4526
  for (; ; ) {
4313
4527
  if (exiting) break;
4314
- if (opts.getAutonomy?.() === "eternal") {
4315
- const engine = opts.getEternalEngine?.();
4316
- if (!engine) {
4317
- opts.renderer.writeWarning("Eternal mode set but no engine wired \u2014 falling back to off.");
4318
- } else {
4319
- const beforeGoal = await loadGoalSafe(opts);
4320
- const beforeIter = beforeGoal?.iterations ?? 0;
4321
- opts.renderer.write(color9.dim(`
4322
- \u21B3 [eternal #${beforeIter + 1}] running iteration\u2026
4323
- `));
4528
+ const autonomy = opts.getAutonomy?.();
4529
+ if (autonomy === "eternal" || autonomy === "eternal-parallel") {
4530
+ const handled = await runReplEternalLoop(opts, () => {
4324
4531
  interrupts = 0;
4325
- try {
4326
- const ok = await engine.runOneIteration();
4327
- const afterGoal = await loadGoalSafe(opts);
4328
- const last = afterGoal?.journal[afterGoal.journal.length - 1];
4329
- if (!ok && !last) {
4330
- opts.renderer.write(color9.dim(" \u21B3 [eternal] iteration produced no progress.\n"));
4331
- } else if (last) {
4332
- const mark = last.status === "success" ? color9.green("\u2713") : last.status === "failure" ? color9.red("\u2717") : color9.amber("\u2298");
4333
- const tail = last.note ? color9.dim(` \u2014 ${last.note.slice(0, 80)}`) : "";
4334
- opts.renderer.write(
4335
- ` ${mark} ${color9.dim(`#${last.iteration}`)} ${color9.dim(`[${last.source}]`)} ${last.task}${tail}
4336
- `
4337
- );
4338
- }
4339
- if (engine.currentState === "stopped") {
4340
- const goal = await loadGoalSafe(opts);
4341
- if (goal?.goalState === "completed") {
4342
- const u = goal.journal.length > 0 ? summarizeUsage(goal) : null;
4343
- const costLine = u && u.iterationsWithUsage > 0 ? color9.dim(
4344
- ` \u2014 ${u.totalCostUsd.toFixed(4)} \xB7 ${u.totalInputTokens} in / ${u.totalOutputTokens} out \xB7 ${goal.iterations} iterations`
4345
- ) : goal.iterations > 0 ? color9.dim(` \u2014 ${goal.iterations} iterations`) : "";
4346
- opts.renderer.write(
4347
- color9.green(`
4348
- \u{1F3AF} Goal completed!${costLine}
4349
-
4350
- `) + color9.dim(" Goal cleared. Use /goal set <mission> to create a new goal.\n")
4351
- );
4352
- if (opts.projectRoot) {
4353
- try {
4354
- const { unlink } = await import("node:fs/promises");
4355
- await unlink(goalFilePath(opts.projectRoot));
4356
- } catch {
4357
- }
4358
- }
4359
- }
4360
- opts.onAutonomy?.("auto");
4361
- continue;
4362
- }
4363
- } catch (err) {
4364
- opts.renderer.writeError(`[eternal] ${toErrorMessage(err)}`);
4365
- }
4366
- await new Promise((resolve3) => setTimeout(resolve3, 250));
4367
- continue;
4368
- }
4369
- } else if (opts.getAutonomy?.() === "eternal-parallel") {
4370
- const engine = opts.getParallelEngine?.();
4371
- if (!engine) {
4372
- opts.renderer.writeWarning(
4373
- "Parallel mode set but no engine wired \u2014 falling back to off."
4374
- );
4375
- } else {
4376
- const beforeGoal = await loadGoalSafe(opts);
4377
- const beforeIter = beforeGoal?.iterations ?? 0;
4378
- const coord = engine.getCoordinator();
4379
- if (coord) {
4380
- const stats = coord.getStats();
4381
- opts.renderer.write(
4382
- color9.dim(
4383
- ` \u250C\u2500 Fleet: ${stats.running} running, ${stats.idle} idle, ${stats.pending} pending, ${stats.completed} done`
4384
- ) + "\n"
4385
- );
4386
- }
4387
- opts.renderer.write(
4388
- color9.magenta(` \u21B3 [parallel #${beforeIter + 1}] launching fan-out\u2026
4389
- `)
4390
- );
4391
- interrupts = 0;
4392
- try {
4393
- await engine.runOneIteration();
4394
- const afterGoal = await loadGoalSafe(opts);
4395
- const last = afterGoal?.journal[afterGoal.journal.length - 1];
4396
- if (coord) {
4397
- const stats = coord.getStats();
4398
- opts.renderer.write(
4399
- color9.dim(
4400
- ` \u2514\u2500 Fleet: ${stats.running} running, ${stats.idle} idle, ${stats.completed} done
4401
- `
4402
- )
4403
- );
4404
- }
4405
- if (last) {
4406
- const mark = last.status === "success" ? color9.green("\u2713") : last.status === "failure" ? color9.red("\u2717") : color9.amber("\u2298");
4407
- const tail = last.note ? color9.dim(` \u2014 ${last.note.slice(0, 80)}`) : "";
4408
- opts.renderer.write(
4409
- ` ${mark} ${color9.dim(`#${last.iteration}`)} ${color9.dim(`[${last.source}]`)} ${last.task}${tail}
4410
- `
4411
- );
4412
- }
4413
- if (engine.currentState === "stopped") {
4414
- const goal = await loadGoalSafe(opts);
4415
- if (goal?.goalState === "completed") {
4416
- const u = goal.journal.length > 0 ? summarizeUsage(goal) : null;
4417
- const costLine = u && u.iterationsWithUsage > 0 ? color9.dim(
4418
- ` \u2014 ${u.totalCostUsd.toFixed(4)} \xB7 ${u.totalInputTokens} in / ${u.totalOutputTokens} out \xB7 ${goal.iterations} iterations`
4419
- ) : goal.iterations > 0 ? color9.dim(` \u2014 ${goal.iterations} iterations`) : "";
4420
- opts.renderer.write(
4421
- color9.green(`
4422
- \u{1F3AF} Goal completed!${costLine}
4423
-
4424
- `) + color9.dim(" Goal cleared. Use /goal set <mission> to create a new goal.\n")
4425
- );
4426
- if (opts.projectRoot) {
4427
- try {
4428
- const { unlink } = await import("node:fs/promises");
4429
- await unlink(goalFilePath(opts.projectRoot));
4430
- } catch {
4431
- }
4432
- }
4433
- }
4434
- opts.onAutonomy?.("auto");
4435
- continue;
4436
- }
4437
- } catch (err) {
4438
- opts.renderer.writeError(`[parallel] ${toErrorMessage(err)}`);
4439
- }
4440
- await new Promise((resolve3) => setTimeout(resolve3, 250));
4441
- continue;
4442
- }
4532
+ });
4533
+ if (handled) continue;
4443
4534
  }
4444
4535
  {
4445
4536
  const mode = opts.getAutonomy?.() ?? "off";
4446
4537
  const suggestions = opts.getSuggestions?.() ?? [];
4447
4538
  if (mode === "suggest" && suggestions.length > 0) {
4448
- const lines = suggestions.map((s, i) => ` ${color9.bold(`${i + 1}.`)} ${color9.dim(s)}`);
4539
+ const lines = suggestions.map((s, i) => ` ${color11.bold(`${i + 1}.`)} ${color11.dim(s)}`);
4449
4540
  opts.renderer.write(
4450
4541
  `
4451
- ${color9.cyan(" \u{1F4A1} Suggested next steps")} ${color9.dim("(use /next 1, /next 2, or /next 1 2 3)")}
4542
+ ${color11.cyan(" \u{1F4A1} Suggested next steps")} ${color11.dim("(use /next 1, /next 2, or /next 1 2 3)")}
4452
4543
  ${lines.join("\n")}
4453
4544
 
4454
4545
  `
@@ -4482,8 +4573,7 @@ ${lines.join("\n")}
4482
4573
  }
4483
4574
  }
4484
4575
  }
4485
- if (!top) {
4486
- } else {
4576
+ if (top) {
4487
4577
  const maxAuto = opts.autoProceedMaxIterations ?? DEFAULT_MAX_CONSECUTIVE_AUTO_PROCEED;
4488
4578
  if (maxAuto > 0 && autoIterCount >= maxAuto) {
4489
4579
  if (!autoCapWarned) {
@@ -4536,7 +4626,7 @@ ${lines.join("\n")}
4536
4626
  autoCapWarned = false;
4537
4627
  autoProceedLoopGuard.reset();
4538
4628
  if (trimmed === "q") {
4539
- opts.renderer.write(color9.dim(" Goodbye!\n"));
4629
+ opts.renderer.write(color11.dim(" Goodbye!\n"));
4540
4630
  break;
4541
4631
  }
4542
4632
  if (trimmed === "wd" || trimmed.startsWith("cd ")) {
@@ -4546,7 +4636,7 @@ ${lines.join("\n")}
4546
4636
  if (res?.message) opts.renderer.write(`${res.message}
4547
4637
  `);
4548
4638
  } catch (err) {
4549
- opts.renderer.writeError(toErrorMessage(err));
4639
+ opts.renderer.writeError(toErrorMessage3(err));
4550
4640
  }
4551
4641
  continue;
4552
4642
  }
@@ -4578,14 +4668,14 @@ ${lines.join("\n")}
4578
4668
  if (specSaved) {
4579
4669
  opts.renderer.write(
4580
4670
  `
4581
- ${color9.cyan(" \u2713 Spec detected and saved! Use /sdd approve to continue.")}
4671
+ ${color11.cyan(" \u2713 Spec detected and saved! Use /sdd approve to continue.")}
4582
4672
  `
4583
4673
  );
4584
4674
  }
4585
4675
  const planSaved = trySaveImplementationPlan(runResult.finalText);
4586
4676
  if (planSaved) {
4587
4677
  opts.renderer.write(`
4588
- ${color9.cyan(" \u2713 Implementation plan saved!")}
4678
+ ${color11.cyan(" \u2713 Implementation plan saved!")}
4589
4679
  `);
4590
4680
  }
4591
4681
  const tasksSaved = await trySaveTasksFromAIOutput(runResult.finalText);
@@ -4594,7 +4684,7 @@ ${color9.cyan(" \u2713 Implementation plan saved!")}
4594
4684
  const count = progress?.total ?? 0;
4595
4685
  opts.renderer.write(
4596
4686
  `
4597
- ${color9.cyan(` \u2713 ${count} tasks detected and saved! Use /sdd approve to execute.`)}
4687
+ ${color11.cyan(` \u2713 ${count} tasks detected and saved! Use /sdd approve to execute.`)}
4598
4688
  `
4599
4689
  );
4600
4690
  }
@@ -4606,13 +4696,13 @@ ${color9.cyan(` \u2713 ${count} tasks detected and saved! Use /sdd approve to e
4606
4696
  if (progress) {
4607
4697
  opts.renderer.write(
4608
4698
  `
4609
- ${color9.cyan(` \u2713 ${autoCompleted} task(s) auto-completed! Progress: ${progress.completed}/${progress.total} (${progress.percentComplete}%)`)}
4699
+ ${color11.cyan(` \u2713 ${autoCompleted} task(s) auto-completed! Progress: ${progress.completed}/${progress.total} (${progress.percentComplete}%)`)}
4610
4700
  `
4611
4701
  );
4612
4702
  const taskList2 = renderTaskListWithProgress();
4613
4703
  if (taskList2) {
4614
4704
  opts.renderer.write(`
4615
- ${color9.dim(taskList2)}
4705
+ ${color11.dim(taskList2)}
4616
4706
  `);
4617
4707
  }
4618
4708
  }
@@ -4620,7 +4710,7 @@ ${color9.dim(taskList2)}
4620
4710
  const taskList2 = renderTaskListWithProgress();
4621
4711
  if (taskList2) {
4622
4712
  opts.renderer.write(`
4623
- ${color9.dim(taskList2)}
4713
+ ${color11.dim(taskList2)}
4624
4714
  `);
4625
4715
  }
4626
4716
  }
@@ -4638,7 +4728,7 @@ ${color9.dim(taskList2)}
4638
4728
  }
4639
4729
  }
4640
4730
  } catch (err) {
4641
- opts.renderer.writeError(toErrorMessage(err));
4731
+ opts.renderer.writeError(toErrorMessage3(err));
4642
4732
  }
4643
4733
  continue;
4644
4734
  }
@@ -4663,22 +4753,22 @@ ${color9.dim(taskList2)}
4663
4753
  }
4664
4754
  if (resolved.source === "open") {
4665
4755
  opts.renderer.write(
4666
- ` ${color9.amber("\u26A0")} ${color9.bold("'continue' has no anchor")} ${color9.dim("\u2014 no pending todo or suggestion.")}
4667
- ` + color9.dim(
4756
+ ` ${color11.amber("\u26A0")} ${color11.bold("'continue' has no anchor")} ${color11.dim("\u2014 no pending todo or suggestion.")}
4757
+ ` + color11.dim(
4668
4758
  " If you proceed, I'll choose the next step from context; that can drift.\n"
4669
4759
  )
4670
4760
  );
4671
- const ans = (await opts.reader.readLine(color9.dim(" Proceed anyway? [Y/n \xB7 e = type your own] "))).trim().toLowerCase();
4761
+ const ans = (await opts.reader.readLine(color11.dim(" Proceed anyway? [Y/n \xB7 e = type your own] "))).trim().toLowerCase();
4672
4762
  if (ans === "n" || ans === "no") {
4673
- opts.renderer.write(color9.dim(" Cancelled \u2014 nothing sent.\n"));
4763
+ opts.renderer.write(color11.dim(" Cancelled \u2014 nothing sent.\n"));
4674
4764
  continue;
4675
4765
  }
4676
4766
  if (ans === "e" || ans === "edit") {
4677
- opts.renderer.write(color9.dim(" Okay \u2014 type what to continue with.\n"));
4767
+ opts.renderer.write(color11.dim(" Okay \u2014 type what to continue with.\n"));
4678
4768
  continue;
4679
4769
  }
4680
4770
  } else {
4681
- opts.renderer.write(color9.dim(` ${resolved.label}
4771
+ opts.renderer.write(color11.dim(` ${resolved.label}
4682
4772
  `));
4683
4773
  }
4684
4774
  builder.appendText(resolved.text);
@@ -4686,7 +4776,7 @@ ${color9.dim(taskList2)}
4686
4776
  const ph = await builder.appendPaste(raw);
4687
4777
  if (ph) {
4688
4778
  const lineCount = raw.split("\n").length;
4689
- opts.renderer.write(color9.dim(` \u21B3 ${ph} (${lineCount} lines)
4779
+ opts.renderer.write(color11.dim(` \u21B3 ${ph} (${lineCount} lines)
4690
4780
  `));
4691
4781
  }
4692
4782
  }
@@ -4739,7 +4829,7 @@ ${taskList}`;
4739
4829
  }) : { blocks: effectiveBlocks, route: "none", convertedImages: 0 };
4740
4830
  if (routed.route === "adapter") {
4741
4831
  opts.renderer.write(
4742
- color9.dim(
4832
+ color11.dim(
4743
4833
  ` \u21B3 image analyzed via ${routed.adapterName ?? "vision adapter"} (${routed.convertedImages} image${routed.convertedImages === 1 ? "" : "s"})
4744
4834
  `
4745
4835
  )
@@ -4773,14 +4863,14 @@ ${taskList}`;
4773
4863
  if (specSaved) {
4774
4864
  opts.renderer.write(
4775
4865
  `
4776
- ${color9.cyan(" \u2713 Spec detected and saved! Use /sdd approve to continue.")}
4866
+ ${color11.cyan(" \u2713 Spec detected and saved! Use /sdd approve to continue.")}
4777
4867
  `
4778
4868
  );
4779
4869
  }
4780
4870
  const planSaved = trySaveImplementationPlan(result.finalText);
4781
4871
  if (planSaved) {
4782
4872
  opts.renderer.write(`
4783
- ${color9.cyan(" \u2713 Implementation plan saved!")}
4873
+ ${color11.cyan(" \u2713 Implementation plan saved!")}
4784
4874
  `);
4785
4875
  }
4786
4876
  const tasksSaved = await trySaveTasksFromAIOutput(result.finalText);
@@ -4789,7 +4879,7 @@ ${color9.cyan(" \u2713 Implementation plan saved!")}
4789
4879
  const count = progress?.total ?? 0;
4790
4880
  opts.renderer.write(
4791
4881
  `
4792
- ${color9.cyan(` \u2713 ${count} tasks detected and saved! Use /sdd approve to execute.`)}
4882
+ ${color11.cyan(` \u2713 ${count} tasks detected and saved! Use /sdd approve to execute.`)}
4793
4883
  `
4794
4884
  );
4795
4885
  }
@@ -4801,13 +4891,13 @@ ${color9.cyan(` \u2713 ${count} tasks detected and saved! Use /sdd approve to e
4801
4891
  if (progress) {
4802
4892
  opts.renderer.write(
4803
4893
  `
4804
- ${color9.cyan(` \u2713 ${autoCompleted} task(s) auto-completed! Progress: ${progress.completed}/${progress.total} (${progress.percentComplete}%)`)}
4894
+ ${color11.cyan(` \u2713 ${autoCompleted} task(s) auto-completed! Progress: ${progress.completed}/${progress.total} (${progress.percentComplete}%)`)}
4805
4895
  `
4806
4896
  );
4807
4897
  if (progress.percentComplete === 100) {
4808
4898
  opts.renderer.write(
4809
4899
  `
4810
- ${color9.green(" \u{1F389} All tasks completed! Use /sdd cancel to end the session.")}
4900
+ ${color11.green(" \u{1F389} All tasks completed! Use /sdd cancel to end the session.")}
4811
4901
  `
4812
4902
  );
4813
4903
  }
@@ -4816,14 +4906,14 @@ ${color9.green(" \u{1F389} All tasks completed! Use /sdd cancel to end the sess
4816
4906
  const taskList2 = renderTaskListWithProgress();
4817
4907
  if (taskList2) {
4818
4908
  opts.renderer.write(`
4819
- ${color9.dim(taskList2)}
4909
+ ${color11.dim(taskList2)}
4820
4910
  `);
4821
4911
  }
4822
4912
  } else {
4823
4913
  const taskList2 = renderTaskListWithProgress();
4824
4914
  if (taskList2) {
4825
4915
  opts.renderer.write(`
4826
- ${color9.dim(taskList2)}
4916
+ ${color11.dim(taskList2)}
4827
4917
  `);
4828
4918
  }
4829
4919
  }
@@ -4840,15 +4930,15 @@ ${color9.dim(taskList2)}
4840
4930
  const ctxChip = effectiveMaxContext && effectiveMaxContext > 0 ? ` ctx: ${renderContextChip(after.input, effectiveMaxContext)}` : "";
4841
4931
  opts.renderer.write(
4842
4932
  `
4843
- ${color9.dim(
4933
+ ${color11.dim(
4844
4934
  `[in: ${fmtTok(after.input - before.input)} out: ${fmtTok(after.output - before.output)} iters: ${result.iterations} cost: ${(costAfter - costBefore).toFixed(4)} ${((Date.now() - startedAt) / 1e3).toFixed(1)}s]${ctxChip}`
4845
4935
  )}
4846
4936
  `
4847
4937
  );
4848
4938
  }
4849
4939
  if (result.status === "done" && opts.getAutonomy) {
4850
- const autonomy = opts.getAutonomy();
4851
- if (autonomy === "suggest" && !hasOpenTodos2(opts.agent.ctx.todos)) {
4940
+ const autonomy2 = opts.getAutonomy();
4941
+ if (autonomy2 === "suggest" && !hasOpenTodos2(opts.agent.ctx.todos)) {
4852
4942
  const suggestPrompt = 'Based on what you just did, suggest 3 exact prompt messages that can be submitted back to you through the TUI or WebUI. Each prompt must ask the agent to perform work; never assign a manual chore to the user. If you include suggestions, wrap them in a balanced <nextsteps>...</nextsteps> block, with one numbered prompt per line and no explanation. If there is nothing meaningful left, say "No further steps needed."';
4853
4943
  const suggestBlocks = [{ type: "text", text: suggestPrompt }];
4854
4944
  const suggestCtrl = new AbortController();
@@ -4867,7 +4957,7 @@ ${color9.dim(
4867
4957
  if (suggestResult.status === "done" && suggestResult.finalText) {
4868
4958
  opts.renderer.write(
4869
4959
  `
4870
- ${color9.cyan(" Suggested next steps:")}
4960
+ ${color11.cyan(" Suggested next steps:")}
4871
4961
  ${suggestResult.finalText}
4872
4962
  `
4873
4963
  );
@@ -4886,8 +4976,8 @@ ${suggestResult.finalText}
4886
4976
  }
4887
4977
  }
4888
4978
  if (result.status === "done" && opts.getNextPredict?.() && !hasOpenTodos2(opts.agent.ctx.todos)) {
4889
- const autonomy = opts.getAutonomy?.() ?? "off";
4890
- if (autonomy === "off") {
4979
+ const autonomy2 = opts.getAutonomy?.() ?? "off";
4980
+ if (autonomy2 === "off") {
4891
4981
  const predictCtrl = new AbortController();
4892
4982
  activeCtrl = predictCtrl;
4893
4983
  try {
@@ -4906,8 +4996,8 @@ ${suggestResult.finalText}
4906
4996
  if (predictions.length > 0) {
4907
4997
  const lines = predictions.map((p, i) => ` ${i + 1}. ${p}`).join("\n");
4908
4998
  opts.renderer.write(`
4909
- ${color9.dim(" \u21B3 likely next:")}
4910
- ${color9.dim(lines)}
4999
+ ${color11.dim(" \u21B3 likely next:")}
5000
+ ${color11.dim(lines)}
4911
5001
  `);
4912
5002
  }
4913
5003
  } catch {
@@ -4917,7 +5007,7 @@ ${color9.dim(lines)}
4917
5007
  }
4918
5008
  }
4919
5009
  } catch (err) {
4920
- opts.renderer.writeError(toErrorMessage(err));
5010
+ opts.renderer.writeError(toErrorMessage3(err));
4921
5011
  } finally {
4922
5012
  activeCtrl = void 0;
4923
5013
  }
@@ -4935,71 +5025,17 @@ async function pasteClipboardImage(builder, opts) {
4935
5025
  try {
4936
5026
  const img = await readClipboardImage();
4937
5027
  if (!img) {
4938
- opts.renderer.write(color9.dim(" no image on clipboard\n"));
5028
+ opts.renderer.write(color11.dim(" no image on clipboard\n"));
4939
5029
  return;
4940
5030
  }
4941
5031
  const placeholder = await builder.appendImage(img.base64, img.mediaType);
4942
5032
  const kb = (img.bytes / 1024).toFixed(0);
4943
- opts.renderer.write(color9.dim(` \u21B3 ${placeholder} (PNG ${kb}KB)
5033
+ opts.renderer.write(color11.dim(` \u21B3 ${placeholder} (PNG ${kb}KB)
4944
5034
  `));
4945
5035
  } catch (err) {
4946
- opts.renderer.writeError(`Clipboard image error: ${toErrorMessage(err)}`);
5036
+ opts.renderer.writeError(`Clipboard image error: ${toErrorMessage3(err)}`);
4947
5037
  }
4948
5038
  }
4949
- async function loadGoalSafe(opts) {
4950
- if (!opts.projectRoot) return null;
4951
- try {
4952
- return await loadGoal(goalFilePath(opts.projectRoot));
4953
- } catch {
4954
- return null;
4955
- }
4956
- }
4957
- async function renderGoalBanner(opts) {
4958
- const goal = await loadGoalSafe(opts);
4959
- if (!goal) return;
4960
- const summary = goal.goal.length > 80 ? `${goal.goal.slice(0, 77)}\u2026` : goal.goal;
4961
- const stateColor = goal.goalState === "active" ? color9.green : goal.goalState === "paused" ? color9.amber : goal.goalState === "completed" ? color9.green : goal.goalState === "abandoned" ? color9.dim : color9.dim;
4962
- opts.renderer.write(
4963
- color9.dim("Goal: ") + stateColor(summary) + color9.dim(` [${goal.goalState}] (iter ${goal.iterations})`) + "\n"
4964
- );
4965
- if (goal.journal.length > 0) {
4966
- const lastEntry = expectDefined(goal.journal[goal.journal.length - 1]);
4967
- const statusIcon = lastEntry.status === "success" ? "\u2713" : lastEntry.status === "failure" ? "\u2717" : lastEntry.status === "aborted" ? "\u2298" : lastEntry.status === "skipped" ? "\u229D" : "\xB7";
4968
- opts.renderer.write(
4969
- color9.dim(` Last: ${statusIcon} ${lastEntry.task} (${lastEntry.status})`) + "\n"
4970
- );
4971
- }
4972
- if (goal.engineState === "running") {
4973
- opts.renderer.write(
4974
- color9.amber(" \u21BA Eternal engine was running when last session ended.") + "\n"
4975
- );
4976
- try {
4977
- const answer = (await opts.reader.readLine(color9.dim(" Resume eternal mode? [y/N] "))).trim().toLowerCase();
4978
- if (answer === "y" || answer === "yes") {
4979
- try {
4980
- await opts.slashRegistry.dispatch("/autonomy eternal", opts.agent.ctx);
4981
- } catch (err) {
4982
- opts.renderer.writeError(`Auto-resume failed: ${toErrorMessage(err)}`);
4983
- }
4984
- } else {
4985
- opts.renderer.write(
4986
- color9.dim(" Not resuming. Use `/autonomy eternal` later to continue.") + "\n"
4987
- );
4988
- }
4989
- } catch {
4990
- opts.renderer.write(color9.dim(" Use `/autonomy eternal` to resume.") + "\n");
4991
- }
4992
- } else if (goal.goalState === "paused") {
4993
- opts.renderer.write(color9.amber(" \u23F8 Goal is paused. Use `/goal resume` to continue.") + "\n");
4994
- } else if (goal.goalState === "completed") {
4995
- opts.renderer.write(
4996
- color9.green(" \u2713 Goal completed! Use `/goal clear` to set a new goal.") + "\n"
4997
- );
4998
- } else if (goal.goalState === "abandoned") {
4999
- opts.renderer.write(color9.dim(" Use `/goal clear` to set a new goal.") + "\n");
5000
- }
5001
- opts.renderer.write("\n");
5002
- }
5003
5039
 
5004
5040
  // src/execution-tui-next-step-callbacks.ts
5005
5041
  function createTuiNextStepCallbacks(input) {
@@ -5998,4 +6034,4 @@ export {
5998
6034
  execute,
5999
6035
  resolveReviewerFallbackModels
6000
6036
  };
6001
- //# sourceMappingURL=execution-547PM3NI.js.map
6037
+ //# sourceMappingURL=execution-4ASWJ7EY.js.map