tmux-ide 2.9.0-beta.21 → 2.9.0-beta.26

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 (209) hide show
  1. package/bin/cli.js +46791 -43589
  2. package/package.json +2 -2
  3. package/packages/contracts/src/__tests__/daemon-wire.test.ts +2 -2
  4. package/packages/contracts/src/__tests__/fixtures/daemon-wire-v3.json +35 -0
  5. package/packages/contracts/src/__tests__/issue-error.test.ts +1 -1
  6. package/packages/contracts/src/__tests__/multiplexer-verbs.test.ts +3 -1
  7. package/packages/contracts/src/__tests__/pane-stream.test.ts +17 -5
  8. package/packages/contracts/src/__tests__/tmux-server-scope.test.ts +166 -0
  9. package/packages/contracts/src/__tests__/window-links.test.ts +243 -0
  10. package/packages/contracts/src/actions-contract.ts +12 -0
  11. package/packages/contracts/src/daemon-resource-request.test.ts +1 -1
  12. package/packages/contracts/src/daemon-wire.ts +10 -5
  13. package/packages/contracts/src/fleet-client-state.ts +3 -0
  14. package/packages/contracts/src/fleet-lifecycle.ts +5 -0
  15. package/packages/contracts/src/index.ts +2 -0
  16. package/packages/contracts/src/interaction-receipts.ts +39 -0
  17. package/packages/contracts/src/issue-error.ts +1 -1
  18. package/packages/contracts/src/multiplexer-verbs.ts +25 -1
  19. package/packages/contracts/src/pane-stream.ts +51 -8
  20. package/packages/contracts/src/tmux-server-scope.ts +172 -0
  21. package/packages/contracts/src/window-links.ts +76 -0
  22. package/packages/contracts/src/workspace-multiplexer.ts +54 -0
  23. package/packages/core/src/interaction-receipts.ts +4 -0
  24. package/packages/daemon/dist/command-center/actions/command-definitions.js +6 -0
  25. package/packages/daemon/dist/command-center/actions/handlers/workspace-multiplexer.js +2 -0
  26. package/packages/daemon/dist/command-center/actions/registry.js +13 -1
  27. package/packages/daemon/dist/command-center/discovery.js +2 -9
  28. package/packages/daemon/dist/command-center/server.js +21 -1
  29. package/packages/daemon/dist/command-center/tmux-server-native-backing.js +37 -0
  30. package/packages/daemon/dist/command-center/tmux-servers.js +351 -0
  31. package/packages/daemon/dist/lib/canonical-daemon-bootstrap.js +64 -8
  32. package/packages/daemon/dist/lib/canonical-daemon.js +5 -2
  33. package/packages/daemon/dist/lib/daemon-embed.js +198 -30
  34. package/packages/daemon/dist/lib/embedded-tmux-server-owners.js +147 -0
  35. package/packages/daemon/dist/lib/fleet-lifecycle-authority.js +31 -11
  36. package/packages/daemon/dist/lib/headless-daemon.js +10 -1
  37. package/packages/daemon/dist/lib/runtime-namespace.js +17 -3
  38. package/packages/daemon/dist/lib/tmux-client-execution.js +59 -0
  39. package/packages/daemon/dist/lib/tmux-named-socket-fence.js +4 -0
  40. package/packages/daemon/dist/lib/tmux-server-generation-runner.js +62 -0
  41. package/packages/daemon/dist/lib/tmux-server-owner.js +285 -0
  42. package/packages/daemon/dist/lib/tmux-server-owners.js +192 -0
  43. package/packages/daemon/dist/lib/tmux-server-proof.js +82 -0
  44. package/packages/daemon/dist/lib/tmux-server-registration.js +85 -0
  45. package/packages/daemon/dist/lib/tmux-server-session-create.js +43 -0
  46. package/packages/daemon/dist/lib/tmux-server-session-open.js +101 -0
  47. package/packages/daemon/dist/lib/tmux-servers-cli.js +134 -0
  48. package/packages/daemon/dist/lib/tmux-session-mutation-fence.js +55 -0
  49. package/packages/daemon/dist/lib/tmux-window-link-guard.js +88 -0
  50. package/packages/daemon/dist/lib/workspace-config-loader.js +3 -0
  51. package/packages/daemon/dist/lib/workspace-multiplexer-verbs.js +82 -1
  52. package/packages/daemon/dist/lib/workspace-pane-creation.js +13 -57
  53. package/packages/daemon/dist/lib/workspace-promotion.js +91 -12
  54. package/packages/daemon/dist/lib/workspace-registry.js +4 -0
  55. package/packages/daemon/dist/server/pane-stream-upgrade.js +20 -6
  56. package/packages/daemon/dist/terminal/attachments/native-runtime.js +61 -17
  57. package/packages/daemon/dist/terminal/mirror/__tests__/scripted-channel.js +9 -1
  58. package/packages/daemon/dist/terminal/mirror/__tests__/simulated-channel.js +11 -2
  59. package/packages/daemon/dist/terminal/mirror/control-channel.js +65 -6
  60. package/packages/daemon/dist/terminal/mirror/mirror-service.js +44 -0
  61. package/packages/daemon/dist/terminal/mirror/session-channel.js +210 -50
  62. package/packages/daemon/dist/terminal/mirror/window-link-authority.js +160 -0
  63. package/packages/daemon/dist/terminal/pane-stream/lease-manager.js +3 -3
  64. package/packages/daemon/dist/terminal/pane-stream/pane-stream-websocket.js +40 -6
  65. package/packages/daemon/dist/terminal/protocol/live-session-identity.js +9 -0
  66. package/packages/daemon/dist/terminal/protocol/native-backing-client.js +2 -1
  67. package/packages/daemon/dist/terminal/session-runtime/interaction-receipt-facts.js +9 -0
  68. package/packages/daemon/dist/terminal/session-runtime/registry.js +6 -0
  69. package/packages/daemon/dist/terminal/session-runtime/semantic-mutation-executor.js +1 -1
  70. package/packages/daemon/dist/terminal/session-runtime/semantic-mutation-resource-changes.js +1 -0
  71. package/packages/daemon/dist/tui/mirror/application-shell-daemon-connection.js +7 -2
  72. package/packages/daemon/dist/tui/mirror/application-shell-server-connection.js +114 -0
  73. package/packages/daemon/dist/tui/mirror/menu-model.js +1 -1
  74. package/packages/daemon/dist/tui/mirror/open-tui-verified-routing.js +34 -4
  75. package/packages/daemon/dist/tui/mirror/open-tui-workspace-runtime-port.js +29 -8
  76. package/packages/daemon/dist/tui/mirror/runtime/application-guided-tour-integration.jsx +119 -0
  77. package/packages/daemon/dist/tui/mirror/runtime/application-guided-tour-owner.js +132 -0
  78. package/packages/daemon/dist/tui/mirror/runtime/application-home-agent-roster.jsx +21 -9
  79. package/packages/daemon/dist/tui/mirror/runtime/application-home-agent-transport.js +63 -1
  80. package/packages/daemon/dist/tui/mirror/runtime/application-home-agents-owner.js +8 -2
  81. package/packages/daemon/dist/tui/mirror/runtime/application-home-agents.js +3 -1
  82. package/packages/daemon/dist/tui/mirror/runtime/application-home-catalog-owner.js +11 -5
  83. package/packages/daemon/dist/tui/mirror/runtime/application-home-catalog.js +140 -75
  84. package/packages/daemon/dist/tui/mirror/runtime/application-home-experience.js +40 -0
  85. package/packages/daemon/dist/tui/mirror/runtime/application-home-fleet.js +132 -0
  86. package/packages/daemon/dist/tui/mirror/runtime/application-machine-agents.js +9 -0
  87. package/packages/daemon/dist/tui/mirror/runtime/application-machine-catalog.js +12 -2
  88. package/packages/daemon/dist/tui/mirror/runtime/application-machine-navigation.js +211 -31
  89. package/packages/daemon/dist/tui/mirror/runtime/application-machine-sidebar.jsx +91 -37
  90. package/packages/daemon/dist/tui/mirror/runtime/application-performance-log.js +20 -7
  91. package/packages/daemon/dist/tui/mirror/runtime/application-root-configuration.js +9 -3
  92. package/packages/daemon/dist/tui/mirror/runtime/application-route-connection.js +95 -2
  93. package/packages/daemon/dist/tui/mirror/runtime/application-shell-home.jsx +6 -2
  94. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-interaction-controller.js +158 -2
  95. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-workspace-policy.js +43 -0
  96. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-workspace.jsx +78 -25
  97. package/packages/daemon/dist/tui/mirror/runtime/application-theme-repaint.js +9 -0
  98. package/packages/daemon/dist/tui/mirror/runtime/fleet-lifecycle-client.js +44 -1
  99. package/packages/daemon/dist/tui/mirror/runtime/guided-tour-coach.jsx +54 -0
  100. package/packages/daemon/dist/tui/mirror/runtime/guided-tour-storage.js +67 -0
  101. package/packages/daemon/dist/tui/mirror/runtime/guided-tour.js +113 -0
  102. package/packages/daemon/dist/tui/mirror/runtime/open-tui-generation-host.js +1 -1
  103. package/packages/daemon/dist/tui/mirror/runtime/resize-terminal-pane.js +4 -0
  104. package/packages/daemon/dist/tui/mirror/runtime/select-terminal-pane.js +2 -1
  105. package/packages/daemon/dist/tui/mirror/runtime/semantic-shell-viewport-resize.js +12 -4
  106. package/packages/daemon/dist/tui/mirror/runtime/terminal-pane-input-router.js +6 -3
  107. package/packages/daemon/dist/tui/mirror/workspace/application-command-description.js +11 -2
  108. package/packages/daemon/dist/tui/mirror/workspace/terminal-window-strip.jsx +2 -1
  109. package/packages/daemon/src/command-center/actions/command-definitions.ts +6 -0
  110. package/packages/daemon/src/command-center/actions/errors.ts +4 -0
  111. package/packages/daemon/src/command-center/actions/handlers/workspace-multiplexer.ts +2 -0
  112. package/packages/daemon/src/command-center/actions/registry.ts +14 -0
  113. package/packages/daemon/src/command-center/discovery.ts +2 -10
  114. package/packages/daemon/src/command-center/server.ts +29 -1
  115. package/packages/daemon/src/command-center/tmux-server-native-backing.ts +49 -0
  116. package/packages/daemon/src/command-center/tmux-servers.ts +479 -0
  117. package/packages/daemon/src/lib/canonical-daemon-bootstrap.ts +111 -4
  118. package/packages/daemon/src/lib/canonical-daemon.ts +15 -3
  119. package/packages/daemon/src/lib/daemon-embed.ts +241 -28
  120. package/packages/daemon/src/lib/embedded-tmux-server-owners.ts +190 -0
  121. package/packages/daemon/src/lib/fleet-lifecycle-authority.ts +33 -9
  122. package/packages/daemon/src/lib/headless-daemon.ts +18 -1
  123. package/packages/daemon/src/lib/runtime-namespace.ts +24 -3
  124. package/packages/daemon/src/lib/tmux-client-execution.ts +56 -0
  125. package/packages/daemon/src/lib/tmux-named-socket-fence.ts +5 -0
  126. package/packages/daemon/src/lib/tmux-server-generation-runner.ts +81 -0
  127. package/packages/daemon/src/lib/tmux-server-owner.ts +336 -0
  128. package/packages/daemon/src/lib/tmux-server-owners.ts +228 -0
  129. package/packages/daemon/src/lib/tmux-server-proof.ts +95 -0
  130. package/packages/daemon/src/lib/tmux-server-registration.ts +105 -0
  131. package/packages/daemon/src/lib/tmux-server-session-create.ts +52 -0
  132. package/packages/daemon/src/lib/tmux-server-session-open.ts +106 -0
  133. package/packages/daemon/src/lib/tmux-servers-cli.ts +186 -0
  134. package/packages/daemon/src/lib/tmux-session-mutation-fence.ts +62 -0
  135. package/packages/daemon/src/lib/tmux-window-link-guard.ts +112 -0
  136. package/packages/daemon/src/lib/workspace-config-loader.ts +3 -0
  137. package/packages/daemon/src/lib/workspace-multiplexer-verbs.ts +121 -1
  138. package/packages/daemon/src/lib/workspace-pane-creation.ts +16 -55
  139. package/packages/daemon/src/lib/workspace-promotion.ts +98 -12
  140. package/packages/daemon/src/lib/workspace-registry.ts +5 -0
  141. package/packages/daemon/src/server/pane-stream-upgrade.ts +25 -5
  142. package/packages/daemon/src/terminal/attachments/native-runtime.ts +70 -16
  143. package/packages/daemon/src/terminal/mirror/control-channel.ts +64 -7
  144. package/packages/daemon/src/terminal/mirror/events.ts +2 -0
  145. package/packages/daemon/src/terminal/mirror/mirror-service.ts +56 -0
  146. package/packages/daemon/src/terminal/mirror/session-channel.ts +245 -50
  147. package/packages/daemon/src/terminal/mirror/window-link-authority.ts +203 -0
  148. package/packages/daemon/src/terminal/pane-stream/lease-manager.ts +3 -3
  149. package/packages/daemon/src/terminal/pane-stream/pane-stream-websocket.ts +50 -6
  150. package/packages/daemon/src/terminal/protocol/live-session-identity.ts +14 -0
  151. package/packages/daemon/src/terminal/protocol/native-backing-client.ts +4 -1
  152. package/packages/daemon/src/terminal/session-runtime/interaction-receipt-facts.ts +9 -0
  153. package/packages/daemon/src/terminal/session-runtime/registry.ts +9 -0
  154. package/packages/daemon/src/terminal/session-runtime/semantic-mutation-executor.ts +2 -2
  155. package/packages/daemon/src/terminal/session-runtime/semantic-mutation-resource-changes.ts +1 -0
  156. package/packages/daemon/src/tui/mirror/application-shell-daemon-connection.ts +28 -2
  157. package/packages/daemon/src/tui/mirror/application-shell-server-connection.ts +154 -0
  158. package/packages/daemon/src/tui/mirror/menu-model.ts +1 -1
  159. package/packages/daemon/src/tui/mirror/open-tui-verified-routing.ts +41 -3
  160. package/packages/daemon/src/tui/mirror/open-tui-workspace-runtime-port.ts +47 -6
  161. package/packages/daemon/src/tui/mirror/runtime/application-entry.ts +2 -1
  162. package/packages/daemon/src/tui/mirror/runtime/application-fleet-session-actions.tsx +10 -4
  163. package/packages/daemon/src/tui/mirror/runtime/application-fleet-tabs.ts +2 -0
  164. package/packages/daemon/src/tui/mirror/runtime/application-guided-tour-integration.tsx +199 -0
  165. package/packages/daemon/src/tui/mirror/runtime/application-guided-tour-owner.ts +162 -0
  166. package/packages/daemon/src/tui/mirror/runtime/application-home-agent-roster.tsx +36 -10
  167. package/packages/daemon/src/tui/mirror/runtime/application-home-agent-transport.ts +69 -0
  168. package/packages/daemon/src/tui/mirror/runtime/application-home-agents-owner.ts +12 -2
  169. package/packages/daemon/src/tui/mirror/runtime/application-home-agents.ts +13 -2
  170. package/packages/daemon/src/tui/mirror/runtime/application-home-catalog-owner.ts +13 -3
  171. package/packages/daemon/src/tui/mirror/runtime/application-home-catalog.ts +172 -100
  172. package/packages/daemon/src/tui/mirror/runtime/application-home-experience.ts +59 -0
  173. package/packages/daemon/src/tui/mirror/runtime/application-home-fleet.ts +175 -0
  174. package/packages/daemon/src/tui/mirror/runtime/application-machine-agents.ts +9 -1
  175. package/packages/daemon/src/tui/mirror/runtime/application-machine-catalog.ts +19 -7
  176. package/packages/daemon/src/tui/mirror/runtime/application-machine-navigation.ts +285 -36
  177. package/packages/daemon/src/tui/mirror/runtime/application-machine-overlays.tsx +1 -1
  178. package/packages/daemon/src/tui/mirror/runtime/application-machine-sidebar.tsx +124 -40
  179. package/packages/daemon/src/tui/mirror/runtime/application-palette-preview.tsx +3 -0
  180. package/packages/daemon/src/tui/mirror/runtime/application-performance-log.ts +18 -6
  181. package/packages/daemon/src/tui/mirror/runtime/application-root-configuration.ts +12 -3
  182. package/packages/daemon/src/tui/mirror/runtime/application-root-v2.tsx +40 -40
  183. package/packages/daemon/src/tui/mirror/runtime/application-route-connection.ts +93 -1
  184. package/packages/daemon/src/tui/mirror/runtime/application-shell-catalog.tsx +4 -0
  185. package/packages/daemon/src/tui/mirror/runtime/application-shell-home.tsx +20 -1
  186. package/packages/daemon/src/tui/mirror/runtime/application-shell-view.tsx +10 -0
  187. package/packages/daemon/src/tui/mirror/runtime/application-terminal-interaction-controller.ts +177 -2
  188. package/packages/daemon/src/tui/mirror/runtime/application-terminal-workspace-policy.ts +62 -0
  189. package/packages/daemon/src/tui/mirror/runtime/application-terminal-workspace.tsx +87 -30
  190. package/packages/daemon/src/tui/mirror/runtime/application-theme-repaint.ts +19 -0
  191. package/packages/daemon/src/tui/mirror/runtime/fleet-lifecycle-client.ts +55 -0
  192. package/packages/daemon/src/tui/mirror/runtime/guided-tour-coach.tsx +118 -0
  193. package/packages/daemon/src/tui/mirror/runtime/guided-tour-storage.ts +72 -0
  194. package/packages/daemon/src/tui/mirror/runtime/guided-tour.ts +147 -0
  195. package/packages/daemon/src/tui/mirror/runtime/open-tui-generation-host.ts +1 -1
  196. package/packages/daemon/src/tui/mirror/runtime/resize-terminal-pane.ts +3 -0
  197. package/packages/daemon/src/tui/mirror/runtime/select-terminal-pane.ts +3 -0
  198. package/packages/daemon/src/tui/mirror/runtime/semantic-shell-viewport-resize.ts +11 -4
  199. package/packages/daemon/src/tui/mirror/runtime/terminal-pane-input-router.ts +15 -4
  200. package/packages/daemon/src/tui/mirror/workspace/application-command-description.ts +13 -2
  201. package/packages/daemon/src/tui/mirror/workspace/terminal-window-strip.tsx +5 -1
  202. package/packages/daemon-client/package.json +3 -1
  203. package/packages/daemon-client/src/index.ts +2 -0
  204. package/packages/daemon-client/src/pane-stream-client.test.ts +108 -38
  205. package/packages/daemon-client/src/pane-stream-client.ts +26 -0
  206. package/packages/daemon-client/src/scoped-tmux-server-transport.test.ts +114 -0
  207. package/packages/daemon-client/src/scoped-tmux-server-transport.ts +385 -0
  208. package/packages/daemon-client/src/tmux-server-client.test.ts +279 -0
  209. package/packages/daemon-client/src/tmux-server-client.ts +287 -0
@@ -432,6 +432,9 @@ export function writeCanonicalDaemonInfo(info, claim) {
432
432
  instanceId: info.instanceId,
433
433
  startedAt: info.startedAt,
434
434
  ...(info.environmentId !== undefined ? { environmentId: info.environmentId } : {}),
435
+ ...(info.tmuxServerProofVersion !== undefined
436
+ ? { tmuxServerProofVersion: info.tmuxServerProofVersion }
437
+ : {}),
435
438
  bindHostname: info.bindHostname,
436
439
  authToken: info.authToken,
437
440
  ...(info.provenance !== undefined ? { provenance: info.provenance } : {}),
@@ -795,11 +798,11 @@ export async function probeCanonicalDaemonHealth(info, parentSignal) {
795
798
  }
796
799
  }
797
800
  /** Credential-free endpoint binding probe; callers compare instanceId to daemon.json. */
798
- export async function probeCanonicalDaemonIdentity(info, parentSignal) {
801
+ export async function probeCanonicalDaemonIdentity(info, parentSignal, includeTmuxServerProof = false) {
799
802
  if (!(await isCanonicalDaemonAlive(info)))
800
803
  return null;
801
804
  try {
802
- const res = await fetch(canonicalDaemonUrl("http", info.bindHostname, info.port, "/identity"), {
805
+ const res = await fetch(canonicalDaemonUrl("http", info.bindHostname, info.port, includeTmuxServerProof ? "/identity?tmuxServerProof=1" : "/identity"), {
803
806
  signal: parentSignal ?? timeoutSignal(750),
804
807
  });
805
808
  if (!res.ok)
@@ -6,7 +6,15 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
6
6
  }
7
7
  return path;
8
8
  };
9
- import { runtimeTmuxArgs } from "./runtime-namespace.js";
9
+ import { createNativeTmuxSessionCreator } from "./tmux-server-session-create.js";
10
+ import { createTmuxSessionMutationFence } from "./tmux-session-mutation-fence.js";
11
+ import { createNativeTmuxSessionOpener } from "./tmux-server-session-open.js";
12
+ import { createServerGenerationFencedTmuxRunner, createServerGenerationFencedTmuxAsyncRunner, } from "./tmux-server-generation-runner.js";
13
+ import { createNativeTmuxServerCatalog } from "./tmux-server-owner.js";
14
+ import { createEmbeddedTmuxServerOwners } from "./embedded-tmux-server-owners.js";
15
+ import { captureTmuxServerProofAsync, captureTmuxServerProof, captureUnboundTmuxSelectorProof, } from "./tmux-server-proof.js";
16
+ import { assertCanonicalDaemonServerIntent } from "./canonical-daemon-bootstrap.js";
17
+ import { runtimeTmuxArgs, resolveTmuxServerIntent, resolveRuntimeNamespace, } from "./runtime-namespace.js";
10
18
  import { createFleetPreviewCapture } from "../command-center/resources/fleet-preview-route.js";
11
19
  import { mountTerminalNativeBackingRoute } from "../command-center/resources/terminal-native-backing-route.js";
12
20
  import { startOwnedEmbeddedDaemon } from "./embedded-daemon-lifecycle.js";
@@ -28,7 +36,7 @@ import { createTmuxAuthorityReplacementProbe } from "./tmux-authority-replacemen
28
36
  import { createNamedSocketFence } from "./tmux-named-socket-fence.js";
29
37
  import { fleetSessionIdForName } from "../command-center/resources/fleet-catalog.js";
30
38
  import { DAEMON_WIRE_PROTOCOL_VERSION, DaemonInstanceIdentitySchemaZ, PANE_STREAM_REDEEM_PATH, PaneStreamLoopbackWebSocketUrlSchemaZ, TERMINAL_ATTACHMENT_REDEEM_PATH, TerminalAttachmentLoopbackWebSocketUrlSchemaZ, } from "@tmux-ide/contracts";
31
- import { classifySessionInspectionError, DaemonSessionMonitor, execTmuxAsync, isConfirmedMissingTmuxTarget, parseDaemonMonitorPanes, readPortProcessFactsAsync, } from "./daemon-session-monitor.js";
39
+ import { classifySessionInspectionError, DaemonSessionMonitor, isConfirmedMissingTmuxTarget, parseDaemonMonitorPanes, readPortProcessFactsAsync, } from "./daemon-session-monitor.js";
32
40
  import { DaemonShutdownError, DaemonStartupError } from "./errors.js";
33
41
  import { handlePtyWebSocket, shutdownPtyBridges } from "../server/ws-route.js";
34
42
  import { broadcastInteractionReceipt, broadcastResourceChanged, handleWsEventsConnection, setFleetFactsObserverDiagnostics, setFleetFactsTmuxRunner, shutdownWsEventObservation, } from "../command-center/ws-events.js";
@@ -101,14 +109,6 @@ function tmux(...args) {
101
109
  timeout: 2_000,
102
110
  }).trim();
103
111
  }
104
- function tmuxSilent(...args) {
105
- try {
106
- return tmux(...args);
107
- }
108
- catch {
109
- return "";
110
- }
111
- }
112
112
  function assertTmuxSession(sessionName, runTmux = (args) => tmux(...args)) {
113
113
  try {
114
114
  runTmux(["has-session", "-t", sessionName]);
@@ -353,7 +353,7 @@ function sameCanonicalInstance(left, right) {
353
353
  left.startedAt === right.startedAt &&
354
354
  left.bindHostname === right.bindHostname);
355
355
  }
356
- async function requestValidatedDaemonShutdown(info, deadline) {
356
+ async function requestValidatedDaemonShutdown(info, deadline, intent) {
357
357
  if (info.supervisionId)
358
358
  throw new DaemonStartupError("A supervised daemon cannot be taken over", "canonical_takeover_refused");
359
359
  const identity = await probeCanonicalDaemonIdentity(info, deadline.signal);
@@ -366,6 +366,8 @@ async function requestValidatedDaemonShutdown(info, deadline) {
366
366
  identity.startedAt !== info.startedAt) {
367
367
  throw new DaemonStartupError("Canonical daemon identity changed before takeover", "canonical_takeover_identity_mismatch");
368
368
  }
369
+ await assertCanonicalDaemonServerIntent(info, intent);
370
+ assertTakeoverDeadline(deadline, "Tmux server intent proof exceeded the takeover deadline");
369
371
  const health = await probeCanonicalDaemonHealth(info, deadline.signal);
370
372
  assertTakeoverDeadline(deadline, "Canonical daemon did not answer the takeover request before the takeover deadline");
371
373
  if (!health ||
@@ -471,7 +473,7 @@ function closeWsGoingAway(ws) {
471
473
  }
472
474
  ws.close(1001, reason);
473
475
  }
474
- async function startHttpServer({ sessionName, requestedPort, bindHostname, dir, authToken, localBypassToken, silent, readProjectAuth, daemonIdentity, workspacePaneCreationBackend, workspaceOpenBackend, workspaceOpenHandoffBackend, fleetLifecycleBackend, workspacePromotionBackend, appWindowMutationBackend, workspaceMultiplexerBackend, workspaceRegistry, terminalInventoryRuntime, getTerminalAttachmentRuntime, peekTerminalAttachmentRuntime, paneStreamRuntime, catalogLiveSessions, catalogFleet, fleetPreviewCapture, sessionRuntimeRegistry, }) {
476
+ async function startHttpServer({ sessionName, requestedPort, bindHostname, dir, authToken, localBypassToken, silent, readProjectAuth, tmuxServerProof, daemonIdentity, workspacePaneCreationBackend, workspaceOpenBackend, workspaceOpenHandoffBackend, fleetLifecycleBackend, workspacePromotionBackend, appWindowMutationBackend, workspaceMultiplexerBackend, workspaceRegistry, terminalInventoryRuntime, getTerminalAttachmentRuntime, peekTerminalAttachmentRuntime, paneStreamRuntime, catalogLiveSessions, catalogFleet, fleetPreviewCapture, sessionRuntimeRegistry, serverOwners, }) {
475
477
  const { createApp } = await import("../command-center/server.js");
476
478
  const { getRequestListener } = await import(__rewriteRelativeImportExtension(requireFromHere.resolve("@hono/node-server"), true));
477
479
  const { AuthService } = await import("./auth/auth-service.js");
@@ -490,6 +492,7 @@ async function startHttpServer({ sessionName, requestedPort, bindHostname, dir,
490
492
  }
491
493
  const authService = new AuthService(authConfig.secret);
492
494
  const app = createApp({
495
+ tmuxServerOwners: serverOwners.owners,
493
496
  authService,
494
497
  authConfig,
495
498
  remoteAccess: {
@@ -499,6 +502,7 @@ async function startHttpServer({ sessionName, requestedPort, bindHostname, dir,
499
502
  ownerToken: localBypassToken ?? null,
500
503
  },
501
504
  daemonIdentity,
505
+ tmuxServerProof,
502
506
  workspacePaneCreationBackend,
503
507
  workspaceOpenBackend,
504
508
  workspaceOpenHandoffBackend,
@@ -558,7 +562,8 @@ async function startHttpServer({ sessionName, requestedPort, bindHostname, dir,
558
562
  });
559
563
  const terminalAttachmentBoundary = attachTerminalAttachmentWebSocket(server, (create) => (create ? getTerminalAttachmentRuntime() : peekTerminalAttachmentRuntime())?.admission ??
560
564
  null);
561
- const paneStreamBoundary = attachPaneStreamWebSocket(server, paneStreamRuntime.coordinator);
565
+ const paneStreamBoundary = attachPaneStreamWebSocket(server, paneStreamRuntime.coordinator, PANE_STREAM_REDEEM_PATH, () => serverOwners.isDefaultCurrent());
566
+ serverOwners.attach(server);
562
567
  try {
563
568
  await new Promise((resolve, reject) => {
564
569
  const onError = (err) => {
@@ -612,6 +617,7 @@ export async function startEmbeddedDaemon(opts) {
612
617
  : startOwnedEmbeddedDaemon(opts, startEmbeddedDaemonGeneration);
613
618
  }
614
619
  async function startEmbeddedDaemonGeneration(opts) {
620
+ const tmuxServerIntent = resolveTmuxServerIntent();
615
621
  const sessionName = opts.sessionName ?? EMBEDDED_SESSION_NAME;
616
622
  const sessionless = opts.sessionName == null;
617
623
  const appSettings = readAppSettings();
@@ -645,7 +651,7 @@ async function startEmbeddedDaemonGeneration(opts) {
645
651
  if (state.status === "valid" && (await isCanonicalDaemonAlive(state.info))) {
646
652
  const takeoverDeadline = createTakeoverDeadline(takeoverTimeoutMs());
647
653
  try {
648
- await requestValidatedDaemonShutdown(state.info, takeoverDeadline);
654
+ await requestValidatedDaemonShutdown(state.info, takeoverDeadline, tmuxServerIntent);
649
655
  claim = await acquireCanonicalDaemonClaimAfterTakeover(state.info, takeoverDeadline);
650
656
  }
651
657
  finally {
@@ -691,7 +697,20 @@ async function startEmbeddedDaemonGeneration(opts) {
691
697
  // caller's ambient TMUX/PATH happens to select.
692
698
  const tmuxAuthority = resolveWorkspacePaneTmuxAuthority();
693
699
  const catalogTmuxRunner = createPinnedWorkspaceTmuxRunner(tmuxAuthority);
694
- const fleetFactsTmuxRunner = createPinnedWorkspaceTmuxAsyncRunner(tmuxAuthority);
700
+ const initialTmuxProof = captureTmuxServerProof(catalogTmuxRunner);
701
+ const initialNativeIdentityParts = initialTmuxProof
702
+ ? catalogTmuxRunner(["display-message", "-p", "#{pid}\t#{start_time}"]).split("\t")
703
+ : null;
704
+ const initialNativeServerIdentity = initialNativeIdentityParts
705
+ ? { pid: initialNativeIdentityParts[0], startTime: initialNativeIdentityParts[1] }
706
+ : undefined;
707
+ const sessionMutationFence = createTmuxSessionMutationFence();
708
+ const nativeGenerationTmuxRunner = sessionMutationFence.wrap(initialNativeServerIdentity
709
+ ? createServerGenerationFencedTmuxRunner(tmuxAuthority, initialNativeServerIdentity)
710
+ : catalogTmuxRunner);
711
+ const fleetFactsTmuxRunner = initialNativeServerIdentity
712
+ ? createServerGenerationFencedTmuxAsyncRunner(tmuxAuthority, initialNativeServerIdentity)
713
+ : createPinnedWorkspaceTmuxAsyncRunner(tmuxAuthority);
695
714
  const tmuxAuthorityReplaced = createTmuxAuthorityReplacementProbe(tmuxAuthority, catalogTmuxRunner);
696
715
  const registryTmuxRunner = createPinnedWorkspaceTmuxRunner(tmuxAuthority, {
697
716
  timeoutMs: WORKSPACE_REGISTRY_TMUX_TIMEOUT_MS,
@@ -714,8 +733,8 @@ async function startEmbeddedDaemonGeneration(opts) {
714
733
  const workspaceRegistry = getDefaultWorkspaceRegistry();
715
734
  await workspaceRegistry.load(() => readWorkspaceRegistrySessionInventory(registryTmuxRunner));
716
735
  const paneSourceCredentials = new PaneSourceCredentialAuthority({
717
- run: (args) => tmuxSilent(...args),
718
- runAsync: (args, signal) => execTmuxAsync(args, signal),
736
+ run: (args) => nativeGenerationTmuxRunner(args),
737
+ runAsync: (args, signal) => fleetFactsTmuxRunner(args, signal),
719
738
  });
720
739
  const legacySession = process.env.TMUX_IDE_SESSION;
721
740
  if (legacySession && !workspaceRegistry.has(legacySession)) {
@@ -754,16 +773,19 @@ async function startEmbeddedDaemonGeneration(opts) {
754
773
  daemonInstanceId: instanceId,
755
774
  registry: workspaceRegistry,
756
775
  tmuxAuthority,
776
+ io: { runTmux: nativeGenerationTmuxRunner },
757
777
  });
758
778
  const workspaceOpen = new WorkspaceOpenAuthority({
759
779
  daemonInstanceId: instanceId,
760
780
  registry: workspaceRegistry,
761
781
  tmuxAuthority,
782
+ io: { runTmux: nativeGenerationTmuxRunner },
762
783
  });
763
784
  const workspacePromotion = new WorkspacePromotionAuthority({
764
785
  daemonInstanceId: instanceId,
765
786
  registry: workspaceRegistry,
766
787
  tmuxAuthority,
788
+ io: { runTmux: fleetFactsTmuxRunner },
767
789
  });
768
790
  if (opts.restoreTmuxWorkspaces) {
769
791
  for (const workspace of workspaceRegistry.list()) {
@@ -779,7 +801,7 @@ async function startEmbeddedDaemonGeneration(opts) {
779
801
  productVersion,
780
802
  startedAt,
781
803
  registry: workspaceRegistry,
782
- runTmux: catalogTmuxRunner,
804
+ runTmux: nativeGenerationTmuxRunner,
783
805
  readFleet: () => readAdoptedFleet(workspaceRegistry, catalogTmuxRunner),
784
806
  });
785
807
  const appWindowMutation = new AppWindowMutationAuthority({
@@ -790,13 +812,22 @@ async function startEmbeddedDaemonGeneration(opts) {
790
812
  daemonInstanceId: instanceId,
791
813
  registry: workspaceRegistry,
792
814
  tmuxAuthority,
815
+ ...(initialTmuxProof
816
+ ? {
817
+ io: {
818
+ runTmux: nativeGenerationTmuxRunner,
819
+ },
820
+ }
821
+ : {}),
793
822
  });
794
823
  let sessionRuntimeRegistry = null;
795
824
  let workspaceOpenHandoff = null;
796
825
  let terminalInventoryRuntime = null;
826
+ let sessionMonitor = null;
797
827
  const externalInteractionObserver = new TmuxExternalInteractionObserver({
798
828
  daemonInstanceId: instanceId,
799
829
  internalReadOwnerToken: localBypassToken,
830
+ io: { runTmux: fleetFactsTmuxRunner },
800
831
  registry: workspaceRegistry,
801
832
  tmuxAuthority,
802
833
  // A gap cannot reconstruct historical interactions. Refresh inventory
@@ -838,6 +869,25 @@ async function startEmbeddedDaemonGeneration(opts) {
838
869
  });
839
870
  let terminalAttachmentRuntime = null;
840
871
  let paneStreamRuntime = null;
872
+ let serverOwners = null;
873
+ const defaultSessionCreator = createNativeTmuxSessionCreator({
874
+ generation: instanceId,
875
+ registry: workspaceRegistry,
876
+ run: nativeGenerationTmuxRunner,
877
+ assertOpen: () => {
878
+ if (serverOwners?.defaultRetired)
879
+ throw new Error("Default tmux owner is retired");
880
+ },
881
+ });
882
+ const defaultSessionOpener = createNativeTmuxSessionOpener({
883
+ generation: instanceId,
884
+ registry: workspaceRegistry,
885
+ run: fleetFactsTmuxRunner,
886
+ assertOpen: () => {
887
+ if (serverOwners?.defaultRetired)
888
+ throw new Error("Default tmux owner is retired");
889
+ },
890
+ });
841
891
  let runtimeTraceStream = null;
842
892
  const closeRuntimeTraceStream = async () => {
843
893
  externalInteractionObserver.setDiagnostics(null);
@@ -856,6 +906,15 @@ async function startEmbeddedDaemonGeneration(opts) {
856
906
  workspaceMultiplexer.readPane(operationId, intent);
857
907
  return;
858
908
  }
909
+ if (intent.verb === "workspace.window.link.select" ||
910
+ intent.verb === "workspace.window.link.unlink" ||
911
+ intent.verb === "workspace.pane.select") {
912
+ return workspaceMultiplexer.mutateWindowLink({ operationId, expectedDaemonInstanceId: instanceId, intent }, (session, action) => {
913
+ if (!sessionRuntimeRegistry)
914
+ throw new Error("Session runtime unavailable");
915
+ return sessionRuntimeRegistry.executeWindowLinkAction(session, action);
916
+ });
917
+ }
859
918
  return workspaceMultiplexer.mutate({ operationId, expectedDaemonInstanceId: instanceId, intent }, timing);
860
919
  };
861
920
  const runtimeTracePath = process.env.TMUX_IDE_SESSION_RUNTIME_TRACE_LOG;
@@ -918,8 +977,9 @@ async function startEmbeddedDaemonGeneration(opts) {
918
977
  publishResourceChange: (change) => broadcastResourceChanged(change, instanceId),
919
978
  },
920
979
  mirror: {
980
+ nativeServerIdentity: initialNativeServerIdentity,
921
981
  executable: tmuxAuthority.executablePath,
922
- resolveSocketPath: () => catalogTmuxRunner(["display-message", "-p", "#{socket_path}"]),
982
+ resolveSocketPath: () => nativeGenerationTmuxRunner(["display-message", "-p", "#{socket_path}"]),
923
983
  internalReadHookEmission: (runtimePaneId, marker) => externalInteractionObserver.internalReadHookEmission(runtimePaneId, marker),
924
984
  ...(selector.kind === "path" ? { socketPath: selector.path } : {}),
925
985
  ...(selector.kind === "name" && selector.name !== "default"
@@ -982,6 +1042,7 @@ async function startEmbeddedDaemonGeneration(opts) {
982
1042
  sessionRuntimeRegistry,
983
1043
  tmuxAuthority: {
984
1044
  executablePath: tmuxAuthority.executablePath,
1045
+ nativeServerIdentity: initialNativeServerIdentity,
985
1046
  socketSelector: tmuxAuthority.socketSelector,
986
1047
  trustedCwd: dir,
987
1048
  ...(tmuxAuthority.socketSelector.kind === "name"
@@ -1026,8 +1087,81 @@ async function startEmbeddedDaemonGeneration(opts) {
1026
1087
  resolvePaneSourceCredential: (credential, resolvedSession, claimedSource) => paneSourceCredentials.resolve(credential, resolvedSession, claimedSource),
1027
1088
  });
1028
1089
  await externalInteractionObserver.start();
1090
+ serverOwners = await createEmbeddedTmuxServerOwners({
1091
+ defaultAuthority: tmuxAuthority,
1092
+ defaultGeneration: instanceId,
1093
+ expectedDefaultProofDigest: initialTmuxProof?.digest ?? null,
1094
+ stateDirectory: resolveRuntimeNamespace().runtimeDir,
1095
+ webSocketBaseUrl: canonicalDaemonUrl("ws", bindHostname, port),
1096
+ defaultOwner: {
1097
+ catalog: createNativeTmuxServerCatalog(workspaceRegistry, fleetFactsTmuxRunner),
1098
+ openSession: async (liveSessionId) => {
1099
+ await createNativeTmuxServerCatalog(workspaceRegistry, fleetFactsTmuxRunner)();
1100
+ const result = await defaultSessionOpener.openSession(liveSessionId);
1101
+ terminalInventoryRuntime.invalidate();
1102
+ return result;
1103
+ },
1104
+ workspaceRegistry,
1105
+ multiplexerBackend: orderedMultiplexerBackend,
1106
+ createSession: defaultSessionCreator.createSession,
1107
+ createSessionPane: async (liveSessionId, request) => {
1108
+ const selectedSession = workspaceRegistry.get(request.intent.workspaceName)?.sessionName;
1109
+ if (!selectedSession)
1110
+ throw new Error("Selected workspace is unavailable");
1111
+ const result = await sessionMutationFence.execute({
1112
+ liveSessionId,
1113
+ sessionName: selectedSession,
1114
+ run: fleetFactsTmuxRunner,
1115
+ mutate: () => workspacePaneCreation.create(request),
1116
+ });
1117
+ terminalInventoryRuntime.invalidate();
1118
+ return result;
1119
+ },
1120
+ mutateSession: async (liveSessionId, request, authenticatedHostClientId) => {
1121
+ const selectedSession = workspaceRegistry.get(request.intent.workspaceName)?.sessionName;
1122
+ if (!selectedSession)
1123
+ throw new Error("Selected workspace is unavailable");
1124
+ return sessionMutationFence.execute({
1125
+ liveSessionId,
1126
+ sessionName: selectedSession,
1127
+ run: fleetFactsTmuxRunner,
1128
+ mutate: () => orderedMultiplexerBackend.mutate(request, authenticatedHostClientId, undefined, true),
1129
+ });
1130
+ },
1131
+ sessionRuntimeRegistry,
1132
+ terminalInventoryRuntime,
1133
+ paneStreamRuntime,
1134
+ dispose: async () => {
1135
+ sessionMonitor?.stop();
1136
+ paneSourceCredentials.dispose();
1137
+ const transportResults = await Promise.allSettled([
1138
+ Promise.resolve().then(() => terminalAttachmentRuntime?.dispose()),
1139
+ Promise.resolve().then(() => paneStreamRuntime.dispose()),
1140
+ ]);
1141
+ const authorityResults = await Promise.allSettled([
1142
+ Promise.resolve().then(() => terminalInventoryRuntime.dispose()),
1143
+ Promise.resolve().then(() => workspacePaneCreation.dispose()),
1144
+ Promise.resolve().then(() => workspaceOpen.dispose()),
1145
+ Promise.resolve().then(() => workspaceOpenHandoff?.dispose()),
1146
+ Promise.resolve().then(() => Promise.all([
1147
+ workspacePromotion.dispose(),
1148
+ defaultSessionOpener.dispose(),
1149
+ defaultSessionCreator.dispose(),
1150
+ ]).then(() => { })),
1151
+ Promise.resolve().then(() => appWindowMutation.dispose()),
1152
+ Promise.resolve().then(() => workspaceMultiplexer.dispose()),
1153
+ Promise.resolve().then(() => externalInteractionObserver.dispose()),
1154
+ ]);
1155
+ await sessionRuntimeRegistry.dispose();
1156
+ const failures = [...transportResults, ...authorityResults].flatMap((result) => result.status === "rejected" ? [result.reason] : []);
1157
+ if (failures.length)
1158
+ throw new AggregateError(failures, "Default tmux owner retirement failed");
1159
+ },
1160
+ },
1161
+ });
1029
1162
  setFleetFactsTmuxRunner(fleetFactsTmuxRunner);
1030
1163
  startedServer = await startHttpServer({
1164
+ serverOwners,
1031
1165
  sessionName,
1032
1166
  requestedPort: port,
1033
1167
  bindHostname,
@@ -1037,6 +1171,11 @@ async function startEmbeddedDaemonGeneration(opts) {
1037
1171
  silent: opts.silent,
1038
1172
  readProjectAuth: !sessionless,
1039
1173
  daemonIdentity: { productVersion, instanceId, startedAt, environmentId },
1174
+ tmuxServerProof: async () => {
1175
+ const deadline = AbortSignal.timeout(500);
1176
+ return ((await captureTmuxServerProofAsync((args) => fleetFactsTmuxRunner(args, deadline))) ??
1177
+ captureUnboundTmuxSelectorProof(tmuxAuthority));
1178
+ },
1040
1179
  workspacePaneCreationBackend: workspacePaneCreation,
1041
1180
  workspaceOpenBackend: workspaceOpen,
1042
1181
  workspaceOpenHandoffBackend: workspaceOpenHandoff,
@@ -1056,6 +1195,7 @@ async function startEmbeddedDaemonGeneration(opts) {
1056
1195
  });
1057
1196
  }
1058
1197
  catch (error) {
1198
+ await serverOwners?.dispose();
1059
1199
  setFleetFactsTmuxRunner(null);
1060
1200
  await Promise.allSettled([
1061
1201
  Promise.resolve().then(() => terminalAttachmentRuntime?.dispose()),
@@ -1064,7 +1204,11 @@ async function startEmbeddedDaemonGeneration(opts) {
1064
1204
  workspacePaneCreation.dispose(),
1065
1205
  workspaceOpen.dispose(),
1066
1206
  Promise.resolve().then(() => workspaceOpenHandoff?.dispose()),
1067
- workspacePromotion.dispose(),
1207
+ Promise.all([
1208
+ workspacePromotion.dispose(),
1209
+ defaultSessionOpener.dispose(),
1210
+ defaultSessionCreator.dispose(),
1211
+ ]).then(() => { }),
1068
1212
  appWindowMutation.dispose(),
1069
1213
  workspaceMultiplexer.dispose(),
1070
1214
  externalInteractionObserver.dispose(),
@@ -1088,6 +1232,7 @@ async function startEmbeddedDaemonGeneration(opts) {
1088
1232
  return [...transportResults, ...runtimeResults].flatMap((result) => result.status === "rejected" ? [result.reason] : []);
1089
1233
  };
1090
1234
  const abortStartedServer = async () => {
1235
+ await serverOwners?.dispose();
1091
1236
  setFleetFactsTmuxRunner(null);
1092
1237
  const terminalFailures = [
1093
1238
  ...(await retireTerminalAttachmentTransport(terminalAttachmentRuntime, terminalAttachmentBoundary)),
@@ -1097,7 +1242,11 @@ async function startEmbeddedDaemonGeneration(opts) {
1097
1242
  const paneDisposal = Promise.resolve().then(() => workspacePaneCreation.dispose());
1098
1243
  const workspaceOpenDisposal = Promise.resolve().then(() => workspaceOpen.dispose());
1099
1244
  const workspaceOpenHandoffDisposal = Promise.resolve().then(() => workspaceOpenHandoff?.dispose());
1100
- const workspacePromotionDisposal = Promise.resolve().then(() => workspacePromotion.dispose());
1245
+ const workspacePromotionDisposal = Promise.resolve().then(() => Promise.all([
1246
+ workspacePromotion.dispose(),
1247
+ defaultSessionOpener.dispose(),
1248
+ defaultSessionCreator.dispose(),
1249
+ ]).then(() => { }));
1101
1250
  const appWindowMutationDisposal = Promise.resolve().then(() => appWindowMutation.dispose());
1102
1251
  const workspaceMultiplexerDisposal = Promise.resolve().then(() => workspaceMultiplexer.dispose());
1103
1252
  const externalInteractionDisposal = Promise.resolve().then(() => externalInteractionObserver.dispose());
@@ -1152,6 +1301,7 @@ async function startEmbeddedDaemonGeneration(opts) {
1152
1301
  environmentId,
1153
1302
  bindHostname,
1154
1303
  authToken: localBypassToken,
1304
+ tmuxServerProofVersion: 1,
1155
1305
  provenance,
1156
1306
  }, claim);
1157
1307
  const published = inspectCanonicalDaemonInfo();
@@ -1199,14 +1349,14 @@ async function startEmbeddedDaemonGeneration(opts) {
1199
1349
  stop.stop();
1200
1350
  },
1201
1351
  });
1202
- const sessionMonitor = sessionless
1352
+ sessionMonitor = sessionless
1203
1353
  ? null
1204
1354
  : new DaemonSessionMonitor({
1205
1355
  sessionName,
1206
1356
  backend: {
1207
1357
  inspectSession: async (candidate, signal) => {
1208
1358
  try {
1209
- await execTmuxAsync(["has-session", "-t", candidate], signal);
1359
+ await fleetFactsTmuxRunner(["has-session", "-t", candidate], signal);
1210
1360
  return "yes";
1211
1361
  }
1212
1362
  catch (error) {
@@ -1229,7 +1379,7 @@ async function startEmbeddedDaemonGeneration(opts) {
1229
1379
  },
1230
1380
  hasClients: async (signal) => {
1231
1381
  try {
1232
- return (await execTmuxAsync(["list-clients"], signal)).length > 0;
1382
+ return (await fleetFactsTmuxRunner(["list-clients"], signal)).length > 0;
1233
1383
  }
1234
1384
  catch {
1235
1385
  return null;
@@ -1237,7 +1387,7 @@ async function startEmbeddedDaemonGeneration(opts) {
1237
1387
  },
1238
1388
  listPanes: async (candidate, signal) => {
1239
1389
  try {
1240
- const raw = await execTmuxAsync([
1390
+ const raw = await fleetFactsTmuxRunner([
1241
1391
  "list-panes",
1242
1392
  "-t",
1243
1393
  candidate,
@@ -1260,7 +1410,7 @@ async function startEmbeddedDaemonGeneration(opts) {
1260
1410
  },
1261
1411
  setPaneOption: async (paneId, option, value, signal) => {
1262
1412
  try {
1263
- await execTmuxAsync(["set-option", "-pt", paneId, option, value], signal);
1413
+ await fleetFactsTmuxRunner(["set-option", "-pt", paneId, option, value], signal);
1264
1414
  }
1265
1415
  catch (error) {
1266
1416
  if (!isConfirmedMissingTmuxTarget(error))
@@ -1269,7 +1419,7 @@ async function startEmbeddedDaemonGeneration(opts) {
1269
1419
  },
1270
1420
  setPaneTitle: async (paneId, title, signal) => {
1271
1421
  try {
1272
- await execTmuxAsync(["select-pane", "-t", paneId, "-T", title], signal);
1422
+ await fleetFactsTmuxRunner(["select-pane", "-t", paneId, "-T", title], signal);
1273
1423
  }
1274
1424
  catch (error) {
1275
1425
  if (!isConfirmedMissingTmuxTarget(error))
@@ -1278,7 +1428,7 @@ async function startEmbeddedDaemonGeneration(opts) {
1278
1428
  },
1279
1429
  refreshClients: async (signal) => {
1280
1430
  try {
1281
- await execTmuxAsync(["refresh-client", "-S"], signal);
1431
+ await fleetFactsTmuxRunner(["refresh-client", "-S"], signal);
1282
1432
  }
1283
1433
  catch (error) {
1284
1434
  if (!isConfirmedMissingTmuxTarget(error))
@@ -1292,7 +1442,20 @@ async function startEmbeddedDaemonGeneration(opts) {
1292
1442
  const apiBaseUrl = canonicalDaemonUrl("http", bindHostname, port);
1293
1443
  const wsUrl = canonicalDaemonUrl("ws", bindHostname, port, "/ws/events");
1294
1444
  const handle = {
1295
- tmuxAuthorityReplaced,
1445
+ tmuxAuthorityReplaced: async () => {
1446
+ if (serverOwners?.defaultRetired)
1447
+ return false;
1448
+ const replaced = await tmuxAuthorityReplaced();
1449
+ // A native server replacement cannot restart unrelated server owners.
1450
+ // Legacy default-only callers retain the established restart adapter.
1451
+ if (replaced &&
1452
+ serverOwners &&
1453
+ (serverOwners.owners.list().length > 1 || serverOwners.defaultRetired)) {
1454
+ await serverOwners.owners.refresh();
1455
+ return false;
1456
+ }
1457
+ return replaced;
1458
+ },
1296
1459
  instanceId,
1297
1460
  pid: process.pid,
1298
1461
  port,
@@ -1320,6 +1483,7 @@ async function startEmbeddedDaemonGeneration(opts) {
1320
1483
  await capture(() => setActivationBackend(null));
1321
1484
  await capture(() => sessionMonitor?.stop());
1322
1485
  paneSourceCredentials.dispose();
1486
+ await capture(() => serverOwners?.dispose());
1323
1487
  // Retire direct-ticket admission, live PTYs, and the direct upgrade
1324
1488
  // listener before touching the legacy WS or HTTP surfaces.
1325
1489
  failures.push(...(await retireTerminalAttachmentTransport(terminalAttachmentRuntime, terminalAttachmentBoundary)));
@@ -1328,7 +1492,11 @@ async function startEmbeddedDaemonGeneration(opts) {
1328
1492
  await capture(() => workspacePaneCreation.dispose());
1329
1493
  await capture(() => workspaceOpen.dispose());
1330
1494
  await capture(() => workspaceOpenHandoff?.dispose());
1331
- await capture(() => workspacePromotion.dispose());
1495
+ await capture(() => Promise.all([
1496
+ workspacePromotion.dispose(),
1497
+ defaultSessionOpener.dispose(),
1498
+ defaultSessionCreator.dispose(),
1499
+ ]).then(() => { }));
1332
1500
  await capture(() => appWindowMutation.dispose());
1333
1501
  await capture(() => workspaceMultiplexer.dispose());
1334
1502
  await capture(() => externalInteractionObserver.dispose());