@wrongstack/cli 0.319.1 → 1.0.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 (105) 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-ND7J7DTD.js → auth-ZUMCDNE5.js} +6 -7
  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/system-prompt-menu.d.ts +7 -0
  12. package/dist/{boot-auto-thin-BZ675EVT.js → boot-auto-thin-MANHOYHE.js} +1 -2
  13. package/dist/{chronicle-6EPPMUC5.js → chronicle-UTFETHP6.js} +1 -2
  14. package/dist/{chunk-HF5VQWIY.js → chunk-5IA5337I.js} +3 -3
  15. package/dist/{chunk-TALOKMIC.js → chunk-C2E24IXZ.js} +31 -15
  16. package/dist/chunk-D2VCUN7M.js +54 -0
  17. package/dist/{chunk-XPX432BZ.js → chunk-DR2OXU46.js} +50 -39
  18. package/dist/{chunk-GGGUZSAU.js → chunk-E6RFXHWD.js} +18 -13
  19. package/dist/{chunk-TYO2OVAD.js → chunk-EWKESL4L.js} +8 -4
  20. package/dist/{chunk-QAC263FZ.js → chunk-FPIWTJ2G.js} +2 -3
  21. package/dist/{chunk-7YLN7YUA.js → chunk-IMWXXF4J.js} +61 -9
  22. package/dist/{chunk-LIWVIEZM.js → chunk-KHWDTNBZ.js} +5 -5
  23. package/dist/{chunk-IMT6PNV5.js → chunk-MNQQ4ZNF.js} +26 -22
  24. package/dist/{chunk-P2OKBDCH.js → chunk-MXEJEYT7.js} +53 -14
  25. package/dist/{chunk-PCBJSXYV.js → chunk-O4A3HHKD.js} +2 -2
  26. package/dist/{chunk-XYKYXFEE.js → chunk-TE3Q32JP.js} +10 -4
  27. package/dist/{chunk-635WW3II.js → chunk-TEBMCYZN.js} +67 -18
  28. package/dist/{chunk-E4I2TF5S.js → chunk-TNK6237M.js} +2 -2
  29. package/dist/chunk-UQUYBDMG.js +51 -0
  30. package/dist/{chunk-F5GA2QW2.js → chunk-ZSZ3EYWH.js} +2 -2
  31. package/dist/{cli-context-K73EIND5.js → cli-context-7X3M6U73.js} +59 -308
  32. package/dist/{cli-main-QXSKKANW.js → cli-main-53KG6HAV.js} +972 -293
  33. package/dist/config-transfer-2YF3CRTN.js +99 -0
  34. package/dist/{diag-doctor-QZVKUAE5.js → diag-doctor-7LYUYU35.js} +1 -2
  35. package/dist/execute-deps.d.ts +5 -1
  36. package/dist/{execution-7ZFY4FJY.js → execution-MIBWBYB6.js} +52 -35
  37. package/dist/{export-ROG3DKTZ.js → export-VVRIOWFV.js} +1 -2
  38. package/dist/{governance-JSGHHA2R.js → governance-RYSHV675.js} +1 -2
  39. package/dist/{hq-4QQJO2GN.js → hq-IG3YRGCO.js} +2 -3
  40. package/dist/hq-command-controller.d.ts +37 -7
  41. package/dist/hq-server/ws.d.ts +1 -1
  42. package/dist/{hq-server-CVAYICIS.js → hq-server-OILU3NPI.js} +2 -3
  43. package/dist/{hq-ttl-KUO3AU7X.js → hq-ttl-VJR65OBJ.js} +1 -2
  44. package/dist/{hq-tunnel-LO55RCZE.js → hq-tunnel-NIJ5EP2Y.js} +1 -2
  45. package/dist/index.js +5 -6
  46. package/dist/{init-4JQSG66Q.js → init-DRMMFG2G.js} +1 -2
  47. package/dist/{kanban-run-mirror-EKVNGXWW.js → kanban-run-mirror-22HQ5FNG.js} +1 -2
  48. package/dist/live-settings-input.d.ts +2 -0
  49. package/dist/{mailbox-serve-VKQIRCCB.js → mailbox-serve-VUCWZ2SJ.js} +2 -3
  50. package/dist/{mcp-AQKSASHD.js → mcp-HOMLC4WE.js} +1 -2
  51. package/dist/{modeldiag-ZL4ROTQ5.js → modeldiag-FMJT37SN.js} +2 -3
  52. package/dist/{per-subcommand-help-6VCIKDUW.js → per-subcommand-help-BWBHYVJO.js} +2 -3
  53. package/dist/{permissions-2PWBL4YU.js → permissions-CFDLXETM.js} +1 -2
  54. package/dist/{plugin-usage-7WCZW4NP.js → plugin-usage-HFBI3TFT.js} +2 -3
  55. package/dist/{plugins-7N3TF2QF.js → plugins-PZ2VZL7V.js} +4 -5
  56. package/dist/{project-BLQ3ALVL.js → project-AOQI5XTK.js} +1 -2
  57. package/dist/{project-manifest-RV5FXGQI.js → project-manifest-7NSFVBM3.js} +1 -2
  58. package/dist/{project-picker-CCQR3W4I.js → project-picker-SVBXMPKX.js} +1 -2
  59. package/dist/{projects-5J727S4L.js → projects-L6C6XLDY.js} +1 -2
  60. package/dist/provider-config-utils.d.ts +1 -1
  61. package/dist/{providers-models-OKKQZIWU.js → providers-models-YVMVYWRS.js} +3 -4
  62. package/dist/{proxy-wiring-QCI7EWQC.js → proxy-wiring-MGRSKZZB.js} +1 -2
  63. package/dist/{quick-XLYLZX4B.js → quick-CNB4Z3HS.js} +1 -2
  64. package/dist/{replay-RZXZKP2U.js → replay-JJ2NOWD6.js} +1 -2
  65. package/dist/{replay-FJ2JBXUA.js → replay-Z3FTJEMM.js} +1 -2
  66. package/dist/{rewind-2FFNOOKS.js → rewind-JA3ZLCNM.js} +1 -2
  67. package/dist/{sdd-runtime-R6FAK2G2.js → sdd-runtime-PTOSPYI4.js} +1 -2
  68. package/dist/services/statusline-config.d.ts +43 -13
  69. package/dist/{sessions-config-KAMEBVOX.js → sessions-config-UL45XKX7.js} +2 -3
  70. package/dist/{sessions-doctor-EXHAZSSE.js → sessions-doctor-QUL37U32.js} +1 -2
  71. package/dist/settings-behavior-sections.d.ts +20 -0
  72. package/dist/short-circuit-flags-UREFSYBL.js +10 -0
  73. package/dist/{simpleui-dist-JKNRCRRK.js → simpleui-dist-CXSIDAXZ.js} +1 -2
  74. package/dist/slash-commands/command-context.d.ts +10 -0
  75. package/dist/slash-commands/statusline.d.ts +1 -1
  76. package/dist/subcommands/handlers/bench-run-config.d.ts +18 -0
  77. package/dist/subcommands/handlers/bench.d.ts +8 -7
  78. package/dist/subcommands/handlers/config-transfer.d.ts +6 -0
  79. package/dist/subcommands-WJLBHVKC.js +9 -0
  80. package/dist/{tools-skills-Q4P27URS.js → tools-skills-GH24UCBY.js} +1 -2
  81. package/dist/{update-K45CS6SS.js → update-5DPB4YD4.js} +1 -2
  82. package/dist/{update-check-PKSMSMD6.js → update-check-BS3DHTSI.js} +1 -2
  83. package/dist/version-help-MYKF724O.js +10 -0
  84. package/dist/webui-server/client-registration.d.ts +9 -1
  85. package/dist/{webui-server-F7MSRHOF.js → webui-server-5R35BHWZ.js} +54 -15
  86. package/dist/wiring/brain-and-orchestration.d.ts +2 -0
  87. package/dist/wiring/cli-execute-builder.d.ts +4 -0
  88. package/dist/wiring/cli-slash-commands-setup.d.ts +1 -0
  89. package/dist/wiring/command-host-state.d.ts +50 -5
  90. package/dist/wiring/external-plugins.d.ts +9 -0
  91. package/dist/wiring/provider-runtime-setup.d.ts +2 -0
  92. package/dist/wiring/runtime-controller-deps.d.ts +3 -0
  93. package/dist/wiring/vector-memory-setup.d.ts +12 -0
  94. package/dist/wiring/wrongtrace-prompt-contributor.d.ts +5 -2
  95. package/dist/{wrongtrace-gate-counters-GSVY372D.js → wrongtrace-gate-counters-7C2EAAZL.js} +1 -2
  96. package/dist/{wrongtrace-telemetry-KBBM5NLQ.js → wrongtrace-telemetry-3ASFKOZO.js} +1 -2
  97. package/package.json +28 -28
  98. package/dist/chunk-7OCVIDC7.js +0 -11
  99. package/dist/chunk-KYDJJLJI.js +0 -52
  100. package/dist/launch-hints.d.ts +0 -49
  101. package/dist/short-circuit-flags-7YUCERBB.js +0 -11
  102. package/dist/subcommands-KE6MEQQP.js +0 -10
  103. package/dist/version-help-WMPSEL4U.js +0 -11
  104. package/dist/webui-server/privileged-actions.d.ts +0 -14
  105. package/dist/wiring/cli-heap-watchdog.d.ts +0 -34
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  createHqCommandDispatcher
3
- } from "./chunk-7YLN7YUA.js";
3
+ } from "./chunk-IMWXXF4J.js";
4
4
  import {
5
5
  runProjectPicker
6
6
  } from "./chunk-WQZW3RDP.js";
@@ -23,9 +23,6 @@ import {
23
23
  runGit,
24
24
  setSuggestions
25
25
  } from "./chunk-SXJTVNWF.js";
26
- import {
27
- setupPlugins
28
- } from "./chunk-HF5VQWIY.js";
29
26
  import {
30
27
  deriveFsAccessPair,
31
28
  filterSafeForProject,
@@ -33,6 +30,9 @@ import {
33
30
  persistConfigSetting,
34
31
  persistTelegramConfig
35
32
  } from "./chunk-JACOMTIH.js";
33
+ import {
34
+ setupPlugins
35
+ } from "./chunk-5IA5337I.js";
36
36
  import {
37
37
  configureSimpleUiRuntimeContext,
38
38
  detectProjectFacts,
@@ -44,7 +44,11 @@ import {
44
44
  fmtTaskResultLine,
45
45
  fmtTok,
46
46
  patchConfig
47
- } from "./chunk-TYO2OVAD.js";
47
+ } from "./chunk-EWKESL4L.js";
48
+ import {
49
+ renderDeepHelpToString,
50
+ renderFocusedHelpToString
51
+ } from "./chunk-MXEJEYT7.js";
48
52
  import {
49
53
  awaitFirstWrongProxyProbe,
50
54
  bootstrapWrongProxy
@@ -59,17 +63,17 @@ import {
59
63
  matchTaskNode,
60
64
  sddState
61
65
  } from "./chunk-JHUJUIOH.js";
62
- import {
63
- startCliHqConnection
64
- } from "./chunk-XYKYXFEE.js";
65
66
  import {
66
67
  PLUGIN_AUDIT_ENTRIES,
67
68
  runPluginManagementCommand
68
- } from "./chunk-635WW3II.js";
69
+ } from "./chunk-TEBMCYZN.js";
69
70
  import "./chunk-JHPXJRRI.js";
70
71
  import {
71
72
  recordGateDecision
72
73
  } from "./chunk-D3K4NYQL.js";
74
+ import {
75
+ BEHAVIOR_SECTION_KEYS
76
+ } from "./chunk-UQUYBDMG.js";
73
77
  import {
74
78
  CLI_VERSION
75
79
  } from "./chunk-XJXDOF63.js";
@@ -80,18 +84,23 @@ import {
80
84
  refreshAcpRegistry,
81
85
  resolveProviderCfg,
82
86
  setupProvider
83
- } from "./chunk-F5GA2QW2.js";
87
+ } from "./chunk-ZSZ3EYWH.js";
88
+ import {
89
+ startCliHqConnection
90
+ } from "./chunk-TE3Q32JP.js";
84
91
  import {
85
92
  LOCAL_LLM_PRESETS,
86
93
  addCustomProvider,
87
94
  addKeyForCatalogProvider,
88
95
  addKeyForProvider,
89
96
  nextCustomProviderId,
97
+ ownDefinitionsAsCatalog,
90
98
  runAuthLocal,
91
99
  runClaudeOAuthLogin,
92
100
  runCopilotOAuthLogin,
93
101
  validateFamily
94
- } from "./chunk-IMT6PNV5.js";
102
+ } from "./chunk-MNQQ4ZNF.js";
103
+ import "./chunk-2VMJ3E5Z.js";
95
104
  import {
96
105
  appendHistory
97
106
  } from "./chunk-B4JLSXZB.js";
@@ -104,10 +113,10 @@ import {
104
113
  } from "./chunk-YMXXOOFN.js";
105
114
  import {
106
115
  parseSpawnFlags
107
- } from "./chunk-GGGUZSAU.js";
116
+ } from "./chunk-E6RFXHWD.js";
108
117
  import {
109
118
  runCodexOAuthLogin
110
- } from "./chunk-E4I2TF5S.js";
119
+ } from "./chunk-TNK6237M.js";
111
120
  import {
112
121
  activeLabel,
113
122
  loadConfigProviders,
@@ -115,19 +124,16 @@ import {
115
124
  normalizeKeys,
116
125
  nowIso,
117
126
  writeKeysBack
118
- } from "./chunk-XPX432BZ.js";
127
+ } from "./chunk-DR2OXU46.js";
119
128
  import {
120
129
  buildWin32CmdShimInvocation
121
130
  } from "./chunk-U3SS4NRH.js";
122
131
  import {
123
132
  checkForUpdate
124
133
  } from "./chunk-YLQEGYV4.js";
125
- import {
126
- __require
127
- } from "./chunk-7OCVIDC7.js";
128
134
 
129
135
  // src/cli-main.ts
130
- import { mailboxSessionTag as mailboxSessionTag6 } from "@wrongstack/core/coordination";
136
+ import { mailboxSessionTag as mailboxSessionTag7 } from "@wrongstack/core/coordination";
131
137
  import { TOKENS as TOKENS13 } from "@wrongstack/core/kernel";
132
138
  import { writeErr as writeErr3 } from "@wrongstack/core/utils";
133
139
  import { setProxyTransitionLogger } from "@wrongstack/core/wiring/proxy-rewrite";
@@ -1094,7 +1100,7 @@ async function loadOnlineAgentsForPrompt(projectDir, skip) {
1094
1100
  }
1095
1101
  }
1096
1102
  async function getSddRuntimeStateForCli() {
1097
- const sdd = await import("./sdd-runtime-R6FAK2G2.js");
1103
+ const sdd = await import("./sdd-runtime-PTOSPYI4.js");
1098
1104
  return {
1099
1105
  tracker: sdd.getTaskTracker(),
1100
1106
  builder: sdd.getActiveBuilder(),
@@ -1136,10 +1142,12 @@ import {
1136
1142
  } from "@wrongstack/core/types";
1137
1143
 
1138
1144
  // src/boot/brain-decision-log.ts
1145
+ import { BrainTierCounter } from "@wrongstack/core/coordination";
1139
1146
  var MAX_BRAIN_LOG_ENTRIES = 20;
1140
1147
  function subscribeBrainDecisionLog(events) {
1141
1148
  const listeners = [];
1142
1149
  const brainLog = [];
1150
+ const tierCounter = new BrainTierCounter();
1143
1151
  const pushBrainLog = (entry) => {
1144
1152
  brainLog.push(entry);
1145
1153
  if (brainLog.length > MAX_BRAIN_LOG_ENTRIES) brainLog.shift();
@@ -1154,8 +1162,10 @@ function subscribeBrainDecisionLog(events) {
1154
1162
  at: e.at,
1155
1163
  kind: "answered",
1156
1164
  question: e.request.question,
1157
- outcome: e.decision.type === "answer" ? e.decision.optionId ?? e.decision.text ?? "" : ""
1165
+ outcome: e.decision.type === "answer" ? e.decision.optionId ?? e.decision.text ?? "" : "",
1166
+ ...e.tier ? { tier: e.tier } : {}
1158
1167
  });
1168
+ tierCounter.record(e.tier);
1159
1169
  });
1160
1170
  subscribe("brain.decision_ask_human", (raw) => {
1161
1171
  const e = raw;
@@ -1163,8 +1173,13 @@ function subscribeBrainDecisionLog(events) {
1163
1173
  at: e.at,
1164
1174
  kind: "ask_human",
1165
1175
  question: e.request.question,
1166
- outcome: "escalated to human"
1176
+ // A pending ask_human is the prompt; the same request lands again as
1177
+ // answered/denied once the human replies. Labelling them apart keeps
1178
+ // the ring readable when both rows are present.
1179
+ outcome: e.pending ? "waiting on a human" : "escalated to human",
1180
+ ...e.tier ? { tier: e.tier } : {}
1167
1181
  });
1182
+ if (!e.pending) tierCounter.record(e.tier);
1168
1183
  });
1169
1184
  subscribe("brain.decision_denied", (raw) => {
1170
1185
  const e = raw;
@@ -1172,8 +1187,10 @@ function subscribeBrainDecisionLog(events) {
1172
1187
  at: e.at,
1173
1188
  kind: "denied",
1174
1189
  question: e.request.question,
1175
- outcome: e.decision.type === "deny" ? e.decision.reason ?? "" : ""
1190
+ outcome: e.decision.type === "deny" ? e.decision.reason ?? "" : "",
1191
+ ...e.tier ? { tier: e.tier } : {}
1176
1192
  });
1193
+ tierCounter.record(e.tier);
1177
1194
  });
1178
1195
  subscribe("brain.council_resolved", (raw) => {
1179
1196
  const e = raw;
@@ -1203,7 +1220,7 @@ function subscribeBrainDecisionLog(events) {
1203
1220
  );
1204
1221
  }
1205
1222
  };
1206
- return { brainLog, pushBrainLog, dispose };
1223
+ return { brainLog, pushBrainLog, getTierStats: () => tierCounter.snapshot(), dispose };
1207
1224
  }
1208
1225
 
1209
1226
  // src/fleet/subagent-hook-runner.ts
@@ -4497,7 +4514,7 @@ function setupBrainAndOrchestration(deps) {
4497
4514
  cwd,
4498
4515
  wpaths,
4499
4516
  teardownHandlers,
4500
- mailboxSessionTag: mailboxSessionTag7,
4517
+ mailboxSessionTag: mailboxSessionTag8,
4501
4518
  brainMailbox,
4502
4519
  agentMonitor,
4503
4520
  manifestPath,
@@ -4622,12 +4639,17 @@ function setupBrainAndOrchestration(deps) {
4622
4639
  brainRuntime.arbiter,
4623
4640
  brainQueue,
4624
4641
  () => brainRuntime.getMode(),
4625
- () => brainRuntime.getSnapshot().terminalPolicy
4642
+ () => brainRuntime.getSnapshot().terminalPolicy,
4643
+ events
4626
4644
  ),
4627
4645
  events
4628
4646
  );
4629
4647
  container.bind(TOKENS6.BrainArbiter, () => brain);
4630
- const { brainLog, dispose: disposeBrainLog } = subscribeBrainDecisionLog(events);
4648
+ const {
4649
+ brainLog,
4650
+ getTierStats: brainTierStats,
4651
+ dispose: disposeBrainLog
4652
+ } = subscribeBrainDecisionLog(events);
4631
4653
  teardownHandlers.push(disposeBrainLog);
4632
4654
  brainMonitor = new BrainMonitor({
4633
4655
  events,
@@ -4654,7 +4676,7 @@ function setupBrainAndOrchestration(deps) {
4654
4676
  body,
4655
4677
  sessionId
4656
4678
  }) => {
4657
- const tag = mailboxSessionTag7(sessionId || context.session?.id || session.id);
4679
+ const tag = mailboxSessionTag8(sessionId || context.session?.id || session.id);
4658
4680
  const leaderUniqueId = `leader@${tag}`;
4659
4681
  await brainMailbox.send({
4660
4682
  from: `brain@${tag}`,
@@ -4780,6 +4802,7 @@ function setupBrainAndOrchestration(deps) {
4780
4802
  return {
4781
4803
  brain,
4782
4804
  brainLog,
4805
+ brainTierStats,
4783
4806
  brainSettings,
4784
4807
  brainRuntime,
4785
4808
  brainQueue,
@@ -4795,6 +4818,7 @@ import { gatedEnhancerReasoning } from "@wrongstack/core/execution";
4795
4818
  import { TOKENS as TOKENS7 } from "@wrongstack/core/kernel";
4796
4819
 
4797
4820
  // src/auth-menu/panel-service.ts
4821
+ import { parseModelRef } from "@wrongstack/core/agent";
4798
4822
  var ANSI_RE = /\u001b\[[0-9;]*m/g;
4799
4823
  function stripAnsi(text) {
4800
4824
  return text.replace(ANSI_RE, "");
@@ -4829,9 +4853,10 @@ function flowDeps(base, io) {
4829
4853
  function isCancel(err) {
4830
4854
  return err instanceof Error && err.name === "AbortError" || err instanceof DOMException && err.name === "AbortError";
4831
4855
  }
4832
- async function runFlow(run) {
4856
+ async function runFlow(run, onSuccess) {
4833
4857
  try {
4834
4858
  const ok = await run();
4859
+ if (ok) await onSuccess?.();
4835
4860
  return { ok };
4836
4861
  } catch (err) {
4837
4862
  if (isCancel(err)) return { ok: false, message: "Cancelled." };
@@ -4843,6 +4868,141 @@ function plainMaskedKey(key) {
4843
4868
  if (key.length <= 8) return "\u2022".repeat(key.length);
4844
4869
  return `${key.slice(0, 4)}\u2026${key.slice(-4)}`;
4845
4870
  }
4871
+ function isRecord(value) {
4872
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4873
+ }
4874
+ function isProviderModelRef(value, providerId) {
4875
+ return typeof value === "string" && parseModelRef(value).provider === providerId;
4876
+ }
4877
+ function removeProviderFallbackReferences(config, providerId) {
4878
+ const removeModelRefs = (value) => Array.isArray(value) ? value.filter((ref) => !isProviderModelRef(ref, providerId)) : void 0;
4879
+ if (Array.isArray(config["fallbackModels"])) {
4880
+ config["fallbackModels"] = removeModelRefs(config["fallbackModels"]);
4881
+ }
4882
+ if (typeof config["fallbackBridge"] === "string" && isProviderModelRef(config["fallbackBridge"], providerId)) {
4883
+ delete config["fallbackBridge"];
4884
+ }
4885
+ if (Array.isArray(config["favoriteModels"])) {
4886
+ config["favoriteModels"] = removeModelRefs(config["favoriteModels"]);
4887
+ }
4888
+ if (isRecord(config["models"])) {
4889
+ for (const [modelId, definition] of Object.entries(config["models"])) {
4890
+ if (isRecord(definition) && definition["provider"] === providerId) {
4891
+ delete config["models"][modelId];
4892
+ }
4893
+ }
4894
+ if (Object.keys(config["models"]).length === 0) delete config["models"];
4895
+ }
4896
+ const removedProfiles = /* @__PURE__ */ new Set();
4897
+ if (isRecord(config["fallbackProfiles"])) {
4898
+ const profiles = config["fallbackProfiles"];
4899
+ for (const [name, chain] of Object.entries(profiles)) {
4900
+ if (!Array.isArray(chain)) continue;
4901
+ const next = chain.filter((ref) => !isProviderModelRef(ref, providerId));
4902
+ if (next.length === 0) {
4903
+ delete profiles[name];
4904
+ removedProfiles.add(name);
4905
+ } else {
4906
+ profiles[name] = next;
4907
+ }
4908
+ }
4909
+ if (Object.keys(profiles).length === 0) delete config["fallbackProfiles"];
4910
+ }
4911
+ const clearRemovedProfile = (entry) => {
4912
+ if (typeof entry["fallbackProfile"] === "string" && removedProfiles.has(entry["fallbackProfile"])) {
4913
+ delete entry["fallbackProfile"];
4914
+ }
4915
+ };
4916
+ if (typeof config["fallbackProfile"] === "string" && removedProfiles.has(config["fallbackProfile"])) {
4917
+ delete config["fallbackProfile"];
4918
+ }
4919
+ if (isRecord(config["modelMatrix"])) {
4920
+ for (const [role, value] of Object.entries(config["modelMatrix"])) {
4921
+ if (!isRecord(value)) continue;
4922
+ if (value["provider"] === providerId) {
4923
+ delete value["provider"];
4924
+ delete value["model"];
4925
+ }
4926
+ clearRemovedProfile(value);
4927
+ if (Object.keys(value).length === 0) delete config["modelMatrix"][role];
4928
+ }
4929
+ if (Object.keys(config["modelMatrix"]).length === 0) delete config["modelMatrix"];
4930
+ }
4931
+ if (isRecord(config["modelTiers"]) && isRecord(config["modelTiers"]["levels"])) {
4932
+ const levels = config["modelTiers"]["levels"];
4933
+ for (const level of Object.values(levels)) {
4934
+ if (!isRecord(level)) continue;
4935
+ if (level["provider"] === providerId) {
4936
+ delete level["provider"];
4937
+ delete level["model"];
4938
+ }
4939
+ clearRemovedProfile(level);
4940
+ }
4941
+ }
4942
+ if (isRecord(config["autonomy"])) {
4943
+ const autonomy = config["autonomy"];
4944
+ if (autonomy["refinerProvider"] === providerId) {
4945
+ delete autonomy["refinerProvider"];
4946
+ delete autonomy["refinerModel"];
4947
+ }
4948
+ if (isProviderModelRef(autonomy["enhanceFallbackModel"], providerId)) {
4949
+ delete autonomy["enhanceFallbackModel"];
4950
+ }
4951
+ if (typeof autonomy["refinerFallbackProfile"] === "string" && removedProfiles.has(autonomy["refinerFallbackProfile"])) {
4952
+ delete autonomy["refinerFallbackProfile"];
4953
+ }
4954
+ }
4955
+ if (isRecord(config["brain"])) {
4956
+ const brain = config["brain"];
4957
+ if (Array.isArray(brain["models"])) {
4958
+ brain["models"] = brain["models"].filter(
4959
+ (entry) => !isProviderModelRef(entry, providerId) && !(isRecord(entry) && entry["provider"] === providerId)
4960
+ );
4961
+ }
4962
+ if (isRecord(brain["council"])) {
4963
+ const council = brain["council"];
4964
+ if (Array.isArray(council["voters"])) {
4965
+ council["voters"] = council["voters"].filter(
4966
+ (entry) => !isProviderModelRef(entry, providerId) && !(isRecord(entry) && entry["provider"] === providerId)
4967
+ );
4968
+ }
4969
+ if (isProviderModelRef(council["judge"], providerId) || isRecord(council["judge"]) && council["judge"]["provider"] === providerId) {
4970
+ delete council["judge"];
4971
+ }
4972
+ }
4973
+ }
4974
+ const councilProfiles = isRecord(config["tools"]) && isRecord(config["tools"]["council"]) ? config["tools"]["council"]["profiles"] : void 0;
4975
+ if (Array.isArray(councilProfiles)) {
4976
+ for (const profile of councilProfiles) {
4977
+ if (!isRecord(profile)) continue;
4978
+ for (const seat of Array.isArray(profile["seats"]) ? profile["seats"] : []) {
4979
+ if (!isRecord(seat) || !isRecord(seat["target"])) continue;
4980
+ const target = seat["target"];
4981
+ if (target["providerId"] === providerId) {
4982
+ delete target["providerId"];
4983
+ delete target["model"];
4984
+ }
4985
+ if (Array.isArray(target["fallbackModels"])) {
4986
+ target["fallbackModels"] = removeModelRefs(target["fallbackModels"]);
4987
+ }
4988
+ clearRemovedProfile(target);
4989
+ if (Object.keys(target).length === 0) delete seat["target"];
4990
+ }
4991
+ if (isRecord(profile["judge"])) {
4992
+ const judge = profile["judge"];
4993
+ if (judge["providerId"] === providerId) {
4994
+ delete judge["providerId"];
4995
+ delete judge["model"];
4996
+ }
4997
+ if (Array.isArray(judge["fallbackModels"])) {
4998
+ judge["fallbackModels"] = removeModelRefs(judge["fallbackModels"]);
4999
+ }
5000
+ clearRemovedProfile(judge);
5001
+ if (Object.keys(judge).length === 0) delete profile["judge"];
5002
+ }
5003
+ }
5004
+ }
5005
+ }
4846
5006
  function createAuthPanelHost(deps) {
4847
5007
  const loadProviders = () => loadConfigProviders(deps.profileConfigPath, deps.vault);
4848
5008
  const mutate = async (mutator) => {
@@ -4851,14 +5011,21 @@ function createAuthPanelHost(deps) {
4851
5011
  await mutateConfigProviders(
4852
5012
  deps.profileConfigPath,
4853
5013
  deps.vault,
4854
- (all) => {
4855
- result = mutator(all);
5014
+ (all, config) => {
5015
+ result = mutator(all, config);
4856
5016
  },
4857
5017
  deps.profileConfigPath
4858
5018
  );
4859
5019
  } catch (err) {
4860
5020
  return err instanceof Error ? err.message : String(err);
4861
5021
  }
5022
+ if (result === null && deps.onProvidersChanged) {
5023
+ try {
5024
+ await deps.onProvidersChanged();
5025
+ } catch (err) {
5026
+ return `Saved, but live config reload failed: ${err instanceof Error ? err.message : String(err)}`;
5027
+ }
5028
+ }
4862
5029
  return result;
4863
5030
  };
4864
5031
  return {
@@ -4896,7 +5063,10 @@ function createAuthPanelHost(deps) {
4896
5063
  loadProviders()
4897
5064
  ]);
4898
5065
  const saved = new Set(Object.keys(providers));
4899
- return catalog.filter((p) => p.family !== "unsupported").sort((a, b) => a.id.localeCompare(b.id)).map((p) => ({
5066
+ return [
5067
+ ...catalog,
5068
+ ...ownDefinitionsAsCatalog(new Set(catalog.map((provider) => provider.id)))
5069
+ ].filter((p) => p.family !== "unsupported").sort((a, b) => a.id.localeCompare(b.id)).map((p) => ({
4900
5070
  id: p.id,
4901
5071
  name: p.name || p.id,
4902
5072
  family: p.family,
@@ -4932,9 +5102,10 @@ function createAuthPanelHost(deps) {
4932
5102
  });
4933
5103
  },
4934
5104
  removeProvider(providerId) {
4935
- return mutate((all) => {
5105
+ return mutate((all, config) => {
4936
5106
  if (!all[providerId]) return `Provider "${providerId}" no longer in config.`;
4937
5107
  delete all[providerId];
5108
+ removeProviderFallbackReferences(config, providerId);
4938
5109
  return null;
4939
5110
  });
4940
5111
  },
@@ -4943,6 +5114,157 @@ function createAuthPanelHost(deps) {
4943
5114
  const providers = await loadProviders();
4944
5115
  const template = providers[providerId] ?? { type: providerId };
4945
5116
  return addKeyForProvider(providerId, flowDeps(deps, io), template);
5117
+ }, deps.onProvidersChanged);
5118
+ },
5119
+ async saveProviderSetup(setup) {
5120
+ const type = setup.type.trim();
5121
+ const alias = setup.alias.trim();
5122
+ const keyLabel = setup.keyLabel.trim();
5123
+ const apiKey = setup.apiKey.trim();
5124
+ const family = validateFamily(setup.family);
5125
+ if (!type) return "Provider id is required.";
5126
+ if (!alias) return "Alias is required.";
5127
+ if (!family) return "Choose a supported protocol family.";
5128
+ if (!keyLabel) return "Key alias is required.";
5129
+ if (!apiKey) return "API key is required.";
5130
+ const split = (value) => value.split(",").map((item) => item.trim()).filter(Boolean);
5131
+ const baseUrl = setup.baseUrl.trim();
5132
+ const models = split(setup.models);
5133
+ const envVars = split(setup.envVars);
5134
+ let catalogDefaultModel;
5135
+ try {
5136
+ catalogDefaultModel = (await deps.modelsRegistry.getProvider(type))?.models?.[0]?.id;
5137
+ } catch {
5138
+ }
5139
+ const result = await mutate((all, config) => {
5140
+ const existing = all[alias];
5141
+ if (existing) {
5142
+ const existingFamily = existing.family ?? family;
5143
+ const existingBaseUrl = existing.baseUrl ?? "";
5144
+ if (existingFamily !== family || existingBaseUrl !== baseUrl) {
5145
+ return `Alias "${alias}" already uses ${existingFamily} / ${existingBaseUrl || "default endpoint"}. Choose a different alias.`;
5146
+ }
5147
+ if (existing.type && existing.type !== type) {
5148
+ return `Alias "${alias}" already belongs to provider type "${existing.type}".`;
5149
+ }
5150
+ }
5151
+ const provider = existing ?? { type, family };
5152
+ provider.type = type;
5153
+ provider.family = family;
5154
+ if (baseUrl) provider.baseUrl = baseUrl;
5155
+ else delete provider.baseUrl;
5156
+ if (models.length > 0) provider.models = models;
5157
+ else if (setup.source === "custom") delete provider.models;
5158
+ if (envVars.length > 0) provider.envVars = envVars;
5159
+ else if (setup.source === "custom") delete provider.envVars;
5160
+ const keys = normalizeKeys(provider);
5161
+ if (keys.some((key) => key.label === keyLabel)) {
5162
+ return `Key alias "${keyLabel}" already exists for "${alias}". Pick another key alias or update that key.`;
5163
+ }
5164
+ keys.push({ label: keyLabel, apiKey, createdAt: nowIso() });
5165
+ writeKeysBack(provider, keys);
5166
+ if (!provider.activeKey) provider.activeKey = keyLabel;
5167
+ all[alias] = provider;
5168
+ if ((!config["provider"] || !config["model"]) && catalogDefaultModel) {
5169
+ config["provider"] = alias;
5170
+ config["model"] = catalogDefaultModel;
5171
+ }
5172
+ return null;
5173
+ });
5174
+ return result;
5175
+ },
5176
+ async saveProviderEdit(edit) {
5177
+ const providerId = edit.providerId.trim();
5178
+ const family = validateFamily(edit.family);
5179
+ if (!providerId) return "Provider id is required.";
5180
+ if (!family) return "Choose a supported protocol family.";
5181
+ const list = (value) => value.split(",").map((item) => item.trim()).filter(Boolean);
5182
+ const baseUrl = edit.baseUrl.trim();
5183
+ const models = list(edit.models);
5184
+ const envVars = list(edit.envVars);
5185
+ return mutate((all) => {
5186
+ const provider = all[providerId];
5187
+ if (!provider) return `Provider "${providerId}" no longer in config.`;
5188
+ provider.family = family;
5189
+ if (baseUrl) provider.baseUrl = baseUrl;
5190
+ else delete provider.baseUrl;
5191
+ if (models.length > 0) provider.models = models;
5192
+ else delete provider.models;
5193
+ if (envVars.length > 0) provider.envVars = envVars;
5194
+ else delete provider.envVars;
5195
+ return null;
5196
+ });
5197
+ },
5198
+ async getModelEdit(providerId, modelId) {
5199
+ const provider = (await loadProviders())[providerId];
5200
+ if (!provider?.models?.includes(modelId)) return null;
5201
+ const details = provider.customModels?.[modelId];
5202
+ const modelsDev = details?.modelsDev ?? {};
5203
+ const limit = modelsDev["limit"];
5204
+ const cost = modelsDev["cost"];
5205
+ return {
5206
+ providerId,
5207
+ modelId,
5208
+ name: typeof modelsDev["name"] === "string" ? modelsDev["name"] : "",
5209
+ contextWindow: limit?.["context"] === void 0 ? "" : String(limit["context"]),
5210
+ maxOutput: details?.maxOutput === void 0 ? limit?.["output"] === void 0 ? "" : String(limit["output"]) : String(details.maxOutput),
5211
+ costInput: cost?.["input"] === void 0 ? "" : String(cost["input"]),
5212
+ costOutput: cost?.["output"] === void 0 ? "" : String(cost["output"])
5213
+ };
5214
+ },
5215
+ async saveModelEdit(edit) {
5216
+ const parse = (value, label) => {
5217
+ if (!value.trim()) return void 0;
5218
+ const number = Number(value);
5219
+ return Number.isFinite(number) && number >= 0 ? number : `${label} must be a non-negative number.`;
5220
+ };
5221
+ const context = parse(edit.contextWindow, "Context window");
5222
+ const output = parse(edit.maxOutput, "Max output");
5223
+ const inputCost = parse(edit.costInput, "Input cost");
5224
+ const outputCost = parse(edit.costOutput, "Output cost");
5225
+ for (const value of [context, output, inputCost, outputCost]) if (typeof value === "string") return value;
5226
+ return mutate((all) => {
5227
+ const provider = all[edit.providerId];
5228
+ if (!provider?.models?.includes(edit.modelId)) return `Model "${edit.modelId}" no longer exists.`;
5229
+ const existing = provider.customModels?.[edit.modelId] ?? {};
5230
+ const modelsDev = { ...existing.modelsDev ?? {} };
5231
+ if (edit.name.trim()) modelsDev["name"] = edit.name.trim();
5232
+ else delete modelsDev["name"];
5233
+ const limit = { ...modelsDev["limit"] ?? {} };
5234
+ if (context === void 0) delete limit["context"];
5235
+ else limit["context"] = context;
5236
+ if (output === void 0) delete limit["output"];
5237
+ else limit["output"] = output;
5238
+ if (Object.keys(limit).length) modelsDev["limit"] = limit;
5239
+ else delete modelsDev["limit"];
5240
+ const cost = { ...modelsDev["cost"] ?? {} };
5241
+ if (inputCost === void 0) delete cost["input"];
5242
+ else cost["input"] = inputCost;
5243
+ if (outputCost === void 0) delete cost["output"];
5244
+ else cost["output"] = outputCost;
5245
+ if (Object.keys(cost).length) modelsDev["cost"] = cost;
5246
+ else delete modelsDev["cost"];
5247
+ if (!provider.customModels) provider.customModels = {};
5248
+ provider.customModels[edit.modelId] = { ...existing, ...Object.keys(modelsDev).length ? { modelsDev } : {} };
5249
+ return null;
5250
+ });
5251
+ },
5252
+ async saveKeyEdit(edit) {
5253
+ const label = edit.label.trim();
5254
+ const apiKey = edit.apiKey.trim();
5255
+ if (!label) return "Key alias is required.";
5256
+ if (!apiKey) return "API key is required.";
5257
+ return mutate((all) => {
5258
+ const provider = all[edit.providerId];
5259
+ if (!provider) return `Provider "${edit.providerId}" no longer in config.`;
5260
+ const keys = normalizeKeys(provider);
5261
+ const original = edit.originalLabel;
5262
+ if (original && !keys.some((key) => key.label === original)) return `Key "${original}" not found.`;
5263
+ if (keys.some((key) => key.label === label && key.label !== original)) return `Key alias "${label}" already exists.`;
5264
+ const next = original ? keys.map((key) => key.label === original ? { ...key, label, apiKey, createdAt: nowIso() } : key) : [...keys, { label, apiKey, createdAt: nowIso() }];
5265
+ writeKeysBack(provider, next);
5266
+ if (!provider.activeKey || provider.activeKey === original) provider.activeKey = label;
5267
+ return null;
4946
5268
  });
4947
5269
  },
4948
5270
  updateKey(providerId, label, io) {
@@ -4969,7 +5291,7 @@ function createAuthPanelHost(deps) {
4969
5291
  }
4970
5292
  io.onLog(`\u2713 Updated ${providerId}/${label}.`);
4971
5293
  return true;
4972
- });
5294
+ }, deps.onProvidersChanged);
4973
5295
  },
4974
5296
  editField(providerId, field, io) {
4975
5297
  return runFlow(async () => {
@@ -5055,7 +5377,7 @@ function createAuthPanelHost(deps) {
5055
5377
  }
5056
5378
  io.onLog(`\u2713 models \u2192 ${list.length === 0 ? "(catalog default)" : list.join(", ")}`);
5057
5379
  return true;
5058
- });
5380
+ }, deps.onProvidersChanged);
5059
5381
  },
5060
5382
  editModelDetails(providerId, modelId, io) {
5061
5383
  return runFlow(async () => {
@@ -5149,7 +5471,7 @@ function createAuthPanelHost(deps) {
5149
5471
  }
5150
5472
  io.onLog(`\u2713 ${modelId} updated`);
5151
5473
  return true;
5152
- });
5474
+ }, deps.onProvidersChanged);
5153
5475
  },
5154
5476
  addModel(providerId, io, opts) {
5155
5477
  return runFlow(async () => {
@@ -5187,7 +5509,7 @@ function createAuthPanelHost(deps) {
5187
5509
  }
5188
5510
  io.onLog(`\u2713 Added model "${modelId}" to ${providerId}`);
5189
5511
  return true;
5190
- });
5512
+ }, deps.onProvidersChanged);
5191
5513
  },
5192
5514
  removeModel(providerId, modelId) {
5193
5515
  return (async () => {
@@ -5237,26 +5559,29 @@ function createAuthPanelHost(deps) {
5237
5559
  return false;
5238
5560
  }
5239
5561
  return addKeyForCatalogProvider(flowDeps(deps, io), chosen);
5240
- });
5562
+ }, deps.onProvidersChanged);
5241
5563
  },
5242
5564
  addCustomProvider(io) {
5243
- return runFlow(() => addCustomProvider(flowDeps(deps, io)));
5565
+ return runFlow(() => addCustomProvider(flowDeps(deps, io)), deps.onProvidersChanged);
5244
5566
  },
5245
- addLocal(presetId, io) {
5567
+ addLocal(presetId, io, opts) {
5246
5568
  return runFlow(async () => {
5247
5569
  const preset = LOCAL_LLM_PRESETS.find((p) => p.id === presetId);
5248
5570
  if (!preset) {
5249
5571
  io.onLog(`\u2717 Unknown local preset "${presetId}".`);
5250
5572
  return false;
5251
5573
  }
5252
- const url = (await io.prompt(`Base URL (Enter = ${preset.defaultBaseUrl})`, { secret: false })).trim();
5574
+ const url = opts?.baseUrl !== void 0 ? opts.baseUrl.trim() : (await io.prompt(`Base URL (Enter = ${preset.defaultBaseUrl})`, {
5575
+ secret: false
5576
+ })).trim();
5253
5577
  const code = await runAuthLocal(flowDeps(deps, io), {
5254
5578
  name: preset.id,
5255
5579
  baseUrl: url || void 0,
5580
+ apiKey: opts !== void 0 ? (opts.apiKey ?? "").trim() : void 0,
5256
5581
  models: "999"
5257
5582
  });
5258
5583
  return code === 0;
5259
- });
5584
+ }, deps.onProvidersChanged);
5260
5585
  },
5261
5586
  oauthLogin(kind, io) {
5262
5587
  return runFlow(async () => {
@@ -5264,7 +5589,7 @@ function createAuthPanelHost(deps) {
5264
5589
  const opts = { signal: io.signal };
5265
5590
  const code = kind === "chatgpt" ? await runCodexOAuthLogin(d, opts) : kind === "claude" ? await runClaudeOAuthLogin(d, opts) : await runCopilotOAuthLogin(d, opts);
5266
5591
  return code === 0;
5267
- });
5592
+ }, deps.onProvidersChanged);
5268
5593
  }
5269
5594
  };
5270
5595
  }
@@ -5292,6 +5617,9 @@ function createRuntimeControllerDeps(input) {
5292
5617
  statuslineLines: input.statuslineLines,
5293
5618
  setStatuslineLines: input.setStatuslineLines,
5294
5619
  saveStatuslineLines: input.saveStatuslineLines,
5620
+ statuslineDensities: input.statuslineDensities,
5621
+ setStatuslineDensities: input.setStatuslineDensities,
5622
+ saveStatuslineDensities: input.saveStatuslineDensities,
5295
5623
  getYolo: input.getYolo,
5296
5624
  onYolo: input.onYolo,
5297
5625
  getAutonomy: input.getAutonomy,
@@ -5400,7 +5728,7 @@ function createRuntimeLifecycleDeps(input) {
5400
5728
  return shared.length > 0 ? shared : input.getCurrentSuggestions();
5401
5729
  },
5402
5730
  autoProceedDelayMs: autonomy?.autoProceedDelayMs ?? 45e3,
5403
- autoProceedMaxIterations: autonomy?.autoProceedMaxIterations ?? 50,
5731
+ autoProceedMaxIterations: autonomy?.autoProceedMaxIterations ?? 0,
5404
5732
  onValidateAutoProceed: (suggestion, lastOutput) => validateAutoProceed(input.context, suggestion, lastOutput),
5405
5733
  getEternalEngine: input.getEternalEngine,
5406
5734
  getParallelEngine: input.getParallelEngine,
@@ -5647,6 +5975,7 @@ async function runCliExecution(params) {
5647
5975
  resolvedProvider,
5648
5976
  logger,
5649
5977
  switchProviderAndModel,
5978
+ reloadProviderConfig,
5650
5979
  applyMaxContext,
5651
5980
  renderer,
5652
5981
  reader,
@@ -5675,6 +6004,9 @@ async function runCliExecution(params) {
5675
6004
  statuslineLines,
5676
6005
  setStatuslineLines,
5677
6006
  saveStatuslineLines: saveStatuslineLines2,
6007
+ statuslineDensities,
6008
+ setStatuslineDensities,
6009
+ saveStatuslineDensities,
5678
6010
  setYoloMode,
5679
6011
  autonomyMode,
5680
6012
  setAutonomyMode,
@@ -5703,7 +6035,7 @@ async function runCliExecution(params) {
5703
6035
  governanceHandle,
5704
6036
  setConfig
5705
6037
  } = params;
5706
- const { execute } = await import("./execution-7ZFY4FJY.js");
6038
+ const { execute } = await import("./execution-MIBWBYB6.js");
5707
6039
  return execute(
5708
6040
  toExecuteDeps({
5709
6041
  core: {
@@ -5779,7 +6111,8 @@ async function runCliExecution(params) {
5779
6111
  authHost: createAuthPanelHost({
5780
6112
  vault,
5781
6113
  modelsRegistry,
5782
- profileConfigPath
6114
+ profileConfigPath,
6115
+ onProvidersChanged: reloadProviderConfig
5783
6116
  }),
5784
6117
  onPanelOpen
5785
6118
  },
@@ -5819,6 +6152,9 @@ async function runCliExecution(params) {
5819
6152
  statuslineLines,
5820
6153
  setStatuslineLines,
5821
6154
  saveStatuslineLines: saveStatuslineLines2,
6155
+ statuslineDensities,
6156
+ setStatuslineDensities,
6157
+ saveStatuslineDensities,
5822
6158
  getYolo: setYoloMode,
5823
6159
  onYolo: setYoloMode,
5824
6160
  getAutonomy: () => autonomyMode,
@@ -5911,6 +6247,7 @@ import { makeAutonomyPromptContributor } from "@wrongstack/core/execution";
5911
6247
  import { sessionScopedPath } from "@wrongstack/core/utils";
5912
6248
 
5913
6249
  // src/wiring/wrongtrace-prompt-contributor.ts
6250
+ import { normalizeTokenSavingTier as normalizeTokenSavingTier2 } from "@wrongstack/core/types";
5914
6251
  import { digestAtlas, summarizeFriction } from "@wrongstack/wrongtrace";
5915
6252
  var CONTRIBUTOR_DEADLINE_MS = 800;
5916
6253
  function raceWithDeadline(p, ms) {
@@ -5929,8 +6266,11 @@ function raceWithDeadline(p, ms) {
5929
6266
  );
5930
6267
  });
5931
6268
  }
5932
- function createWrongTracePromptContributor() {
5933
- return async () => {
6269
+ function createWrongTracePromptContributor(options = {}) {
6270
+ const tier = normalizeTokenSavingTier2(options.tokenSavingMode);
6271
+ return async (ctx) => {
6272
+ if (ctx.subagent) return [];
6273
+ if (tier === "minimal" || tier === "aggressive") return [];
5934
6274
  try {
5935
6275
  const wt = await raceWithDeadline(getWrongTrace(), CONTRIBUTOR_DEADLINE_MS);
5936
6276
  if (!wt?.isAvailable) return [];
@@ -6026,7 +6366,9 @@ function bindSystemPromptBuilder(deps) {
6026
6366
  // is reachable, the leader prompt carries a compact atlas digest +
6027
6367
  // friction summary block. Fail-open and deadline-bounded (<1s), so
6028
6368
  // an absent/slow daemon never stalls the boot prompt.
6029
- createWrongTracePromptContributor()
6369
+ createWrongTracePromptContributor({
6370
+ tokenSavingMode: deps.tokenSavingMode
6371
+ })
6030
6372
  ]
6031
6373
  })
6032
6374
  );
@@ -6041,7 +6383,7 @@ import {
6041
6383
  makeSessionNoteTool as makeSessionNoteTool2
6042
6384
  } from "@wrongstack/core/coordination";
6043
6385
  import { createContextManagerTool } from "@wrongstack/core/infrastructure";
6044
- import { normalizeTokenSavingTier as normalizeTokenSavingTier2 } from "@wrongstack/core/types";
6386
+ import { normalizeTokenSavingTier as normalizeTokenSavingTier3 } from "@wrongstack/core/types";
6045
6387
  import { configureChildEnvGitIdentity } from "@wrongstack/core/utils";
6046
6388
  import { registerCanonicalHostTools } from "@wrongstack/runtime/tool-registration";
6047
6389
  import { configureDangerBypass, configureExecPolicy } from "@wrongstack/tools";
@@ -6674,7 +7016,7 @@ ${commit.out}`;
6674
7016
 
6675
7017
  // src/boot/tool-registry.ts
6676
7018
  function registerBuiltinTools(deps) {
6677
- const tier = normalizeTokenSavingTier2(deps.config.features.tokenSavingMode);
7019
+ const tier = normalizeTokenSavingTier3(deps.config.features.tokenSavingMode);
6678
7020
  registerCanonicalHostTools({
6679
7021
  registry: deps.toolRegistry,
6680
7022
  tier,
@@ -7595,9 +7937,9 @@ async function generateCommitMessageWithLLM(diff, opts) {
7595
7937
  const userPrompt = `Here is the git diff:
7596
7938
 
7597
7939
  ${diff}`;
7940
+ const signal = new AbortController();
7941
+ const timeout = setTimeout(() => signal.abort(), 15e3);
7598
7942
  try {
7599
- const signal = new AbortController();
7600
- const timeout = setTimeout(() => signal.abort(), 15e3);
7601
7943
  const resp = await opts.provider.complete(
7602
7944
  {
7603
7945
  model: opts.model,
@@ -7608,7 +7950,6 @@ ${diff}`;
7608
7950
  },
7609
7951
  { signal: signal.signal }
7610
7952
  );
7611
- clearTimeout(timeout);
7612
7953
  const rawContent = resp.content;
7613
7954
  const text = Array.isArray(rawContent) ? rawContent[0]?.text ?? "" : typeof rawContent === "object" && rawContent !== null ? rawContent.text ?? "" : String(rawContent);
7614
7955
  const message = expectDefined3(text.trim().split("\n")[0]);
@@ -7616,6 +7957,8 @@ ${diff}`;
7616
7957
  return message;
7617
7958
  }
7618
7959
  } catch {
7960
+ } finally {
7961
+ clearTimeout(timeout);
7619
7962
  }
7620
7963
  return "chore: update";
7621
7964
  }
@@ -8031,57 +8374,25 @@ function formatDiagnostics(input) {
8031
8374
  import * as fs3 from "node:fs/promises";
8032
8375
  import * as os from "node:os";
8033
8376
  import * as path9 from "node:path";
8377
+ import {
8378
+ clampLine,
8379
+ defaultChipEnabledMap,
8380
+ STATUSLINE_DENSITY_LEVELS,
8381
+ STATUSLINE_ITEMS
8382
+ } from "@wrongstack/core/statusline";
8034
8383
  import { ERROR_CODES, FsError } from "@wrongstack/core/types";
8035
8384
  import { atomicWrite, resolveWstackPaths, toErrorMessage as toErrorMessage3 } from "@wrongstack/core/utils";
8036
8385
  var CONFIG_ENV = "WRONGSTACK_STATUSLINE_CONFIG";
8037
- var STATUSLINE_CONFIG_VERSION = 2;
8038
- var STATUSLINE_CONFIG_KEYS = [
8039
- "state",
8040
- "model",
8041
- "context",
8042
- "tokens",
8043
- "cache",
8044
- "cost",
8045
- "queue",
8046
- "hint",
8047
- "index",
8048
- "breaker",
8049
- "yolo",
8050
- "autonomy",
8051
- "eternal_stage",
8052
- "elapsed",
8053
- "project",
8054
- "working_dir",
8055
- "goal",
8056
- "mode",
8057
- "auto_proceed",
8058
- "git",
8059
- "sessions",
8060
- "tools",
8061
- "theme",
8062
- "token_saving",
8063
- "processes",
8064
- "version",
8065
- "dropped_tools",
8066
- "prompt_variant",
8067
- "side_effects",
8068
- "todos",
8069
- "plan",
8070
- "tasks",
8071
- "fleet",
8072
- "brain",
8073
- "debug_stream",
8074
- "enhance",
8075
- "next_steps",
8076
- "mailbox",
8077
- "fleet_agents",
8078
- "memory_context"
8079
- ];
8080
- var DEFAULTS = Object.fromEntries(
8081
- STATUSLINE_CONFIG_KEYS.map((key) => [key, true])
8082
- );
8386
+ var STATUSLINE_CONFIG_VERSION = 3;
8387
+ var STATUSLINE_CONFIG_KEYS = STATUSLINE_ITEMS;
8388
+ var DEFAULTS = defaultChipEnabledMap();
8083
8389
  function emptyDocument() {
8084
- return { version: STATUSLINE_CONFIG_VERSION, chips: { ...DEFAULTS }, lines: {} };
8390
+ return {
8391
+ version: STATUSLINE_CONFIG_VERSION,
8392
+ chips: { ...DEFAULTS },
8393
+ lines: {},
8394
+ densities: {}
8395
+ };
8085
8396
  }
8086
8397
  function resolveConfigPath() {
8087
8398
  const override = process.env[CONFIG_ENV];
@@ -8092,12 +8403,12 @@ function resolveConfigPath() {
8092
8403
  });
8093
8404
  return paths.profileStatuslineConfig(paths.profileName);
8094
8405
  }
8095
- function isRecord(value) {
8406
+ function isRecord2(value) {
8096
8407
  return typeof value === "object" && value !== null && !Array.isArray(value);
8097
8408
  }
8098
8409
  function normalizeChips(value) {
8099
8410
  const config = { ...DEFAULTS };
8100
- if (!isRecord(value)) return config;
8411
+ if (!isRecord2(value)) return config;
8101
8412
  for (const key of STATUSLINE_CONFIG_KEYS) {
8102
8413
  if (typeof value[key] === "boolean") config[key] = value[key];
8103
8414
  }
@@ -8105,33 +8416,50 @@ function normalizeChips(value) {
8105
8416
  }
8106
8417
  function normalizeLines(value) {
8107
8418
  const lines = {};
8108
- if (!isRecord(value)) return lines;
8419
+ if (!isRecord2(value)) return lines;
8109
8420
  for (const key of STATUSLINE_CONFIG_KEYS) {
8110
8421
  const raw = value[key];
8111
8422
  if (typeof raw !== "number" || !Number.isInteger(raw)) continue;
8112
- lines[key] = Math.min(4, Math.max(1, raw));
8423
+ lines[key] = clampLine(raw);
8113
8424
  }
8114
8425
  return lines;
8115
8426
  }
8427
+ function normalizeDensities(value) {
8428
+ const densities = {};
8429
+ if (!isRecord2(value)) return densities;
8430
+ for (const key of STATUSLINE_CONFIG_KEYS) {
8431
+ const raw = value[key];
8432
+ if (typeof raw !== "string") continue;
8433
+ if (!STATUSLINE_DENSITY_LEVELS.includes(raw)) continue;
8434
+ densities[key] = raw;
8435
+ }
8436
+ return densities;
8437
+ }
8116
8438
  function parseDocument(value) {
8117
- if (isRecord(value) && (isRecord(value["chips"]) || isRecord(value["lines"]))) {
8439
+ if (isRecord2(value) && (isRecord2(value["chips"]) || isRecord2(value["lines"]) || isRecord2(value["densities"]))) {
8118
8440
  return {
8119
8441
  version: STATUSLINE_CONFIG_VERSION,
8120
8442
  chips: normalizeChips(value["chips"]),
8121
- lines: normalizeLines(value["lines"])
8443
+ lines: normalizeLines(value["lines"]),
8444
+ densities: normalizeDensities(value["densities"])
8122
8445
  };
8123
8446
  }
8124
- return { version: STATUSLINE_CONFIG_VERSION, chips: normalizeChips(value), lines: {} };
8447
+ return {
8448
+ version: STATUSLINE_CONFIG_VERSION,
8449
+ chips: normalizeChips(value),
8450
+ lines: {},
8451
+ densities: {}
8452
+ };
8125
8453
  }
8126
8454
  function isMissingKnownChips(value) {
8127
- return !isRecord(value) || STATUSLINE_CONFIG_KEYS.some((key) => typeof value[key] !== "boolean");
8455
+ return !isRecord2(value) || STATUSLINE_CONFIG_KEYS.some((key) => typeof value[key] !== "boolean");
8128
8456
  }
8129
8457
  function needsRewrite(value) {
8130
- if (isRecord(value) && isRecord(value["chips"])) {
8458
+ if (isRecord2(value) && isRecord2(value["chips"])) {
8131
8459
  if (value["version"] !== STATUSLINE_CONFIG_VERSION) return true;
8132
8460
  if (isMissingKnownChips(value["chips"])) return true;
8133
- if (!isRecord(value["lines"])) return true;
8134
- return JSON.stringify(normalizeLines(value["lines"])) !== JSON.stringify(value["lines"]);
8461
+ if (!isRecord2(value["lines"]) || !isRecord2(value["densities"])) return true;
8462
+ return JSON.stringify(normalizeLines(value["lines"])) !== JSON.stringify(value["lines"]) || JSON.stringify(normalizeDensities(value["densities"])) !== JSON.stringify(value["densities"]);
8135
8463
  }
8136
8464
  return true;
8137
8465
  }
@@ -8160,7 +8488,7 @@ async function ensureStatuslineConfig() {
8160
8488
  raw = JSON.parse(await fs3.readFile(resolveConfigPath(), "utf8"));
8161
8489
  config = parseDocument(raw);
8162
8490
  } catch (error) {
8163
- if (isRecord(error) && error["code"] === "ENOENT") {
8491
+ if (isRecord2(error) && error["code"] === "ENOENT") {
8164
8492
  sawFile = false;
8165
8493
  config = emptyDocument();
8166
8494
  } else {
@@ -8188,7 +8516,8 @@ async function saveStatuslineConfig(config) {
8188
8516
  {
8189
8517
  version: STATUSLINE_CONFIG_VERSION,
8190
8518
  chips: normalizeChips(config.chips),
8191
- lines: normalizeLines(config.lines)
8519
+ lines: normalizeLines(config.lines),
8520
+ densities: normalizeDensities(config.densities)
8192
8521
  },
8193
8522
  null,
8194
8523
  2
@@ -8206,9 +8535,33 @@ async function saveStatuslineConfig(config) {
8206
8535
  async function loadStatuslineLines() {
8207
8536
  return (await loadStatuslineConfig()).lines;
8208
8537
  }
8209
- async function saveStatuslineLines(lines) {
8210
- const doc = await ensureStatuslineConfig();
8211
- await saveStatuslineConfig({ ...doc, lines: normalizeLines(lines) });
8538
+ async function loadStatuslineDensities() {
8539
+ return (await loadStatuslineConfig()).densities;
8540
+ }
8541
+ var docMutationChain = Promise.resolve();
8542
+ function queueDocMutation(mutate) {
8543
+ const run = docMutationChain.then(mutate, mutate);
8544
+ docMutationChain = run.then(
8545
+ () => void 0,
8546
+ () => void 0
8547
+ );
8548
+ return run;
8549
+ }
8550
+ async function saveStatuslineLayout(layout) {
8551
+ await queueDocMutation(async () => {
8552
+ const doc = await ensureStatuslineConfig();
8553
+ await saveStatuslineConfig({
8554
+ ...doc,
8555
+ lines: normalizeLines(layout.lines ?? doc.lines),
8556
+ densities: normalizeDensities(layout.densities ?? doc.densities)
8557
+ });
8558
+ });
8559
+ }
8560
+ async function saveStatuslineChips(chips) {
8561
+ await queueDocMutation(async () => {
8562
+ const doc = await ensureStatuslineConfig();
8563
+ await saveStatuslineConfig({ ...doc, chips: normalizeChips(chips) });
8564
+ });
8212
8565
  }
8213
8566
 
8214
8567
  // src/slash-commands/helpers.ts
@@ -9246,7 +9599,7 @@ import { randomUUID as randomUUID6 } from "node:crypto";
9246
9599
  import { color as color15 } from "@wrongstack/core/utils";
9247
9600
 
9248
9601
  // src/slash-commands/brain-council.ts
9249
- import { parseModelRef } from "@wrongstack/core/agent";
9602
+ import { parseModelRef as parseModelRef2 } from "@wrongstack/core/agent";
9250
9603
  import {
9251
9604
  BUILTIN_COUNCIL_PERSONA_IDS,
9252
9605
  BUILTIN_COUNCIL_PERSONAS
@@ -9258,11 +9611,12 @@ var COUNCIL_NUMERIC_OPS = {
9258
9611
  timeout: "perCallTimeoutMs",
9259
9612
  concurrency: "maxConcurrency",
9260
9613
  votertokens: "voterMaxTokens",
9261
- judgetokens: "judgeMaxTokens"
9614
+ judgetokens: "judgeMaxTokens",
9615
+ rounds: "deliberationRounds"
9262
9616
  };
9263
9617
  var PERSONA_SHORTHANDS = new Set(BUILTIN_COUNCIL_PERSONA_IDS);
9264
9618
  function parseRefEntry(ref) {
9265
- const parsed = parseModelRef(ref);
9619
+ const parsed = parseModelRef2(ref);
9266
9620
  const model = parsed.model?.trim();
9267
9621
  if (!model) return null;
9268
9622
  return parsed.provider ? { provider: parsed.provider, model } : { model };
@@ -9391,22 +9745,19 @@ async function handleBrainCouncilSubcommand(rest, opts, applyPatch) {
9391
9745
  return `Brain council ${op} set to ${color13.cyan(applied === void 0 ? "default" : String(applied))}`;
9392
9746
  });
9393
9747
  }
9394
- const msg = `Unknown council subcommand: ${op}. Use on, off, minrisk, voters, personas, judge, quorum, approval, distinctness, timeout, concurrency, votertokens, or judgetokens.`;
9748
+ const msg = `Unknown council subcommand: ${op}. Use on, off, minrisk, voters, personas, judge, quorum, approval, distinctness, timeout, concurrency, votertokens, judgetokens, or rounds.`;
9395
9749
  opts.renderer.writeWarning(msg);
9396
9750
  return { message: msg };
9397
9751
  }
9398
9752
 
9399
9753
  // src/slash-commands/brain-status.ts
9400
9754
  import { readFile as readFile5 } from "node:fs/promises";
9755
+ import { DETERMINISTIC_BRAIN_TIERS } from "@wrongstack/core/coordination";
9401
9756
  import { color as color14 } from "@wrongstack/core/utils";
9402
- var DETERMINISTIC_TIER_NAMES = [
9403
- "rule",
9404
- "policy",
9405
- "heuristic",
9406
- "cache",
9407
- "ledger-guard",
9408
- "terminal"
9409
- ];
9757
+ function councilRoundsSummary(snapshot) {
9758
+ const rounds = snapshot.council.deliberationRounds ?? 2;
9759
+ return rounds > 1 ? `, ${rounds} rounds` : ", no deliberation";
9760
+ }
9410
9761
  function fmtAge(at) {
9411
9762
  const s = Math.max(0, Math.round((Date.now() - at) / 1e3));
9412
9763
  if (s < 60) return `${s}s ago`;
@@ -9440,7 +9791,7 @@ function formatBrainStatus(opts) {
9440
9791
  const councilSeats = opts.brainSettings?.councilLabels ?? [];
9441
9792
  if (councilSeats.length > 0) {
9442
9793
  lines.push(
9443
- ` council: ${color14.cyan(councilSeats.join(", "))}${snapshot ? color14.dim(` (minRisk: ${snapshot.council.minRisk}${judgeSummary(snapshot)})`) : ""}`
9794
+ ` council: ${color14.cyan(councilSeats.join(", "))}${snapshot ? color14.dim(` (minRisk: ${snapshot.council.minRisk}${judgeSummary(snapshot)}${councilRoundsSummary(snapshot)})`) : ""}`
9444
9795
  );
9445
9796
  } else if (snapshot) {
9446
9797
  lines.push(` council: ${color14.dim("disabled (/brain council on + voters)")}`);
@@ -9469,21 +9820,25 @@ function formatBrainStatus(opts) {
9469
9820
  }
9470
9821
  function formatBrainStats(opts) {
9471
9822
  const log = opts.getBrainLog?.() ?? [];
9823
+ const councilWarnings = log.filter((entry) => entry.kind === "council_warn");
9824
+ const lifetime = opts.brainTierStats?.();
9472
9825
  const counts = /* @__PURE__ */ new Map();
9473
- const councilWarnings = [];
9474
- for (const entry of log) {
9475
- if (entry.kind === "council_warn") {
9476
- councilWarnings.push(entry);
9477
- continue;
9826
+ if (lifetime) {
9827
+ for (const [tier, n] of Object.entries(lifetime.byTier)) counts.set(tier, n ?? 0);
9828
+ if (lifetime.unattributed > 0) counts.set("unattributed", lifetime.unattributed);
9829
+ } else {
9830
+ for (const entry of log) {
9831
+ if (entry.kind === "council_warn") continue;
9832
+ counts.set(entry.tier ?? "unattributed", (counts.get(entry.tier ?? "unattributed") ?? 0) + 1);
9478
9833
  }
9479
- const tier = entry.tier ?? "unattributed";
9480
- counts.set(tier, (counts.get(tier) ?? 0) + 1);
9481
9834
  }
9482
- let free = 0;
9483
- let paid = 0;
9484
- for (const [tier, n] of counts) {
9485
- if (DETERMINISTIC_TIER_NAMES.includes(tier)) free += n;
9486
- else if (tier === "llm" || tier === "council") paid += n;
9835
+ let free = lifetime?.deterministic ?? 0;
9836
+ let paid = lifetime?.llmBacked ?? 0;
9837
+ if (!lifetime) {
9838
+ for (const [tier, n] of counts) {
9839
+ if (DETERMINISTIC_BRAIN_TIERS.has(tier)) free += n;
9840
+ else if (tier === "llm" || tier === "council") paid += n;
9841
+ }
9487
9842
  }
9488
9843
  const lines = [color14.bold("Brain decision tiers"), ""];
9489
9844
  if (counts.size === 0) {
@@ -9516,7 +9871,9 @@ function formatBrainStats(opts) {
9516
9871
  }
9517
9872
  lines.push(
9518
9873
  "",
9519
- color14.dim(` Based on the last ${log.length} logged decision(s) of this session.`)
9874
+ color14.dim(
9875
+ lifetime ? ` ${lifetime.total} decision(s) this session.` : ` Based on the last ${log.length} logged decision(s) of this session.`
9876
+ )
9520
9877
  );
9521
9878
  return lines.join("\n");
9522
9879
  }
@@ -12447,7 +12804,7 @@ function buildDoctorCommand(opts) {
12447
12804
  ].join("\n");
12448
12805
  async function loadPluginSchemas() {
12449
12806
  try {
12450
- const { BUILTIN_PLUGIN_FACTORIES } = await import("./plugins-7N3TF2QF.js");
12807
+ const { BUILTIN_PLUGIN_FACTORIES } = await import("./plugins-PZ2VZL7V.js");
12451
12808
  const settled = await Promise.allSettled(BUILTIN_PLUGIN_FACTORIES.map((f) => f()));
12452
12809
  const loaded = [];
12453
12810
  for (const s of settled) {
@@ -12851,7 +13208,7 @@ import * as fs7 from "node:fs/promises";
12851
13208
  import {
12852
13209
  diagnoseFallbackConfig,
12853
13210
  normalizeModelRef,
12854
- parseModelRef as parseModelRef2,
13211
+ parseModelRef as parseModelRef3,
12855
13212
  runtimeFallbackChain,
12856
13213
  simulateFallbackFailover,
12857
13214
  smartDefaultFallbackChain
@@ -12860,7 +13217,7 @@ import { decryptConfigSecrets, encryptConfigSecrets, noOpVault as noOpVault2 } f
12860
13217
  import { ConfigError } from "@wrongstack/core/types";
12861
13218
  import { atomicWrite as atomicWrite4, color as color25, toErrorMessage as toErrorMessage10 } from "@wrongstack/core/utils";
12862
13219
  function refInvalidReason(ref, config) {
12863
- const parsed = parseModelRef2(ref);
13220
+ const parsed = parseModelRef3(ref);
12864
13221
  if (!parsed.model) return "no model in reference";
12865
13222
  const favorites = config.favoriteModels ?? [];
12866
13223
  if (favorites.length === 0) return void 0;
@@ -12870,7 +13227,7 @@ function refInvalidReason(ref, config) {
12870
13227
  return void 0;
12871
13228
  }
12872
13229
  function refStaleModelListWarning(ref, config) {
12873
- const parsed = parseModelRef2(ref);
13230
+ const parsed = parseModelRef3(ref);
12874
13231
  if (!parsed.model) return "no model in reference";
12875
13232
  const providerId = parsed.provider ?? config.provider;
12876
13233
  const entry = config.providers?.[providerId];
@@ -13159,7 +13516,7 @@ function buildFallbackCommand(opts) {
13159
13516
  };
13160
13517
  }
13161
13518
  const ref = normalizeRef(parts.slice(2).join(" "));
13162
- const parsed = parseModelRef2(ref);
13519
+ const parsed = parseModelRef3(ref);
13163
13520
  if (!ref || !parsed.provider || !parsed.model) {
13164
13521
  return {
13165
13522
  message: `${color25.amber("Usage:")} /fallback bridge set <provider/model>`
@@ -13401,13 +13758,13 @@ ${color25.dim("Add favorites first: /fallback fav add <ref>, or fix provider mod
13401
13758
  return { message: `${color25.amber("Already favorite")}: ${color25.cyan(ref)}` };
13402
13759
  }
13403
13760
  const providerEntry = (() => {
13404
- const parsed = parseModelRef2(ref);
13761
+ const parsed = parseModelRef3(ref);
13405
13762
  const provId = parsed.provider ?? config.provider;
13406
13763
  return config.providers?.[provId];
13407
13764
  })();
13408
- if (providerEntry?.models && providerEntry.models.length > 0 && !providerEntry.models.includes(parseModelRef2(ref).model)) {
13765
+ if (providerEntry?.models && providerEntry.models.length > 0 && !providerEntry.models.includes(parseModelRef3(ref).model)) {
13409
13766
  return {
13410
- message: `${color25.red("Cannot favorite")}: "${ref}" \u2014 ${parseModelRef2(ref).model} not in ${parseModelRef2(ref).provider ?? config.provider} model list (${providerEntry.models.join(", ")}). ${color25.dim("Pick a model the provider actually exposes.")}`
13767
+ message: `${color25.red("Cannot favorite")}: "${ref}" \u2014 ${parseModelRef3(ref).model} not in ${parseModelRef3(ref).provider ?? config.provider} model list (${providerEntry.models.join(", ")}). ${color25.dim("Pick a model the provider actually exposes.")}`
13411
13768
  };
13412
13769
  }
13413
13770
  favorites.push(ref);
@@ -15841,6 +16198,75 @@ function buildHealthCommand(opts) {
15841
16198
  };
15842
16199
  }
15843
16200
 
16201
+ // src/slash-commands/slash-deep-help.ts
16202
+ var slashToSubcommand = {
16203
+ // ── Existing slash commands ───────────────────────────────────────
16204
+ // These slash commands ARE registered today. The wiring on the
16205
+ // slash side imports `renderSlashFocusedHelp` from this module
16206
+ // and short-circuits `help` / `--help` / `-h` to the focused
16207
+ // block. The entries here are the bridge that wires each
16208
+ // slash command to its top-level subcommand counterpart.
16209
+ auth: "auth",
16210
+ mcp: "mcp",
16211
+ plugin: "plugin",
16212
+ models: "models",
16213
+ sessions: "sessions",
16214
+ tools: "tools",
16215
+ init: "init",
16216
+ doctor: "doctor",
16217
+ // ── Forward-compatible bindings ───────────────────────────────────
16218
+ // No slash command with this name exists yet. When a future
16219
+ // contributor adds one (e.g. `packages/cli/src/slash-commands/config.ts`
16220
+ // with `name: 'config'`), the entry below is the wiring point
16221
+ // for `/help <name>` to render the same block `wstack <name> --help`
16222
+ // would write. The contributor still has to add the
16223
+ // `wantsDeepHelp` / focused-help short-circuit to the new slash
16224
+ // command's `run()` method (mirroring the pattern in
16225
+ // `auth.ts` / `mcp.ts` / etc.) — this map just registers the
16226
+ // dispatch target for the existing `/help <name>` renderer.
16227
+ //
16228
+ // Adding an entry here is a one-line, type-checked change.
16229
+ // There's no runtime cost when the slash command doesn't exist
16230
+ // yet — `renderSlashFocusedHelp` only fires when the user types
16231
+ // `/help <name>`, and if the slash command isn't registered,
16232
+ // the existing inline-help path is the fallback.
16233
+ config: "config",
16234
+ audit: "audit",
16235
+ replay: "replay",
16236
+ rewind: "rewind",
16237
+ export: "export",
16238
+ usage: "usage",
16239
+ providers: "providers",
16240
+ skills: "skills",
16241
+ update: "update",
16242
+ projects: "projects",
16243
+ acp: "acp",
16244
+ modeldiag: "modeldiag",
16245
+ bench: "bench",
16246
+ diag: "diag",
16247
+ version: "version",
16248
+ // `quick` is intercepted by `boot()` for the TUI launch, but
16249
+ // its focused-help entry (`wstack quick --help`) still resolves
16250
+ // through the per-subcommand-help table. Including it here
16251
+ // means a future `/quick` slash command (if one is ever added)
16252
+ // gets the focused-help wiring automatically.
16253
+ quick: "quick"
16254
+ };
16255
+ var slashesWithFocusedHelp = Object.keys(slashToSubcommand);
16256
+ function resolveSlashSubcommand(slashName) {
16257
+ return slashToSubcommand[slashName];
16258
+ }
16259
+ function renderSlashFocusedHelp(slashName) {
16260
+ const sub = resolveSlashSubcommand(slashName);
16261
+ if (!sub) return void 0;
16262
+ return renderFocusedHelpToString(sub);
16263
+ }
16264
+ function renderSlashDeepHelp(slashName, deep) {
16265
+ const sub = resolveSlashSubcommand(slashName);
16266
+ if (!sub) return void 0;
16267
+ return renderDeepHelpToString(`${sub}:${deep}`);
16268
+ }
16269
+
15844
16270
  // src/slash-commands/help.ts
15845
16271
  function buildHelpCommand(opts) {
15846
16272
  return {
@@ -15864,6 +16290,12 @@ function buildHelpCommand(opts) {
15864
16290
  return { message: "" };
15865
16291
  }
15866
16292
  if (query) {
16293
+ const queryParts = query.split(/\s+/).filter(Boolean);
16294
+ if (queryParts.length === 2) {
16295
+ const head = queryParts[0].replace(/^\//, "");
16296
+ const deepHelp = renderSlashDeepHelp(head, queryParts[1]);
16297
+ if (deepHelp) return { message: deepHelp };
16298
+ }
15867
16299
  const needle = query.startsWith("/") ? query.slice(1) : query;
15868
16300
  let match;
15869
16301
  for (const entry of opts.registry.listWithOwner()) {
@@ -15884,7 +16316,8 @@ function buildHelpCommand(opts) {
15884
16316
  const header = `/${prefix}${match.cmd.name}`;
15885
16317
  const aliasLine = match.cmd.aliases?.length ? `Aliases: ${match.cmd.aliases.map((a) => `/${prefix}${a}`).join(", ")}
15886
16318
  ` : "";
15887
- const body = match.cmd.help ?? match.cmd.description;
16319
+ const focused = renderSlashFocusedHelp(match.cmd.name);
16320
+ const body = [match.cmd.help ?? match.cmd.description, focused].filter(Boolean).join("\n\n");
15888
16321
  return {
15889
16322
  message: [
15890
16323
  header,
@@ -18529,7 +18962,7 @@ function errorMessage(err) {
18529
18962
 
18530
18963
  // src/slash-commands/memory.ts
18531
18964
  import { toErrorMessage as toErrorMessage18 } from "@wrongstack/core/utils";
18532
- import { getSageSurface as getSageSurface3 } from "@wrongstack/sage";
18965
+ import { getSageSurface as getSageSurface4 } from "@wrongstack/sage";
18533
18966
 
18534
18967
  // src/slash-commands/memory-audience.ts
18535
18968
  import { toErrorMessage as toErrorMessage14 } from "@wrongstack/core/utils";
@@ -19854,6 +20287,7 @@ import { toErrorMessage as toErrorMessage17 } from "@wrongstack/core/utils";
19854
20287
  import {
19855
20288
  fileTriageProposals,
19856
20289
  formatTriageReport,
20290
+ getSageSurface as getSageSurface3,
19857
20291
  runTriage
19858
20292
  } from "@wrongstack/sage";
19859
20293
  var DEFAULT_MAX_PHASE3 = 1e3;
@@ -19975,8 +20409,7 @@ Usage: /memory triage [--dry-run|--apply] [--limit N] [--max-phase3 N] [--max-ph
19975
20409
  function getSage(opts) {
19976
20410
  if (!opts.memoryStore) return null;
19977
20411
  try {
19978
- const { getSageSurface: getSageSurface4 } = __require("@wrongstack/sage");
19979
- return getSageSurface4(opts.memoryStore);
20412
+ return getSageSurface3(opts.memoryStore) ?? null;
19980
20413
  } catch {
19981
20414
  return null;
19982
20415
  }
@@ -20069,7 +20502,7 @@ function buildMemoryCommand(opts) {
20069
20502
  async run(args) {
20070
20503
  const store = opts.memoryStore;
20071
20504
  if (!store) return { message: "No memory store configured." };
20072
- const Sage = getSageSurface3(store);
20505
+ const Sage = getSageSurface4(store);
20073
20506
  const { cmd, rest } = parseSubcommand(args);
20074
20507
  const restJoined = rest.join(" ").trim();
20075
20508
  switch (cmd) {
@@ -20282,7 +20715,7 @@ function buildMemoryCommand(opts) {
20282
20715
  };
20283
20716
  }
20284
20717
  try {
20285
- const lexical = await Sage.searchSage(restJoined, { limit: 20 });
20718
+ const lexical = Sage.searchSageWithBreakdown ? (await Sage.searchSageWithBreakdown(restJoined, { limit: 20 })).filter((hit) => hit.lexicalScore !== null).sort((a, b) => (b.lexicalScore ?? 0) - (a.lexicalScore ?? 0)).map((hit) => hit.memory) : await Sage.searchSage(restJoined, { limit: 20 });
20286
20719
  const race = await runSearchRace(restJoined, lexical, vectorStore, { limit: 20 });
20287
20720
  return { message: formatSearchRace(race) };
20288
20721
  } catch (err) {
@@ -22057,7 +22490,7 @@ function buildPruneCommand(opts) {
22057
22490
  return {
22058
22491
  name: "prune",
22059
22492
  category: "Session",
22060
- description: "Delete old sessions. /prune (default 30d), /prune 7, /prune --rebuild-index.",
22493
+ description: "Delete old sessions. /prune (default 30d). To compress instead of delete, use /sessions archive.",
22061
22494
  help: "Usage:\n /prune Delete sessions older than 30 days.\n /prune 14 Delete sessions older than 14 days.\n /prune --dry-run Show what would be deleted without deleting.\n /prune --rebuild-index Rebuild the session index from disk.",
22062
22495
  async run(args) {
22063
22496
  const parts = args.split(/\s+/).filter(Boolean);
@@ -23452,7 +23885,11 @@ ${sddHelp()}`
23452
23885
  }
23453
23886
 
23454
23887
  // src/slash-commands/session.ts
23455
- import { extractInterruptedTools, SessionRecovery } from "@wrongstack/core/storage";
23888
+ import {
23889
+ extractInterruptedTools,
23890
+ getSessionRegistry,
23891
+ SessionRecovery
23892
+ } from "@wrongstack/core/storage";
23456
23893
  import { color as color47, isPidAlive, toErrorMessage as toErrorMessage21 } from "@wrongstack/core/utils";
23457
23894
  function statusIcon2(status) {
23458
23895
  switch (status) {
@@ -23484,6 +23921,12 @@ function agentStatusIcon(status) {
23484
23921
  return color47.dim("?");
23485
23922
  }
23486
23923
  }
23924
+ function formatBytes(value) {
23925
+ if (!value || !Number.isFinite(value) || value <= 0) return "0B";
23926
+ if (value < 1024) return `${value}B`;
23927
+ if (value < 1024 * 1024) return `${(value / 1024).toFixed(1)}KB`;
23928
+ return `${(value / (1024 * 1024)).toFixed(1)}MB`;
23929
+ }
23487
23930
  function fmtDuration(startedAt) {
23488
23931
  const diff = Date.now() - new Date(startedAt).getTime();
23489
23932
  const min = Math.floor(diff / 6e4);
@@ -23501,8 +23944,7 @@ function fmtAgentLine(agent) {
23501
23944
  }
23502
23945
  function getRegistry() {
23503
23946
  try {
23504
- const mod = __require("@wrongstack/core/storage");
23505
- return mod.getSessionRegistry?.();
23947
+ return getSessionRegistry();
23506
23948
  } catch {
23507
23949
  return void 0;
23508
23950
  }
@@ -23529,7 +23971,7 @@ function buildLoadCommand(opts) {
23529
23971
  name: "sessions",
23530
23972
  category: "Session",
23531
23973
  aliases: ["resume", "load"],
23532
- description: "List recent sessions, show incomplete ones (--incomplete), or plan a recovery (--recover <id>).",
23974
+ description: "List, resume, archive, or recover sessions. /sessions archive compresses old JSONL logs.",
23533
23975
  async run(args) {
23534
23976
  const parts = args.split(/\s+/).filter(Boolean);
23535
23977
  const first = parts[0]?.toLowerCase();
@@ -23578,6 +24020,58 @@ function buildLoadCommand(opts) {
23578
24020
  return { message: color47.red(`Rename failed: ${toErrorMessage21(err)}`) };
23579
24021
  }
23580
24022
  }
24023
+ if (first === "archive") {
24024
+ if (!opts.sessionStore?.archive || !opts.sessionStore.archiveIdle) {
24025
+ return { message: color47.yellow("Session store does not support archive.") };
24026
+ }
24027
+ const apply = parts.includes("--apply");
24028
+ const targetId = parts.filter((p) => p !== "--apply" && p !== "archive")[0];
24029
+ if (targetId) {
24030
+ try {
24031
+ const result2 = await opts.sessionStore.archive(targetId);
24032
+ return {
24033
+ message: result2.action === "archived" ? color47.green(
24034
+ `Archived ${targetId} (${formatBytes(result2.uncompressedBytes)} \u2192 ${formatBytes(result2.compressedBytes)})`
24035
+ ) : color47.dim(`Archive ${result2.action}: ${targetId}${result2.reason ? ` (${result2.reason})` : ""}`)
24036
+ };
24037
+ } catch (err) {
24038
+ return { message: color47.red(`Archive failed: ${toErrorMessage21(err)}`) };
24039
+ }
24040
+ }
24041
+ if (!apply) {
24042
+ const preview = await opts.sessionStore.list(1e3);
24043
+ return {
24044
+ message: [
24045
+ color47.bold("Dry run \u2014 gzip existing closed session logs (JSONL stays the resume authority)."),
24046
+ color47.dim("Last 20 stay hot; everything else is gzipped immediately. /prune still deletes."),
24047
+ color47.dim(`Currently listed: ${preview.length} session(s).`),
24048
+ "",
24049
+ color47.dim("Run /sessions archive --apply to compress, or /sessions archive <id> for one session.")
24050
+ ].join("\n")
24051
+ };
24052
+ }
24053
+ const result = await opts.sessionStore.archiveIdle({ backfill: true });
24054
+ return {
24055
+ message: `Archived ${color47.green(String(result.archived))} \xB7 skipped ${color47.dim(String(result.skipped))} \xB7 failed ${result.failed ? color47.red(String(result.failed)) : color47.dim("0")}.`
24056
+ };
24057
+ }
24058
+ if (first === "rehydrate") {
24059
+ const targetId = parts[1];
24060
+ if (!targetId) {
24061
+ return { message: color47.yellow("Usage: /sessions rehydrate <sessionId>") };
24062
+ }
24063
+ if (!opts.sessionStore?.rehydrate) {
24064
+ return { message: color47.yellow("Session store does not support rehydrate.") };
24065
+ }
24066
+ try {
24067
+ const result = await opts.sessionStore.rehydrate(targetId);
24068
+ return {
24069
+ message: result.action === "rehydrated" ? color47.green(`Rehydrated ${targetId}`) : color47.dim(`Rehydrate ${result.action}: ${targetId}`)
24070
+ };
24071
+ } catch (err) {
24072
+ return { message: color47.red(`Rehydrate failed: ${toErrorMessage21(err)}`) };
24073
+ }
24074
+ }
23581
24075
  if (first === "delete") {
23582
24076
  const targetId = parts[1];
23583
24077
  if (!targetId) {
@@ -23712,10 +24206,11 @@ function buildLoadCommand(opts) {
23712
24206
  }
23713
24207
  const stat6 = parts2.join(" ");
23714
24208
  const date = color47.dim(s.startedAt.slice(0, 16).replace("T", " "));
24209
+ const archived = s.storageState === "cold" ? color47.dim(" gz") : "";
23715
24210
  const isCurrent = s.id === currentId;
23716
24211
  const marker = isCurrent ? color47.cyan(" (current)") : "";
23717
24212
  const label = s.name ? `${color47.bold(s.id)} ${color47.cyan(`(${s.name})`)}` : color47.bold(s.id);
23718
- return ` ${label}${marker}
24213
+ return ` ${label}${marker}${archived}
23719
24214
  ${date} ${stat6}
23720
24215
  ${color47.dim(s.title)}`;
23721
24216
  });
@@ -23992,7 +24487,7 @@ async function killSession(sessionId, confirm) {
23992
24487
 
23993
24488
  // src/slash-commands/setmodel.ts
23994
24489
  import * as fs15 from "node:fs/promises";
23995
- import { fallbackProfileChain, parseModelRef as parseModelRef3 } from "@wrongstack/core/agent";
24490
+ import { fallbackProfileChain, parseModelRef as parseModelRef4 } from "@wrongstack/core/agent";
23996
24491
  import { AGENT_CATALOG as AGENT_CATALOG2, AGENTS_BY_PHASE as AGENTS_BY_PHASE3 } from "@wrongstack/core/agent-catalog";
23997
24492
  import {
23998
24493
  MATRIX_PHASE_KEYS,
@@ -24390,7 +24885,7 @@ function buildSetModelCommand(opts) {
24390
24885
  const first = chain[0];
24391
24886
  if (!first)
24392
24887
  return { message: `${color48.red("Empty profile")}: ${color48.amber(profile)}` };
24393
- const parsed = parseModelRef3(first);
24888
+ const parsed = parseModelRef4(first);
24394
24889
  const provider2 = parsed.provider ?? config.provider;
24395
24890
  if (!keyed.includes(provider2)) {
24396
24891
  return {
@@ -25189,6 +25684,38 @@ var THEME_META = {
25189
25684
  "gruvbox-dark-hard": {
25190
25685
  name: "Gruvbox Dark Hard",
25191
25686
  desc: "Maximum contrast Gruvbox on deep pitch charcoal"
25687
+ },
25688
+ "oceanic-next": {
25689
+ name: "Oceanic Next",
25690
+ desc: "Teal-and-slate classic \u2014 calm blue, warm coral"
25691
+ },
25692
+ "one-half-dark": {
25693
+ name: "One Half Dark",
25694
+ desc: "Atom's One Half \u2014 One Dark with cleaner contrast"
25695
+ },
25696
+ "ayu-mirage": { name: "Ayu Mirage", desc: "Dusk-slate Ayu, between Dark and Light" },
25697
+ seti: { name: "Seti", desc: "Long-running VS Code classic \u2014 charcoal, gold, cyan" },
25698
+ "paraiso-dark": { name: "Paraiso Dark", desc: "Base16 plum \u2014 warm, muted, low-glare" },
25699
+ darcula: { name: "Darcula", desc: "JetBrains' default dark \u2014 grey-green with amber" },
25700
+ "slack-dark": { name: "Slack Aubergine", desc: "Deep aubergine with sky blue and lime" },
25701
+ "vitesse-black": { name: "Vitesse Black", desc: "Vitesse on true black \u2014 least glare here" },
25702
+ "atom-dark": { name: "Atom Dark", desc: "The original Atom grey \u2014 neutral, low-chroma" },
25703
+ "github-dark-high-contrast": {
25704
+ name: "GitHub Dark High Contrast",
25705
+ desc: "Accessible GitHub \u2014 boosted text and borders"
25706
+ },
25707
+ "contrast-max": {
25708
+ name: "Maximum Contrast",
25709
+ desc: "Original \u2014 pure black, AAA-targeted text and borders"
25710
+ },
25711
+ "colorblind-safe": {
25712
+ name: "Colorblind Safe",
25713
+ desc: "Original \u2014 blue/orange coding, no red-vs-green reliance"
25714
+ },
25715
+ sandstone: { name: "Sandstone", desc: "Original \u2014 warm stone neutrals with sage and clay" },
25716
+ "everforest-hard": {
25717
+ name: "Everforest Hard",
25718
+ desc: "Everforest on its deepest base \u2014 more depth, same greens"
25192
25719
  }
25193
25720
  };
25194
25721
  var THEME_OPTIONS = THEME_PRESET_IDS.map((id) => ({ id, ...THEME_META[id] }));
@@ -26590,6 +27117,7 @@ import { color as color56 } from "@wrongstack/core/utils";
26590
27117
 
26591
27118
  // src/slash-commands/settings-mutations.ts
26592
27119
  import { noOpVault as noOpVault10 } from "@wrongstack/core/security";
27120
+ import { CONFIG_BEHAVIOR_DEFAULTS } from "@wrongstack/core/storage";
26593
27121
  import {
26594
27122
  isReasoningEffort as isReasoningEffort3,
26595
27123
  REASONING_EFFORT_LEVELS as REASONING_EFFORT_LEVELS3
@@ -26608,7 +27136,6 @@ function formatDelay(ms) {
26608
27136
  var ALL_SETTINGS_KEYS = [
26609
27137
  "delay",
26610
27138
  "mode",
26611
- "hints",
26612
27139
  "debug-stream",
26613
27140
  "config-scope",
26614
27141
  "fs-access",
@@ -26649,7 +27176,8 @@ var ALL_SETTINGS_KEYS = [
26649
27176
  "statusline",
26650
27177
  "animation",
26651
27178
  "read-symbols",
26652
- "defaults"
27179
+ "defaults",
27180
+ "reset"
26653
27181
  ];
26654
27182
  async function executeSettingsSubcommand(sub, rest, opts) {
26655
27183
  const activeProfile = opts.configStore.get().activeProfile ?? "default";
@@ -26750,19 +27278,6 @@ async function executeSettingsSubcommand(sub, rest, opts) {
26750
27278
  });
26751
27279
  return { message: `${color54.green("\u2713")} default autonomy \u2192 ${color54.bold(raw)}` };
26752
27280
  }
26753
- if (sub === "hints") {
26754
- const raw = (rest[0] ?? "").toLowerCase();
26755
- if (!["on", "off"].includes(raw)) {
26756
- return { message: `${color54.amber("Usage:")} /settings hints on|off` };
26757
- }
26758
- const on = raw === "on";
26759
- await persistConfigSetting(persistDeps, (cfg) => {
26760
- cfg.hints = on;
26761
- });
26762
- return {
26763
- message: `${color54.green("\u2713")} launch hints \u2192 ${on ? color54.cyan("on") : color54.dim("off")}`
26764
- };
26765
- }
26766
27281
  if (sub === "debug-stream") {
26767
27282
  const raw = (rest[0] ?? "").toLowerCase();
26768
27283
  if (!["on", "off"].includes(raw)) {
@@ -27445,6 +27960,9 @@ async function executeSettingsSubcommand(sub, rest, opts) {
27445
27960
  });
27446
27961
  return { message: `${color54.green("\u2713")} animation style \u2192 ${color54.cyan(raw)}` };
27447
27962
  }
27963
+ if (sub === "reset") {
27964
+ return executeSettingsReset(rest, persistDeps, opts, activeProfile);
27965
+ }
27448
27966
  return {
27449
27967
  message: `${color54.red("Unknown setting")} "${sub}". ${unknownSubcommand(sub, ALL_SETTINGS_KEYS, "settings")}`
27450
27968
  };
@@ -27454,6 +27972,62 @@ async function executeSettingsSubcommand(sub, rest, opts) {
27454
27972
  };
27455
27973
  }
27456
27974
  }
27975
+ var RESET_SECTIONS = BEHAVIOR_SECTION_KEYS;
27976
+ async function executeSettingsReset(rest, persistDeps, opts, profileName) {
27977
+ const args = rest.map((a) => a.toLowerCase()).filter(Boolean);
27978
+ if (args.length === 0) {
27979
+ return {
27980
+ message: [
27981
+ `${color54.amber("Usage:")} /settings reset all ${color54.dim("or pick sections:")}`,
27982
+ ` ${RESET_SECTIONS.join(", ")}`,
27983
+ color54.dim(
27984
+ `Identity is kept (providers, models, API keys, MCP servers, extensions, plugins, fallbacks). Profile: ${profileName}`
27985
+ )
27986
+ ].join("\n")
27987
+ };
27988
+ }
27989
+ const wantsAll = args.includes("all");
27990
+ const invalid = args.filter((a) => a !== "all" && !RESET_SECTIONS.includes(a));
27991
+ if (invalid.length > 0) {
27992
+ return {
27993
+ message: `${color54.red("Unknown section")}: ${invalid.join(", ")}. Valid: ${color54.cyan(RESET_SECTIONS.join(", "))}, all`
27994
+ };
27995
+ }
27996
+ const sections = wantsAll ? [...RESET_SECTIONS] : [...new Set(args)];
27997
+ if (!opts.confirm) {
27998
+ return {
27999
+ message: `${color54.red("Reset unavailable")}: no confirmation surface in this context. Run /settings reset from the interactive REPL or TUI.`
28000
+ };
28001
+ }
28002
+ const confirmed = await opts.confirm(
28003
+ `Reset ${sections.length} section(s) of profile "${profileName}" to factory defaults? ${sections.join(", ")}`,
28004
+ false
28005
+ );
28006
+ if (confirmed !== true) {
28007
+ return { message: `${color54.dim("Reset cancelled \u2014 nothing changed.")}` };
28008
+ }
28009
+ const defaults = structuredClone(CONFIG_BEHAVIOR_DEFAULTS);
28010
+ const patch = {};
28011
+ for (const key of sections) {
28012
+ const value = defaults[key];
28013
+ if (value === void 0) continue;
28014
+ patch[key] = value !== null && typeof value === "object" ? { ...value } : value;
28015
+ }
28016
+ await persistConfigSetting(persistDeps, (cfg) => {
28017
+ for (const [key, value] of Object.entries(patch)) {
28018
+ if (value !== null && typeof value === "object") {
28019
+ const current = cfg[key] ?? {};
28020
+ cfg[key] = { ...current, ...value };
28021
+ } else {
28022
+ cfg[key] = value;
28023
+ }
28024
+ }
28025
+ });
28026
+ opts.configStore.update(patch);
28027
+ return {
28028
+ message: `${color54.green("\u2713")} Reset ${sections.length} section(s) \u2192 ${color54.cyan(sections.join(", "))} ${color54.dim(`profile: ${profileName}; some halves apply on next session start`)}`
28029
+ };
28030
+ }
27457
28031
 
27458
28032
  // src/slash-commands/settings-view.ts
27459
28033
  import { resolveFleetChatVerbosity } from "@wrongstack/core/types";
@@ -27466,7 +28040,6 @@ var SETTINGS_HELP = [
27466
28040
  " /settings stream-fleet off|full Fleet-chat verbosity (on = full)",
27467
28041
  " /settings chime on|off Ring terminal bell when a run completes",
27468
28042
  " /settings confirm-exit on|off Ask for confirmation before interrupt/exit",
27469
- " /settings hints on|off Show or suppress rotating launch hints",
27470
28043
  " /settings debug-stream on|off Raw SSE hex-dump to stderr for debugging",
27471
28044
  " /settings config-scope global|project Save settings globally or per-project",
27472
28045
  " /settings fs-access unrestricted|project File-tool access scope (project = confine to project root)",
@@ -27480,6 +28053,7 @@ var SETTINGS_HELP = [
27480
28053
  " /settings semver-part patch|minor|major|auto Default part for /semver and the semver_bump tool",
27481
28054
  " /settings breaker on|off Enable/disable the process circuit breaker (gates bash/exec)",
27482
28055
  " /settings breaker-timeout <seconds> Auto kill/reset delay when the breaker trips (0 = manual)",
28056
+ " /settings reset [all|<section>...] Reset behavior sections to factory defaults (asks first; identity kept)",
27483
28057
  " /settings context-mode balanced|frugal|deep Context window policy",
27484
28058
  " /settings context-strategy hybrid|intelligent|selective Compactor strategy",
27485
28059
  " /settings context-auto-compact on|off Auto-compact context when thresholds crossed",
@@ -27523,7 +28097,6 @@ function formatSettingsDefaults() {
27523
28097
  "",
27524
28098
  ` auto-proceed delay: ${color55.cyan("45s")} ${color55.dim("(WRONGSTACK_AUTO_PROCEED_DELAY_MS env)")}`,
27525
28099
  ` default autonomy mode: ${color55.cyan("off")}`,
27526
- ` launch hints: ${color55.cyan("on")}`,
27527
28100
  ` iteration timeout: ${color55.cyan("5 min")}`,
27528
28101
  ` session timeout: ${color55.cyan("30 min")}`,
27529
28102
  ` max iterations: ${color55.cyan("100")}`,
@@ -27535,7 +28108,6 @@ function formatCurrentSettingsView(opts) {
27535
28108
  const autonomy = opts.configStore.get().autonomy;
27536
28109
  const delay = autonomy?.autoProceedDelayMs ?? 45e3;
27537
28110
  const mode = autonomy?.defaultMode ?? "off";
27538
- const hints = opts.configStore.get().hints !== false;
27539
28111
  const debugStream = opts.configStore.get().debugStream === true;
27540
28112
  const configScope = opts.configStore.get().configScope ?? "global";
27541
28113
  const fsAccess = opts.configStore.get().tools?.restrictToProjectRoot === true ? "project" : "unrestricted";
@@ -27584,7 +28156,6 @@ function formatCurrentSettingsView(opts) {
27584
28156
  ` fleet chat: ${color55.cyan(resolveFleetChatVerbosity(au))} ${color55.dim("change: /settings stream-fleet off|full")}`,
27585
28157
  ` completion chime: ${au?.chime === true ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings chime on|off")}`,
27586
28158
  ` confirm before exit: ${au?.confirmExit !== false ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings confirm-exit on|off")}`,
27587
- ` launch hints: ${hints ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings hints on|off")}`,
27588
28159
  ` debug stream: ${debugStream ? color55.cyan("on") : color55.dim("off")} ${color55.dim("change: /settings debug-stream on|off")}`,
27589
28160
  ` config scope: ${color55.cyan(configScope)} ${color55.dim("change: /settings config-scope global|project")}`,
27590
28161
  ` filesystem access: ${color55.cyan(fsAccess)} ${color55.dim("change: /settings fs-access unrestricted|project")}`,
@@ -28079,67 +28650,68 @@ function buildDirectorCommand(opts) {
28079
28650
  }
28080
28651
 
28081
28652
  // src/slash-commands/statusline.ts
28082
- var ITEM_DESCRIPTIONS = {
28083
- state: "Agent run state / thinking spinner",
28084
- model: "Current provider/model id",
28085
- todos: "Todo items (pending/in-progress/done counts)",
28086
- plan: "Plan board items (open/in-progress/done)",
28087
- tasks: "Task board items (structured work with type/priority)",
28088
- fleet: "Fleet agent status (running/idle/pending/completed)",
28089
- fleet_agents: "Per-agent live detail row",
28090
- git: "Git branch name",
28091
- elapsed: "Session elapsed time",
28092
- context: "Context window usage (input tokens)",
28093
- tokens: "Input/output token counters",
28094
- cache: "Prompt cache hit ratio",
28095
- cost: "Token cost estimate (input/output/total)",
28096
- queue: "Queued prompt count",
28097
- hint: "Transient status hint text",
28098
- index: "Codebase indexing status",
28099
- breaker: "Process breaker countdown",
28100
- working_dir: "Current working directory",
28101
- project: "Project name",
28102
- yolo: "YOLO permission mode",
28103
- autonomy: "Autonomy mode",
28104
- eternal_stage: "Autonomy stage",
28105
- goal: "Active goal summary",
28106
- mode: "Active agent mode label",
28107
- auto_proceed: "Auto-proceed countdown",
28108
- sessions: "Live session count",
28109
- tools: "Registered tool count",
28110
- theme: "Active color theme preset",
28111
- token_saving: "Token-saving mode indicator",
28112
- side_effects: "Side-effect / audit event count",
28113
- processes: "Tracked bash/exec process count",
28114
- version: "WrongStack version + update notice (right-anchored)",
28115
- dropped_tools: "Tools dropped from the provider request (maxTools limit)",
28116
- prompt_variant: "System prompt variant (Lite / Standard / Pro)",
28117
- brain: "Brain arbiter decisions",
28118
- mailbox: "Mailbox unread messages and peers",
28119
- enhance: "Prompt-enhance countdown",
28120
- debug_stream: "Stream debug telemetry",
28121
- next_steps: "Next-step auto-submit countdown",
28122
- memory_context: "Memory context detail (total records + active-in-context)"
28123
- };
28653
+ import {
28654
+ CHIP_DESCRIPTIONS,
28655
+ clampLine as clampLine2,
28656
+ effectiveDensity,
28657
+ effectiveLine,
28658
+ LINE_TITLES,
28659
+ STATUSLINE_DENSITY_LEVELS as STATUSLINE_DENSITY_LEVELS2
28660
+ } from "@wrongstack/core/statusline";
28124
28661
  var ALL_CONFIG_KEYS = STATUSLINE_CONFIG_KEYS;
28662
+ function isConfigKey(value) {
28663
+ return value != null && ALL_CONFIG_KEYS.includes(value);
28664
+ }
28665
+ function isDensity(value) {
28666
+ return value === "auto" || value != null && STATUSLINE_DENSITY_LEVELS2.includes(value);
28667
+ }
28668
+ function renderLayout(cfg) {
28669
+ const out = [];
28670
+ for (const line of [1, 2, 3, 4]) {
28671
+ const items = ALL_CONFIG_KEYS.filter(
28672
+ (key) => effectiveLine(key, cfg.lines) === line && cfg.chips[key] !== false
28673
+ );
28674
+ out.push(`Line ${line} \u2014 ${LINE_TITLES[line]}`);
28675
+ out.push(
28676
+ items.length === 0 ? " (empty)" : ` ${items.map((key) => {
28677
+ const density = effectiveDensity(key, cfg.densities);
28678
+ return density === "auto" ? key : `${key}:${density}`;
28679
+ }).join(" ")}`
28680
+ );
28681
+ }
28682
+ const off = ALL_CONFIG_KEYS.filter((key) => cfg.chips[key] === false);
28683
+ if (off.length > 0) out.push(`Off \u2014 ${off.join(" ")}`);
28684
+ return out;
28685
+ }
28125
28686
  function buildStatuslineCommand(deps) {
28126
28687
  return {
28127
28688
  name: "statusline",
28128
28689
  category: "Config",
28129
28690
  aliases: ["sl"],
28130
- description: "Customize status bar chips: /statusline [item] [on|off|reset]",
28691
+ description: "Customize status bar chips: /statusline [item] [on|off|line N|density D]",
28131
28692
  help: [
28132
- "Usage: /statusline [item] [on|off|reset]",
28133
- " /statusline \u2014 show current config",
28134
- " /statusline <item> \u2014 toggle item on/off",
28135
- " /statusline <item> on \u2014 enable a chip",
28136
- " /statusline <item> off \u2014 disable a chip",
28137
- " /statusline all on \u2014 enable all chips",
28138
- " /statusline all off \u2014 disable all chips",
28139
- " /statusline reset \u2014 restore defaults",
28693
+ "Usage: /statusline \u2014 open the picker (TUI) or list the config",
28694
+ " /statusline preview \u2014 show the four lines as they are laid out",
28695
+ " /statusline <item> \u2014 toggle a chip on/off",
28696
+ " /statusline <item> on|off \u2014 enable/disable a chip",
28697
+ " /statusline <item> line <1-4> \u2014 move a chip to another line",
28698
+ " /statusline <item> density <d> \u2014 pin a chip to auto|full|short|micro",
28699
+ " /statusline all on|off \u2014 enable/disable every chip",
28700
+ " /statusline layout reset \u2014 restore default lines and densities",
28701
+ " /statusline reset \u2014 restore default chip visibility",
28702
+ "",
28703
+ "Lines are assigned by volatility:",
28704
+ " 1 IDENTITY fixed for the session",
28705
+ " 2 VITALS redraws every token",
28706
+ " 3 SAFETY & WORK posture + work in flight",
28707
+ " 4 ASYNC background activity & countdowns",
28708
+ "",
28709
+ "Density controls how much of a chip renders. With `auto` the rail",
28710
+ "shortens the widest chip first and only drops a chip once every chip",
28711
+ "on that line is already at `micro`.",
28140
28712
  "",
28141
28713
  "Available items:",
28142
- ...ALL_CONFIG_KEYS.map((k) => ` ${k.padEnd(12)} ${ITEM_DESCRIPTIONS[k]}`),
28714
+ ...ALL_CONFIG_KEYS.map((k) => ` ${k.padEnd(16)} ${CHIP_DESCRIPTIONS[k]}`),
28143
28715
  "",
28144
28716
  "Density mode (minimum/detailed/no-color) is a separate setting \u2014 see /settings.",
28145
28717
  "These toggles set chip eligibility in any mode; some chips only render in detailed mode.",
@@ -28149,8 +28721,8 @@ function buildStatuslineCommand(deps) {
28149
28721
  async run(args) {
28150
28722
  const cfg = await deps.getConfig();
28151
28723
  const trimmed = args.trim();
28152
- const parts = trimmed.split(/\s+/);
28153
- const [item, action] = parts;
28724
+ const parts = trimmed.split(/\s+/).filter(Boolean);
28725
+ const [item, action, value] = parts;
28154
28726
  if (!item && deps.onPanelOpen?.current) {
28155
28727
  const opened = deps.onPanelOpen.current("statuslineOpen");
28156
28728
  if (opened) return { message: "Opened statusline picker." };
@@ -28160,14 +28732,26 @@ function buildStatuslineCommand(deps) {
28160
28732
  for (const k of ALL_CONFIG_KEYS) {
28161
28733
  const val = cfg.chips[k];
28162
28734
  if (val === void 0) continue;
28163
- lines.push(` ${val ? "\u25CF" : "\u25CB"} ${k.padEnd(12)} ${ITEM_DESCRIPTIONS[k]}`);
28735
+ const line = effectiveLine(k, cfg.lines);
28736
+ const density = effectiveDensity(k, cfg.densities);
28737
+ lines.push(
28738
+ ` ${val ? "\u25CF" : "\u25CB"} ${k.padEnd(16)} L${line} ${density === "auto" ? " " : density.padEnd(5)} ${CHIP_DESCRIPTIONS[k]}`
28739
+ );
28164
28740
  }
28165
28741
  return { message: lines.join("\n") };
28166
28742
  }
28743
+ if (item === "preview") {
28744
+ return { message: ["StatusBar layout:", ...renderLayout(cfg)].join("\n") };
28745
+ }
28167
28746
  if (item === "reset") {
28168
28747
  await deps.setConfig({ ...cfg, chips: { ...DEFAULTS } });
28169
- deps.setHiddenItems([]);
28170
- return { message: "StatusBar config reset to defaults." };
28748
+ deps.setHiddenItems(ALL_CONFIG_KEYS.filter((k) => DEFAULTS[k] === false));
28749
+ return { message: "StatusBar chip visibility reset to defaults." };
28750
+ }
28751
+ if (item === "layout") {
28752
+ if (action !== "reset") return { message: "Usage: /statusline layout reset" };
28753
+ await deps.setConfig({ ...cfg, lines: {}, densities: {} });
28754
+ return { message: "StatusBar layout reset: default lines and densities restored." };
28171
28755
  }
28172
28756
  if (item === "all") {
28173
28757
  const onOff2 = action?.toLowerCase();
@@ -28184,13 +28768,31 @@ function buildStatuslineCommand(deps) {
28184
28768
  message: `statusline all: ${onOff2 === "on" ? "showing all chips" : "hiding all chips"}`
28185
28769
  };
28186
28770
  }
28187
- const validItems = ALL_CONFIG_KEYS;
28188
- if (!validItems.includes(item)) {
28771
+ if (!isConfigKey(item)) {
28189
28772
  return {
28190
28773
  message: `Unknown item "${item}". Run /statusline to see available items.`
28191
28774
  };
28192
28775
  }
28193
28776
  const onOff = action?.toLowerCase();
28777
+ if (onOff === "line") {
28778
+ const parsed = Number(value);
28779
+ if (!Number.isInteger(parsed) || parsed < 1 || parsed > 4) {
28780
+ return { message: `Usage: /statusline ${item} line 1|2|3|4` };
28781
+ }
28782
+ const line = clampLine2(parsed);
28783
+ await deps.setConfig({ ...cfg, lines: { ...cfg.lines, [item]: line } });
28784
+ return { message: `statusline ${item}: line ${line} (${LINE_TITLES[line]})` };
28785
+ }
28786
+ if (onOff === "density") {
28787
+ if (!isDensity(value)) {
28788
+ return { message: `Usage: /statusline ${item} density auto|full|short|micro` };
28789
+ }
28790
+ const densities = { ...cfg.densities };
28791
+ if (value === "auto") delete densities[item];
28792
+ else densities[item] = value;
28793
+ await deps.setConfig({ ...cfg, densities });
28794
+ return { message: `statusline ${item}: density ${value}` };
28795
+ }
28194
28796
  if (!onOff) {
28195
28797
  const currentValue = cfg.chips[item] ?? true;
28196
28798
  const newValue = !currentValue;
@@ -28203,7 +28805,7 @@ function buildStatuslineCommand(deps) {
28203
28805
  return { message: `statusline ${item}: ${newValue ? "on" : "off"}` };
28204
28806
  }
28205
28807
  if (onOff !== "on" && onOff !== "off") {
28206
- return { message: `Usage: /statusline ${item} on|off` };
28808
+ return { message: `Usage: /statusline ${item} on|off|line <1-4>|density <level>` };
28207
28809
  }
28208
28810
  await deps.setConfig({ ...cfg, chips: { ...cfg.chips, [item]: onOff === "on" } });
28209
28811
  if (onOff === "off") {
@@ -29936,7 +30538,7 @@ function buildToolCommand(opts) {
29936
30538
  );
29937
30539
  }
29938
30540
  async function runAutoThinDryRun() {
29939
- const { runBootAutoThin } = await import("./boot-auto-thin-BZ675EVT.js");
30541
+ const { runBootAutoThin } = await import("./boot-auto-thin-MANHOYHE.js");
29940
30542
  const cfg = getAutoThin();
29941
30543
  const result = await runBootAutoThin({
29942
30544
  toolRegistry: opts.toolRegistry,
@@ -30000,7 +30602,7 @@ function buildToolCommand(opts) {
30000
30602
  if (!cfg.enabled) {
30001
30603
  return `${color63.amber("Auto-thinning is off")}. Run ${color63.cyan("/settings autothin on")} first.`;
30002
30604
  }
30003
- const { runBootAutoThin } = await import("./boot-auto-thin-BZ675EVT.js");
30605
+ const { runBootAutoThin } = await import("./boot-auto-thin-MANHOYHE.js");
30004
30606
  const result = await runBootAutoThin({
30005
30607
  toolRegistry: opts.toolRegistry,
30006
30608
  events: opts.events,
@@ -31517,6 +32119,7 @@ function setupCliSlashCommands(params) {
31517
32119
  brainSettings,
31518
32120
  brainRuntime,
31519
32121
  initialBrainLog,
32122
+ brainTierStats,
31520
32123
  coordinatorController,
31521
32124
  statusTracker,
31522
32125
  shadowController,
@@ -31603,6 +32206,7 @@ function setupCliSlashCommands(params) {
31603
32206
  brainSettings,
31604
32207
  brainRuntime,
31605
32208
  getBrainLog: () => initialBrainLog,
32209
+ brainTierStats,
31606
32210
  ...coordinatorController ? { coordinatorController } : {},
31607
32211
  statusTracker,
31608
32212
  shadowController,
@@ -31696,7 +32300,8 @@ function setupCliSlashCommands(params) {
31696
32300
  // src/wiring/command-host-state.ts
31697
32301
  import {
31698
32302
  areSubagentsAllowedForSession as areSubagentsAllowedForSession4,
31699
- FLEET_ROSTER as FLEET_ROSTER5
32303
+ FLEET_ROSTER as FLEET_ROSTER5,
32304
+ mailboxSessionTag as mailboxSessionTag6
31700
32305
  } from "@wrongstack/core/coordination";
31701
32306
  import {
31702
32307
  AgentError as AgentError3,
@@ -31759,8 +32364,7 @@ async function loadStatuslineHiddenItems() {
31759
32364
  for (const k of STATUSLINE_CONFIG_KEYS) {
31760
32365
  chips[k] = !items.includes(k);
31761
32366
  }
31762
- const doc2 = await ensureStatuslineConfig();
31763
- await saveStatuslineConfig({ ...doc2, chips });
32367
+ await saveStatuslineChips(chips);
31764
32368
  };
31765
32369
  return { hiddenItems: hiddenItemsList, setHiddenItems, saveHiddenItems };
31766
32370
  }
@@ -31772,15 +32376,12 @@ async function setupCommandHostState(input) {
31772
32376
  );
31773
32377
  const interruptController = createInterruptController();
31774
32378
  input.hqCommandController.interruptLeader = () => interruptController.abortLeader();
32379
+ const liveSessionId = () => input.sessionRef.current?.id ?? input.session.id;
32380
+ input.hqCommandController.sessionId = liveSessionId;
32381
+ input.hqCommandController.sessionTag = () => mailboxSessionTag6(liveSessionId());
31775
32382
  input.hqCommandController.killFleet = () => killFleet2(input.getDirector());
31776
32383
  input.hqCommandController.terminateAgent = (subagentId) => terminateAgent(input.getDirector(), subagentId);
31777
- input.hqCommandController.spawnAgent = (role, task, maxIterations) => spawnAgent2(
31778
- input.getDirector(),
31779
- input.sessionRef.current?.id ?? input.session.id,
31780
- role,
31781
- task,
31782
- maxIterations
31783
- );
32384
+ input.hqCommandController.spawnAgent = (role, task, maxIterations) => spawnAgent2(input.getDirector(), liveSessionId(), role, task, maxIterations);
31784
32385
  const enhanceController = createEnhanceController(input.getConfig());
31785
32386
  const statuslineConfigDeps = createStatuslineConfigDeps();
31786
32387
  const hidden = await loadStatuslineHiddenItems();
@@ -31799,7 +32400,16 @@ async function setupCommandHostState(input) {
31799
32400
  };
31800
32401
  const saveStatuslineLines2 = async (next) => {
31801
32402
  currentLines = { ...next };
31802
- await saveStatuslineLines(next);
32403
+ await saveStatuslineLayout({ lines: next });
32404
+ };
32405
+ const statuslineDensities = await loadStatuslineDensities();
32406
+ let currentDensities = { ...statuslineDensities };
32407
+ const setStatuslineDensities = (next) => {
32408
+ currentDensities = { ...next };
32409
+ };
32410
+ const saveStatuslineDensities = async (next) => {
32411
+ currentDensities = { ...next };
32412
+ await saveStatuslineLayout({ densities: next });
31803
32413
  };
31804
32414
  const agentsMonitorController = createAgentsMonitorController();
31805
32415
  const onPanelOpen = { current: null };
@@ -31849,6 +32459,10 @@ async function setupCommandHostState(input) {
31849
32459
  getCurrentStatuslineLines: () => currentLines,
31850
32460
  setStatuslineLines,
31851
32461
  saveStatuslineLines: saveStatuslineLines2,
32462
+ statuslineDensities: { ...statuslineDensities },
32463
+ getCurrentStatuslineDensities: () => currentDensities,
32464
+ setStatuslineDensities,
32465
+ saveStatuslineDensities,
31852
32466
  agentsMonitorController,
31853
32467
  onPanelOpen,
31854
32468
  goalHost,
@@ -31895,7 +32509,7 @@ async function spawnAgent2(director, sessionId, role, task, maxIterations) {
31895
32509
  const base = FLEET_ROSTER5[role] ?? {
31896
32510
  id: `manual-${Date.now()}`,
31897
32511
  name: role,
31898
- maxIterations: maxIterations ?? 50,
32512
+ maxIterations: maxIterations ?? 0,
31899
32513
  maxToolCalls: 200
31900
32514
  };
31901
32515
  const config = task !== void 0 ? { ...base, task } : base;
@@ -32396,7 +33010,7 @@ function setupHqTelemetry(deps) {
32396
33010
  agentMonitor,
32397
33011
  brainMailbox,
32398
33012
  teardownHandlers,
32399
- mailboxSessionTag: mailboxSessionTag7,
33013
+ mailboxSessionTag: mailboxSessionTag8,
32400
33014
  hqPublisherRef,
32401
33015
  mcpRegistry
32402
33016
  } = deps;
@@ -32405,7 +33019,11 @@ function setupHqTelemetry(deps) {
32405
33019
  const hqCommandController = {
32406
33020
  steerMailbox: brainMailbox,
32407
33021
  interruptLeader: () => false,
32408
- sessionTag: () => mailboxSessionTag7(session.id),
33022
+ sessionTag: () => mailboxSessionTag8(session.id),
33023
+ // Boot-session seed. `setupCommandHostState` rebinds both to the LIVE
33024
+ // writer ref, because an in-process resume / session.new swaps
33025
+ // `ctx.session` for a new writer object and this captured one goes stale.
33026
+ sessionId: () => session.id,
32409
33027
  allowRunCommand: () => flags["hq-allow-exec"] === true
32410
33028
  };
32411
33029
  const hqOnCommand = createHqCommandDispatcher(hqCommandController);
@@ -32569,7 +33187,7 @@ import { NotifierImpl } from "@wrongstack/core/notifications";
32569
33187
  import {
32570
33188
  SlashCommandRegistry
32571
33189
  } from "@wrongstack/core/registry";
32572
- import { normalizeTokenSavingTier as normalizeTokenSavingTier3 } from "@wrongstack/core/types";
33190
+ import { normalizeTokenSavingTier as normalizeTokenSavingTier4 } from "@wrongstack/core/types";
32573
33191
  import {
32574
33192
  CONTEXT_WINDOW_MODE_PINNED_META_KEY as CONTEXT_WINDOW_MODE_PINNED_META_KEY2,
32575
33193
  resolveContextWindowPolicy as resolveContextWindowPolicy3
@@ -33620,7 +34238,7 @@ async function setupLifecycleAndPlugins(deps) {
33620
34238
  toolRegistry,
33621
34239
  events,
33622
34240
  log: logger,
33623
- lazyMode: normalizeTokenSavingTier3(config.features.tokenSavingMode) !== "off",
34241
+ lazyMode: normalizeTokenSavingTier4(config.features.tokenSavingMode) !== "off",
33624
34242
  cacheDir: wpaths.cacheDir,
33625
34243
  authorizationProviderFactory: createVaultBackedMcpAuthorizationProviderFactory({
33626
34244
  store: mcpTokenStore
@@ -34105,7 +34723,10 @@ function setupProviderRuntime(deps) {
34105
34723
  "uiLocale"
34106
34724
  ];
34107
34725
  const activeProfileOf = (c) => typeof c.activeProfile === "string" && c.activeProfile ? c.activeProfile : "default";
34108
- if (process.env["WRONGSTACK_DISABLE_CONFIG_WATCH"] !== "1") {
34726
+ let reloadProviderConfig = async () => {
34727
+ };
34728
+ const configWatchEnabled = process.env["WRONGSTACK_DISABLE_CONFIG_WATCH"] !== "1";
34729
+ {
34109
34730
  let activeProfile = activeProfileOf(cfg);
34110
34731
  let configLayers = [];
34111
34732
  const rebuildLayers = () => {
@@ -34196,6 +34817,7 @@ function setupProviderRuntime(deps) {
34196
34817
  );
34197
34818
  }
34198
34819
  };
34820
+ reloadProviderConfig = onAnyConfigChange;
34199
34821
  let watchers = [];
34200
34822
  const openWatchers = () => {
34201
34823
  watchers = configLayers.map(
@@ -34213,20 +34835,22 @@ function setupProviderRuntime(deps) {
34213
34835
  for (const w of watchers) w.close();
34214
34836
  watchers = [];
34215
34837
  };
34216
- openWatchers();
34217
- teardownHandlers.push(
34218
- configStore.watch((next) => {
34219
- const nextProfile = activeProfileOf(next);
34220
- if (nextProfile === activeProfile) return;
34221
- activeProfile = nextProfile;
34222
- closeWatchers();
34223
- rebuildLayers();
34224
- openWatchers();
34225
- previousSnapshotSerialized = void 0;
34226
- void onAnyConfigChange();
34227
- })
34228
- );
34229
- teardownHandlers.push(closeWatchers);
34838
+ if (configWatchEnabled) {
34839
+ openWatchers();
34840
+ teardownHandlers.push(
34841
+ configStore.watch((next) => {
34842
+ const nextProfile = activeProfileOf(next);
34843
+ if (nextProfile === activeProfile) return;
34844
+ activeProfile = nextProfile;
34845
+ closeWatchers();
34846
+ rebuildLayers();
34847
+ openWatchers();
34848
+ previousSnapshotSerialized = void 0;
34849
+ void onAnyConfigChange();
34850
+ })
34851
+ );
34852
+ teardownHandlers.push(closeWatchers);
34853
+ }
34230
34854
  }
34231
34855
  return {
34232
34856
  resolveProviderCfg: resolveProviderCfg2,
@@ -34234,7 +34858,8 @@ function setupProviderRuntime(deps) {
34234
34858
  buildProviderForModel,
34235
34859
  refreshMaxContextFor,
34236
34860
  refreshRuntimeModelStateFor,
34237
- switchProviderAndModel
34861
+ switchProviderAndModel,
34862
+ reloadProviderConfig
34238
34863
  };
34239
34864
  }
34240
34865
 
@@ -34455,7 +35080,7 @@ async function setupReplayAndGovernance({
34455
35080
  const replayFlag = flags["replay"];
34456
35081
  const recordFlag = flags["record"];
34457
35082
  if (typeof replayFlag === "string" || recordFlag === true) {
34458
- const { bindReplayToContainer } = await import("./replay-FJ2JBXUA.js");
35083
+ const { bindReplayToContainer } = await import("./replay-Z3FTJEMM.js");
34459
35084
  const mode = recordFlag === true ? "record" : "replay";
34460
35085
  bindReplayToContainer({
34461
35086
  container,
@@ -34643,7 +35268,7 @@ async function prepareRuntimeDispatch(input) {
34643
35268
  // src/wiring/session-establishment.ts
34644
35269
  import * as path31 from "node:path";
34645
35270
  import { TOKENS as TOKENS12 } from "@wrongstack/core/kernel";
34646
- import { getSessionRegistry as getSessionRegistry2 } from "@wrongstack/core/storage";
35271
+ import { getSessionRegistry as getSessionRegistry3 } from "@wrongstack/core/storage";
34647
35272
  import { addFatalSalvageHook } from "@wrongstack/core/utils";
34648
35273
 
34649
35274
  // src/wiring/session.ts
@@ -34680,7 +35305,7 @@ import {
34680
35305
  } from "@wrongstack/tools/session-kanban";
34681
35306
 
34682
35307
  // src/wiring/resume-candidate.ts
34683
- import { getSessionRegistry, SessionRecovery as SessionRecovery2 } from "@wrongstack/core/storage";
35308
+ import { getSessionRegistry as getSessionRegistry2, SessionRecovery as SessionRecovery2 } from "@wrongstack/core/storage";
34684
35309
  var MAX_CANDIDATES = 20;
34685
35310
  async function pickResumeCandidate(options) {
34686
35311
  const live = await liveSessionIds(options.globalRoot);
@@ -34701,7 +35326,7 @@ async function recentCandidates(sessionStore) {
34701
35326
  }
34702
35327
  async function liveSessionIds(globalRoot) {
34703
35328
  try {
34704
- const registry = getSessionRegistry(globalRoot);
35329
+ const registry = getSessionRegistry2(globalRoot);
34705
35330
  const entries = await registry.list();
34706
35331
  return new Set(entries.map((entry) => entry.sessionId));
34707
35332
  } catch {
@@ -35021,7 +35646,7 @@ async function setupSessionEstablishment(args) {
35021
35646
  const sessionStore = container.resolve(TOKENS12.SessionStore);
35022
35647
  const tokenCounter = container.resolve(TOKENS12.TokenCounter);
35023
35648
  tokenCounter.setSessionId?.(() => sessionRef.current?.id);
35024
- const sessionRegistry = getSessionRegistry2(wpaths.globalRoot);
35649
+ const sessionRegistry = getSessionRegistry3(wpaths.globalRoot);
35025
35650
  const sessResult = await setupSession({
35026
35651
  config: { model: config.model, provider: config.provider },
35027
35652
  wpaths,
@@ -35111,11 +35736,11 @@ async function setupSessionRegistry(deps) {
35111
35736
  };
35112
35737
  let ownershipEstablished = false;
35113
35738
  try {
35114
- const [{ getSessionRegistry: getSessionRegistry3 }, { AgentStatusTracker, FleetNotifier }] = await Promise.all([
35739
+ const [{ getSessionRegistry: getSessionRegistry4 }, { AgentStatusTracker, FleetNotifier }] = await Promise.all([
35115
35740
  import("@wrongstack/core/storage"),
35116
35741
  import("@wrongstack/core/coordination")
35117
35742
  ]);
35118
- const registry = getSessionRegistry3(wpaths.globalRoot);
35743
+ const registry = getSessionRegistry4(wpaths.globalRoot);
35119
35744
  const projectSlug = path32.basename(wpaths.projectDir);
35120
35745
  const projectName = path32.basename(projectRoot);
35121
35746
  let gitBranch = await new Promise((resolve8) => {
@@ -35208,7 +35833,9 @@ async function setupSessionRegistry(deps) {
35208
35833
  // src/session-event-wiring.ts
35209
35834
  import {
35210
35835
  createChronicleContext,
35836
+ createChronicleCounterSink,
35211
35837
  createChronicleEventJournal,
35838
+ resolveChronicleDetail,
35212
35839
  startChronicleFileObserver,
35213
35840
  startChronicleHealthMonitor,
35214
35841
  wireDecisionsToChronicle,
@@ -35232,6 +35859,10 @@ function resolveChronicleRetentionDays(config) {
35232
35859
  if (raw <= 0) return 0;
35233
35860
  return Math.max(MIN_CHRONICLE_RETENTION_DAYS, raw);
35234
35861
  }
35862
+ function chronicleLimit(config, key) {
35863
+ const raw = config.chronicle?.[key];
35864
+ return typeof raw === "number" && Number.isFinite(raw) && raw > 0 ? raw : void 0;
35865
+ }
35235
35866
  function tryCreateChronicleJournal(options) {
35236
35867
  try {
35237
35868
  return createChronicleEventJournal(options);
@@ -35273,11 +35904,18 @@ function wireSessionEvents(deps) {
35273
35904
  let chronicleFileObserver;
35274
35905
  let stopChronicleHealth;
35275
35906
  let stopNetworkTelemetry;
35907
+ let disposeCounterSink;
35276
35908
  if (deps.events && wpaths.projectDir) {
35277
35909
  const retentionDays = resolveChronicleRetentionDays(config);
35278
35910
  chronicleHandle = tryCreateChronicleJournal({
35279
35911
  projectRoot,
35280
35912
  retentionDays,
35913
+ // Undefined means "whatever the daemon already runs with": these only
35914
+ // take effect for the client that wins the spawn race, so passing an
35915
+ // explicit fallback here would imply a control this layer does not have.
35916
+ maxEvents: chronicleLimit(config, "maxEvents"),
35917
+ maxBytes: chronicleLimit(config, "maxBytes"),
35918
+ metricsRowRetentionDays: chronicleLimit(config, "metricsRowRetentionDays"),
35281
35919
  projectPaths: {
35282
35920
  globalRoot: wpaths.globalRoot,
35283
35921
  projectId: wpaths.projectHash ?? wpaths.projectSlug,
@@ -35287,7 +35925,12 @@ function wireSessionEvents(deps) {
35287
35925
  });
35288
35926
  }
35289
35927
  if (chronicleHandle && deps.events) {
35290
- chronicleJournal = chronicleHandle.journal;
35928
+ const counterSink = createChronicleCounterSink({
35929
+ inner: chronicleHandle.journal,
35930
+ level: resolveChronicleDetail(config)
35931
+ });
35932
+ chronicleJournal = counterSink;
35933
+ disposeCounterSink = () => counterSink.dispose();
35291
35934
  const location = chronicleHandle.identity;
35292
35935
  const chronicleContext = createChronicleContext(
35293
35936
  {
@@ -35613,6 +36256,7 @@ function wireSessionEvents(deps) {
35613
36256
  stopChronicleHealth?.();
35614
36257
  stopNetworkTelemetry?.();
35615
36258
  unsubscribeChronicle?.();
36259
+ await disposeCounterSink?.();
35616
36260
  if (chronicleFileObserver) {
35617
36261
  try {
35618
36262
  await (await chronicleFileObserver).close();
@@ -35899,12 +36543,17 @@ import * as path33 from "node:path";
35899
36543
  import {
35900
36544
  startFirstBootSageSync,
35901
36545
  subscribeVectorMemoryToSage,
36546
+ sweepStaleSageMirrors,
35902
36547
  TransformersEmbeddingProvider,
35903
36548
  VectorMemoryStore,
35904
36549
  wrapMemoryPortWithVectorRecall
35905
36550
  } from "@wrongstack/vector-memory";
36551
+ var DEFAULT_VECTOR_WEIGHT = 0.3;
35906
36552
  async function setupVectorMemory(args) {
35907
- const { projectRoot, flags, logger, memoryStore, teardownHandlers } = args;
36553
+ const { projectRoot, flags, logger, memoryStore, teardownHandlers, tuning } = args;
36554
+ if (tuning?.enabled === false) {
36555
+ return { memoryStore, vectorMemoryStore: void 0, vectorMemoryModelCacheDir: "" };
36556
+ }
35908
36557
  let vectorMemoryStore;
35909
36558
  const vectorMemoryModelCacheDir = path33.join(
35910
36559
  projectRoot,
@@ -35935,7 +36584,10 @@ async function setupVectorMemory(args) {
35935
36584
  });
35936
36585
  wrapped = wrapMemoryPortWithVectorRecall(wrapped, {
35937
36586
  store: vectorMemoryStore,
35938
- weight: 0.3
36587
+ weight: tuning?.weight ?? DEFAULT_VECTOR_WEIGHT,
36588
+ ...tuning?.threshold !== void 0 ? { threshold: tuning.threshold } : {},
36589
+ ...tuning?.vectorOnlyThreshold !== void 0 ? { vectorOnlyThreshold: tuning.vectorOnlyThreshold } : {},
36590
+ ...tuning?.maxMaterializations !== void 0 ? { maxMaterializations: tuning.maxMaterializations } : {}
35939
36591
  });
35940
36592
  const mirrorHandle = subscribeVectorMemoryToSage({
35941
36593
  store: vectorMemoryStore,
@@ -35943,6 +36595,11 @@ async function setupVectorMemory(args) {
35943
36595
  logger
35944
36596
  });
35945
36597
  teardownHandlers.push(() => mirrorHandle.dispose());
36598
+ void sweepStaleSageMirrors({
36599
+ store: vectorMemoryStore,
36600
+ memoryStore: wrapped,
36601
+ logger
36602
+ });
35946
36603
  if (flags["vector-sync"] === true) {
35947
36604
  const forced = await startFirstBootSageSync({
35948
36605
  store: vectorMemoryStore,
@@ -36011,7 +36668,8 @@ async function runInteractive(cliCtx) {
36011
36668
  flags,
36012
36669
  logger,
36013
36670
  memoryStore,
36014
- teardownHandlers
36671
+ teardownHandlers,
36672
+ tuning: config.Sage?.vector
36015
36673
  });
36016
36674
  memoryStore = vectorWrappedMemoryStore;
36017
36675
  const skillLoader = container.resolve(TOKENS13.SkillLoader);
@@ -36227,7 +36885,12 @@ async function runInteractive(cliCtx) {
36227
36885
  container.override(TOKENS13.ProviderModelStatusTracker, () => statusTracker);
36228
36886
  bootstrapWrongProxy(config.tools?.wrongProxy);
36229
36887
  await awaitFirstWrongProxyProbe();
36230
- const { buildProviderForId: buildProviderForId2, buildProviderForModel, switchProviderAndModel } = setupProviderRuntime({
36888
+ const {
36889
+ buildProviderForId: buildProviderForId2,
36890
+ buildProviderForModel,
36891
+ switchProviderAndModel,
36892
+ reloadProviderConfig
36893
+ } = setupProviderRuntime({
36231
36894
  config,
36232
36895
  onConfigUpdate: (newConfig) => {
36233
36896
  config = newConfig;
@@ -36300,7 +36963,15 @@ async function runInteractive(cliCtx) {
36300
36963
  events,
36301
36964
  autonomyModeRef
36302
36965
  });
36303
- const { brain, brainLog, brainSettings, brainRuntime, multiAgentHost, shadowController } = setupBrainAndOrchestration({
36966
+ const {
36967
+ brain,
36968
+ brainLog,
36969
+ brainTierStats,
36970
+ brainSettings,
36971
+ brainRuntime,
36972
+ multiAgentHost,
36973
+ shadowController
36974
+ } = setupBrainAndOrchestration({
36304
36975
  events,
36305
36976
  config,
36306
36977
  vault,
@@ -36319,7 +36990,7 @@ async function runInteractive(cliCtx) {
36319
36990
  cwd,
36320
36991
  wpaths,
36321
36992
  teardownHandlers,
36322
- mailboxSessionTag: mailboxSessionTag6,
36993
+ mailboxSessionTag: mailboxSessionTag7,
36323
36994
  brainMailbox,
36324
36995
  agentMonitor,
36325
36996
  manifestPath,
@@ -36350,7 +37021,7 @@ async function runInteractive(cliCtx) {
36350
37021
  agentMonitor,
36351
37022
  brainMailbox,
36352
37023
  teardownHandlers,
36353
- mailboxSessionTag: mailboxSessionTag6,
37024
+ mailboxSessionTag: mailboxSessionTag7,
36354
37025
  hqPublisherRef,
36355
37026
  mcpRegistry
36356
37027
  });
@@ -36388,6 +37059,9 @@ async function runInteractive(cliCtx) {
36388
37059
  statuslineLines,
36389
37060
  setStatuslineLines,
36390
37061
  saveStatuslineLines: saveStatuslineLines2,
37062
+ statuslineDensities,
37063
+ setStatuslineDensities,
37064
+ saveStatuslineDensities,
36391
37065
  agentsMonitorController,
36392
37066
  onPanelOpen,
36393
37067
  goalHost,
@@ -36456,6 +37130,7 @@ async function runInteractive(cliCtx) {
36456
37130
  brainSettings,
36457
37131
  brainRuntime,
36458
37132
  initialBrainLog: brainLog,
37133
+ brainTierStats,
36459
37134
  coordinatorController,
36460
37135
  statusTracker,
36461
37136
  shadowController,
@@ -36600,6 +37275,7 @@ async function runInteractive(cliCtx) {
36600
37275
  resolvedProvider,
36601
37276
  logger,
36602
37277
  switchProviderAndModel,
37278
+ reloadProviderConfig,
36603
37279
  applyMaxContext,
36604
37280
  renderer,
36605
37281
  reader,
@@ -36627,6 +37303,9 @@ async function runInteractive(cliCtx) {
36627
37303
  statuslineLines,
36628
37304
  setStatuslineLines,
36629
37305
  saveStatuslineLines: saveStatuslineLines2,
37306
+ statuslineDensities,
37307
+ setStatuslineDensities,
37308
+ saveStatuslineDensities,
36630
37309
  setYoloMode,
36631
37310
  autonomyMode,
36632
37311
  setAutonomyMode: (mode) => {
@@ -36668,4 +37347,4 @@ export {
36668
37347
  CLI_VERSION,
36669
37348
  runInteractive
36670
37349
  };
36671
- //# sourceMappingURL=cli-main-QXSKKANW.js.map
37350
+ //# sourceMappingURL=cli-main-53KG6HAV.js.map