@wrongstack/cli 0.300.0 → 0.302.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/{acp-IDNS2YVE.js → acp-DATHHPNT.js} +34 -15
  2. package/dist/acp-server-agent.d.ts +1 -1
  3. package/dist/{audit-2ZSFGNIF.js → audit-QRCLEHHW.js} +5 -1
  4. package/dist/{auth-6T6ZOT2R.js → auth-PJD3JRH2.js} +150 -37
  5. package/dist/boot/dispatch-webui.d.ts +3 -16
  6. package/dist/boot/launch-menu.d.ts +2 -4
  7. package/dist/boot/tool-registry.d.ts +3 -0
  8. package/dist/boot/webui-session-child.d.ts +91 -0
  9. package/dist/chimera-reviewer-policy.d.ts +10 -3
  10. package/dist/chimera-work-registry.d.ts +19 -0
  11. package/dist/{chronicle-QQEQFSSE.js → chronicle-63MFCZN6.js} +26 -5
  12. package/dist/{chunk-YWUPHRGB.js → chunk-263G3FMB.js} +33 -10
  13. package/dist/{chunk-GYDQABMA.js → chunk-2KDOFTTM.js} +44 -32
  14. package/dist/{chunk-V76R7DC5.js → chunk-3MOUBRKZ.js} +311 -309
  15. package/dist/chunk-CSAPOCBP.js +24 -0
  16. package/dist/{chunk-N7ULWBO5.js → chunk-ETOEGL3V.js} +3 -7
  17. package/dist/{chunk-3MWUZMOL.js → chunk-GUHQQG63.js} +14 -3
  18. package/dist/chunk-KE7E7DPX.js +38 -0
  19. package/dist/{chunk-PEMN4T5O.js → chunk-MT6FGXO3.js} +23 -4
  20. package/dist/chunk-PFVVUH5B.js +127 -0
  21. package/dist/{chunk-DPJZQCVP.js → chunk-YMXXOOFN.js} +1 -1
  22. package/dist/{chunk-4WJKVQJY.js → chunk-ZECLGUTF.js} +15 -3
  23. package/dist/cli-context.d.ts +2 -0
  24. package/dist/{cli-main-7B3G2YSG.js → cli-main-EOJ74CI4.js} +336 -99
  25. package/dist/execute-deps.d.ts +3 -0
  26. package/dist/{execution-SHGM7BVC.js → execution-CQ772VPS.js} +246 -97
  27. package/dist/execution-chimera-cascade.d.ts +3 -4
  28. package/dist/execution-chimera-review.d.ts +2 -3
  29. package/dist/execution-cleanup.d.ts +3 -2
  30. package/dist/execution.d.ts +1 -1
  31. package/dist/{export-TPORYVRZ.js → export-DOBGPY23.js} +12 -1
  32. package/dist/fleet/host-context.d.ts +1 -1
  33. package/dist/fleet/host-helpers.d.ts +14 -0
  34. package/dist/fleet/status-broadcast.d.ts +1 -1
  35. package/dist/{hq-DVDD4XPV.js → hq-LN5CJHCM.js} +2 -2
  36. package/dist/hq-server/routes.d.ts +10 -1
  37. package/dist/hq-server/ws.d.ts +17 -6
  38. package/dist/{hq-server-DQHLNHDL.js → hq-server-S7HZG3PA.js} +3 -2
  39. package/dist/index.js +142 -100
  40. package/dist/live-settings-input.d.ts +5 -0
  41. package/dist/{mcp-CYLPUEHC.js → mcp-OHPJH73U.js} +6 -2
  42. package/dist/{modeldiag-YOQZHBQV.js → modeldiag-3DOK4BWW.js} +2 -2
  43. package/dist/{plugin-usage-EOG4ET4S.js → plugin-usage-YEVLOR33.js} +7 -3
  44. package/dist/{plugins-56CMWMPR.js → plugins-K3BAUP4D.js} +3 -3
  45. package/dist/profile-config-path.d.ts +0 -2
  46. package/dist/provider-helpers.d.ts +0 -5
  47. package/dist/{providers-models-K6RT7ABI.js → providers-models-WEZ4EGLL.js} +6 -5
  48. package/dist/{replay-KCTXNMZQ.js → replay-FCBNHW3K.js} +5 -1
  49. package/dist/{rewind-EJMVFVLS.js → rewind-AOD3JIYX.js} +5 -1
  50. package/dist/{sessions-config-NLCMK3BY.js → sessions-config-XXN7267N.js} +8 -3
  51. package/dist/subcommands/flags.d.ts +23 -0
  52. package/dist/terminal-format.d.ts +15 -0
  53. package/dist/{webui-server-G3EKFXLL.js → webui-server-NFNRGNNT.js} +54 -29
  54. package/dist/webui-server-options.d.ts +7 -0
  55. package/dist/wiring/brain-and-orchestration.d.ts +1 -1
  56. package/dist/wiring/mailbox-bridge-bootstrap.d.ts +3 -1
  57. package/dist/wiring/management-tools.d.ts +9 -1
  58. package/dist/wiring/pipeline.d.ts +5 -5
  59. package/dist/wiring/plugins.d.ts +2 -3
  60. package/dist/wiring/provider-utility-tools.d.ts +1 -0
  61. package/dist/wiring/tools.d.ts +4 -5
  62. package/package.json +23 -23
@@ -25,22 +25,34 @@ import {
25
25
  trySaveSpecFromAIOutput,
26
26
  trySaveTasksFromAIOutput
27
27
  } from "./chunk-XTIXVJXP.js";
28
+ import {
29
+ WEBUI_SESSION_CHILD_CAPABILITIES,
30
+ writeWebuiSessionChildError,
31
+ writeWebuiSessionChildReady
32
+ } from "./chunk-PFVVUH5B.js";
28
33
  import {
29
34
  theme
30
35
  } from "./chunk-QD544J2B.js";
31
36
  import {
32
37
  fmtTok
33
38
  } from "./chunk-TYO2OVAD.js";
39
+ import {
40
+ terminalLink,
41
+ terminalText
42
+ } from "./chunk-KE7E7DPX.js";
34
43
  import {
35
44
  CLI_VERSION
36
45
  } from "./chunk-XJXDOF63.js";
37
46
  import {
38
47
  resolveActiveApiKey
39
48
  } from "./chunk-PJHET45A.js";
49
+ import {
50
+ activeProfileConfigPath
51
+ } from "./chunk-YMXXOOFN.js";
40
52
  import "./chunk-7OCVIDC7.js";
41
53
 
42
54
  // src/execution.ts
43
- import * as path11 from "node:path";
55
+ import * as path12 from "node:path";
44
56
  import { effectiveFallbackChain as effectiveFallbackChain2, setQueuedMessagesSnapshot as setQueuedMessagesSnapshot2 } from "@wrongstack/core/agent";
45
57
  import { attachTodosCheckpoint as attachTodosCheckpoint2 } from "@wrongstack/core/storage";
46
58
  import { normalizeTokenSavingTier as normalizeTokenSavingTier2 } from "@wrongstack/core/types";
@@ -148,6 +160,7 @@ async function runTuiDispatch(options) {
148
160
  }
149
161
 
150
162
  // src/boot/dispatch-webui.ts
163
+ import * as path from "node:path";
151
164
  import { color as color2 } from "@wrongstack/core/utils";
152
165
  async function runWebUIDispatch(ctx) {
153
166
  const {
@@ -183,12 +196,14 @@ async function runWebUIDispatch(ctx) {
183
196
  agentTranscripts,
184
197
  sddSubagentFactory,
185
198
  onKanbanDispatch,
186
- getFleetBudget
199
+ getFleetBudget,
200
+ webuiSessionChild
187
201
  } = ctx;
188
- const isSimpleUi = flags["simpleui"] === true;
202
+ const isSessionChild = Boolean(webuiSessionChild);
203
+ const isSimpleUi = !isSessionChild && flags["simpleui"] === true;
189
204
  agent.disableInteractiveConfirmation();
190
205
  renderer.setSilent(true);
191
- const { runWebUI } = await import("./webui-server-G3EKFXLL.js");
206
+ const { runWebUI } = await import("./webui-server-NFNRGNNT.js");
192
207
  const flagValue = (names) => {
193
208
  for (const name of names) {
194
209
  if (!Object.hasOwn(flags, name)) continue;
@@ -231,22 +246,32 @@ async function runWebUIDispatch(ctx) {
231
246
  let webuiRequireToken;
232
247
  let frontendDistDir;
233
248
  try {
234
- webuiHost = flagValue(["webui-host", "host"]) ?? process.env["WEBUI_HOST"] ?? process.env["WS_HOST"] ?? "127.0.0.1";
249
+ webuiHost = webuiSessionChild?.host ?? flagValue(["webui-host", "host"]) ?? process.env["WEBUI_HOST"] ?? process.env["WS_HOST"] ?? "127.0.0.1";
235
250
  const defaultPort = isSimpleUi ? 3466 : 3456;
236
- webuiPort = parsePort(
251
+ webuiPort = webuiSessionChild?.port ?? parsePort(
237
252
  flagValue(["webui-port", "http-port", "port", "ws-port"]) ?? process.env["WEBUI_PORT"] ?? process.env["PORT"] ?? process.env["WS_PORT"],
238
253
  defaultPort,
239
254
  "--port"
240
255
  );
241
- webuiAccessToken = flagValue(["webui-token"]) ?? process.env["WEBUI_TOKEN"] ?? process.env["WEBUI_AUTH_TOKEN"];
242
- webuiPublicUrl = flagValue(["webui-public-url", "public-url"]) ?? process.env["WEBUI_PUBLIC_URL"];
243
- webuiPublicWsUrl = flagValue(["webui-public-ws-url", "public-ws-url"]) ?? process.env["WEBUI_PUBLIC_WS_URL"];
244
- webuiRequireToken = flagBoolean(["webui-require-token", "require-token"]) ?? envFlag("WEBUI_REQUIRE_TOKEN");
256
+ webuiAccessToken = webuiSessionChild?.token ?? flagValue(["webui-token"]) ?? process.env["WEBUI_TOKEN"] ?? process.env["WEBUI_AUTH_TOKEN"];
257
+ webuiPublicUrl = webuiSessionChild?.publicUrl ?? flagValue(["webui-public-url", "public-url"]) ?? process.env["WEBUI_PUBLIC_URL"];
258
+ webuiPublicWsUrl = webuiSessionChild?.publicWsUrl ?? flagValue(["webui-public-ws-url", "public-ws-url"]) ?? process.env["WEBUI_PUBLIC_WS_URL"];
259
+ webuiRequireToken = webuiSessionChild?.requireToken ?? flagBoolean(["webui-require-token", "require-token"]) ?? envFlag("WEBUI_REQUIRE_TOKEN");
245
260
  if (isSimpleUi) {
246
261
  const { ensureSimpleUiDistDir } = await import("./simpleui-dist-JIFGUJO7.js");
247
262
  frontendDistDir = await ensureSimpleUiDistDir();
248
263
  }
249
264
  } catch (err) {
265
+ if (webuiSessionChild) {
266
+ await writeWebuiSessionChildError(webuiSessionChild.readyFile, {
267
+ protocolVersion: webuiSessionChild.protocolVersion,
268
+ runtimeId: webuiSessionChild.runtimeId,
269
+ parentShellId: webuiSessionChild.parentShellId,
270
+ phase: "validate_args",
271
+ recoverable: false,
272
+ error: err
273
+ }).catch(() => void 0);
274
+ }
250
275
  renderer.setSilent(false);
251
276
  renderer.writeInfo(color2.red(` ${err instanceof Error ? err.message : String(err)}`));
252
277
  return 1;
@@ -264,9 +289,11 @@ async function runWebUIDispatch(ctx) {
264
289
  publicUrl: webuiPublicUrl,
265
290
  publicWsUrl: webuiPublicWsUrl,
266
291
  requireToken: webuiRequireToken,
292
+ strictPort: webuiSessionChild?.strictPort,
267
293
  projectRoot,
268
294
  appConfig: config,
269
- open: !!flags.open,
295
+ open: webuiSessionChild ? false : !!flags.open,
296
+ webuiSessionChild,
270
297
  agentTranscripts,
271
298
  hqAllowExec: flagBoolean(["hq-allow-exec"]) ?? false,
272
299
  modelsRegistry,
@@ -309,12 +336,57 @@ async function runWebUIDispatch(ctx) {
309
336
  // listening, using the RESOLVED port. Requested ports auto-advance past
310
337
  // busy ports inside runWebUI, so a banner printed up-front lies whenever
311
338
  // the default when it is taken (a second instance, leftover socket).
312
- onListening: ({ url }) => {
339
+ onListening: ({ httpPort, host, url, authToken }) => {
340
+ if (webuiSessionChild) {
341
+ void writeWebuiSessionChildReady(webuiSessionChild.readyFile, {
342
+ type: "webui.session_child.ready",
343
+ protocolVersion: webuiSessionChild.protocolVersion,
344
+ runtime: {
345
+ role: "session-child",
346
+ runtimeId: webuiSessionChild.runtimeId,
347
+ pid: process.pid,
348
+ parentPid: webuiSessionChild.parentPid,
349
+ parentShellId: webuiSessionChild.parentShellId,
350
+ startedAt: (/* @__PURE__ */ new Date()).toISOString()
351
+ },
352
+ project: {
353
+ projectRoot,
354
+ workingDir: webuiSessionChild.workingDir,
355
+ projectSlug: path.basename(projectRoot) || projectRoot,
356
+ projectName: path.basename(projectRoot) || projectRoot
357
+ },
358
+ session: {
359
+ sessionId: session.id,
360
+ created: !webuiSessionChild.resume,
361
+ resumed: webuiSessionChild.resume,
362
+ provider: config.provider,
363
+ model: config.model
364
+ },
365
+ endpoint: {
366
+ surface: "webui",
367
+ host,
368
+ httpPort,
369
+ url,
370
+ ...webuiPublicUrl ? { publicUrl: webuiPublicUrl } : {},
371
+ ...webuiPublicWsUrl ? { publicWsUrl: webuiPublicWsUrl } : {},
372
+ requireToken: webuiRequireToken,
373
+ auth: authToken ? { scheme: "registry-token", tokenPresent: true, token: authToken } : { scheme: "none", tokenPresent: false }
374
+ },
375
+ registry: {
376
+ webuiInstanceRegistered: true,
377
+ sessionRegistered: true
378
+ },
379
+ capabilities: [...WEBUI_SESSION_CHILD_CAPABILITIES]
380
+ }).catch(() => void 0);
381
+ return;
382
+ }
313
383
  const surface = isSimpleUi ? "SimpleUI" : "WebUI";
314
- renderer.writeInfo(color2.green(` \u2726 ${surface} running \u2192 ${color2.bold(url)}`));
315
384
  renderer.writeInfo(
316
- color2.dim(` Press Ctrl+C in this terminal to stop the ${surface} server.
317
- `)
385
+ ` \u2726 ${terminalText(surface, "success", { bold: true })} ${terminalText("running \u2192", "muted")} ${terminalLink(url)}`
386
+ );
387
+ renderer.writeInfo(
388
+ ` ${terminalText(`Press Ctrl+C in this terminal to stop the ${surface} server.`, "muted")}
389
+ `
318
390
  );
319
391
  },
320
392
  // Make autonomy.switch from the browser flip the CLI's real
@@ -337,6 +409,16 @@ async function runWebUIDispatch(ctx) {
337
409
  );
338
410
  resolve3(0);
339
411
  }).catch((err) => {
412
+ if (webuiSessionChild) {
413
+ void writeWebuiSessionChildError(webuiSessionChild.readyFile, {
414
+ protocolVersion: webuiSessionChild.protocolVersion,
415
+ runtimeId: webuiSessionChild.runtimeId,
416
+ parentShellId: webuiSessionChild.parentShellId,
417
+ phase: "start_server",
418
+ recoverable: false,
419
+ error: err
420
+ }).catch(() => void 0);
421
+ }
340
422
  renderer.setSilent(false);
341
423
  renderer.writeInfo(
342
424
  color2.red(
@@ -353,8 +435,8 @@ async function runWebUIDispatch(ctx) {
353
435
  function resolveExecutionMode(positional, flags) {
354
436
  const prompt = typeof flags["prompt"] === "string" ? flags["prompt"] : "";
355
437
  if (positional.length > 0 || prompt.length > 0) return "single-shot";
356
- if (flags.tui && flags["no-tui"] !== true && !flags.webui) return "tui";
357
- if (flags.webui) return "webui";
438
+ if (flags.tui && flags["no-tui"] !== true && !flags.webui && !flags["webui-session-child"]) return "tui";
439
+ if (flags.webui || flags["webui-session-child"]) return "webui";
358
440
  return "repl";
359
441
  }
360
442
 
@@ -494,7 +576,7 @@ function createTuiCoordinatorCallbacks({
494
576
  }
495
577
 
496
578
  // src/boot/tui-coordinator-setup.ts
497
- import * as path from "node:path";
579
+ import * as path2 from "node:path";
498
580
  import { AutonomousCoordinator } from "@wrongstack/core/coordination";
499
581
  function setupAutonomousCoordinator(ctx) {
500
582
  const { state, events, context, wpaths, mailbox, director, getDirector, coordinatorController, onCoordinatorStopSetter } = ctx;
@@ -503,7 +585,7 @@ function setupAutonomousCoordinator(ctx) {
503
585
  const currentDirector = getDirector?.() ?? director;
504
586
  if (!currentDirector) return null;
505
587
  const transcript = context.session.transcriptPath;
506
- const sessionDir = transcript ? path.dirname(transcript) : wpaths.projectDir;
588
+ const sessionDir = transcript ? path2.dirname(transcript) : wpaths.projectDir;
507
589
  const llmProvider = {
508
590
  decide: async (prompt) => {
509
591
  const sysPrompt = [
@@ -714,10 +796,10 @@ function wireGoal(events) {
714
796
  }
715
797
 
716
798
  // src/boot/tui-live-sessions.ts
717
- import * as path2 from "node:path";
799
+ import * as path3 from "node:path";
718
800
  async function getLiveSessions(ctx) {
719
801
  const { SessionRegistry } = await import("@wrongstack/core/storage");
720
- const globalRoot = path2.dirname(ctx.state.wpaths.globalConfig);
802
+ const globalRoot = path3.dirname(ctx.state.wpaths.globalConfig);
721
803
  const registry = new SessionRegistry(globalRoot);
722
804
  const sessions = await registry.list();
723
805
  return sessions.filter((s) => s.status !== "stale").map((s) => ({
@@ -747,7 +829,7 @@ function onSwitchToSession(ctx, _sessionId, targetRoot, projectName) {
747
829
  }
748
830
 
749
831
  // src/boot/tui-project-picker-callback.ts
750
- import * as path3 from "node:path";
832
+ import * as path4 from "node:path";
751
833
  import { color as color3 } from "@wrongstack/core/utils";
752
834
  async function getProjectPickerItems(ctx) {
753
835
  const { buildPickerItems } = await import("./project-picker-BOCWHBXP.js");
@@ -761,7 +843,7 @@ async function onProjectSelect(ctx, slug, kind) {
761
843
  try {
762
844
  if (kind === "action") {
763
845
  if (slug === "new-session") {
764
- const name = path3.basename(state.projectRoot) || state.projectRoot;
846
+ const name = path4.basename(state.projectRoot) || state.projectRoot;
765
847
  const err2 = await switchProjectInPlace2(state.projectRoot, name);
766
848
  if (err2) renderer.write(color3.red(`Project switch failed: ${err2}
767
849
  `));
@@ -772,8 +854,8 @@ async function onProjectSelect(ctx, slug, kind) {
772
854
  const manifest = await loadManifest(state.wpaths.globalConfig);
773
855
  const project = manifest.projects.find((p) => p.slug === slug);
774
856
  if (!project) return;
775
- const targetRoot = path3.resolve(project.root);
776
- if (path3.resolve(state.projectRoot) === targetRoot) return;
857
+ const targetRoot = path4.resolve(project.root);
858
+ if (path4.resolve(state.projectRoot) === targetRoot) return;
777
859
  const fleetStatus = director?.status();
778
860
  const fleetRunning = fleetStatus?.subagents.filter((a) => a.status === "running").length ?? 0;
779
861
  const eternalActive = getEternalEngine?.()?.currentState === "running";
@@ -811,7 +893,7 @@ ${parts.join("\n")}
811
893
  import { spawn } from "node:child_process";
812
894
  import { createRequire } from "node:module";
813
895
  import * as fs from "node:fs/promises";
814
- import * as path4 from "node:path";
896
+ import * as path5 from "node:path";
815
897
  import { color as color4 } from "@wrongstack/core/utils";
816
898
  async function handleProjectSwitchSpawn(opts) {
817
899
  const PROJECT_SWITCH_EXIT_CODE = 42;
@@ -824,8 +906,8 @@ async function handleProjectSwitchSpawn(opts) {
824
906
  try {
825
907
  const req = createRequire(import.meta.url);
826
908
  const pkgPath = req.resolve("@wrongstack/cli/package.json");
827
- const pkgDir = path4.dirname(pkgPath);
828
- cliPath = path4.join(pkgDir, "dist", "index.js");
909
+ const pkgDir = path5.dirname(pkgPath);
910
+ cliPath = path5.join(pkgDir, "dist", "index.js");
829
911
  await fs.access(cliPath);
830
912
  } catch {
831
913
  cliPath = process.argv[1] ?? "";
@@ -837,13 +919,16 @@ async function handleProjectSwitchSpawn(opts) {
837
919
  const nodeExe = process.execPath;
838
920
  const spawnArgs = [cliPath, "--no-interactive"];
839
921
  if (resumeSessionId) spawnArgs.push("--resume", resumeSessionId);
840
- spawn(nodeExe, spawnArgs, {
922
+ const child = spawn(nodeExe, spawnArgs, {
841
923
  cwd: root,
842
924
  stdio: "ignore",
843
- detached: true
844
- }).on("error", (err) => {
925
+ detached: true,
926
+ windowsHide: true
927
+ });
928
+ child.on("error", (err) => {
845
929
  console.error(color4.red(`Failed to spawn wstack: ${err.message}`));
846
930
  });
931
+ child.unref();
847
932
  console.log(
848
933
  [
849
934
  "",
@@ -858,7 +943,7 @@ async function handleProjectSwitchSpawn(opts) {
858
943
 
859
944
  // src/boot/tui-project-switch.ts
860
945
  import * as fs2 from "node:fs/promises";
861
- import * as path5 from "node:path";
946
+ import * as path6 from "node:path";
862
947
  import {
863
948
  DefaultSystemPromptBuilder,
864
949
  setQueuedMessagesSnapshot
@@ -879,7 +964,7 @@ async function switchProjectInPlace(ctx, targetRoot, displayName) {
879
964
  skillLoader,
880
965
  attachTodosCheckpoint: attachTodosCheckpoint3
881
966
  } = ctx;
882
- const resolved = path5.resolve(targetRoot);
967
+ const resolved = path6.resolve(targetRoot);
883
968
  const stat2 = await fs2.stat(resolved).catch(() => null);
884
969
  if (!stat2?.isDirectory()) return `Cannot switch: not a directory: ${resolved}`;
885
970
  const oldWriter = context.session;
@@ -918,7 +1003,7 @@ async function switchProjectInPlace(ctx, targetRoot, displayName) {
918
1003
  await state.activateSessionIdentity(nextWriter.id, {
919
1004
  projectSlug: nextWpaths.projectSlug,
920
1005
  projectRoot: resolved,
921
- projectName: displayName || path5.basename(resolved),
1006
+ projectName: displayName || path6.basename(resolved),
922
1007
  workingDir: resolved
923
1008
  });
924
1009
  } catch (err) {
@@ -938,6 +1023,7 @@ async function switchProjectInPlace(ctx, targetRoot, displayName) {
938
1023
  context.state.replaceMessages([]);
939
1024
  context.state.replaceTodos([]);
940
1025
  context.clearFileTracking();
1026
+ context.clearMemoryEvidence?.();
941
1027
  context.tokenCounter.reset();
942
1028
  context.meta["packageTrackerOpts"] = { storageDir: nextWpaths.projectDir, projectRoot: resolved };
943
1029
  context.state.setMeta(
@@ -979,7 +1065,8 @@ async function switchProjectInPlace(ctx, targetRoot, displayName) {
979
1065
  context.systemPrompt = await switchBuilder.build({
980
1066
  cwd: resolved,
981
1067
  projectRoot: resolved,
982
- tools: agent.tools.list(),
1068
+ tools: agent.tools.listForProvider(),
1069
+ catalogTools: agent.tools.list(),
983
1070
  provider: context.provider.id,
984
1071
  model: context.model
985
1072
  });
@@ -1053,7 +1140,7 @@ async function onSDDOutput(output) {
1053
1140
  }
1054
1141
 
1055
1142
  // src/boot/tui-session-resume.ts
1056
- import * as path6 from "node:path";
1143
+ import * as path7 from "node:path";
1057
1144
  import { attachTodosCheckpoint, loadTodosCheckpoint } from "@wrongstack/core/storage";
1058
1145
  import { sessionScopedPath as sessionScopedPath2 } from "@wrongstack/core/utils";
1059
1146
  async function resumeSession(ctx, sessionId) {
@@ -1079,7 +1166,7 @@ async function resumeSession(ctx, sessionId) {
1079
1166
  }
1080
1167
  try {
1081
1168
  const { SessionRegistry } = await import("@wrongstack/core/storage");
1082
- const registry = new SessionRegistry(path6.dirname(state.wpaths.globalConfig));
1169
+ const registry = new SessionRegistry(path7.dirname(state.wpaths.globalConfig));
1083
1170
  const live = (await registry.list()).find(
1084
1171
  (s) => s.sessionId === canonicalSessionId && s.status !== "stale" && s.pid !== process.pid
1085
1172
  );
@@ -1290,10 +1377,10 @@ async function resumeSession(ctx, sessionId) {
1290
1377
 
1291
1378
  // src/boot/tui-settings-adapter.ts
1292
1379
  import * as fs3 from "node:fs/promises";
1293
- import * as path7 from "node:path";
1380
+ import * as path8 from "node:path";
1294
1381
  import { decryptConfigSecrets, encryptConfigSecrets, noOpVault } from "@wrongstack/core/security";
1295
1382
  import { normalizeTokenSavingTier, resolveFleetChatVerbosity } from "@wrongstack/core/types";
1296
- import { atomicWrite } from "@wrongstack/core/utils";
1383
+ import { atomicWrite, deepMerge } from "@wrongstack/core/utils";
1297
1384
  import { getProcessRegistry } from "@wrongstack/tools";
1298
1385
  var PANEL_IDS_CLI = [
1299
1386
  "projectPicker",
@@ -1372,6 +1459,7 @@ function createSettingsAdapter(ctx) {
1372
1459
  auditLevel: cfg.session?.auditLevel ?? "standard",
1373
1460
  indexOnStart: cfg.indexing?.onSessionStart !== false,
1374
1461
  maxIterations: cfg.tools?.maxIterations ?? 500,
1462
+ nextStepsTool: cfg.tools?.nextsteps?.enabled === true,
1375
1463
  restrictFsToRoot: resolvedRestrict,
1376
1464
  autoProceedMaxIterations: cfg.autonomy?.autoProceedMaxIterations ?? 50,
1377
1465
  debugStream: cfg.debugStream ?? false,
@@ -1411,12 +1499,15 @@ function createSettingsAdapter(ctx) {
1411
1499
  }
1412
1500
  async function saveSettings(s) {
1413
1501
  try {
1414
- if (s.mode !== void 0 || s.delayMs !== void 0 || s.titleAnimation !== void 0 || s.yolo !== void 0 || s.fleetChatVerbosity !== void 0 || s.chime !== void 0 || s.confirmExit !== void 0 || s.mouseMode !== void 0 || s.featureMcp !== void 0 || s.featurePlugins !== void 0 || s.featureMemory !== void 0 || s.featureSkills !== void 0 || s.featureModelsRegistry !== void 0 || s.featureTokenSaving !== void 0 || s.allowOutsideProjectRoot !== void 0 || s.contextAutoCompact !== void 0 || s.contextStrategy !== void 0 || s.contextMode !== void 0 || s.maxConcurrent !== void 0 || s.logLevel !== void 0 || s.auditLevel !== void 0 || s.indexOnStart !== void 0 || s.maxIterations !== void 0 || s.restrictFsToRoot !== void 0 || s.nextPrediction !== void 0 || s.debugStream !== void 0 || s.shellBangWarningDontShowAgain !== void 0 || s.configScope !== void 0 || s.enhanceDelayMs !== void 0 || s.enhanceEnabled !== void 0 || s.enhanceLanguage !== void 0 || s.midRunSendPicker !== void 0 || s.statuslineMode !== void 0 || s.thinkingWord !== void 0 || s.animationStyle !== void 0 || s.autonomyNextPrompt !== void 0 || s.autoProceedMaxIterations !== void 0 || s.reasoningMode !== void 0 || s.reasoningEffort !== void 0 || s.reasoningPreserve !== void 0 || s.cacheTtl !== void 0 || s.breakerEnabled !== void 0 || s.breakerAutoKillResetMs !== void 0 || s.showModelReasoning !== void 0 || s.showAgentSwarmPanel !== void 0 || s.panelPositions !== void 0 || s.showSageMemoryInject !== void 0 || s.sageMemoryInjectThreshold !== void 0 || s.readSymbols !== void 0) {
1502
+ if (s.mode !== void 0 || s.delayMs !== void 0 || s.titleAnimation !== void 0 || s.yolo !== void 0 || s.fleetChatVerbosity !== void 0 || s.chime !== void 0 || s.confirmExit !== void 0 || s.mouseMode !== void 0 || s.featureMcp !== void 0 || s.featurePlugins !== void 0 || s.featureMemory !== void 0 || s.featureSkills !== void 0 || s.featureModelsRegistry !== void 0 || s.featureTokenSaving !== void 0 || s.allowOutsideProjectRoot !== void 0 || s.contextAutoCompact !== void 0 || s.contextStrategy !== void 0 || s.contextMode !== void 0 || s.maxConcurrent !== void 0 || s.logLevel !== void 0 || s.auditLevel !== void 0 || s.indexOnStart !== void 0 || s.maxIterations !== void 0 || s.nextStepsTool !== void 0 || s.restrictFsToRoot !== void 0 || s.nextPrediction !== void 0 || s.debugStream !== void 0 || s.shellBangWarningDontShowAgain !== void 0 || s.configScope !== void 0 || s.enhanceDelayMs !== void 0 || s.enhanceEnabled !== void 0 || s.enhanceLanguage !== void 0 || s.midRunSendPicker !== void 0 || s.statuslineMode !== void 0 || s.thinkingWord !== void 0 || s.animationStyle !== void 0 || s.autonomyNextPrompt !== void 0 || s.autoProceedMaxIterations !== void 0 || s.reasoningMode !== void 0 || s.reasoningEffort !== void 0 || s.reasoningPreserve !== void 0 || s.cacheTtl !== void 0 || s.breakerEnabled !== void 0 || s.breakerAutoKillResetMs !== void 0 || s.showModelReasoning !== void 0 || s.showAgentSwarmPanel !== void 0 || s.panelPositions !== void 0 || s.showSageMemoryInject !== void 0 || s.sageMemoryInjectThreshold !== void 0 || s.readSymbols !== void 0) {
1415
1503
  const cfg = configStore.get();
1416
- const activeProfileName = cfg.activeProfile ?? "default";
1417
1504
  const persistDeps = {
1418
1505
  configStore,
1419
- profileConfigPath: wpaths.profileConfig(activeProfileName),
1506
+ // Third copy of "which profile is active" — an inline cast plus a
1507
+ // `?? 'default'`, identical to `activeProfileConfigPath` two files
1508
+ // over. The comment above already promised this resolution was
1509
+ // delegated; now it is.
1510
+ profileConfigPath: activeProfileConfigPath(wpaths, cfg),
1420
1511
  inProjectConfigPath: wpaths.inProjectConfig,
1421
1512
  vault: noOpVault,
1422
1513
  resolveProfilePath: (name) => wpaths.profileConfig(name)
@@ -1506,9 +1597,10 @@ function createSettingsAdapter(ctx) {
1506
1597
  idx.onSessionStart = s.indexOnStart;
1507
1598
  decrypted.indexing = idx;
1508
1599
  }
1509
- if (s.maxIterations !== void 0 || fsAccess !== void 0) {
1600
+ if (s.maxIterations !== void 0 || s.nextStepsTool !== void 0 || fsAccess !== void 0) {
1510
1601
  const tools = decrypted.tools ?? {};
1511
1602
  if (s.maxIterations !== void 0) tools.maxIterations = s.maxIterations;
1603
+ if (s.nextStepsTool !== void 0) tools.nextsteps = { enabled: s.nextStepsTool };
1512
1604
  if (fsAccess !== void 0) tools.restrictToProjectRoot = fsAccess.restrictToProjectRoot;
1513
1605
  decrypted.tools = tools;
1514
1606
  }
@@ -1563,7 +1655,7 @@ function createSettingsAdapter(ctx) {
1563
1655
  const destRaw = await fs3.readFile(actualTarget, "utf8");
1564
1656
  const destParsed = JSON.parse(destRaw);
1565
1657
  const destDecrypted = decryptConfigSecrets(destParsed, noOpVault);
1566
- mergedToWrite = { ...destDecrypted, ...decrypted };
1658
+ mergedToWrite = deepMerge(destDecrypted, decrypted);
1567
1659
  } catch (err) {
1568
1660
  if (err.code !== "ENOENT") {
1569
1661
  throw new Error(
@@ -1576,7 +1668,7 @@ function createSettingsAdapter(ctx) {
1576
1668
  const isProjectTarget = actualTarget === wpaths.inProjectConfig;
1577
1669
  const toWrite = isProjectTarget ? filterSafeForProject(mergedToWrite) : mergedToWrite;
1578
1670
  const encrypted = encryptConfigSecrets(toWrite, noOpVault);
1579
- await fs3.mkdir(path7.dirname(actualTarget), { recursive: true });
1671
+ await fs3.mkdir(path8.dirname(actualTarget), { recursive: true });
1580
1672
  await atomicWrite(actualTarget, JSON.stringify(encrypted, null, 2), { mode: 384 });
1581
1673
  const currentConfig = configStore.get();
1582
1674
  const nextModelRuntime = {
@@ -1620,7 +1712,7 @@ function createSettingsAdapter(ctx) {
1620
1712
  ...decrypted.indexing ?? {}
1621
1713
  }
1622
1714
  } : {},
1623
- ...s.maxIterations !== void 0 || fsAccess !== void 0 ? {
1715
+ ...s.maxIterations !== void 0 || s.nextStepsTool !== void 0 || fsAccess !== void 0 ? {
1624
1716
  tools: {
1625
1717
  ...currentConfig.tools,
1626
1718
  ...decrypted.tools ?? {}
@@ -1734,6 +1826,7 @@ function createBrainPanelHost(deps) {
1734
1826
  councilDistinctness: snap.council.distinctness,
1735
1827
  councilPerCallTimeoutMs: snap.council.perCallTimeoutMs,
1736
1828
  councilMaxConcurrency: snap.council.maxConcurrency,
1829
+ councilVoterMaxTokens: snap.council.voterMaxTokens,
1737
1830
  councilJudgeMaxTokens: snap.council.judgeMaxTokens,
1738
1831
  // The EFFECTIVE judge, not `council.judge`. The configured one is
1739
1832
  // usually absent, so the panel used to read "auto" and say nothing
@@ -1815,6 +1908,7 @@ function createBrainPanelHost(deps) {
1815
1908
  setCouncilDistinctness: (mode) => apply({ council: { distinctness: mode } }),
1816
1909
  setCouncilPerCallTimeout: (ms) => apply({ council: { perCallTimeoutMs: ms ?? null } }),
1817
1910
  setCouncilMaxConcurrency: (count) => apply({ council: { maxConcurrency: count ?? null } }),
1911
+ setCouncilVoterMaxTokens: (tokens) => apply({ council: { voterMaxTokens: tokens ?? null } }),
1818
1912
  setCouncilJudgeMaxTokens: (tokens) => apply({ council: { judgeMaxTokens: tokens ?? null } }),
1819
1913
  setLedgerEnabled: (on) => apply({ ledger: { enabled: on } }),
1820
1914
  setAutoDeny: (count) => apply({ ledger: { autoDenyAfterFailures: count ?? null } }),
@@ -1851,7 +1945,7 @@ var reviewerRoundRobinCursor = 0;
1851
1945
  function __resetReviewerRoundRobinCursor(value = 0) {
1852
1946
  reviewerRoundRobinCursor = value;
1853
1947
  }
1854
- function assignReviewerModelsRoundRobin(provider, model, fallbackModels, statusTracker) {
1948
+ function assignReviewerModels(provider, model, fallbackModels, selection = "round-robin", statusTracker, random = Math.random) {
1855
1949
  const pool = buildReviewerModelPool(provider, model, fallbackModels, statusTracker);
1856
1950
  if (pool.length <= 1) {
1857
1951
  return {
@@ -1860,20 +1954,24 @@ function assignReviewerModelsRoundRobin(provider, model, fallbackModels, statusT
1860
1954
  fallbackModels: [...fallbackModels]
1861
1955
  };
1862
1956
  }
1957
+ const cursor = selection === "random" ? Math.min(pool.length - 1, Math.floor(Math.max(0, random()) * pool.length)) : reviewerRoundRobinCursor;
1863
1958
  const assignment = selectRoundRobinReviewerAssignment(
1864
1959
  pool,
1865
- reviewerRoundRobinCursor,
1960
+ cursor,
1866
1961
  provider,
1867
1962
  model,
1868
1963
  statusTracker
1869
1964
  );
1870
- reviewerRoundRobinCursor = assignment.nextCursor;
1965
+ if (selection === "round-robin") reviewerRoundRobinCursor = assignment.nextCursor;
1871
1966
  return {
1872
1967
  provider: assignment.provider,
1873
1968
  model: assignment.model,
1874
1969
  fallbackModels: assignment.fallbackModels
1875
1970
  };
1876
1971
  }
1972
+ function assignReviewerModelsRoundRobin(provider, model, fallbackModels, statusTracker) {
1973
+ return assignReviewerModels(provider, model, fallbackModels, "round-robin", statusTracker);
1974
+ }
1877
1975
  var MAX_REVIEWER_ATTEMPTS = 4;
1878
1976
  var REVIEWER_ATTEMPT_TIMEOUT_MS = 9e5;
1879
1977
  var REVIEWER_LADDER_BUDGET_MS = 12e5;
@@ -1976,7 +2074,7 @@ async function finalizeExecutionCleanup(input) {
1976
2074
  session,
1977
2075
  tokenCounter,
1978
2076
  events,
1979
- getPendingChimeraWork,
2077
+ chimeraWork,
1980
2078
  director,
1981
2079
  reader
1982
2080
  } = input;
@@ -2028,25 +2126,34 @@ async function finalizeExecutionCleanup(input) {
2028
2126
  })
2029
2127
  );
2030
2128
  });
2031
- events.emit("session.ended", {
2032
- id: activeSession.id,
2033
- sessionId: activeSession.id,
2034
- usage: tokenCounter.total()
2035
- });
2036
- if (getPendingChimeraWork) {
2037
- const chimeraWork = getPendingChimeraWork();
2038
- if (chimeraWork) {
2039
- await chimeraWork.catch((err) => {
2040
- console.warn(
2041
- JSON.stringify({
2042
- level: "warn",
2043
- event: "shutdown.chimera_work_failed",
2044
- message: `Pending chimera work failed: ${err instanceof Error ? err.message : String(err)}`,
2045
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
2046
- })
2047
- );
2048
- });
2129
+ const sessionEndProducers = /* @__PURE__ */ new Set();
2130
+ events.emit(
2131
+ "session.ended",
2132
+ {
2133
+ id: activeSession.id,
2134
+ sessionId: activeSession.id,
2135
+ usage: tokenCounter.total(),
2136
+ waitUntil: (work) => {
2137
+ const tracked = Promise.resolve(work).finally(() => sessionEndProducers.delete(tracked));
2138
+ void tracked.catch(() => void 0);
2139
+ sessionEndProducers.add(tracked);
2140
+ }
2141
+ }
2142
+ );
2143
+ try {
2144
+ while (sessionEndProducers.size > 0) {
2145
+ await Promise.allSettled([...sessionEndProducers]);
2049
2146
  }
2147
+ await chimeraWork?.drainAndClose();
2148
+ } catch (err) {
2149
+ console.warn(
2150
+ JSON.stringify({
2151
+ level: "warn",
2152
+ event: "shutdown.chimera_work_failed",
2153
+ message: `Pending chimera work failed: ${err instanceof Error ? err.message : String(err)}`,
2154
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
2155
+ })
2156
+ );
2050
2157
  }
2051
2158
  if (director) {
2052
2159
  try {
@@ -2447,9 +2554,46 @@ var FleetStatusLine = class {
2447
2554
  }
2448
2555
  };
2449
2556
 
2557
+ // src/chimera-work-registry.ts
2558
+ function createChimeraWorkRegistry() {
2559
+ const pending = /* @__PURE__ */ new Set();
2560
+ let accepting = true;
2561
+ let closePromise;
2562
+ const track = (work) => {
2563
+ if (!accepting) return false;
2564
+ const tracked = Promise.resolve(work).finally(() => {
2565
+ pending.delete(tracked);
2566
+ });
2567
+ void tracked.catch(() => void 0);
2568
+ pending.add(tracked);
2569
+ return true;
2570
+ };
2571
+ const snapshot = () => {
2572
+ if (pending.size === 0) return void 0;
2573
+ return Promise.allSettled([...pending]).then(() => void 0);
2574
+ };
2575
+ const drainAndClose = () => {
2576
+ closePromise ??= (async () => {
2577
+ while (pending.size > 0) {
2578
+ await Promise.allSettled([...pending]);
2579
+ }
2580
+ accepting = false;
2581
+ })();
2582
+ return closePromise;
2583
+ };
2584
+ return {
2585
+ track,
2586
+ pending: snapshot,
2587
+ drainAndClose,
2588
+ get size() {
2589
+ return pending.size;
2590
+ }
2591
+ };
2592
+ }
2593
+
2450
2594
  // src/execution-chimera-cascade.ts
2451
2595
  import * as fsp from "node:fs/promises";
2452
- import * as path8 from "node:path";
2596
+ import * as path9 from "node:path";
2453
2597
  import { emitReviewIfChanged } from "@wrongstack/core/plugin";
2454
2598
 
2455
2599
  // src/chimera-review-task.ts
@@ -2708,7 +2852,7 @@ function installChimeraCascadeHandler({
2708
2852
  director,
2709
2853
  session,
2710
2854
  getPendingWork,
2711
- setPendingWork,
2855
+ trackWork,
2712
2856
  buildLadder
2713
2857
  }) {
2714
2858
  events.onPattern("chimera.cascade_needed", (_event, payload) => {
@@ -2797,7 +2941,7 @@ function installChimeraCascadeHandler({
2797
2941
  }
2798
2942
  await maybeReReviewCascade({ events, session, bundle: p.bundle });
2799
2943
  })();
2800
- setPendingWork(pendingWork);
2944
+ trackWork(pendingWork);
2801
2945
  });
2802
2946
  }
2803
2947
  async function maybeReReviewCascade({
@@ -2812,7 +2956,7 @@ async function maybeReReviewCascade({
2812
2956
  const reReadFiles = [];
2813
2957
  for (const f of bundle.files) {
2814
2958
  try {
2815
- const absPath = path8.join(bundle.cwd, f.path);
2959
+ const absPath = path9.join(bundle.cwd, f.path);
2816
2960
  const content = await fsp.readFile(absPath, "utf8");
2817
2961
  reReadFiles.push({ path: f.path, status: "modified", content });
2818
2962
  } catch {
@@ -2836,7 +2980,7 @@ async function maybeReReviewCascade({
2836
2980
  stopReason: "end_turn",
2837
2981
  usage: { input: 0, output: 0 }
2838
2982
  });
2839
- const emitted = emitReviewIfChanged(
2983
+ const emitted = await emitReviewIfChanged(
2840
2984
  { events, emitCustom: events.emitCustom.bind(events) },
2841
2985
  reReviewBundle
2842
2986
  );
@@ -2881,7 +3025,7 @@ async function maybeReReviewCascade({
2881
3025
 
2882
3026
  // src/execution-chimera-review.ts
2883
3027
  import { randomUUID as randomUUID3 } from "node:crypto";
2884
- import path9 from "node:path";
3028
+ import path10 from "node:path";
2885
3029
  import { effectiveFallbackChain } from "@wrongstack/core/agent";
2886
3030
  import {
2887
3031
  CHIMERA_REVIEW_PROMPT,
@@ -2894,7 +3038,7 @@ import {
2894
3038
  function normalizeFileKeyForCitation(raw, cwd) {
2895
3039
  const forward = raw.replace(/\\/g, "/").replace(/^\.\//, "");
2896
3040
  const isAbsolute = forward.startsWith("/") || /^[a-zA-Z]:\//.test(forward);
2897
- const pathMod = process.platform === "win32" ? path9.win32 : path9;
3041
+ const pathMod = process.platform === "win32" ? path10.win32 : path10;
2898
3042
  const relative = isAbsolute ? pathMod.relative(cwd, forward).replace(/\\/g, "/").replace(/^\.\//, "") : forward;
2899
3043
  return process.platform === "win32" ? relative.toLowerCase() : relative;
2900
3044
  }
@@ -2908,13 +3052,14 @@ function installChimeraReviewHandler({
2908
3052
  projectDir,
2909
3053
  statusTracker,
2910
3054
  persistReview = persistChimeraReview,
2911
- setPendingWork
3055
+ trackWork
2912
3056
  }) {
2913
3057
  events.onPattern("chimera.review_needed", (_event, payload) => {
2914
3058
  const p = payload;
2915
3059
  const reviewSessionId = agent.ctx.activeRunSessionId ?? agent.ctx.session?.id ?? session.id;
2916
3060
  const dir = director;
2917
3061
  if (!dir) {
3062
+ void recordCompletedReview(events, { bundle: p }).catch(() => void 0);
2918
3063
  return;
2919
3064
  }
2920
3065
  if (p.files.length === 0) return;
@@ -2957,11 +3102,11 @@ function installChimeraReviewHandler({
2957
3102
  `\u{1F982} Chimera report persistence failed: ${message}. The review remains in the session transcript and mailbox.`
2958
3103
  );
2959
3104
  } finally {
2960
- recordCompletedReview(events, completion);
3105
+ await recordCompletedReview(events, completion);
2961
3106
  events.emitCustom("chimera.review_complete", completion);
2962
3107
  }
2963
3108
  };
2964
- setPendingWork(
3109
+ trackWork(
2965
3110
  (async () => {
2966
3111
  let subagentId;
2967
3112
  try {
@@ -2973,10 +3118,11 @@ function installChimeraReviewHandler({
2973
3118
  const baseProvider = rawProvider || tProvider || config.provider;
2974
3119
  const baseModel = rawModel || tModel || config.model;
2975
3120
  const baseFallbacks = p.reviewFallbackModels ? [...p.reviewFallbackModels] : resolveReviewerFallbackModels(void 0);
2976
- const assigned = assignReviewerModelsRoundRobin(
3121
+ const assigned = assignReviewerModels(
2977
3122
  baseProvider,
2978
3123
  baseModel,
2979
3124
  baseFallbacks,
3125
+ p.reviewModelSelection ?? "round-robin",
2980
3126
  statusTracker
2981
3127
  );
2982
3128
  const ladder = buildReviewerAttemptLadder({
@@ -3090,16 +3236,16 @@ function installChimeraReviewHandler({
3090
3236
  const changedBasenameIndex = /* @__PURE__ */ new Map();
3091
3237
  for (const file of p.files) {
3092
3238
  const normalized = normalizeFileKeyForCitation(file.path, p.cwd);
3093
- const basename5 = path9.basename(file.path).toLowerCase();
3094
- const bucket = changedBasenameIndex.get(basename5);
3239
+ const basename6 = path10.basename(file.path).toLowerCase();
3240
+ const bucket = changedBasenameIndex.get(basename6);
3095
3241
  if (bucket) bucket.push(normalized);
3096
- else changedBasenameIndex.set(basename5, [normalized]);
3242
+ else changedBasenameIndex.set(basename6, [normalized]);
3097
3243
  }
3098
3244
  const droppedCitations = citedFindings.filter((finding) => {
3099
3245
  const citedKey = normalizeFileKeyForCitation(finding.location.file, p.cwd);
3100
3246
  if (citedPaths.has(citedKey)) return false;
3101
- const basename5 = path9.basename(finding.location.file).toLowerCase();
3102
- const bucket = changedBasenameIndex.get(basename5);
3247
+ const basename6 = path10.basename(finding.location.file).toLowerCase();
3248
+ const bucket = changedBasenameIndex.get(basename6);
3103
3249
  return !(bucket && bucket.length === 1);
3104
3250
  });
3105
3251
  const effectiveHasFindings = reviewHasFindings && (parsedReview.findings.length === 0 || parsedReview.findings.length > droppedCitations.length);
@@ -3621,7 +3767,7 @@ function printBanner(renderer, projectName) {
3621
3767
 
3622
3768
  // src/repl-client-registration.ts
3623
3769
  import * as crypto from "node:crypto";
3624
- import * as path10 from "node:path";
3770
+ import * as path11 from "node:path";
3625
3771
  import {
3626
3772
  getSharedProjectMailbox,
3627
3773
  resolveProjectDir
@@ -3634,7 +3780,7 @@ function registerReplClient(opts) {
3634
3780
  const hqConnection = startCliHqConnection({
3635
3781
  clientKind: "repl",
3636
3782
  projectRoot: replProjectRoot,
3637
- projectName: path10.basename(replProjectRoot),
3783
+ projectName: path11.basename(replProjectRoot),
3638
3784
  appConfig: opts.appConfig,
3639
3785
  capabilities: ["telemetry.publish", "mailbox.summary"]
3640
3786
  });
@@ -3648,7 +3794,7 @@ function registerReplClient(opts) {
3648
3794
  clientMailbox.registerClient({
3649
3795
  clientId,
3650
3796
  sessionId: opts.getSessionId?.() ?? replProjectRoot,
3651
- name: `REPL [${path10.basename(replProjectRoot)}]`,
3797
+ name: `REPL [${path11.basename(replProjectRoot)}]`,
3652
3798
  source: "repl",
3653
3799
  pid: process.pid
3654
3800
  }).then(() => {
@@ -4442,7 +4588,8 @@ async function execute(deps) {
4442
4588
  slashRegistry,
4443
4589
  tokenCounter,
4444
4590
  activateSessionIdentity,
4445
- updateInfo: initialUpdateInfo
4591
+ updateInfo: initialUpdateInfo,
4592
+ webuiSessionChild
4446
4593
  },
4447
4594
  session: {
4448
4595
  session,
@@ -4555,7 +4702,7 @@ async function execute(deps) {
4555
4702
  const profileName = config.activeProfile ?? "default";
4556
4703
  const bootUpdateInfo = initialUpdateInfo;
4557
4704
  const offStorageObservability = installStorageObservability(events, context.traceId);
4558
- let pendingChimeraWork;
4705
+ const chimeraWork = createChimeraWorkRegistry();
4559
4706
  installChimeraReviewHandler({
4560
4707
  events,
4561
4708
  director,
@@ -4569,8 +4716,8 @@ async function execute(deps) {
4569
4716
  // this, a 429-stricken model is re-spawned on every concurrent reviewer
4570
4717
  // turn and burns the whole chain instead of staying quarantined.
4571
4718
  statusTracker,
4572
- setPendingWork: (work) => {
4573
- pendingChimeraWork = work;
4719
+ trackWork: (work) => {
4720
+ chimeraWork.track(work);
4574
4721
  }
4575
4722
  });
4576
4723
  installChimeraCascadeHandler({
@@ -4581,9 +4728,9 @@ async function execute(deps) {
4581
4728
  profileChain: effectiveFallbackChain2(config),
4582
4729
  session: { provider: config.provider, model: config.model }
4583
4730
  }),
4584
- getPendingWork: () => pendingChimeraWork,
4585
- setPendingWork: (work) => {
4586
- pendingChimeraWork = work;
4731
+ getPendingWork: () => chimeraWork.pending(),
4732
+ trackWork: (work) => {
4733
+ chimeraWork.track(work);
4587
4734
  }
4588
4735
  });
4589
4736
  let code = 0;
@@ -4910,6 +5057,7 @@ async function execute(deps) {
4910
5057
  sddSubagentFactory,
4911
5058
  statusTracker,
4912
5059
  updateInfo: bootUpdateInfo,
5060
+ webuiSessionChild,
4913
5061
  getFleetBudget: () => {
4914
5062
  const d = getDirector?.() ?? null;
4915
5063
  if (!d) return null;
@@ -4952,7 +5100,7 @@ async function execute(deps) {
4952
5100
  attachments,
4953
5101
  effectiveMaxContext,
4954
5102
  getEffectiveMaxContext,
4955
- projectName: path11.basename(projectRoot) || void 0,
5103
+ projectName: path12.basename(projectRoot) || void 0,
4956
5104
  projectRoot,
4957
5105
  appConfig: config,
4958
5106
  getSessionId: () => agent.ctx.session?.id ?? session.id,
@@ -4995,7 +5143,7 @@ async function execute(deps) {
4995
5143
  session,
4996
5144
  tokenCounter,
4997
5145
  events,
4998
- getPendingChimeraWork: () => pendingChimeraWork,
5146
+ chimeraWork,
4999
5147
  director,
5000
5148
  reader
5001
5149
  });
@@ -5006,8 +5154,9 @@ export {
5006
5154
  CHIMERA_REVIEW_READ_ONLY_TOOLS,
5007
5155
  __resetReviewerRoundRobinCursor,
5008
5156
  applyChimeraReviewerReadOnlyPolicy,
5157
+ assignReviewerModels,
5009
5158
  assignReviewerModelsRoundRobin,
5010
5159
  execute,
5011
5160
  resolveReviewerFallbackModels
5012
5161
  };
5013
- //# sourceMappingURL=execution-SHGM7BVC.js.map
5162
+ //# sourceMappingURL=execution-CQ772VPS.js.map