@wrongstack/cli 0.319.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/data/providers.json +22 -15
  2. package/dist/{acp-5ANIAOZC.js → acp-3LARESEO.js} +113 -10
  3. package/dist/acp-hq-telemetry.d.ts +44 -0
  4. package/dist/{audit-ZPCLCC3C.js → audit-46YK5DSC.js} +1 -2
  5. package/dist/{auth-KF5TAD7V.js → auth-KIBJZZIE.js} +5 -6
  6. package/dist/auth-menu/add-provider.d.ts +7 -0
  7. package/dist/auth-menu/panel-service.d.ts +2 -20
  8. package/dist/{auto-discover-providers-MHFLDSD3.js → auto-discover-providers-VQU3IZMR.js} +1 -2
  9. package/dist/{bench-XYG56AMO.js → bench-YBU6BVQP.js} +175 -35
  10. package/dist/boot/brain-decision-log.d.ts +22 -2
  11. package/dist/{boot-auto-thin-BZ675EVT.js → boot-auto-thin-MANHOYHE.js} +1 -2
  12. package/dist/{chronicle-6EPPMUC5.js → chronicle-UTFETHP6.js} +1 -2
  13. package/dist/{chunk-VWCZL4OH.js → chunk-4HV5RKZH.js} +5 -5
  14. package/dist/{chunk-42JD25KU.js → chunk-5IA5337I.js} +3 -3
  15. package/dist/{chunk-7JBKXVMK.js → chunk-C2E24IXZ.js} +44 -32
  16. package/dist/{chunk-7CECQDNH.js → chunk-D3K4NYQL.js} +1 -1
  17. package/dist/{chunk-XPX432BZ.js → chunk-DR2OXU46.js} +50 -39
  18. package/dist/{chunk-4JRIWVJ4.js → chunk-ERX4BLKP.js} +1 -1
  19. package/dist/chunk-ETYHZPXP.js +52 -0
  20. package/dist/{chunk-TYO2OVAD.js → chunk-EWKESL4L.js} +8 -4
  21. package/dist/{chunk-QAC263FZ.js → chunk-FPIWTJ2G.js} +2 -3
  22. package/dist/{chunk-7YLN7YUA.js → chunk-IMWXXF4J.js} +61 -9
  23. package/dist/{chunk-G7337TTK.js → chunk-IS2PPBQV.js} +1 -1
  24. package/dist/{chunk-G3IMKQRH.js → chunk-JHPXJRRI.js} +1 -1
  25. package/dist/{chunk-XHIEA6LG.js → chunk-MNQQ4ZNF.js} +26 -22
  26. package/dist/{chunk-P2OKBDCH.js → chunk-MXEJEYT7.js} +53 -14
  27. package/dist/{chunk-PCBJSXYV.js → chunk-O4A3HHKD.js} +2 -2
  28. package/dist/{chunk-XYKYXFEE.js → chunk-TE3Q32JP.js} +10 -4
  29. package/dist/{chunk-H7GABTGS.js → chunk-TEBMCYZN.js} +69 -30
  30. package/dist/{chunk-E4I2TF5S.js → chunk-TNK6237M.js} +2 -2
  31. package/dist/{chunk-SYIBTG3X.js → chunk-VOTTENR5.js} +3 -5
  32. package/dist/chunk-WHOIR577.js +1 -0
  33. package/dist/{chunk-2ZNBRZ4W.js → chunk-WQZW3RDP.js} +2 -2
  34. package/dist/{chunk-GGGUZSAU.js → chunk-Z7A5MXKJ.js} +18 -12
  35. package/dist/{chunk-F5GA2QW2.js → chunk-ZSZ3EYWH.js} +2 -2
  36. package/dist/{cli-context-LH4QP4W2.js → cli-context-CYMKNOK3.js} +58 -307
  37. package/dist/{cli-main-72XUFUCL.js → cli-main-TTIVR4DI.js} +925 -329
  38. package/dist/{diag-doctor-LFCCBPMD.js → diag-doctor-7LYUYU35.js} +4 -6
  39. package/dist/execute-deps.d.ts +5 -1
  40. package/dist/{execution-DKJDNPYF.js → execution-3Y55IWBK.js} +512 -469
  41. package/dist/{export-ROG3DKTZ.js → export-VVRIOWFV.js} +1 -2
  42. package/dist/{governance-JSGHHA2R.js → governance-RYSHV675.js} +1 -2
  43. package/dist/{hq-3GWBFLON.js → hq-IG3YRGCO.js} +2 -3
  44. package/dist/hq-command-controller.d.ts +37 -7
  45. package/dist/hq-server/routes.d.ts +1 -1
  46. package/dist/hq-server/ws.d.ts +1 -1
  47. package/dist/{hq-server-OARPUSQJ.js → hq-server-OILU3NPI.js} +2 -3
  48. package/dist/{hq-ttl-KUO3AU7X.js → hq-ttl-VJR65OBJ.js} +1 -2
  49. package/dist/{hq-tunnel-LO55RCZE.js → hq-tunnel-NIJ5EP2Y.js} +1 -2
  50. package/dist/index.js +5 -6
  51. package/dist/{init-4JQSG66Q.js → init-DRMMFG2G.js} +1 -2
  52. package/dist/{kanban-run-mirror-EKVNGXWW.js → kanban-run-mirror-22HQ5FNG.js} +1 -2
  53. package/dist/live-settings-input.d.ts +2 -0
  54. package/dist/{mailbox-serve-VKQIRCCB.js → mailbox-serve-VUCWZ2SJ.js} +2 -3
  55. package/dist/{mcp-AQKSASHD.js → mcp-HOMLC4WE.js} +1 -2
  56. package/dist/{modeldiag-5FRMT6FQ.js → modeldiag-FMJT37SN.js} +2 -3
  57. package/dist/{per-subcommand-help-6VCIKDUW.js → per-subcommand-help-BWBHYVJO.js} +2 -3
  58. package/dist/{permissions-2PWBL4YU.js → permissions-CFDLXETM.js} +1 -2
  59. package/dist/{plugin-usage-CYUORYM6.js → plugin-usage-HFBI3TFT.js} +2 -3
  60. package/dist/{plugins-RV3OBBND.js → plugins-PZ2VZL7V.js} +4 -5
  61. package/dist/{project-BLQ3ALVL.js → project-AOQI5XTK.js} +1 -2
  62. package/dist/{project-manifest-YFTJ3D5N.js → project-manifest-7NSFVBM3.js} +2 -3
  63. package/dist/{project-picker-R5TYAE3Q.js → project-picker-SVBXMPKX.js} +3 -4
  64. package/dist/{projects-5J727S4L.js → projects-L6C6XLDY.js} +1 -2
  65. package/dist/provider-config-utils.d.ts +1 -1
  66. package/dist/{providers-models-OKKQZIWU.js → providers-models-YVMVYWRS.js} +3 -4
  67. package/dist/{proxy-wiring-EQB5X5YH.js → proxy-wiring-MGRSKZZB.js} +3 -4
  68. package/dist/{quick-XLYLZX4B.js → quick-CNB4Z3HS.js} +1 -2
  69. package/dist/{replay-RZXZKP2U.js → replay-JJ2NOWD6.js} +1 -2
  70. package/dist/{replay-FJ2JBXUA.js → replay-Z3FTJEMM.js} +1 -2
  71. package/dist/{rewind-2FFNOOKS.js → rewind-JA3ZLCNM.js} +1 -2
  72. package/dist/{sdd-runtime-FLKCSTYV.js → sdd-runtime-PTOSPYI4.js} +2 -3
  73. package/dist/services/sdd-runtime.d.ts +1 -1
  74. package/dist/services/statusline-config.d.ts +43 -13
  75. package/dist/{sessions-config-KAMEBVOX.js → sessions-config-UL45XKX7.js} +2 -3
  76. package/dist/{sessions-doctor-EXHAZSSE.js → sessions-doctor-QUL37U32.js} +1 -2
  77. package/dist/short-circuit-flags-6PSP56L7.js +10 -0
  78. package/dist/{simpleui-dist-JKNRCRRK.js → simpleui-dist-CXSIDAXZ.js} +1 -2
  79. package/dist/slash-commands/command-context.d.ts +10 -0
  80. package/dist/slash-commands/sdd.d.ts +1 -1
  81. package/dist/slash-commands/statusline.d.ts +1 -1
  82. package/dist/subcommands/handlers/bench-run-config.d.ts +18 -0
  83. package/dist/subcommands/handlers/bench.d.ts +8 -7
  84. package/dist/subcommands-HZQKA4G2.js +9 -0
  85. package/dist/{tools-skills-Q4P27URS.js → tools-skills-GH24UCBY.js} +1 -2
  86. package/dist/{update-K45CS6SS.js → update-5DPB4YD4.js} +1 -2
  87. package/dist/{update-check-PKSMSMD6.js → update-check-BS3DHTSI.js} +1 -2
  88. package/dist/version-help-MYKF724O.js +10 -0
  89. package/dist/webui-server/client-registration.d.ts +9 -1
  90. package/dist/{webui-server-SY4EQCKD.js → webui-server-T6AMOXJJ.js} +54 -13
  91. package/dist/wiring/brain-and-orchestration.d.ts +2 -0
  92. package/dist/wiring/cli-execute-builder.d.ts +4 -0
  93. package/dist/wiring/cli-slash-commands-setup.d.ts +1 -0
  94. package/dist/wiring/command-host-state.d.ts +50 -5
  95. package/dist/wiring/external-plugins.d.ts +9 -0
  96. package/dist/wiring/provider-runtime-setup.d.ts +2 -0
  97. package/dist/wiring/runtime-controller-deps.d.ts +3 -0
  98. package/dist/wiring/vector-memory-setup.d.ts +12 -0
  99. package/dist/wiring/wrongtrace-gate.d.ts +2 -2
  100. package/dist/wiring/wrongtrace-hooks.d.ts +1 -1
  101. package/dist/wiring/wrongtrace-prompt-contributor.d.ts +5 -2
  102. package/dist/{wrongtrace-gate-counters-P5BCBXQN.js → wrongtrace-gate-counters-7C2EAAZL.js} +2 -3
  103. package/dist/{wrongtrace-telemetry-FNLANZ5I.js → wrongtrace-telemetry-3ASFKOZO.js} +2 -3
  104. package/package.json +28 -28
  105. package/dist/chunk-7OCVIDC7.js +0 -11
  106. package/dist/chunk-ALE5KHCA.js +0 -1
  107. package/dist/chunk-OZDE3OWD.js +0 -52
  108. package/dist/launch-hints.d.ts +0 -49
  109. package/dist/short-circuit-flags-U6CJAF6J.js +0 -11
  110. package/dist/subcommands-J4JMWC5W.js +0 -10
  111. package/dist/version-help-WMPSEL4U.js +0 -11
  112. package/dist/webui-server/privileged-actions.d.ts +0 -14
  113. package/dist/wiring/cli-heap-watchdog.d.ts +0 -34
@@ -21,8 +21,8 @@ import {
21
21
  } from "./chunk-GPPRNAKW.js";
22
22
  import {
23
23
  fmtTok
24
- } from "./chunk-TYO2OVAD.js";
25
- import "./chunk-ALE5KHCA.js";
24
+ } from "./chunk-EWKESL4L.js";
25
+ import "./chunk-WHOIR577.js";
26
26
  import {
27
27
  advanceToNextTask,
28
28
  autoDetectTaskCompletion,
@@ -40,19 +40,18 @@ import {
40
40
  terminalLink,
41
41
  terminalText
42
42
  } from "./chunk-HXJYHAR4.js";
43
- import {
44
- startCliHqConnection
45
- } from "./chunk-XYKYXFEE.js";
46
43
  import {
47
44
  CLI_VERSION
48
45
  } from "./chunk-XJXDOF63.js";
46
+ import {
47
+ startCliHqConnection
48
+ } from "./chunk-TE3Q32JP.js";
49
49
  import {
50
50
  activeProfileConfigPath
51
51
  } from "./chunk-YMXXOOFN.js";
52
52
  import {
53
53
  resolveActiveApiKey
54
- } from "./chunk-XPX432BZ.js";
55
- import "./chunk-7OCVIDC7.js";
54
+ } from "./chunk-DR2OXU46.js";
56
55
 
57
56
  // src/execution.ts
58
57
  import * as path14 from "node:path";
@@ -212,7 +211,7 @@ async function runWebUIDispatch(ctx) {
212
211
  const isSimpleUi = !isSessionChild && flags["simpleui"] === true;
213
212
  agent.disableInteractiveConfirmation();
214
213
  renderer.setSilent(true);
215
- const { runWebUI } = await import("./webui-server-SY4EQCKD.js");
214
+ const { runWebUI } = await import("./webui-server-T6AMOXJJ.js");
216
215
  const flagValue = (names) => {
217
216
  for (const name of names) {
218
217
  if (!Object.hasOwn(flags, name)) continue;
@@ -267,7 +266,7 @@ async function runWebUIDispatch(ctx) {
267
266
  webuiPublicWsUrl = webuiSessionChild?.publicWsUrl ?? flagValue(["webui-public-ws-url", "public-ws-url"]) ?? process.env["WEBUI_PUBLIC_WS_URL"];
268
267
  webuiRequireToken = webuiSessionChild?.requireToken ?? flagBoolean(["webui-require-token", "require-token"]) ?? envFlag("WEBUI_REQUIRE_TOKEN");
269
268
  if (isSimpleUi) {
270
- const { ensureSimpleUiDistDir } = await import("./simpleui-dist-JKNRCRRK.js");
269
+ const { ensureSimpleUiDistDir } = await import("./simpleui-dist-CXSIDAXZ.js");
271
270
  frontendDistDir = await ensureSimpleUiDistDir();
272
271
  }
273
272
  } catch (err) {
@@ -415,7 +414,7 @@ async function runWebUIDispatch(ctx) {
415
414
  applyLiveSettings?.({ yolo: enabled });
416
415
  },
417
416
  onWrongProxyPrefsChange: (payload) => {
418
- void import("./proxy-wiring-EQB5X5YH.js").then(
417
+ void import("./proxy-wiring-MGRSKZZB.js").then(
419
418
  ({ applyWrongProxyPrefs }) => applyWrongProxyPrefs(payload)
420
419
  );
421
420
  }
@@ -893,7 +892,7 @@ function onSwitchToSession(ctx, _sessionId, targetRoot, projectName) {
893
892
  import * as path4 from "node:path";
894
893
  import { color as color3 } from "@wrongstack/core/utils";
895
894
  async function getProjectPickerItems(ctx) {
896
- const { buildPickerItems } = await import("./project-picker-R5TYAE3Q.js");
895
+ const { buildPickerItems } = await import("./project-picker-SVBXMPKX.js");
897
896
  return buildPickerItems({
898
897
  globalConfigPath: ctx.state.wpaths.globalConfig,
899
898
  currentProjectRoot: ctx.state.projectRoot
@@ -911,7 +910,7 @@ async function onProjectSelect(ctx, slug, kind) {
911
910
  }
912
911
  return;
913
912
  }
914
- const { loadManifest, saveManifest } = await import("./project-manifest-YFTJ3D5N.js");
913
+ const { loadManifest, saveManifest } = await import("./project-manifest-7NSFVBM3.js");
915
914
  const manifest = await loadManifest(state.wpaths.globalConfig);
916
915
  const project = manifest.projects.find((p) => p.slug === slug);
917
916
  if (!project) return;
@@ -1214,7 +1213,7 @@ async function switchProjectInPlace(ctx, targetRoot, displayName) {
1214
1213
 
1215
1214
  // src/boot/tui-sdd-callback.ts
1216
1215
  async function getSDDContext() {
1217
- const { getActiveSDDContext: getActiveSDDContext2 } = await import("./sdd-runtime-FLKCSTYV.js");
1216
+ const { getActiveSDDContext: getActiveSDDContext2 } = await import("./sdd-runtime-PTOSPYI4.js");
1218
1217
  return getActiveSDDContext2();
1219
1218
  }
1220
1219
  async function onSDDOutput(output) {
@@ -1225,7 +1224,7 @@ async function onSDDOutput(output) {
1225
1224
  autoDetectTaskCompletion: autoDetectTaskCompletion2,
1226
1225
  getTaskProgress: getTaskProgress2,
1227
1226
  getActiveSDDPhase: getActiveSDDPhase2
1228
- } = await import("./sdd-runtime-FLKCSTYV.js");
1227
+ } = await import("./sdd-runtime-PTOSPYI4.js");
1229
1228
  const messages = [];
1230
1229
  const specSaved = await trySaveSpecFromAIOutput2(output);
1231
1230
  if (specSaved) messages.push("\u2713 Spec detected and saved! Use /sdd approve to continue.");
@@ -1851,7 +1850,15 @@ function coerceAgentSwarmMode(v) {
1851
1850
  if (typeof v === "string" && (v === "bottom" || v === "sidebar" || v === "off")) return v;
1852
1851
  return "bottom";
1853
1852
  }
1854
- var ANIMATION_STYLES = ["rainbow", "wave", "pulse", "dots", "breathe", "static", "cycle"];
1853
+ var ANIMATION_STYLES = [
1854
+ "rainbow",
1855
+ "wave",
1856
+ "pulse",
1857
+ "dots",
1858
+ "breathe",
1859
+ "static",
1860
+ "cycle"
1861
+ ];
1855
1862
  function normalizeAnimationStyle(raw) {
1856
1863
  return typeof raw === "string" && ANIMATION_STYLES.includes(raw) ? raw : "rainbow";
1857
1864
  }
@@ -1899,6 +1906,11 @@ function createSettingsAdapter(ctx) {
1899
1906
  auditLevel: cfg.session?.auditLevel ?? "standard",
1900
1907
  indexOnStart: cfg.indexing?.onSessionStart !== false,
1901
1908
  maxIterations: cfg.tools?.maxIterations ?? 500,
1909
+ // Multi-diff summary threshold — mirrors the WebUI parity path
1910
+ // (pref-helpers.ts reads/writes `decrypted.autonomy.multiDiffSummaryThreshold`;
1911
+ // here we read from `decrypted.tools.multiDiffSummaryThreshold` to
1912
+ // match the Tools-section write gate added in saveSettings).
1913
+ multiDiffSummaryThreshold: cfg.tools?.multiDiffSummaryThreshold ?? 5,
1902
1914
  nextStepsTool: cfg.tools?.nextsteps?.enabled === true,
1903
1915
  restrictFsToRoot: resolvedRestrict,
1904
1916
  autoProceedMaxIterations: cfg.autonomy?.autoProceedMaxIterations ?? 50,
@@ -1948,7 +1960,7 @@ function createSettingsAdapter(ctx) {
1948
1960
  }
1949
1961
  async function saveSettings(s) {
1950
1962
  try {
1951
- if (s.mode !== void 0 || s.delayMs !== void 0 || s.titleAnimation !== void 0 || s.yolo !== void 0 || s.fleetChatVerbosity !== void 0 || s.chime !== void 0 || s.confirmExit !== void 0 || s.mouseMode !== void 0 || s.featureMcp !== void 0 || s.featurePlugins !== void 0 || s.featureMemory !== void 0 || s.featureSkills !== void 0 || s.featureModelsRegistry !== void 0 || s.featureTokenSaving !== void 0 || s.allowOutsideProjectRoot !== void 0 || s.contextAutoCompact !== void 0 || s.contextStrategy !== void 0 || s.contextMode !== void 0 || s.maxConcurrent !== void 0 || s.logLevel !== void 0 || s.auditLevel !== void 0 || s.indexOnStart !== void 0 || s.maxIterations !== void 0 || s.nextStepsTool !== void 0 || s.restrictFsToRoot !== void 0 || s.nextPrediction !== void 0 || s.debugStream !== void 0 || s.shellBangWarningDontShowAgain !== void 0 || s.configScope !== void 0 || s.enhanceDelayMs !== void 0 || s.enhanceEnabled !== void 0 || s.enhanceLanguage !== void 0 || s.midRunSendPicker !== void 0 || s.statuslineMode !== void 0 || s.thinkingWord !== void 0 || s.animationStyle !== void 0 || s.autonomyNextPrompt !== void 0 || s.autoProceedMaxIterations !== void 0 || s.reasoningMode !== void 0 || s.reasoningEffort !== void 0 || s.reasoningPreserve !== void 0 || s.cacheTtl !== void 0 || s.breakerEnabled !== void 0 || s.breakerAutoKillResetMs !== void 0 || s.showModelReasoning !== void 0 || s.showAgentSwarmPanel !== void 0 || s.showSidebar !== void 0 || s.panelPositions !== void 0 || s.showSageMemoryInject !== void 0 || s.sageMemoryInjectThreshold !== void 0 || s.readSymbols !== void 0 || // WrongProxy / WrongTrace: gate the persisted-section write on
1963
+ if (s.mode !== void 0 || s.delayMs !== void 0 || s.titleAnimation !== void 0 || s.yolo !== void 0 || s.fleetChatVerbosity !== void 0 || s.chime !== void 0 || s.confirmExit !== void 0 || s.mouseMode !== void 0 || s.featureMcp !== void 0 || s.featurePlugins !== void 0 || s.featureMemory !== void 0 || s.featureSkills !== void 0 || s.featureModelsRegistry !== void 0 || s.featureTokenSaving !== void 0 || s.allowOutsideProjectRoot !== void 0 || s.contextAutoCompact !== void 0 || s.contextStrategy !== void 0 || s.contextMode !== void 0 || s.maxConcurrent !== void 0 || s.logLevel !== void 0 || s.auditLevel !== void 0 || s.indexOnStart !== void 0 || s.maxIterations !== void 0 || s.multiDiffSummaryThreshold !== void 0 || s.nextStepsTool !== void 0 || s.restrictFsToRoot !== void 0 || s.nextPrediction !== void 0 || s.debugStream !== void 0 || s.shellBangWarningDontShowAgain !== void 0 || s.configScope !== void 0 || s.enhanceDelayMs !== void 0 || s.enhanceEnabled !== void 0 || s.enhanceLanguage !== void 0 || s.midRunSendPicker !== void 0 || s.statuslineMode !== void 0 || s.thinkingWord !== void 0 || s.animationStyle !== void 0 || s.autonomyNextPrompt !== void 0 || s.autoProceedMaxIterations !== void 0 || s.reasoningMode !== void 0 || s.reasoningEffort !== void 0 || s.reasoningPreserve !== void 0 || s.cacheTtl !== void 0 || s.breakerEnabled !== void 0 || s.breakerAutoKillResetMs !== void 0 || s.showModelReasoning !== void 0 || s.showAgentSwarmPanel !== void 0 || s.showSidebar !== void 0 || s.panelPositions !== void 0 || s.showSageMemoryInject !== void 0 || s.sageMemoryInjectThreshold !== void 0 || s.readSymbols !== void 0 || // WrongProxy / WrongTrace: gate the persisted-section write on
1952
1964
  // either key being present in the live patch. Without this, a
1953
1965
  // picker toggle round-trip would silently no-op the persistence
1954
1966
  // layer (the runtime probe would never read the change).
@@ -2058,6 +2070,9 @@ function createSettingsAdapter(ctx) {
2058
2070
  s.wrongProxyEnabled !== void 0 || s.wrongProxyUrl !== void 0) {
2059
2071
  const tools = decrypted.tools ?? {};
2060
2072
  if (s.maxIterations !== void 0) tools.maxIterations = s.maxIterations;
2073
+ if (s.multiDiffSummaryThreshold !== void 0) {
2074
+ tools.multiDiffSummaryThreshold = s.multiDiffSummaryThreshold;
2075
+ }
2061
2076
  if (s.nextStepsTool !== void 0) tools.nextsteps = { enabled: s.nextStepsTool };
2062
2077
  if (fsAccess !== void 0) tools.restrictToProjectRoot = fsAccess.restrictToProjectRoot;
2063
2078
  if (s.wrongProxyEnabled !== void 0 || s.wrongProxyUrl !== void 0) {
@@ -2176,7 +2191,7 @@ function createSettingsAdapter(ctx) {
2176
2191
  ...decrypted.indexing ?? {}
2177
2192
  }
2178
2193
  } : {},
2179
- ...s.maxIterations !== void 0 || s.nextStepsTool !== void 0 || fsAccess !== void 0 || // WrongProxy / WrongTrace: must be in the tools guard or the
2194
+ ...s.maxIterations !== void 0 || s.multiDiffSummaryThreshold !== void 0 || s.nextStepsTool !== void 0 || fsAccess !== void 0 || // WrongProxy / WrongTrace: must be in the tools guard or the
2180
2195
  // in-memory ConfigStore never sees the freshly-saved values,
2181
2196
  // and the next picker open in the same process would overwrite
2182
2197
  // the on-disk selection with stale state. See Chimera review.
@@ -2331,6 +2346,7 @@ function createBrainPanelHost(deps) {
2331
2346
  councilPerCallTimeoutMs: snap.council.perCallTimeoutMs,
2332
2347
  councilMaxConcurrency: snap.council.maxConcurrency,
2333
2348
  councilVoterMaxTokens: snap.council.voterMaxTokens,
2349
+ councilDeliberationRounds: snap.council.deliberationRounds,
2334
2350
  councilJudgeMaxTokens: snap.council.judgeMaxTokens,
2335
2351
  // The EFFECTIVE judge, not `council.judge`. The configured one is
2336
2352
  // usually absent, so the panel used to read "auto" and say nothing
@@ -2413,6 +2429,7 @@ function createBrainPanelHost(deps) {
2413
2429
  setCouncilPerCallTimeout: (ms) => apply({ council: { perCallTimeoutMs: ms ?? null } }),
2414
2430
  setCouncilMaxConcurrency: (count) => apply({ council: { maxConcurrency: count ?? null } }),
2415
2431
  setCouncilVoterMaxTokens: (tokens) => apply({ council: { voterMaxTokens: tokens ?? null } }),
2432
+ setCouncilDeliberationRounds: (rounds) => apply({ council: { deliberationRounds: rounds ?? null } }),
2416
2433
  setCouncilJudgeMaxTokens: (tokens) => apply({ council: { judgeMaxTokens: tokens ?? null } }),
2417
2434
  setLedgerEnabled: (on) => apply({ ledger: { enabled: on } }),
2418
2435
  setAutoDeny: (count) => apply({ ledger: { autoDenyAfterFailures: count ?? null } }),
@@ -2665,7 +2682,7 @@ async function finalizeExecutionCleanup(input) {
2665
2682
  })
2666
2683
  );
2667
2684
  } else {
2668
- const { reportWrongTraceSessionTelemetry } = await import("./wrongtrace-telemetry-FNLANZ5I.js");
2685
+ const { reportWrongTraceSessionTelemetry } = await import("./wrongtrace-telemetry-3ASFKOZO.js");
2669
2686
  const usage = tokenCounter.total();
2670
2687
  const report = reportWrongTraceSessionTelemetry({
2671
2688
  sessionId: activeSession.id,
@@ -2693,7 +2710,7 @@ async function finalizeExecutionCleanup(input) {
2693
2710
  } catch {
2694
2711
  }
2695
2712
  try {
2696
- const { snapshotGateDecisions, persistWrongTraceGateCounters } = await import("./wrongtrace-gate-counters-P5BCBXQN.js");
2713
+ const { snapshotGateDecisions, persistWrongTraceGateCounters } = await import("./wrongtrace-gate-counters-7C2EAAZL.js");
2697
2714
  const projectRoot = agent.ctx.projectRoot;
2698
2715
  if (projectRoot) {
2699
2716
  await persistWrongTraceGateCounters(projectRoot, snapshotGateDecisions());
@@ -2814,7 +2831,7 @@ function resolveKanbanDispatchRoute(config, spawnOpts) {
2814
2831
  tier = resolved.tier;
2815
2832
  provider = provider ?? resolved.provider ?? config.provider;
2816
2833
  model = model ?? resolved.model;
2817
- fallbackModels = fallbackModels ?? (resolved.fallbackModels?.slice() ?? void 0);
2834
+ fallbackModels = fallbackModels ?? resolved.fallbackModels?.slice() ?? void 0;
2818
2835
  }
2819
2836
  }
2820
2837
  return { provider, model, fallbackModels, ...tier ? { tier } : {} };
@@ -3453,8 +3470,12 @@ function buildChimeraReviewTaskDescription(p) {
3453
3470
  lines.push("---");
3454
3471
  lines.push("");
3455
3472
  lines.push("**Review Instructions:**");
3456
- lines.push("- Review the diffs and new file contents carefully for real bugs, broken logic, null dereferences, and security gaps.");
3457
- lines.push("- Stay strictly within the scoped diffs. DO NOT audit unchanged files, pre-existing debt, or stylistic preferences.");
3473
+ lines.push(
3474
+ "- Review the diffs and new file contents carefully for real bugs, broken logic, null dereferences, and security gaps."
3475
+ );
3476
+ lines.push(
3477
+ "- Stay strictly within the scoped diffs. DO NOT audit unchanged files, pre-existing debt, or stylistic preferences."
3478
+ );
3458
3479
  lines.push("- Use tools only when you need surrounding lines to verify a concrete issue.");
3459
3480
  lines.push("- Once the diff is validated, output your report (findings or all-clear) promptly.");
3460
3481
  return lines.join("\n");
@@ -3651,122 +3672,126 @@ function installChimeraCascadeHandler({
3651
3672
  persistEvidence,
3652
3673
  teardownHandlers
3653
3674
  }) {
3654
- const off = events.onPattern("chimera.cascade_needed", (_event, payload) => {
3655
- const p = payload;
3656
- const dir = director;
3657
- if (!dir) return;
3658
- if (p.agents.length === 0) return;
3659
- const previousWork = getPendingWork();
3660
- const pendingWork = (async () => {
3661
- try {
3662
- await previousWork;
3663
- } catch {
3664
- }
3665
- const agentEvidence = [];
3666
- for (const agentKind of p.agents) {
3675
+ const off = events.onPattern(
3676
+ "chimera.cascade_needed",
3677
+ (_event, payload) => {
3678
+ const p = payload;
3679
+ const dir = director;
3680
+ if (!dir) return;
3681
+ if (p.agents.length === 0) return;
3682
+ const previousWork = getPendingWork();
3683
+ const pendingWork = (async () => {
3667
3684
  try {
3668
- const taskDesc = buildChimeraCascadeTaskDescription(agentKind, p);
3669
- const role = agentKind === "security-scanner" ? "security-scanner" : "bug-hunter";
3670
- const ladder = buildLadder?.() ?? INHERIT_ONLY_LADDER;
3671
- const outcome = await runSubagentModelLadder({
3672
- director: dir,
3673
- ladder,
3674
- attemptTimeoutMs: CASCADE_ATTEMPT_TIMEOUT_MS,
3675
- budgetMs: CASCADE_LADDER_BUDGET_MS,
3676
- buildConfig: (attempt, timeoutMs) => ({
3677
- name: `chimera-cascade-${agentKind}`,
3678
- role,
3679
- maxIterations: 40,
3680
- maxToolCalls: 200,
3681
- timeoutMs,
3682
- // Cascade agents are ephemeral infrastructure: like reviewers,
3683
- // they must not consume the leader's lifetime maxSpawns budget.
3684
- spawnBudgetExempt: true,
3685
- // Model-driven completion (see core coordination/subagent-finish.ts):
3686
- // a rung crossing its wall-clock budget is notified in-band
3687
- // between tool batches and finishes its own turn within the
3688
- // grace window instead of being killed. Ladder-retry semantics
3689
- // are intact: a rung that still exhausts the grace window lands
3690
- // as a `timeout` task result, which advances the ladder, and
3691
- // `buildRetryPreamble` below already warns the successor that
3692
- // the tree may hold the dead rung's partial edits.
3693
- gracefulFinish: true,
3694
- // Rung 0 stays unpinned so the role model matrix still decides;
3695
- // later rungs pin a model precisely because it just failed.
3696
- ...attempt.tier === "inherit" ? {} : {
3697
- provider: attempt.provider,
3698
- model: attempt.model,
3699
- fallbackModels: attempt.fallbackModels
3685
+ await previousWork;
3686
+ } catch {
3687
+ }
3688
+ const agentEvidence = [];
3689
+ for (const agentKind of p.agents) {
3690
+ try {
3691
+ const taskDesc = buildChimeraCascadeTaskDescription(agentKind, p);
3692
+ const role = agentKind === "security-scanner" ? "security-scanner" : "bug-hunter";
3693
+ const ladder = buildLadder?.() ?? INHERIT_ONLY_LADDER;
3694
+ const outcome = await runSubagentModelLadder({
3695
+ director: dir,
3696
+ ladder,
3697
+ attemptTimeoutMs: CASCADE_ATTEMPT_TIMEOUT_MS,
3698
+ budgetMs: CASCADE_LADDER_BUDGET_MS,
3699
+ buildConfig: (attempt, timeoutMs) => ({
3700
+ name: `chimera-cascade-${agentKind}`,
3701
+ role,
3702
+ maxIterations: 40,
3703
+ maxToolCalls: 200,
3704
+ timeoutMs,
3705
+ // Cascade agents are ephemeral infrastructure: like reviewers,
3706
+ // they must not consume the leader's lifetime maxSpawns budget.
3707
+ spawnBudgetExempt: true,
3708
+ // Model-driven completion (see core coordination/subagent-finish.ts):
3709
+ // a rung crossing its wall-clock budget is notified in-band
3710
+ // between tool batches and finishes its own turn within the
3711
+ // grace window instead of being killed. Ladder-retry semantics
3712
+ // are intact: a rung that still exhausts the grace window lands
3713
+ // as a `timeout` task result, which advances the ladder, and
3714
+ // `buildRetryPreamble` below already warns the successor that
3715
+ // the tree may hold the dead rung's partial edits.
3716
+ gracefulFinish: true,
3717
+ // Rung 0 stays unpinned so the role model matrix still decides;
3718
+ // later rungs pin a model precisely because it just failed.
3719
+ ...attempt.tier === "inherit" ? {} : {
3720
+ provider: attempt.provider,
3721
+ model: attempt.model,
3722
+ fallbackModels: attempt.fallbackModels
3723
+ }
3724
+ }),
3725
+ // Cascade agents write files, so a successor must be told the tree
3726
+ // may already hold the dead attempt's partial edits.
3727
+ buildTask: (_attempt, failures) => `${buildRetryPreamble(failures)}${taskDesc}`,
3728
+ onAttemptFailed: async (failure, next) => {
3729
+ if (!next) return;
3730
+ await session.append({
3731
+ type: "error",
3732
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
3733
+ message: `\u{1F982} Chimera cascade (${agentKind}) on ${failure.model} failed (${failure.reason}) \u2014 retrying on ${attemptLabel(next)} (${next.tier}).`,
3734
+ phase: "agent"
3735
+ });
3700
3736
  }
3701
- }),
3702
- // Cascade agents write files, so a successor must be told the tree
3703
- // may already hold the dead attempt's partial edits.
3704
- buildTask: (_attempt, failures) => `${buildRetryPreamble(failures)}${taskDesc}`,
3705
- onAttemptFailed: async (failure, next) => {
3706
- if (!next) return;
3737
+ });
3738
+ const result = outcome.result;
3739
+ if (result?.status === "success") {
3740
+ const resultText = typeof result.result === "string" ? result.result : JSON.stringify(result.result);
3741
+ const claimed = extractCascadeEvidence(resultText);
3742
+ if (claimed) {
3743
+ agentEvidence.push({ agentKind, evidence: claimed });
3744
+ }
3745
+ await session.append({
3746
+ type: "llm_response",
3747
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
3748
+ content: [
3749
+ {
3750
+ type: "text",
3751
+ text: `\u{1F982} Chimera cascade (${agentKind}) \u2014 ${resultText}`
3752
+ }
3753
+ ],
3754
+ stopReason: "end_turn",
3755
+ usage: { input: 0, output: 0 }
3756
+ });
3757
+ } else {
3758
+ const detail = outcome.lastError ? outcome.lastError instanceof Error ? outcome.lastError.message : String(outcome.lastError) : `${result?.status ?? "unknown"}: ${result?.error?.message ?? "no result"}`;
3707
3759
  await session.append({
3708
3760
  type: "error",
3709
3761
  ts: (/* @__PURE__ */ new Date()).toISOString(),
3710
- message: `\u{1F982} Chimera cascade (${agentKind}) on ${failure.model} failed (${failure.reason}) \u2014 retrying on ${attemptLabel(next)} (${next.tier}).`,
3762
+ message: `\u{1F982} Chimera cascade (${agentKind}) ${result?.status ?? "unknown"}: ${detail} \u2014 exhausted ${outcome.attemptsUsed} of ${ladder.length} model(s)`,
3711
3763
  phase: "agent"
3712
3764
  });
3713
3765
  }
3714
- });
3715
- const result = outcome.result;
3716
- if (result?.status === "success") {
3717
- const resultText = typeof result.result === "string" ? result.result : JSON.stringify(result.result);
3718
- const claimed = extractCascadeEvidence(resultText);
3719
- if (claimed) {
3720
- agentEvidence.push({ agentKind, evidence: claimed });
3721
- }
3722
- await session.append({
3723
- type: "llm_response",
3724
- ts: (/* @__PURE__ */ new Date()).toISOString(),
3725
- content: [
3726
- {
3727
- type: "text",
3728
- text: `\u{1F982} Chimera cascade (${agentKind}) \u2014 ${resultText}`
3729
- }
3730
- ],
3731
- stopReason: "end_turn",
3732
- usage: { input: 0, output: 0 }
3733
- });
3734
- } else {
3735
- const detail = outcome.lastError ? outcome.lastError instanceof Error ? outcome.lastError.message : String(outcome.lastError) : `${result?.status ?? "unknown"}: ${result?.error?.message ?? "no result"}`;
3766
+ } catch (err) {
3736
3767
  await session.append({
3737
3768
  type: "error",
3738
3769
  ts: (/* @__PURE__ */ new Date()).toISOString(),
3739
- message: `\u{1F982} Chimera cascade (${agentKind}) ${result?.status ?? "unknown"}: ${detail} \u2014 exhausted ${outcome.attemptsUsed} of ${ladder.length} model(s)`,
3770
+ message: `\u{1F982} Chimera cascade (${agentKind}) failed: ${err instanceof Error ? err.message : String(err)}`,
3740
3771
  phase: "agent"
3741
3772
  });
3742
3773
  }
3743
- } catch (err) {
3744
- await session.append({
3745
- type: "error",
3746
- ts: (/* @__PURE__ */ new Date()).toISOString(),
3747
- message: `\u{1F982} Chimera cascade (${agentKind}) failed: ${err instanceof Error ? err.message : String(err)}`,
3748
- phase: "agent"
3749
- });
3750
3774
  }
3751
- }
3752
- const accumulatedEvidence = {};
3753
- for (const { evidence } of agentEvidence) {
3754
- for (const name of ["typecheck", "lint", "tests"]) {
3755
- if (evidence[name]) accumulatedEvidence[name] = evidence[name];
3775
+ const accumulatedEvidence = {};
3776
+ for (const { evidence } of agentEvidence) {
3777
+ for (const name of ["typecheck", "lint", "tests"]) {
3778
+ if (evidence[name]) accumulatedEvidence[name] = evidence[name];
3779
+ }
3756
3780
  }
3757
- }
3758
- await maybeReReviewCascade({
3759
- events,
3760
- session,
3761
- bundle: p.bundle,
3762
- reportId: p.reportId,
3763
- claimedEvidence: accumulatedEvidence,
3764
- verifyEvidence,
3765
- persistEvidence
3766
- });
3767
- })();
3768
- trackWork(pendingWork);
3769
- }, "chimera-cascade");
3781
+ await maybeReReviewCascade({
3782
+ events,
3783
+ session,
3784
+ bundle: p.bundle,
3785
+ reportId: p.reportId,
3786
+ claimedEvidence: accumulatedEvidence,
3787
+ verifyEvidence,
3788
+ persistEvidence
3789
+ });
3790
+ })();
3791
+ trackWork(pendingWork);
3792
+ },
3793
+ "chimera-cascade"
3794
+ );
3770
3795
  if (off) teardownHandlers?.push(off);
3771
3796
  }
3772
3797
  async function maybeReReviewCascade({
@@ -3948,372 +3973,376 @@ function installChimeraReviewHandler({
3948
3973
  trackWork,
3949
3974
  teardownHandlers
3950
3975
  }) {
3951
- const off = events.onPattern("chimera.review_needed", (_event, payload) => {
3952
- const p = payload;
3953
- const reviewSessionId = agent.ctx.activeRunSessionId ?? agent.ctx.session?.id ?? session.id;
3954
- if (!areSubagentsAllowedForSession(reviewSessionId)) {
3955
- void recordCompletedReview(events, { bundle: p }).catch(() => void 0);
3956
- return;
3957
- }
3958
- const dir = director;
3959
- if (!dir) {
3960
- void recordCompletedReview(events, { bundle: p }).catch(() => void 0);
3961
- return;
3962
- }
3963
- if (p.files.length === 0) return;
3964
- const appendChimeraNotice = async (message) => {
3965
- try {
3966
- await session.append({
3967
- type: "error",
3968
- ts: (/* @__PURE__ */ new Date()).toISOString(),
3969
- message,
3970
- phase: "agent"
3971
- });
3972
- } catch (err) {
3973
- console.warn(
3974
- JSON.stringify({
3975
- level: "warn",
3976
- event: "execution.chimera_notice_append_failed",
3977
- message: err instanceof Error ? err.message : String(err),
3978
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
3979
- })
3980
- );
3976
+ const off = events.onPattern(
3977
+ "chimera.review_needed",
3978
+ (_event, payload) => {
3979
+ const p = payload;
3980
+ const reviewSessionId = agent.ctx.activeRunSessionId ?? agent.ctx.session?.id ?? session.id;
3981
+ if (!areSubagentsAllowedForSession(reviewSessionId)) {
3982
+ void recordCompletedReview(events, { bundle: p }).catch(() => void 0);
3983
+ return;
3981
3984
  }
3982
- };
3983
- const persistAndEmitCompletion = async (completion) => {
3984
- try {
3985
- await persistReview(completion, projectDir);
3986
- events.emitCustom("chimera.review_persisted", {
3987
- reportId: completion.reportId,
3988
- sessionId: completion.sessionId,
3989
- cwd: completion.cwd
3990
- });
3991
- } catch (error) {
3992
- const message = error instanceof Error ? error.message : String(error);
3993
- events.emitCustom("chimera.review_persistence_failed", {
3994
- reportId: completion.reportId,
3995
- sessionId: completion.sessionId,
3996
- cwd: completion.cwd,
3997
- error: message
3998
- });
3999
- await appendChimeraNotice(
4000
- `\u{1F982} Chimera report persistence failed: ${message}. The review remains in the session transcript and mailbox.`
4001
- );
4002
- } finally {
4003
- await recordCompletedReview(events, completion);
4004
- events.emitCustom("chimera.review_complete", completion);
3985
+ const dir = director;
3986
+ if (!dir) {
3987
+ void recordCompletedReview(events, { bundle: p }).catch(() => void 0);
3988
+ return;
4005
3989
  }
4006
- };
4007
- trackWork(
4008
- (async () => {
4009
- let subagentId;
3990
+ if (p.files.length === 0) return;
3991
+ const appendChimeraNotice = async (message) => {
4010
3992
  try {
4011
- const taskDesc = buildChimeraReviewTaskDescription(p);
4012
- const tProvider = config.provider?.trim() || void 0;
4013
- const tModel = config.model?.trim() || void 0;
4014
- const rawProvider = p.reviewFallbackModels ? p.config.provider?.trim() || void 0 : tProvider;
4015
- const rawModel = p.reviewFallbackModels ? p.config.model?.trim() || void 0 : tModel;
4016
- const baseProvider = rawProvider || tProvider || config.provider;
4017
- const baseModel = rawModel || tModel || config.model;
4018
- const configFallbacks = [...p.config.fallbackModels ?? []];
4019
- if (p.config.fallbackProfile) {
4020
- configFallbacks.push(...fallbackProfileChain2(config, p.config.fallbackProfile));
4021
- }
4022
- const baseFallbacks = p.reviewFallbackModels ? [...p.reviewFallbackModels] : resolveReviewerFallbackModels(
4023
- configFallbacks.length > 0 ? configFallbacks : void 0
4024
- );
4025
- const assigned = assignReviewerModels(
4026
- baseProvider,
4027
- baseModel,
4028
- baseFallbacks,
4029
- p.reviewModelSelection ?? "round-robin",
4030
- statusTracker
3993
+ await session.append({
3994
+ type: "error",
3995
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
3996
+ message,
3997
+ phase: "agent"
3998
+ });
3999
+ } catch (err) {
4000
+ console.warn(
4001
+ JSON.stringify({
4002
+ level: "warn",
4003
+ event: "execution.chimera_notice_append_failed",
4004
+ message: err instanceof Error ? err.message : String(err),
4005
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
4006
+ })
4031
4007
  );
4032
- const ladder = buildReviewerAttemptLadder({
4033
- assigned,
4034
- profileChain: effectiveFallbackChain(config),
4035
- session: { provider: config.provider, model: config.model }
4008
+ }
4009
+ };
4010
+ const persistAndEmitCompletion = async (completion) => {
4011
+ try {
4012
+ await persistReview(completion, projectDir);
4013
+ events.emitCustom("chimera.review_persisted", {
4014
+ reportId: completion.reportId,
4015
+ sessionId: completion.sessionId,
4016
+ cwd: completion.cwd
4036
4017
  });
4037
- const ladderRefs = ladder.map(attemptLabel);
4038
- const outcome = await runSubagentModelLadder({
4039
- director: dir,
4040
- ladder,
4041
- budgetMs: REVIEWER_LADDER_BUDGET_MS,
4042
- keepWinnerAlive: false,
4043
- buildConfig: (attempt, timeoutMs) => applyChimeraReviewerReadOnlyPolicy({
4044
- name: "chimera-review",
4045
- role: "reviewer",
4046
- systemPromptOverride: CHIMERA_REVIEW_PROMPT,
4047
- maxIterations: 50,
4048
- maxToolCalls: 250,
4049
- timeoutMs,
4050
- provider: attempt.provider,
4051
- model: attempt.model,
4052
- fallbackModels: attempt.fallbackModels,
4053
- // Reviewers are ephemeral background infrastructure: they must
4054
- // not consume the leader's lifetime maxSpawns budget.
4055
- spawnBudgetExempt: true
4056
- }),
4057
- // The reviewer is read-only, so a retry re-runs the task verbatim.
4058
- buildTask: () => taskDesc,
4059
- onAttemptFailed: async (failure, next) => {
4060
- console.warn(
4061
- JSON.stringify({
4062
- level: "warn",
4063
- event: "execution.chimera_reviewer_attempt_failed",
4064
- message: failure.reason,
4065
- model: failure.model,
4066
- tier: failure.tier,
4018
+ } catch (error) {
4019
+ const message = error instanceof Error ? error.message : String(error);
4020
+ events.emitCustom("chimera.review_persistence_failed", {
4021
+ reportId: completion.reportId,
4022
+ sessionId: completion.sessionId,
4023
+ cwd: completion.cwd,
4024
+ error: message
4025
+ });
4026
+ await appendChimeraNotice(
4027
+ `\u{1F982} Chimera report persistence failed: ${message}. The review remains in the session transcript and mailbox.`
4028
+ );
4029
+ } finally {
4030
+ await recordCompletedReview(events, completion);
4031
+ events.emitCustom("chimera.review_complete", completion);
4032
+ }
4033
+ };
4034
+ trackWork(
4035
+ (async () => {
4036
+ let subagentId;
4037
+ try {
4038
+ const taskDesc = buildChimeraReviewTaskDescription(p);
4039
+ const tProvider = config.provider?.trim() || void 0;
4040
+ const tModel = config.model?.trim() || void 0;
4041
+ const rawProvider = p.reviewFallbackModels ? p.config.provider?.trim() || void 0 : tProvider;
4042
+ const rawModel = p.reviewFallbackModels ? p.config.model?.trim() || void 0 : tModel;
4043
+ const baseProvider = rawProvider || tProvider || config.provider;
4044
+ const baseModel = rawModel || tModel || config.model;
4045
+ const configFallbacks = [...p.config.fallbackModels ?? []];
4046
+ if (p.config.fallbackProfile) {
4047
+ configFallbacks.push(...fallbackProfileChain2(config, p.config.fallbackProfile));
4048
+ }
4049
+ const baseFallbacks = p.reviewFallbackModels ? [...p.reviewFallbackModels] : resolveReviewerFallbackModels(
4050
+ configFallbacks.length > 0 ? configFallbacks : void 0
4051
+ );
4052
+ const assigned = assignReviewerModels(
4053
+ baseProvider,
4054
+ baseModel,
4055
+ baseFallbacks,
4056
+ p.reviewModelSelection ?? "round-robin",
4057
+ statusTracker
4058
+ );
4059
+ const ladder = buildReviewerAttemptLadder({
4060
+ assigned,
4061
+ profileChain: effectiveFallbackChain(config),
4062
+ session: { provider: config.provider, model: config.model }
4063
+ });
4064
+ const ladderRefs = ladder.map(attemptLabel);
4065
+ const outcome = await runSubagentModelLadder({
4066
+ director: dir,
4067
+ ladder,
4068
+ budgetMs: REVIEWER_LADDER_BUDGET_MS,
4069
+ keepWinnerAlive: false,
4070
+ buildConfig: (attempt, timeoutMs) => applyChimeraReviewerReadOnlyPolicy({
4071
+ name: "chimera-review",
4072
+ role: "reviewer",
4073
+ systemPromptOverride: CHIMERA_REVIEW_PROMPT,
4074
+ maxIterations: 50,
4075
+ maxToolCalls: 250,
4076
+ timeoutMs,
4077
+ provider: attempt.provider,
4078
+ model: attempt.model,
4079
+ fallbackModels: attempt.fallbackModels,
4080
+ // Reviewers are ephemeral background infrastructure: they must
4081
+ // not consume the leader's lifetime maxSpawns budget.
4082
+ spawnBudgetExempt: true
4083
+ }),
4084
+ // The reviewer is read-only, so a retry re-runs the task verbatim.
4085
+ buildTask: () => taskDesc,
4086
+ onAttemptFailed: async (failure, next) => {
4087
+ console.warn(
4088
+ JSON.stringify({
4089
+ level: "warn",
4090
+ event: "execution.chimera_reviewer_attempt_failed",
4091
+ message: failure.reason,
4092
+ model: failure.model,
4093
+ tier: failure.tier,
4094
+ attempt: failure.attempt,
4095
+ of: ladder.length,
4096
+ nextModel: next ? attemptLabel(next) : void 0,
4097
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
4098
+ })
4099
+ );
4100
+ if (!next) return;
4101
+ events.emitCustom("chimera.reviewer_model_fallback", {
4102
+ from: failure.model,
4103
+ to: attemptLabel(next),
4104
+ tier: next.tier,
4067
4105
  attempt: failure.attempt,
4068
4106
  of: ladder.length,
4069
- nextModel: next ? attemptLabel(next) : void 0,
4070
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
4071
- })
4072
- );
4073
- if (!next) return;
4074
- events.emitCustom("chimera.reviewer_model_fallback", {
4075
- from: failure.model,
4076
- to: attemptLabel(next),
4077
- tier: next.tier,
4078
- attempt: failure.attempt,
4079
- of: ladder.length,
4080
- reason: failure.reason
4081
- });
4082
- await appendChimeraNotice(
4083
- `\u{1F982} Chimera review on ${failure.model} failed (${failure.reason}) \u2014 retrying the same review on ${attemptLabel(next)} (${next.tier}).`
4084
- );
4085
- },
4086
- onRecovered: async (attempt, failures) => {
4087
- await appendChimeraNotice(
4088
- `\u{1F982} Chimera review recovered on ${attemptLabel(attempt)} (${attempt.tier}) after ${failures.length} failed attempt(s).`
4089
- );
4090
- }
4091
- });
4092
- subagentId = outcome.subagentId;
4093
- const result = outcome.result;
4094
- if (result?.status !== "success") {
4095
- const exhaustedDetail = outcome.lastError ? outcome.lastError instanceof Error ? outcome.lastError.message : String(outcome.lastError) : `${result?.status ?? "unknown"}: ${result?.error?.message ?? "no result"}`;
4096
- try {
4097
- await session.append({
4098
- type: "error",
4099
- ts: (/* @__PURE__ */ new Date()).toISOString(),
4100
- message: `\u{1F982} Chimera review subagent ${result?.status ?? "unknown"}: ${exhaustedDetail} \u2014 exhausted ${outcome.attemptsUsed} of ${ladder.length} model(s): ${ladderRefs.join(" \u2192 ")}`,
4101
- phase: "agent"
4107
+ reason: failure.reason
4108
+ });
4109
+ await appendChimeraNotice(
4110
+ `\u{1F982} Chimera review on ${failure.model} failed (${failure.reason}) \u2014 retrying the same review on ${attemptLabel(next)} (${next.tier}).`
4111
+ );
4112
+ },
4113
+ onRecovered: async (attempt, failures) => {
4114
+ await appendChimeraNotice(
4115
+ `\u{1F982} Chimera review recovered on ${attemptLabel(attempt)} (${attempt.tier}) after ${failures.length} failed attempt(s).`
4116
+ );
4117
+ }
4118
+ });
4119
+ subagentId = outcome.subagentId;
4120
+ const result = outcome.result;
4121
+ if (result?.status !== "success") {
4122
+ const exhaustedDetail = outcome.lastError ? outcome.lastError instanceof Error ? outcome.lastError.message : String(outcome.lastError) : `${result?.status ?? "unknown"}: ${result?.error?.message ?? "no result"}`;
4123
+ try {
4124
+ await session.append({
4125
+ type: "error",
4126
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
4127
+ message: `\u{1F982} Chimera review subagent ${result?.status ?? "unknown"}: ${exhaustedDetail} \u2014 exhausted ${outcome.attemptsUsed} of ${ladder.length} model(s): ${ladderRefs.join(" \u2192 ")}`,
4128
+ phase: "agent"
4129
+ });
4130
+ } catch (err) {
4131
+ console.error(
4132
+ JSON.stringify({
4133
+ level: "error",
4134
+ event: "execution.chimera_append_failed",
4135
+ message: err instanceof Error ? err.message : String(err),
4136
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
4137
+ })
4138
+ );
4139
+ }
4140
+ await persistAndEmitCompletion({
4141
+ bundle: p,
4142
+ reviewText: "",
4143
+ status: result?.status ?? "unknown",
4144
+ cwd: p.cwd,
4145
+ sessionId: reviewSessionId,
4146
+ reportId: randomUUID3()
4102
4147
  });
4103
- } catch (err) {
4104
- console.error(
4105
- JSON.stringify({
4106
- level: "error",
4107
- event: "execution.chimera_append_failed",
4108
- message: err instanceof Error ? err.message : String(err),
4109
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
4110
- })
4111
- );
4148
+ return;
4112
4149
  }
4150
+ const reviewText = typeof result.result === "string" ? result.result.trim() : JSON.stringify(result.result);
4151
+ const reportId = randomUUID3();
4152
+ const reviewSource = classifyChimeraReviewSource(p);
4153
+ const winningAttempt = outcome.wonAt ? ladder[outcome.wonAt - 1] : void 0;
4154
+ const parsedReport = parseChimeraReviewReport(reviewText, {
4155
+ sessionId: reviewSessionId,
4156
+ agentId: p.fileProvenance?.find((entry) => entry.agentId)?.agentId ?? "chimera-review",
4157
+ reviewerModel: winningAttempt ? attemptLabel(winningAttempt) : void 0,
4158
+ reviewType: reviewSource,
4159
+ reportId
4160
+ });
4161
+ const verifiedFindings = await verifyFindingsAgainstDisk(parsedReport.findings, {
4162
+ cwd: p.cwd
4163
+ });
4164
+ const verifiedParsedReport = {
4165
+ ...parsedReport,
4166
+ findings: verifiedFindings
4167
+ };
4113
4168
  await persistAndEmitCompletion({
4114
4169
  bundle: p,
4115
- reviewText: "",
4116
- status: result?.status ?? "unknown",
4170
+ reviewText,
4171
+ status: "success",
4117
4172
  cwd: p.cwd,
4118
4173
  sessionId: reviewSessionId,
4119
- reportId: randomUUID3()
4174
+ reportId,
4175
+ parsedReport: verifiedParsedReport
4120
4176
  });
4121
- return;
4122
- }
4123
- const reviewText = typeof result.result === "string" ? result.result.trim() : JSON.stringify(result.result);
4124
- const reportId = randomUUID3();
4125
- const reviewSource = classifyChimeraReviewSource(p);
4126
- const winningAttempt = outcome.wonAt ? ladder[outcome.wonAt - 1] : void 0;
4127
- const parsedReport = parseChimeraReviewReport(reviewText, {
4128
- sessionId: reviewSessionId,
4129
- agentId: p.fileProvenance?.find((entry) => entry.agentId)?.agentId ?? "chimera-review",
4130
- reviewerModel: winningAttempt ? attemptLabel(winningAttempt) : void 0,
4131
- reviewType: reviewSource,
4132
- reportId
4133
- });
4134
- const verifiedFindings = await verifyFindingsAgainstDisk(parsedReport.findings, {
4135
- cwd: p.cwd
4136
- });
4137
- const verifiedParsedReport = {
4138
- ...parsedReport,
4139
- findings: verifiedFindings
4140
- };
4141
- await persistAndEmitCompletion({
4142
- bundle: p,
4143
- reviewText,
4144
- status: "success",
4145
- cwd: p.cwd,
4146
- sessionId: reviewSessionId,
4147
- reportId,
4148
- parsedReport: verifiedParsedReport
4149
- });
4150
- if (reviewText) {
4151
- const reviewHasFindings = !isChimeraAllClearReview(reviewText);
4152
- const citedFindings = verifiedFindings.filter((finding) => finding.location);
4153
- const citedPaths = new Set(
4154
- p.files.map((file) => normalizeFileKeyForCitation(file.path, p.cwd))
4155
- );
4156
- const changedBasenameIndex = /* @__PURE__ */ new Map();
4157
- for (const file of p.files) {
4158
- const normalized = normalizeFileKeyForCitation(file.path, p.cwd);
4159
- const basename7 = path12.basename(file.path).toLowerCase();
4160
- const bucket = changedBasenameIndex.get(basename7);
4161
- if (bucket) bucket.push(normalized);
4162
- else changedBasenameIndex.set(basename7, [normalized]);
4163
- }
4164
- const inScopeCited = citedFindings.filter((finding) => {
4165
- const citedKey = normalizeFileKeyForCitation(finding.location.file, p.cwd);
4166
- if (citedPaths.has(citedKey)) return true;
4167
- const suffixMatches = [...citedPaths].filter(
4168
- (cp) => cp.endsWith(`/${citedKey}`) || cp === citedKey
4177
+ if (reviewText) {
4178
+ const reviewHasFindings = !isChimeraAllClearReview(reviewText);
4179
+ const citedFindings = verifiedFindings.filter((finding) => finding.location);
4180
+ const citedPaths = new Set(
4181
+ p.files.map((file) => normalizeFileKeyForCitation(file.path, p.cwd))
4169
4182
  );
4170
- if (suffixMatches.length === 1) return true;
4171
- const basename7 = path12.basename(finding.location.file).toLowerCase();
4172
- const bucket = changedBasenameIndex.get(basename7);
4173
- return !!(bucket && bucket.length === 1);
4174
- });
4175
- const droppedCitations = citedFindings.filter(
4176
- (finding) => !inScopeCited.includes(finding)
4177
- );
4178
- const actionableFindings = inScopeCited.filter(
4179
- (finding) => finding.verification?.status === "verified"
4180
- );
4181
- const unverifiedInScope = inScopeCited.filter(
4182
- (finding) => finding.verification?.status === "unverified"
4183
- );
4184
- const failedVerificationCount = inScopeCited.filter(
4185
- (finding) => finding.verification?.status === "failed"
4186
- ).length;
4187
- const effectiveHasFindings = reviewHasFindings && (actionableFindings.length > 0 || unverifiedInScope.length > 0);
4188
- const verifiedCount = actionableFindings.length;
4189
- const unverifiedCount = unverifiedInScope.length;
4190
- const hallucinationNote = droppedCitations.length > 0 ? `
4183
+ const changedBasenameIndex = /* @__PURE__ */ new Map();
4184
+ for (const file of p.files) {
4185
+ const normalized = normalizeFileKeyForCitation(file.path, p.cwd);
4186
+ const basename7 = path12.basename(file.path).toLowerCase();
4187
+ const bucket = changedBasenameIndex.get(basename7);
4188
+ if (bucket) bucket.push(normalized);
4189
+ else changedBasenameIndex.set(basename7, [normalized]);
4190
+ }
4191
+ const inScopeCited = citedFindings.filter((finding) => {
4192
+ const citedKey = normalizeFileKeyForCitation(finding.location.file, p.cwd);
4193
+ if (citedPaths.has(citedKey)) return true;
4194
+ const suffixMatches = [...citedPaths].filter(
4195
+ (cp) => cp.endsWith(`/${citedKey}`) || cp === citedKey
4196
+ );
4197
+ if (suffixMatches.length === 1) return true;
4198
+ const basename7 = path12.basename(finding.location.file).toLowerCase();
4199
+ const bucket = changedBasenameIndex.get(basename7);
4200
+ return !!(bucket && bucket.length === 1);
4201
+ });
4202
+ const droppedCitations = citedFindings.filter(
4203
+ (finding) => !inScopeCited.includes(finding)
4204
+ );
4205
+ const actionableFindings = inScopeCited.filter(
4206
+ (finding) => finding.verification?.status === "verified"
4207
+ );
4208
+ const unverifiedInScope = inScopeCited.filter(
4209
+ (finding) => finding.verification?.status === "unverified"
4210
+ );
4211
+ const failedVerificationCount = inScopeCited.filter(
4212
+ (finding) => finding.verification?.status === "failed"
4213
+ ).length;
4214
+ const effectiveHasFindings = reviewHasFindings && (actionableFindings.length > 0 || unverifiedInScope.length > 0);
4215
+ const verifiedCount = actionableFindings.length;
4216
+ const unverifiedCount = unverifiedInScope.length;
4217
+ const hallucinationNote = droppedCitations.length > 0 ? `
4191
4218
 
4192
4219
  \u26A0\uFE0F Citation validation: ${droppedCitations.length} finding(s) cite files outside the changed-file set and should be verified before acting.` : "";
4193
- const subject = `\u{1F982} Chimera report ready \u2014 ${p.files.length} file(s) checked`;
4194
- let reviewMailMessageId;
4195
- try {
4196
- const directive = effectiveHasFindings ? "Chimera found potential issues. This report is informational: no leader turn, fix agent, or cascade was started. Open the report and explicitly ask the leader to act if you want changes." : "Chimera completed with no actionable findings. No follow-up was started.";
4197
- const reviewBody = reviewText.length > 7500 ? truncateAtCodePointBoundary(reviewText, 7500) + "\n\n\u2026(truncated, full report is in the Chimera report store)" : reviewText;
4198
- const body = `${directive}${hallucinationNote}
4220
+ const subject = `\u{1F982} Chimera report ready \u2014 ${p.files.length} file(s) checked`;
4221
+ let reviewMailMessageId;
4222
+ try {
4223
+ const directive = effectiveHasFindings ? "Chimera found potential issues. This report is informational: no leader turn, fix agent, or cascade was started. Open the report and explicitly ask the leader to act if you want changes." : "Chimera completed with no actionable findings. No follow-up was started.";
4224
+ const reviewBody = reviewText.length > 7500 ? truncateAtCodePointBoundary(reviewText, 7500) + "\n\n\u2026(truncated, full report is in the Chimera report store)" : reviewText;
4225
+ const body = `${directive}${hallucinationNote}
4199
4226
 
4200
4227
  ${reviewBody}`;
4201
- const mailMsg = await mailbox.send({
4202
- from: "chimera-review",
4203
- to: "leader",
4204
- type: "result",
4205
- audience: "leaders",
4206
- subject,
4207
- body,
4208
- priority: "normal",
4209
- // Session-affinity stamp: the recipient's leader filter
4210
- // uses this to drop the message for any leader whose current
4211
- // session id does NOT match the originating session of the
4212
- // review (`reviewSessionId` is captured above from the
4213
- // agent's active run / session id). Without this token the
4214
- // project-wide mailbox would deliver every chimera result to
4215
- // every leader, inviting them to act on reports that belong
4216
- // to a different session.
4217
- sessionAffinity: {
4218
- sessionId: reviewSessionId,
4219
- reportId,
4220
- kind: "chimera.review"
4221
- }
4222
- });
4223
- if (!mailMsg?.id) throw new Error("mailbox.send returned no message id");
4224
- reviewMailMessageId = mailMsg.id;
4225
- events.emitCustom("chimera.mailbox_delivered", {
4226
- subject,
4227
- autoFixMode: "off",
4228
- fileCount: p.files.length,
4229
- reviewLength: reviewText.length,
4230
- messageId: reviewMailMessageId
4231
- });
4232
- if (!reviewHasFindings) {
4233
- try {
4234
- await mailbox.ack({
4235
- messageId: reviewMailMessageId,
4236
- readerId: "chimera",
4237
- completed: true,
4238
- outcome: "Review completed with no actionable findings."
4239
- });
4240
- } catch (ackError) {
4241
- console.warn(
4242
- JSON.stringify({
4243
- level: "warn",
4244
- event: "execution.chimera_mailbox_completion_failed",
4245
- message: ackError instanceof Error ? ackError.message : String(ackError),
4228
+ const mailMsg = await mailbox.send({
4229
+ from: "chimera-review",
4230
+ to: "leader",
4231
+ type: "result",
4232
+ audience: "leaders",
4233
+ subject,
4234
+ body,
4235
+ priority: "normal",
4236
+ // Session-affinity stamp: the recipient's leader filter
4237
+ // uses this to drop the message for any leader whose current
4238
+ // session id does NOT match the originating session of the
4239
+ // review (`reviewSessionId` is captured above from the
4240
+ // agent's active run / session id). Without this token the
4241
+ // project-wide mailbox would deliver every chimera result to
4242
+ // every leader, inviting them to act on reports that belong
4243
+ // to a different session.
4244
+ sessionAffinity: {
4245
+ sessionId: reviewSessionId,
4246
+ reportId,
4247
+ kind: "chimera.review"
4248
+ }
4249
+ });
4250
+ if (!mailMsg?.id) throw new Error("mailbox.send returned no message id");
4251
+ reviewMailMessageId = mailMsg.id;
4252
+ events.emitCustom("chimera.mailbox_delivered", {
4253
+ subject,
4254
+ autoFixMode: "off",
4255
+ fileCount: p.files.length,
4256
+ reviewLength: reviewText.length,
4257
+ messageId: reviewMailMessageId
4258
+ });
4259
+ if (!reviewHasFindings) {
4260
+ try {
4261
+ await mailbox.ack({
4246
4262
  messageId: reviewMailMessageId,
4247
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
4248
- })
4249
- );
4263
+ readerId: "chimera",
4264
+ completed: true,
4265
+ outcome: "Review completed with no actionable findings."
4266
+ });
4267
+ } catch (ackError) {
4268
+ console.warn(
4269
+ JSON.stringify({
4270
+ level: "warn",
4271
+ event: "execution.chimera_mailbox_completion_failed",
4272
+ message: ackError instanceof Error ? ackError.message : String(ackError),
4273
+ messageId: reviewMailMessageId,
4274
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
4275
+ })
4276
+ );
4277
+ }
4250
4278
  }
4279
+ } catch (mailErr) {
4280
+ const errMsg = mailErr instanceof Error ? mailErr.message : String(mailErr);
4281
+ console.error(
4282
+ JSON.stringify({
4283
+ level: "error",
4284
+ event: "execution.chimera_mailbox_failed",
4285
+ message: errMsg,
4286
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
4287
+ })
4288
+ );
4289
+ events.emitCustom("chimera.mailbox_failed", {
4290
+ subject,
4291
+ autoFixMode: "off",
4292
+ fileCount: p.files.length,
4293
+ reviewLength: reviewText.length,
4294
+ error: errMsg
4295
+ });
4296
+ await session.append({
4297
+ type: "error",
4298
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
4299
+ message: `\u{1F982} Chimera report ${reportId} is ready, but mailbox delivery failed: ${errMsg}. No follow-up was started.`,
4300
+ phase: "agent"
4301
+ });
4251
4302
  }
4252
- } catch (mailErr) {
4253
- const errMsg = mailErr instanceof Error ? mailErr.message : String(mailErr);
4254
- console.error(
4255
- JSON.stringify({
4256
- level: "error",
4257
- event: "execution.chimera_mailbox_failed",
4258
- message: errMsg,
4259
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
4260
- })
4261
- );
4262
- events.emitCustom("chimera.mailbox_failed", {
4263
- subject,
4264
- autoFixMode: "off",
4303
+ const findingCount = actionableFindings.length;
4304
+ const message = effectiveHasFindings ? `\u{1F982} Chimera report ready \u2014 ${findingCount || "unparsed"} potential finding(s) (${verifiedCount} verified against disk, ${unverifiedCount} unverified, ${failedVerificationCount} failed) across ${p.files.length} file(s). No follow-up started; open the mailbox and explicitly ask the leader to act if wanted.` : `\u{1F982} Chimera report ready \u2014 ${p.files.length} file(s) checked, no actionable findings. No follow-up started.`;
4305
+ events.emitCustom("chimera.report_available", {
4306
+ reportId,
4307
+ sessionId: reviewSessionId,
4308
+ message,
4265
4309
  fileCount: p.files.length,
4266
- reviewLength: reviewText.length,
4267
- error: errMsg
4310
+ findingCount,
4311
+ hasActionableFindings: effectiveHasFindings,
4312
+ ...reviewMailMessageId ? { messageId: reviewMailMessageId } : {}
4268
4313
  });
4314
+ }
4315
+ } catch (err) {
4316
+ try {
4269
4317
  await session.append({
4270
4318
  type: "error",
4271
4319
  ts: (/* @__PURE__ */ new Date()).toISOString(),
4272
- message: `\u{1F982} Chimera report ${reportId} is ready, but mailbox delivery failed: ${errMsg}. No follow-up was started.`,
4320
+ message: `\u{1F982} Chimera review failed: ${err instanceof Error ? err.message : String(err)}`,
4273
4321
  phase: "agent"
4274
4322
  });
4323
+ } catch (appendErr) {
4324
+ console.error(
4325
+ JSON.stringify({
4326
+ level: "error",
4327
+ event: "execution.chimera_review_append_failed",
4328
+ message: appendErr instanceof Error ? appendErr.message : String(appendErr),
4329
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
4330
+ })
4331
+ );
4275
4332
  }
4276
- const findingCount = actionableFindings.length;
4277
- const message = effectiveHasFindings ? `\u{1F982} Chimera report ready \u2014 ${findingCount || "unparsed"} potential finding(s) (${verifiedCount} verified against disk, ${unverifiedCount} unverified, ${failedVerificationCount} failed) across ${p.files.length} file(s). No follow-up started; open the mailbox and explicitly ask the leader to act if wanted.` : `\u{1F982} Chimera report ready \u2014 ${p.files.length} file(s) checked, no actionable findings. No follow-up started.`;
4278
- events.emitCustom("chimera.report_available", {
4279
- reportId,
4280
- sessionId: reviewSessionId,
4281
- message,
4282
- fileCount: p.files.length,
4283
- findingCount,
4284
- hasActionableFindings: effectiveHasFindings,
4285
- ...reviewMailMessageId ? { messageId: reviewMailMessageId } : {}
4286
- });
4287
- }
4288
- } catch (err) {
4289
- try {
4290
- await session.append({
4291
- type: "error",
4292
- ts: (/* @__PURE__ */ new Date()).toISOString(),
4293
- message: `\u{1F982} Chimera review failed: ${err instanceof Error ? err.message : String(err)}`,
4294
- phase: "agent"
4295
- });
4296
- } catch (appendErr) {
4297
- console.error(
4298
- JSON.stringify({
4299
- level: "error",
4300
- event: "execution.chimera_review_append_failed",
4301
- message: appendErr instanceof Error ? appendErr.message : String(appendErr),
4302
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
4303
- })
4304
- );
4305
- }
4306
- } finally {
4307
- if (subagentId) {
4308
- try {
4309
- await dir.terminate(subagentId);
4310
- } catch {
4333
+ } finally {
4334
+ if (subagentId) {
4335
+ try {
4336
+ await dir.terminate(subagentId);
4337
+ } catch {
4338
+ }
4311
4339
  }
4312
4340
  }
4313
- }
4314
- })()
4315
- );
4316
- }, "chimera-review");
4341
+ })()
4342
+ );
4343
+ },
4344
+ "chimera-review"
4345
+ );
4317
4346
  if (off) teardownHandlers?.push(off);
4318
4347
  }
4319
4348
  async function persistChimeraReview(payload, projectDir) {
@@ -4416,7 +4445,7 @@ ${list}`);
4416
4445
  function parsePredictions(raw, max = 3) {
4417
4446
  const text = raw.trim();
4418
4447
  if (!text) return [];
4419
- if (/^none\b/i.test(text) || /no further steps/i.test(text)) return [];
4448
+ if (/^none\.?\s*$/i.test(text) || /^no further steps/i.test(text)) return [];
4420
4449
  const out = [];
4421
4450
  for (const lineRaw of text.split("\n")) {
4422
4451
  const line = lineRaw.trim();
@@ -4825,9 +4854,7 @@ async function runReplEternalLoop(opts, onInterruptsReset) {
4825
4854
  if (autonomy === "eternal-parallel") {
4826
4855
  const engine = opts.getParallelEngine?.();
4827
4856
  if (!engine) {
4828
- opts.renderer.writeWarning(
4829
- "Parallel mode set but no engine wired \u2014 falling back to off."
4830
- );
4857
+ opts.renderer.writeWarning("Parallel mode set but no engine wired \u2014 falling back to off.");
4831
4858
  return false;
4832
4859
  }
4833
4860
  const beforeGoal = await loadGoalSafe(opts);
@@ -4841,10 +4868,8 @@ async function runReplEternalLoop(opts, onInterruptsReset) {
4841
4868
  ) + "\n"
4842
4869
  );
4843
4870
  }
4844
- opts.renderer.write(
4845
- color8.magenta(` \u21B3 [parallel #${beforeIter + 1}] launching fan-out\u2026
4846
- `)
4847
- );
4871
+ opts.renderer.write(color8.magenta(` \u21B3 [parallel #${beforeIter + 1}] launching fan-out\u2026
4872
+ `));
4848
4873
  onInterruptsReset();
4849
4874
  try {
4850
4875
  await engine.runOneIteration();
@@ -5691,7 +5716,11 @@ function tierMenu(store) {
5691
5716
  ],
5692
5717
  body: "A tier binds a fallback profile, a spend budget and a runtime setting under one name, then routes work to it by role or phase. While disabled, spawns resolve exactly as they did before tiers existed.",
5693
5718
  actions: [
5694
- { key: "t", label: enabled ? "turn off" : "turn on", command: `/tier ${enabled ? "off" : "on"}` }
5719
+ {
5720
+ key: "t",
5721
+ label: enabled ? "turn off" : "turn on",
5722
+ command: `/tier ${enabled ? "off" : "on"}`
5723
+ }
5695
5724
  ]
5696
5725
  },
5697
5726
  {
@@ -5725,8 +5754,14 @@ function tierMenu(store) {
5725
5754
  details: [
5726
5755
  { label: "rung", value: `${index + 1} of ${levelIds.length}` },
5727
5756
  { label: "profile", value: level?.fallbackProfile ?? "(none)" },
5728
- { label: "max cost", value: level?.maxCostUsd !== void 0 ? `$${level.maxCostUsd}` : "(role default)" },
5729
- { label: "max iterations", value: level?.maxIterations !== void 0 ? String(level.maxIterations) : "(role default)" },
5757
+ {
5758
+ label: "max cost",
5759
+ value: level?.maxCostUsd !== void 0 ? `$${level.maxCostUsd}` : "(role default)"
5760
+ },
5761
+ {
5762
+ label: "max iterations",
5763
+ value: level?.maxIterations !== void 0 ? String(level.maxIterations) : "(role default)"
5764
+ },
5730
5765
  { label: "routed by", value: routedBy.join(", ") || "(nothing)" }
5731
5766
  ],
5732
5767
  body: [
@@ -6101,6 +6136,9 @@ async function execute(deps) {
6101
6136
  statuslineLines,
6102
6137
  setStatuslineLines,
6103
6138
  saveStatuslineLines,
6139
+ statuslineDensities,
6140
+ setStatuslineDensities,
6141
+ saveStatuslineDensities,
6104
6142
  getYolo,
6105
6143
  onYolo,
6106
6144
  getAutonomy,
@@ -6384,6 +6422,8 @@ async function execute(deps) {
6384
6422
  ensureAutonomousCoordinator
6385
6423
  }),
6386
6424
  onClearHistory: (dispatch) => {
6425
+ void attachments.clear().catch(() => {
6426
+ });
6387
6427
  dispatch({ type: "clearHistory", model: context.model, provider: context.provider.id });
6388
6428
  dispatch({ type: "resetContextChip" });
6389
6429
  dispatch({ type: "streamReset" });
@@ -6403,6 +6443,9 @@ async function execute(deps) {
6403
6443
  statuslineLines,
6404
6444
  setStatuslineLines,
6405
6445
  saveStatuslineLines,
6446
+ statuslineDensities,
6447
+ setStatuslineDensities,
6448
+ saveStatuslineDensities,
6406
6449
  getPluginItems,
6407
6450
  onPluginToggle,
6408
6451
  getMcpServers,
@@ -6614,7 +6657,7 @@ async function execute(deps) {
6614
6657
  ...createKanbanDispatchHandler({ config, events, skillLoader, sddSubagentFactory })
6615
6658
  });
6616
6659
  } else {
6617
- const headlessKanbanMirror = projectRoot ? (await import("./kanban-run-mirror-EKVNGXWW.js")).createKanbanRunMirror({
6660
+ const headlessKanbanMirror = projectRoot ? (await import("./kanban-run-mirror-22HQ5FNG.js")).createKanbanRunMirror({
6618
6661
  projectRoot,
6619
6662
  events,
6620
6663
  broadcast: () => {
@@ -6698,4 +6741,4 @@ export {
6698
6741
  execute,
6699
6742
  resolveReviewerFallbackModels
6700
6743
  };
6701
- //# sourceMappingURL=execution-DKJDNPYF.js.map
6744
+ //# sourceMappingURL=execution-3Y55IWBK.js.map