@wrongstack/cli 0.302.0 → 0.302.2

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 (112) hide show
  1. package/data/providers.json +41 -155
  2. package/dist/{acp-DATHHPNT.js → acp-XCE4JJF3.js} +4 -4
  3. package/dist/{audit-QRCLEHHW.js → audit-BBR22QH3.js} +2 -2
  4. package/dist/{auth-PJD3JRH2.js → auth-K7CYVVKH.js} +121 -78
  5. package/dist/auth-menu/index.d.ts +5 -5
  6. package/dist/auth-menu/local.d.ts +4 -5
  7. package/dist/auth-menu/openai-codex-oauth.d.ts +1 -1
  8. package/dist/{auto-discover-providers-DRW4OZHG.js → auto-discover-providers-MHFLDSD3.js} +2 -2
  9. package/dist/{bench-7ZDWSNEF.js → bench-XNDUJOSZ.js} +10 -11
  10. package/dist/boot/auto-discover-providers.d.ts +1 -1
  11. package/dist/boot/container-wiring.d.ts +3 -3
  12. package/dist/boot/dispatch-webui.d.ts +1 -1
  13. package/dist/boot/system-prompt.d.ts +1 -2
  14. package/dist/boot/tool-registry.d.ts +1 -1
  15. package/dist/boot/tui-coordinator-setup.d.ts +1 -1
  16. package/dist/boot/tui-project-picker-callback.d.ts +1 -1
  17. package/dist/boot-config.d.ts +2 -2
  18. package/dist/boot.d.ts +1 -1
  19. package/dist/{chunk-ETOEGL3V.js → chunk-3IC4IEZC.js} +7 -2
  20. package/dist/{chunk-PFVVUH5B.js → chunk-3JPTNADJ.js} +3 -2
  21. package/dist/{chunk-4GVH7V3S.js → chunk-52C7PD2H.js} +1 -1
  22. package/dist/{chunk-OP47B3IX.js → chunk-7YLN7YUA.js} +7 -2
  23. package/dist/{chunk-263G3FMB.js → chunk-B4JLSXZB.js} +11 -14
  24. package/dist/{chunk-I5MEUFDI.js → chunk-BXQG3H2Y.js} +8 -3
  25. package/dist/{chunk-MT6FGXO3.js → chunk-C5NXM2SI.js} +19 -6
  26. package/dist/{chunk-XTIXVJXP.js → chunk-DGXNL7OT.js} +1 -1
  27. package/dist/{chunk-3MOUBRKZ.js → chunk-FJVCVZIV.js} +974 -935
  28. package/dist/{chunk-MRLYDHQ7.js → chunk-JQURRYU4.js} +4 -6
  29. package/dist/{chunk-ZECLGUTF.js → chunk-KV6DNQT6.js} +2 -2
  30. package/dist/{chunk-F4PEGAJZ.js → chunk-NUIHRGPY.js} +1 -1
  31. package/dist/{chunk-GUHQQG63.js → chunk-RK7E3IXT.js} +2 -4
  32. package/dist/{chunk-PYTFS4MC.js → chunk-SSSJQVUY.js} +27 -16
  33. package/dist/{chunk-PJHET45A.js → chunk-SZ42FYPT.js} +3 -3
  34. package/dist/{chunk-2KDOFTTM.js → chunk-WOXUE2CN.js} +1067 -900
  35. package/dist/{chunk-A6Q5KGLV.js → chunk-YKBRFSGL.js} +5 -5
  36. package/dist/cli-context.d.ts +2 -2
  37. package/dist/cli-eternal-flag.d.ts +1 -2
  38. package/dist/{cli-main-EOJ74CI4.js → cli-main-PJMDZHDK.js} +2680 -2133
  39. package/dist/context-limit.d.ts +11 -5
  40. package/dist/{diag-doctor-OQ3AA63O.js → diag-doctor-ZF5BF2MK.js} +2 -3
  41. package/dist/execute-deps.d.ts +1 -1
  42. package/dist/{execution-CQ772VPS.js → execution-LZRYRGDD.js} +234 -143
  43. package/dist/{export-DOBGPY23.js → export-CCUXRJOU.js} +3 -11
  44. package/dist/fleet/host-supervisor.d.ts +1 -1
  45. package/dist/fleet/host.d.ts +1 -1
  46. package/dist/fleet/routing.d.ts +1 -2
  47. package/dist/goal-host.d.ts +2 -2
  48. package/dist/hooks-wiring.d.ts +1 -1
  49. package/dist/{hq-LN5CJHCM.js → hq-AHPAE7EN.js} +104 -55
  50. package/dist/hq-command-controller.d.ts +1 -1
  51. package/dist/hq-server/routes/system-handlers.d.ts +1 -2
  52. package/dist/hq-server/routes.d.ts +7 -7
  53. package/dist/{hq-server-S7HZG3PA.js → hq-server-KU2Z54QU.js} +2 -2
  54. package/dist/index.d.ts +1 -1
  55. package/dist/index.js +2635 -2642
  56. package/dist/mailbox-bridge-bootstrap.d.ts +2 -2
  57. package/dist/{mcp-OHPJH73U.js → mcp-E5EBGOHF.js} +6 -6
  58. package/dist/mcp-serve.d.ts +1 -1
  59. package/dist/{modeldiag-3DOK4BWW.js → modeldiag-SIVUOX2Y.js} +18 -13
  60. package/dist/{permissions-FNYLZIL4.js → permissions-2PWBL4YU.js} +5 -3
  61. package/dist/picker.d.ts +1 -1
  62. package/dist/plugin-management.d.ts +1 -1
  63. package/dist/{plugin-usage-YEVLOR33.js → plugin-usage-PTEETL3J.js} +2 -2
  64. package/dist/{plugins-K3BAUP4D.js → plugins-XRGWC3NJ.js} +3 -3
  65. package/dist/pre-launch.d.ts +2 -2
  66. package/dist/{providers-models-WEZ4EGLL.js → providers-models-VV74TRQ2.js} +86 -37
  67. package/dist/repl.d.ts +1 -1
  68. package/dist/{replay-FCBNHW3K.js → replay-WBRMEWQ5.js} +2 -2
  69. package/dist/{rewind-AOD3JIYX.js → rewind-7RE6ONIC.js} +17 -17
  70. package/dist/{sdd-runtime-AIJCJGWC.js → sdd-runtime-GFZ3NJKS.js} +2 -2
  71. package/dist/{sessions-config-XXN7267N.js → sessions-config-YX2ZPAFM.js} +36 -32
  72. package/dist/{simpleui-dist-JIFGUJO7.js → simpleui-dist-33VO3QHF.js} +9 -2
  73. package/dist/slash-commands/agents.d.ts +14 -0
  74. package/dist/slash-commands/command-context.d.ts +2 -3
  75. package/dist/slash-commands/helpers.d.ts +1 -1
  76. package/dist/slash-commands/index.d.ts +1 -1
  77. package/dist/slash-commands/intake.d.ts +10 -0
  78. package/dist/slash-commands/memory-triage.d.ts +1 -1
  79. package/dist/slash-commands/provider-status.d.ts +1 -1
  80. package/dist/subcommands/handlers/hq.d.ts +20 -0
  81. package/dist/subcommands/handlers/per-subcommand-help-data.d.ts +1 -1
  82. package/dist/{update-MV6TUACD.js → update-LTDJGAFU.js} +3 -3
  83. package/dist/{update-check-UMYTOH7Z.js → update-check-WARHSVZA.js} +2 -2
  84. package/dist/webui-server/connection-handler.d.ts +1 -1
  85. package/dist/webui-server/context-breakdown.d.ts +1 -1
  86. package/dist/webui-server/cost-helpers.d.ts +1 -1
  87. package/dist/webui-server/lifecycle.d.ts +1 -1
  88. package/dist/webui-server/prefs-seeding.d.ts +1 -1
  89. package/dist/webui-server/setup-events.d.ts +1 -1
  90. package/dist/webui-server/static-serve.d.ts +1 -1
  91. package/dist/{webui-server-NFNRGNNT.js → webui-server-E3OPEKU5.js} +18 -10
  92. package/dist/webui-server-options.d.ts +1 -1
  93. package/dist/wiring/command-host-state.d.ts +2 -2
  94. package/dist/wiring/controllers.d.ts +1 -2
  95. package/dist/wiring/dep-watcher.d.ts +1 -1
  96. package/dist/wiring/director-setup.d.ts +3 -3
  97. package/dist/wiring/eternal-command-handlers.d.ts +2 -2
  98. package/dist/wiring/management-tools.d.ts +2 -2
  99. package/dist/wiring/provider-runtime.d.ts +1 -1
  100. package/dist/wiring/provider-status.d.ts +1 -1
  101. package/dist/wiring/provider-utility-tools.d.ts +3 -3
  102. package/dist/wiring/provider.d.ts +1 -1
  103. package/dist/wiring/replay.d.ts +1 -1
  104. package/dist/wiring/runtime-controller-deps.d.ts +1 -1
  105. package/dist/wiring/runtime-dispatch-state.d.ts +1 -2
  106. package/dist/wiring/runtime-lifecycle-deps.d.ts +2 -2
  107. package/dist/wiring/runtime-picker-deps.d.ts +1 -2
  108. package/dist/wiring/sage.d.ts +1 -1
  109. package/dist/wiring/session-command-handlers.d.ts +1 -2
  110. package/dist/wiring/session.d.ts +6 -1
  111. package/dist/wiring/slash-commands.d.ts +2 -3
  112. package/package.json +23 -23
@@ -24,18 +24,24 @@ import {
24
24
  trySaveImplementationPlan,
25
25
  trySaveSpecFromAIOutput,
26
26
  trySaveTasksFromAIOutput
27
- } from "./chunk-XTIXVJXP.js";
27
+ } from "./chunk-DGXNL7OT.js";
28
28
  import {
29
29
  WEBUI_SESSION_CHILD_CAPABILITIES,
30
30
  writeWebuiSessionChildError,
31
31
  writeWebuiSessionChildReady
32
- } from "./chunk-PFVVUH5B.js";
32
+ } from "./chunk-3JPTNADJ.js";
33
33
  import {
34
34
  theme
35
35
  } from "./chunk-QD544J2B.js";
36
36
  import {
37
37
  fmtTok
38
38
  } from "./chunk-TYO2OVAD.js";
39
+ import {
40
+ resolveActiveApiKey
41
+ } from "./chunk-SZ42FYPT.js";
42
+ import {
43
+ activeProfileConfigPath
44
+ } from "./chunk-YMXXOOFN.js";
39
45
  import {
40
46
  terminalLink,
41
47
  terminalText
@@ -43,12 +49,6 @@ import {
43
49
  import {
44
50
  CLI_VERSION
45
51
  } from "./chunk-XJXDOF63.js";
46
- import {
47
- resolveActiveApiKey
48
- } from "./chunk-PJHET45A.js";
49
- import {
50
- activeProfileConfigPath
51
- } from "./chunk-YMXXOOFN.js";
52
52
  import "./chunk-7OCVIDC7.js";
53
53
 
54
54
  // src/execution.ts
@@ -203,7 +203,7 @@ async function runWebUIDispatch(ctx) {
203
203
  const isSimpleUi = !isSessionChild && flags["simpleui"] === true;
204
204
  agent.disableInteractiveConfirmation();
205
205
  renderer.setSilent(true);
206
- const { runWebUI } = await import("./webui-server-NFNRGNNT.js");
206
+ const { runWebUI } = await import("./webui-server-E3OPEKU5.js");
207
207
  const flagValue = (names) => {
208
208
  for (const name of names) {
209
209
  if (!Object.hasOwn(flags, name)) continue;
@@ -258,7 +258,7 @@ async function runWebUIDispatch(ctx) {
258
258
  webuiPublicWsUrl = webuiSessionChild?.publicWsUrl ?? flagValue(["webui-public-ws-url", "public-ws-url"]) ?? process.env["WEBUI_PUBLIC_WS_URL"];
259
259
  webuiRequireToken = webuiSessionChild?.requireToken ?? flagBoolean(["webui-require-token", "require-token"]) ?? envFlag("WEBUI_REQUIRE_TOKEN");
260
260
  if (isSimpleUi) {
261
- const { ensureSimpleUiDistDir } = await import("./simpleui-dist-JIFGUJO7.js");
261
+ const { ensureSimpleUiDistDir } = await import("./simpleui-dist-33VO3QHF.js");
262
262
  frontendDistDir = await ensureSimpleUiDistDir();
263
263
  }
264
264
  } catch (err) {
@@ -435,7 +435,8 @@ async function runWebUIDispatch(ctx) {
435
435
  function resolveExecutionMode(positional, flags) {
436
436
  const prompt = typeof flags["prompt"] === "string" ? flags["prompt"] : "";
437
437
  if (positional.length > 0 || prompt.length > 0) return "single-shot";
438
- if (flags.tui && flags["no-tui"] !== true && !flags.webui && !flags["webui-session-child"]) return "tui";
438
+ if (flags.tui && flags["no-tui"] !== true && !flags.webui && !flags["webui-session-child"])
439
+ return "tui";
439
440
  if (flags.webui || flags["webui-session-child"]) return "webui";
440
441
  return "repl";
441
442
  }
@@ -579,7 +580,17 @@ function createTuiCoordinatorCallbacks({
579
580
  import * as path2 from "node:path";
580
581
  import { AutonomousCoordinator } from "@wrongstack/core/coordination";
581
582
  function setupAutonomousCoordinator(ctx) {
582
- const { state, events, context, wpaths, mailbox, director, getDirector, coordinatorController, onCoordinatorStopSetter } = ctx;
583
+ const {
584
+ state,
585
+ events,
586
+ context,
587
+ wpaths,
588
+ mailbox,
589
+ director,
590
+ getDirector,
591
+ coordinatorController,
592
+ onCoordinatorStopSetter
593
+ } = ctx;
583
594
  const ensure = () => {
584
595
  if (state.autonomousCoordinator) return state.autonomousCoordinator;
585
596
  const currentDirector = getDirector?.() ?? director;
@@ -601,7 +612,9 @@ function setupAutonomousCoordinator(ctx) {
601
612
  Context: ${JSON.stringify(prompt.context)}
602
613
 
603
614
  Options:
604
- ${prompt.options.map((o, i) => ` ${i + 1}. [${o.id}] ${o.label}${o.consequence ? ` \u2014 ${o.consequence}` : ""}`).join("\n")}
615
+ ${prompt.options.map(
616
+ (o, i) => ` ${i + 1}. [${o.id}] ${o.label}${o.consequence ? ` \u2014 ${o.consequence}` : ""}`
617
+ ).join("\n")}
605
618
 
606
619
  Risk: ${prompt.risk}
607
620
 
@@ -622,7 +635,9 @@ Reply with ONLY the JSON object.`
622
635
  },
623
636
  { signal: context.signal }
624
637
  );
625
- const text = resp.content.filter((b) => b.type === "text").map((b) => b.text).join("\n").trim();
638
+ const text = resp.content.filter(
639
+ (b) => b.type === "text"
640
+ ).map((b) => b.text).join("\n").trim();
626
641
  const cleaned = text.replace(/^```(?:json)?\s*/i, "").replace(/```$/, "").trim();
627
642
  try {
628
643
  const parsed = JSON.parse(cleaned);
@@ -666,14 +681,20 @@ Reply with ONLY the JSON object.`
666
681
  coordinatorController["onCoordinatorTasks"] = async () => {
667
682
  if (!state.autonomousCoordinator) return null;
668
683
  await state.autonomousCoordinator.graph.load();
669
- return state.autonomousCoordinator.auction.getPendingTasks().map((task) => ({ id: task.id, title: task.title, priority: task.priority, tags: task.tags }));
684
+ return state.autonomousCoordinator.auction.getPendingTasks().map((task) => ({
685
+ id: task.id,
686
+ title: task.title,
687
+ priority: task.priority,
688
+ tags: task.tags
689
+ }));
670
690
  };
671
691
  coordinatorController["onCoordinatorClaim"] = async (taskId) => {
672
692
  if (!state.autonomousCoordinator) return "No coordinator is active.";
673
693
  await state.autonomousCoordinator.graph.load();
674
694
  const goal = state.autonomousCoordinator.graph.get(taskId);
675
695
  if (goal?.type !== "goal") return `Task ${taskId.slice(0, 8)} not found.`;
676
- if (goal.status !== "pending") return `Task ${taskId.slice(0, 8)} is ${goal.status}, not claimable.`;
696
+ if (goal.status !== "pending")
697
+ return `Task ${taskId.slice(0, 8)} is ${goal.status}, not claimable.`;
677
698
  const ok = await state.autonomousCoordinator.auction.claim(
678
699
  taskId,
679
700
  `terminal@${context.session.id ?? "unknown"}`,
@@ -687,8 +708,12 @@ Reply with ONLY the JSON object.`
687
708
  await state.autonomousCoordinator.graph.load();
688
709
  const goal = state.autonomousCoordinator.graph.get(taskId);
689
710
  if (goal?.type !== "goal") return `Task ${taskId.slice(0, 8)} not found.`;
690
- if (goal.status !== "in_progress") return `Task ${taskId.slice(0, 8)} is ${goal.status}, cannot complete.`;
691
- await state.autonomousCoordinator.reportTaskCompletion(taskId, result ?? "Terminal worker completed the task");
711
+ if (goal.status !== "in_progress")
712
+ return `Task ${taskId.slice(0, 8)} is ${goal.status}, cannot complete.`;
713
+ await state.autonomousCoordinator.reportTaskCompletion(
714
+ taskId,
715
+ result ?? "Terminal worker completed the task"
716
+ );
692
717
  return null;
693
718
  };
694
719
  coordinatorController["onCoordinatorFail"] = async (taskId, error) => {
@@ -696,7 +721,8 @@ Reply with ONLY the JSON object.`
696
721
  await state.autonomousCoordinator.graph.load();
697
722
  const goal = state.autonomousCoordinator.graph.get(taskId);
698
723
  if (goal?.type !== "goal") return `Task ${taskId.slice(0, 8)} not found.`;
699
- if (goal.status !== "in_progress") return `Task ${taskId.slice(0, 8)} is ${goal.status}, cannot fail.`;
724
+ if (goal.status !== "in_progress")
725
+ return `Task ${taskId.slice(0, 8)} is ${goal.status}, cannot fail.`;
700
726
  await state.autonomousCoordinator.reportTaskFailure(taskId, error);
701
727
  return null;
702
728
  };
@@ -705,8 +731,18 @@ Reply with ONLY the JSON object.`
705
731
  await state.autonomousCoordinator.syncFromGraph();
706
732
  const stats = state.autonomousCoordinator.getStats();
707
733
  return {
708
- goals: { total: stats.goals.total, done: stats.goals.done, pending: stats.goals.pending, failed: stats.goals.failed },
709
- dag: { running: stats.dag.running, ready: stats.dag.ready, done: stats.dag.done, failed: stats.dag.failed },
734
+ goals: {
735
+ total: stats.goals.total,
736
+ done: stats.goals.done,
737
+ pending: stats.goals.pending,
738
+ failed: stats.goals.failed
739
+ },
740
+ dag: {
741
+ running: stats.dag.running,
742
+ ready: stats.dag.ready,
743
+ done: stats.dag.done,
744
+ failed: stats.dag.failed
745
+ },
710
746
  auction: { pending: stats.auction.pending, inProgress: stats.auction.in_progress }
711
747
  };
712
748
  };
@@ -798,9 +834,9 @@ function wireGoal(events) {
798
834
  // src/boot/tui-live-sessions.ts
799
835
  import * as path3 from "node:path";
800
836
  async function getLiveSessions(ctx) {
801
- const { SessionRegistry } = await import("@wrongstack/core/storage");
837
+ const { getSessionRegistry } = await import("@wrongstack/core/storage");
802
838
  const globalRoot = path3.dirname(ctx.state.wpaths.globalConfig);
803
- const registry = new SessionRegistry(globalRoot);
839
+ const registry = getSessionRegistry(globalRoot);
804
840
  const sessions = await registry.list();
805
841
  return sessions.filter((s) => s.status !== "stale").map((s) => ({
806
842
  sessionId: s.sessionId,
@@ -863,9 +899,12 @@ async function onProjectSelect(ctx, slug, kind) {
863
899
  const hasActiveAgents = fleetRunning > 0 || eternalActive || parallelActive;
864
900
  if (hasActiveAgents) {
865
901
  const parts = [
866
- color3.yellow("\u26A0 Switching project in place; active background work is still tied to the previous project:")
902
+ color3.yellow(
903
+ "\u26A0 Switching project in place; active background work is still tied to the previous project:"
904
+ )
867
905
  ];
868
- if (fleetRunning > 0) parts.push(color3.dim(` \u2022 ${fleetRunning} subagent(s) currently running`));
906
+ if (fleetRunning > 0)
907
+ parts.push(color3.dim(` \u2022 ${fleetRunning} subagent(s) currently running`));
869
908
  if (eternalActive) parts.push(color3.dim(" \u2022 Eternal engine is active"));
870
909
  if (parallelActive) parts.push(color3.dim(" \u2022 Parallel engine is active"));
871
910
  parts.push("");
@@ -881,18 +920,16 @@ ${parts.join("\n")}
881
920
  `));
882
921
  } catch (err) {
883
922
  renderer.write(
884
- color3.red(
885
- `Project switch failed: ${err instanceof Error ? err.message : String(err)}
886
- `
887
- )
923
+ color3.red(`Project switch failed: ${err instanceof Error ? err.message : String(err)}
924
+ `)
888
925
  );
889
926
  }
890
927
  }
891
928
 
892
929
  // src/boot/tui-project-spawn.ts
893
930
  import { spawn } from "node:child_process";
894
- import { createRequire } from "node:module";
895
931
  import * as fs from "node:fs/promises";
932
+ import { createRequire } from "node:module";
896
933
  import * as path5 from "node:path";
897
934
  import { color as color4 } from "@wrongstack/core/utils";
898
935
  async function handleProjectSwitchSpawn(opts) {
@@ -968,6 +1005,7 @@ async function switchProjectInPlace(ctx, targetRoot, displayName) {
968
1005
  const stat2 = await fs2.stat(resolved).catch(() => null);
969
1006
  if (!stat2?.isDirectory()) return `Cannot switch: not a directory: ${resolved}`;
970
1007
  const oldWriter = context.session;
1008
+ const oldSessionStore = state.activeSessionStore;
971
1009
  const oldUsage = tokenCounter.total();
972
1010
  const oldProjectRoot = state.projectRoot;
973
1011
  const nextWpaths = resolveWstackPaths({
@@ -992,23 +1030,53 @@ async function switchProjectInPlace(ctx, targetRoot, displayName) {
992
1030
  } catch (err) {
993
1031
  await nextWriter.close().catch(() => void 0);
994
1032
  await nextSessionStore.delete(nextWriter.id).catch(() => void 0);
1033
+ await nextSessionStore.dispose?.();
995
1034
  return `Cannot switch: ${err instanceof Error ? err.message : String(err)}`;
996
1035
  }
997
1036
  if (!state.activateSessionIdentity) {
998
1037
  await nextWriter.close().catch(() => void 0);
999
1038
  await nextSessionStore.delete(nextWriter.id).catch(() => void 0);
1039
+ await nextSessionStore.dispose?.();
1000
1040
  return "Cannot switch: session ownership registry is unavailable.";
1001
1041
  }
1042
+ let targetClaim;
1043
+ let targetActivated = false;
1002
1044
  try {
1003
- await state.activateSessionIdentity(nextWriter.id, {
1045
+ const { getSessionRegistry } = await import("@wrongstack/core/storage");
1046
+ const registry = getSessionRegistry(state.wpaths.globalRoot);
1047
+ targetClaim = await registry.reserveResume({
1048
+ sessionId: nextWriter.id,
1049
+ projectSlug: nextWpaths.projectSlug,
1050
+ projectRoot: resolved
1051
+ });
1052
+ const target = {
1004
1053
  projectSlug: nextWpaths.projectSlug,
1005
1054
  projectRoot: resolved,
1006
1055
  projectName: displayName || path6.basename(resolved),
1007
1056
  workingDir: resolved
1057
+ };
1058
+ await targetClaim.activate({
1059
+ sessionId: nextWriter.id,
1060
+ ...target,
1061
+ clientType: "tui",
1062
+ pid: process.pid,
1063
+ startedAt: (/* @__PURE__ */ new Date()).toISOString()
1008
1064
  });
1065
+ targetActivated = true;
1066
+ await state.activateSessionIdentity(nextWriter.id, target);
1009
1067
  } catch (err) {
1068
+ if (!targetActivated) await targetClaim?.cancel().catch(() => void 0);
1069
+ else if (oldWriter) {
1070
+ await state.activateSessionIdentity(oldWriter.id, {
1071
+ projectSlug: state.wpaths.projectSlug,
1072
+ projectRoot: oldProjectRoot,
1073
+ projectName: path6.basename(oldProjectRoot),
1074
+ workingDir: context.workingDir
1075
+ }).catch(() => void 0);
1076
+ }
1010
1077
  await nextWriter.close().catch(() => void 0);
1011
1078
  await nextSessionStore.delete(nextWriter.id).catch(() => void 0);
1079
+ await nextSessionStore.dispose?.();
1012
1080
  return `Cannot switch: ${err instanceof Error ? err.message : String(err)}`;
1013
1081
  }
1014
1082
  await Promise.resolve(state.detachActiveTodosCheckpoint?.()).catch(() => void 0);
@@ -1093,6 +1161,7 @@ async function switchProjectInPlace(ctx, targetRoot, displayName) {
1093
1161
  })
1094
1162
  );
1095
1163
  }
1164
+ await oldSessionStore?.dispose?.().catch(() => void 0);
1096
1165
  const emitUntyped = events.emit;
1097
1166
  emitUntyped("project.switched", { from: oldProjectRoot, to: resolved, name: displayName });
1098
1167
  return null;
@@ -1100,7 +1169,7 @@ async function switchProjectInPlace(ctx, targetRoot, displayName) {
1100
1169
 
1101
1170
  // src/boot/tui-sdd-callback.ts
1102
1171
  async function getSDDContext() {
1103
- const { getActiveSDDContext: getActiveSDDContext2 } = await import("./sdd-runtime-AIJCJGWC.js");
1172
+ const { getActiveSDDContext: getActiveSDDContext2 } = await import("./sdd-runtime-GFZ3NJKS.js");
1104
1173
  return getActiveSDDContext2();
1105
1174
  }
1106
1175
  async function onSDDOutput(output) {
@@ -1111,11 +1180,10 @@ async function onSDDOutput(output) {
1111
1180
  autoDetectTaskCompletion: autoDetectTaskCompletion2,
1112
1181
  getTaskProgress: getTaskProgress2,
1113
1182
  getActiveSDDPhase: getActiveSDDPhase2
1114
- } = await import("./sdd-runtime-AIJCJGWC.js");
1183
+ } = await import("./sdd-runtime-GFZ3NJKS.js");
1115
1184
  const messages = [];
1116
1185
  const specSaved = await trySaveSpecFromAIOutput2(output);
1117
- if (specSaved)
1118
- messages.push("\u2713 Spec detected and saved! Use /sdd approve to continue.");
1186
+ if (specSaved) messages.push("\u2713 Spec detected and saved! Use /sdd approve to continue.");
1119
1187
  const planSaved = trySaveImplementationPlan2(output);
1120
1188
  if (planSaved) messages.push("\u2713 Implementation plan saved!");
1121
1189
  const tasksSaved = await trySaveTasksFromAIOutput2(output);
@@ -1164,22 +1232,9 @@ async function resumeSession(ctx, sessionId) {
1164
1232
  );
1165
1233
  return null;
1166
1234
  }
1167
- try {
1168
- const { SessionRegistry } = await import("@wrongstack/core/storage");
1169
- const registry = new SessionRegistry(path7.dirname(state.wpaths.globalConfig));
1170
- const live = (await registry.list()).find(
1171
- (s) => s.sessionId === canonicalSessionId && s.status !== "stale" && s.pid !== process.pid
1172
- );
1173
- if (live) {
1174
- throw new Error(
1175
- `Session is open in another running wstack (pid ${live.pid}) \u2014 it cannot be resumed here while live.`
1176
- );
1177
- }
1178
- } catch (err) {
1179
- if (err instanceof Error && err.message.startsWith("Session is open")) throw err;
1180
- }
1181
1235
  const previousSessionId = agent.ctx.session?.id;
1182
1236
  let identityClaimed = false;
1237
+ let resumeClaim;
1183
1238
  let writerSwapped = false;
1184
1239
  let openedWriter;
1185
1240
  let oldWriter;
@@ -1189,12 +1244,34 @@ async function resumeSession(ctx, sessionId) {
1189
1244
  let oldPlanPath;
1190
1245
  let oldTaskPath;
1191
1246
  try {
1192
- if (state.activateSessionIdentity) {
1247
+ if (state.wpaths.projectSlug && state.wpaths.globalRoot) {
1248
+ const { getSessionRegistry } = await import("@wrongstack/core/storage");
1249
+ const registry = getSessionRegistry(state.wpaths.globalRoot);
1250
+ resumeClaim = await registry.reserveResume({
1251
+ sessionId: canonicalSessionId,
1252
+ projectSlug: state.wpaths.projectSlug,
1253
+ projectRoot: state.projectRoot
1254
+ });
1255
+ } else if (state.activateSessionIdentity) {
1193
1256
  await state.activateSessionIdentity(canonicalSessionId);
1194
1257
  identityClaimed = true;
1195
1258
  }
1196
1259
  const resumed = await state.activeSessionStore.resume(canonicalSessionId);
1197
1260
  openedWriter = resumed.writer;
1261
+ if (resumeClaim) {
1262
+ await resumeClaim.activate({
1263
+ sessionId: canonicalSessionId,
1264
+ projectSlug: state.wpaths.projectSlug,
1265
+ projectRoot: state.projectRoot,
1266
+ projectName: path7.basename(state.projectRoot),
1267
+ workingDir: agent.ctx.workingDir,
1268
+ clientType: "tui",
1269
+ pid: process.pid,
1270
+ startedAt: (/* @__PURE__ */ new Date()).toISOString()
1271
+ });
1272
+ identityClaimed = true;
1273
+ await state.activateSessionIdentity?.(canonicalSessionId);
1274
+ }
1198
1275
  const meta = resumed.data.metadata;
1199
1276
  const entries = replaySessionMessages(
1200
1277
  resumed.data.messages,
@@ -1329,6 +1406,7 @@ async function resumeSession(ctx, sessionId) {
1329
1406
  void oldWriterFinalize;
1330
1407
  return result;
1331
1408
  } catch (err) {
1409
+ if (!identityClaimed) await resumeClaim?.cancel().catch(() => void 0);
1332
1410
  if (identityClaimed && previousSessionId) {
1333
1411
  await state.activateSessionIdentity?.(previousSessionId).catch((rollbackErr) => {
1334
1412
  console.error(
@@ -2127,19 +2205,16 @@ async function finalizeExecutionCleanup(input) {
2127
2205
  );
2128
2206
  });
2129
2207
  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
- }
2208
+ events.emit("session.ended", {
2209
+ id: activeSession.id,
2210
+ sessionId: activeSession.id,
2211
+ usage: tokenCounter.total(),
2212
+ waitUntil: (work) => {
2213
+ const tracked = Promise.resolve(work).finally(() => sessionEndProducers.delete(tracked));
2214
+ void tracked.catch(() => void 0);
2215
+ sessionEndProducers.add(tracked);
2141
2216
  }
2142
- );
2217
+ });
2143
2218
  try {
2144
2219
  while (sessionEndProducers.size > 0) {
2145
2220
  await Promise.allSettled([...sessionEndProducers]);
@@ -2196,10 +2271,7 @@ import { randomUUID } from "node:crypto";
2196
2271
  import { WIDE_SUBAGENT_CAPABILITIES } from "@wrongstack/core/security";
2197
2272
 
2198
2273
  // src/kanban-dispatch-route.ts
2199
- import {
2200
- fallbackProfileChain,
2201
- parseModelRef as parseModelRef2
2202
- } from "@wrongstack/core/agent";
2274
+ import { fallbackProfileChain, parseModelRef as parseModelRef2 } from "@wrongstack/core/agent";
2203
2275
  function resolveKanbanDispatchRoute(config, spawnOpts) {
2204
2276
  let provider = spawnOpts?.provider;
2205
2277
  let model = spawnOpts?.model;
@@ -2330,8 +2402,7 @@ function createReplFleetCallbacks({
2330
2402
  }
2331
2403
 
2332
2404
  // src/fleet-statusline.ts
2333
- import { color as color5 } from "@wrongstack/core/utils";
2334
- import { onResize } from "@wrongstack/core/utils";
2405
+ import { color as color5, onResize } from "@wrongstack/core/utils";
2335
2406
  function fmtElapsed(ms) {
2336
2407
  const s = Math.floor(ms / 1e3);
2337
2408
  if (s < 60) return `${s}s`;
@@ -3236,16 +3307,16 @@ function installChimeraReviewHandler({
3236
3307
  const changedBasenameIndex = /* @__PURE__ */ new Map();
3237
3308
  for (const file of p.files) {
3238
3309
  const normalized = normalizeFileKeyForCitation(file.path, p.cwd);
3239
- const basename6 = path10.basename(file.path).toLowerCase();
3240
- const bucket = changedBasenameIndex.get(basename6);
3310
+ const basename7 = path10.basename(file.path).toLowerCase();
3311
+ const bucket = changedBasenameIndex.get(basename7);
3241
3312
  if (bucket) bucket.push(normalized);
3242
- else changedBasenameIndex.set(basename6, [normalized]);
3313
+ else changedBasenameIndex.set(basename7, [normalized]);
3243
3314
  }
3244
3315
  const droppedCitations = citedFindings.filter((finding) => {
3245
3316
  const citedKey = normalizeFileKeyForCitation(finding.location.file, p.cwd);
3246
3317
  if (citedPaths.has(citedKey)) return false;
3247
- const basename6 = path10.basename(finding.location.file).toLowerCase();
3248
- const bucket = changedBasenameIndex.get(basename6);
3318
+ const basename7 = path10.basename(finding.location.file).toLowerCase();
3319
+ const bucket = changedBasenameIndex.get(basename7);
3249
3320
  return !(bucket && bucket.length === 1);
3250
3321
  });
3251
3322
  const effectiveHasFindings = reviewHasFindings && (parsedReview.findings.length === 0 || parsedReview.findings.length > droppedCitations.length);
@@ -3534,11 +3605,23 @@ async function predictNextTasks(input, opts) {
3534
3605
  }
3535
3606
 
3536
3607
  // src/repl.ts
3537
- import { toErrorMessage } from "@wrongstack/core/utils";
3538
- import { color as color9, estimateRequestTokensCalibrated as estimateRequestTokensCalibrated2, expectDefined, hasOpenTodos as hasOpenTodos2 } from "@wrongstack/core/utils";
3539
3608
  import { detectContinueIntent, InputBuilder, resolveContinuation } from "@wrongstack/core/agent";
3540
3609
  import { goalFilePath, loadGoal, summarizeUsage } from "@wrongstack/core/goal";
3610
+ import {
3611
+ color as color9,
3612
+ estimateRequestTokensCalibrated as estimateRequestTokensCalibrated2,
3613
+ expectDefined,
3614
+ hasOpenTodos as hasOpenTodos2,
3615
+ toErrorMessage
3616
+ } from "@wrongstack/core/utils";
3541
3617
  import { readClipboardImage, routeImagesForModel } from "@wrongstack/runtime";
3618
+ import { createAutoProceedLoopGuard } from "@wrongstack/tools/auto-proceed-loop-guard";
3619
+
3620
+ // src/repl-auto-proceed.ts
3621
+ import { color as color6, estimateRequestTokensCalibrated } from "@wrongstack/core/utils";
3622
+ import {
3623
+ GROUNDED_NO_PROGRESS_STEER
3624
+ } from "@wrongstack/tools/auto-proceed-loop-guard";
3542
3625
 
3543
3626
  // src/repl-suggestions.ts
3544
3627
  import { hasOpenTodos } from "@wrongstack/core/utils";
@@ -3556,8 +3639,6 @@ function parseSuggestionsFromOutput(finalText, todos) {
3556
3639
  }
3557
3640
 
3558
3641
  // src/repl-auto-proceed.ts
3559
- import { color as color6, estimateRequestTokensCalibrated } from "@wrongstack/core/utils";
3560
- import { GROUNDED_NO_PROGRESS_STEER } from "@wrongstack/tools/auto-proceed-loop-guard";
3561
3642
  async function runAutoProceed(opts, suggestion, delayMs, ctrl, loopGuard, grounded = false) {
3562
3643
  const truncated = suggestion.length > 80 ? `${suggestion.slice(0, 77)}\u2026` : suggestion;
3563
3644
  console.log(
@@ -3708,6 +3789,54 @@ async function runContextCompaction(opts, _signal) {
3708
3789
  }
3709
3790
  }
3710
3791
 
3792
+ // src/repl-client-registration.ts
3793
+ import * as crypto from "node:crypto";
3794
+ import * as path11 from "node:path";
3795
+ import { getSharedProjectMailbox, resolveProjectDir } from "@wrongstack/core/coordination";
3796
+ import { wstackGlobalRoot } from "@wrongstack/core/utils";
3797
+ function registerReplClient(opts) {
3798
+ const replProjectRoot = opts.projectRoot ?? process.cwd();
3799
+ const projectDir = resolveProjectDir(replProjectRoot, wstackGlobalRoot());
3800
+ const clientId = `repl@${crypto.randomUUID().slice(0, 8)}`;
3801
+ const hqConnection = startCliHqConnection({
3802
+ clientKind: "repl",
3803
+ projectRoot: replProjectRoot,
3804
+ projectName: path11.basename(replProjectRoot),
3805
+ appConfig: opts.appConfig,
3806
+ capabilities: ["telemetry.publish", "mailbox.summary"]
3807
+ });
3808
+ const clientMailbox = getSharedProjectMailbox(
3809
+ projectDir,
3810
+ void 0,
3811
+ () => hqConnection.getPublisher()
3812
+ );
3813
+ let closed = false;
3814
+ let clientHeartbeat;
3815
+ clientMailbox.registerClient({
3816
+ clientId,
3817
+ sessionId: opts.getSessionId?.() ?? replProjectRoot,
3818
+ name: `REPL [${path11.basename(replProjectRoot)}]`,
3819
+ source: "repl",
3820
+ pid: process.pid
3821
+ }).then(() => {
3822
+ if (closed) return;
3823
+ clientHeartbeat = setInterval(() => {
3824
+ clientMailbox.clientHeartbeat({ clientId, sessionId: opts.getSessionId?.() ?? replProjectRoot }).catch(() => {
3825
+ });
3826
+ }, 15e3);
3827
+ }).catch(() => {
3828
+ });
3829
+ return {
3830
+ clientId,
3831
+ close() {
3832
+ closed = true;
3833
+ if (clientHeartbeat) clearInterval(clientHeartbeat);
3834
+ clientMailbox.deregisterClient(clientId).catch(() => void 0);
3835
+ hqConnection.stop();
3836
+ }
3837
+ };
3838
+ }
3839
+
3711
3840
  // src/repl-input.ts
3712
3841
  import { color as color7 } from "@wrongstack/core/utils";
3713
3842
  async function readPossiblyMultiline(opts) {
@@ -3765,59 +3894,7 @@ function printBanner(renderer, projectName) {
3765
3894
  `);
3766
3895
  }
3767
3896
 
3768
- // src/repl-client-registration.ts
3769
- import * as crypto from "node:crypto";
3770
- import * as path11 from "node:path";
3771
- import {
3772
- getSharedProjectMailbox,
3773
- resolveProjectDir
3774
- } from "@wrongstack/core/coordination";
3775
- import { wstackGlobalRoot } from "@wrongstack/core/utils";
3776
- function registerReplClient(opts) {
3777
- const replProjectRoot = opts.projectRoot ?? process.cwd();
3778
- const projectDir = resolveProjectDir(replProjectRoot, wstackGlobalRoot());
3779
- const clientId = `repl@${crypto.randomUUID().slice(0, 8)}`;
3780
- const hqConnection = startCliHqConnection({
3781
- clientKind: "repl",
3782
- projectRoot: replProjectRoot,
3783
- projectName: path11.basename(replProjectRoot),
3784
- appConfig: opts.appConfig,
3785
- capabilities: ["telemetry.publish", "mailbox.summary"]
3786
- });
3787
- const clientMailbox = getSharedProjectMailbox(
3788
- projectDir,
3789
- void 0,
3790
- () => hqConnection.getPublisher()
3791
- );
3792
- let closed = false;
3793
- let clientHeartbeat;
3794
- clientMailbox.registerClient({
3795
- clientId,
3796
- sessionId: opts.getSessionId?.() ?? replProjectRoot,
3797
- name: `REPL [${path11.basename(replProjectRoot)}]`,
3798
- source: "repl",
3799
- pid: process.pid
3800
- }).then(() => {
3801
- if (closed) return;
3802
- clientHeartbeat = setInterval(() => {
3803
- clientMailbox.clientHeartbeat({ clientId, sessionId: opts.getSessionId?.() ?? replProjectRoot }).catch(() => {
3804
- });
3805
- }, 15e3);
3806
- }).catch(() => {
3807
- });
3808
- return {
3809
- clientId,
3810
- close() {
3811
- closed = true;
3812
- if (clientHeartbeat) clearInterval(clientHeartbeat);
3813
- clientMailbox.deregisterClient(clientId).catch(() => void 0);
3814
- hqConnection.stop();
3815
- }
3816
- };
3817
- }
3818
-
3819
3897
  // src/repl.ts
3820
- import { createAutoProceedLoopGuard } from "@wrongstack/tools/auto-proceed-loop-guard";
3821
3898
  var DEFAULT_MAX_CONSECUTIVE_AUTO_PROCEED = 50;
3822
3899
  async function runRepl(opts) {
3823
3900
  if (opts.banner !== false) printBanner(opts.renderer, opts.projectName);
@@ -3931,9 +4008,7 @@ async function runRepl(opts) {
3931
4008
  continue;
3932
4009
  }
3933
4010
  } catch (err) {
3934
- opts.renderer.writeError(
3935
- `[eternal] ${toErrorMessage(err)}`
3936
- );
4011
+ opts.renderer.writeError(`[eternal] ${toErrorMessage(err)}`);
3937
4012
  }
3938
4013
  await new Promise((resolve3) => setTimeout(resolve3, 250));
3939
4014
  continue;
@@ -4007,9 +4082,7 @@ async function runRepl(opts) {
4007
4082
  continue;
4008
4083
  }
4009
4084
  } catch (err) {
4010
- opts.renderer.writeError(
4011
- `[parallel] ${toErrorMessage(err)}`
4012
- );
4085
+ opts.renderer.writeError(`[parallel] ${toErrorMessage(err)}`);
4013
4086
  }
4014
4087
  await new Promise((resolve3) => setTimeout(resolve3, 250));
4015
4088
  continue;
@@ -4041,6 +4114,16 @@ ${lines.join("\n")}
4041
4114
  const resolved = resolveContinuation({ todos, suggestions: [] });
4042
4115
  top = resolved.source === "todo" ? resolved.text : "";
4043
4116
  groundedTodo = top !== "";
4117
+ if (resolved.source === "todo" && resolved.todoId) {
4118
+ const selected = todos.find((todo) => todo.id === resolved.todoId);
4119
+ if (selected?.status === "pending") {
4120
+ opts.agent.ctx.state.replaceTodos(
4121
+ todos.map(
4122
+ (todo) => todo.id === resolved.todoId ? { ...todo, status: "in_progress" } : todo.status === "in_progress" ? { ...todo, status: "pending" } : todo
4123
+ )
4124
+ );
4125
+ }
4126
+ }
4044
4127
  }
4045
4128
  if (!top) {
4046
4129
  } else {
@@ -4207,10 +4290,22 @@ ${color9.dim(taskList2)}
4207
4290
  todos: opts.agent.ctx.todos,
4208
4291
  suggestions: getSuggestions()
4209
4292
  });
4293
+ if (resolved.source === "todo" && resolved.todoId) {
4294
+ const selected = opts.agent.ctx.todos.find((todo) => todo.id === resolved.todoId);
4295
+ if (selected?.status === "pending") {
4296
+ opts.agent.ctx.state.replaceTodos(
4297
+ opts.agent.ctx.todos.map(
4298
+ (todo) => todo.id === resolved.todoId ? { ...todo, status: "in_progress" } : todo.status === "in_progress" ? { ...todo, status: "pending" } : todo
4299
+ )
4300
+ );
4301
+ }
4302
+ }
4210
4303
  if (resolved.source === "open") {
4211
4304
  opts.renderer.write(
4212
4305
  ` ${color9.amber("\u26A0")} ${color9.bold("'continue' has no anchor")} ${color9.dim("\u2014 no pending todo or suggestion.")}
4213
- ` + color9.dim(" If you proceed, I'll choose the next step from context; that can drift.\n")
4306
+ ` + color9.dim(
4307
+ " If you proceed, I'll choose the next step from context; that can drift.\n"
4308
+ )
4214
4309
  );
4215
4310
  const ans = (await opts.reader.readLine(color9.dim(" Proceed anyway? [Y/n \xB7 e = type your own] "))).trim().toLowerCase();
4216
4311
  if (ans === "n" || ans === "no") {
@@ -4487,9 +4582,7 @@ async function pasteClipboardImage(builder, opts) {
4487
4582
  opts.renderer.write(color9.dim(` \u21B3 ${placeholder} (PNG ${kb}KB)
4488
4583
  `));
4489
4584
  } catch (err) {
4490
- opts.renderer.writeError(
4491
- `Clipboard image error: ${toErrorMessage(err)}`
4492
- );
4585
+ opts.renderer.writeError(`Clipboard image error: ${toErrorMessage(err)}`);
4493
4586
  }
4494
4587
  }
4495
4588
  async function loadGoalSafe(opts) {
@@ -4525,9 +4618,7 @@ async function renderGoalBanner(opts) {
4525
4618
  try {
4526
4619
  await opts.slashRegistry.dispatch("/autonomy eternal", opts.agent.ctx);
4527
4620
  } catch (err) {
4528
- opts.renderer.writeError(
4529
- `Auto-resume failed: ${toErrorMessage(err)}`
4530
- );
4621
+ opts.renderer.writeError(`Auto-resume failed: ${toErrorMessage(err)}`);
4531
4622
  }
4532
4623
  } else {
4533
4624
  opts.renderer.write(
@@ -5159,4 +5250,4 @@ export {
5159
5250
  execute,
5160
5251
  resolveReviewerFallbackModels
5161
5252
  };
5162
- //# sourceMappingURL=execution-CQ772VPS.js.map
5253
+ //# sourceMappingURL=execution-LZRYRGDD.js.map