tmux-ide 2.9.2 → 2.9.3

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 (263) hide show
  1. package/README.md +1 -1
  2. package/bin/cli.js +2071 -625
  3. package/package.json +14 -5
  4. package/packages/contracts/src/desktop-host.ts +3 -0
  5. package/packages/contracts/src/saved-machines.ts +19 -0
  6. package/packages/contracts/src/terminal-replica.ts +1 -1
  7. package/packages/core/package.json +3 -2
  8. package/packages/core/src/terminal-delivery.ts +51 -3
  9. package/packages/core/src/terminal-fnv64-wasm.ts +4 -3
  10. package/packages/core/src/terminal-replica-hash-cache.ts +129 -31
  11. package/packages/core/src/terminal-replica-owned-row.ts +27 -0
  12. package/packages/core/src/terminal-replica.ts +13 -28
  13. package/packages/daemon/dist/command-center/daemon-fleet-facts-observer.js +96 -10
  14. package/packages/daemon/dist/command-center/resources/saved-machine-route.js +40 -1
  15. package/packages/daemon/dist/command-center/ws-events.js +5 -24
  16. package/packages/daemon/dist/lib/canonical-daemon-bootstrap.js +8 -0
  17. package/packages/daemon/dist/lib/canonical-daemon.js +28 -2
  18. package/packages/daemon/dist/lib/daemon-embed.js +1 -1
  19. package/packages/daemon/dist/lib/daemon-service-manager.js +122 -0
  20. package/packages/daemon/dist/lib/daemon-service-plan.js +127 -0
  21. package/packages/daemon/dist/lib/daemon-service.js +259 -0
  22. package/packages/daemon/dist/lib/install-origin.js +2 -0
  23. package/packages/daemon/dist/lib/local-fleet-request.js +9 -3
  24. package/packages/daemon/dist/lib/log.js +6 -10
  25. package/packages/daemon/dist/lib/managed-installer-update.js +67 -0
  26. package/packages/daemon/dist/lib/{tui-download-lock.js → private-operation-lock.js} +11 -11
  27. package/packages/daemon/dist/lib/remote-daemon-info.js +3 -2
  28. package/packages/daemon/dist/lib/remote-daemon-lifecycle.js +4 -4
  29. package/packages/daemon/dist/lib/remote-tmux-command.js +10 -0
  30. package/packages/daemon/dist/lib/runtime-namespace.js +28 -16
  31. package/packages/daemon/dist/lib/saved-machines.js +40 -2
  32. package/packages/daemon/dist/lib/ssh-daemon-transport.js +24 -9
  33. package/packages/daemon/dist/lib/tmux-server-owner.js +1 -1
  34. package/packages/daemon/dist/lib/tmux-server-registration.js +21 -3
  35. package/packages/daemon/dist/lib/tui-binary.js +2 -2
  36. package/packages/daemon/dist/lib/update.js +18 -0
  37. package/packages/daemon/dist/lib/workspace-multiplexer-verbs.js +24 -1
  38. package/packages/daemon/dist/machines.js +40 -4
  39. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Info.plist +2 -2
  40. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/MacOS/tmux-ide-notifier +0 -0
  41. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Resources/Assets.car +0 -0
  42. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/_CodeSignature/CodeResources +2 -2
  43. package/packages/daemon/dist/terminal/attachments/direct-websocket.js +4 -1
  44. package/packages/daemon/dist/terminal/attachments/native-runtime.js +22 -13
  45. package/packages/daemon/dist/terminal/mirror/mirror-service.js +101 -3
  46. package/packages/daemon/dist/terminal/mirror/registered-window-guard.js +62 -0
  47. package/packages/daemon/dist/terminal/mirror/session-channel.js +75 -4
  48. package/packages/daemon/dist/terminal/mirror/shared-window-index.js +45 -0
  49. package/packages/daemon/dist/terminal/pane-stream/pane-stream-websocket.js +11 -1
  50. package/packages/daemon/dist/terminal/session-runtime/multiplexer-backend.js +1 -0
  51. package/packages/daemon/dist/terminal/session-runtime/registry.js +56 -7
  52. package/packages/daemon/dist/terminal/session-runtime/semantic-mutation-executor.js +3 -1
  53. package/packages/daemon/dist/tui/mirror/dialog-model.js +2 -35
  54. package/packages/daemon/dist/tui/mirror/runtime/application-daemon-authority-owner.js +8 -0
  55. package/packages/daemon/dist/tui/mirror/runtime/application-home-fleet.js +20 -2
  56. package/packages/daemon/dist/tui/mirror/runtime/application-machine-agents.js +7 -1
  57. package/packages/daemon/dist/tui/mirror/runtime/application-machine-authority.js +59 -9
  58. package/packages/daemon/dist/tui/mirror/runtime/application-machine-navigation.js +27 -19
  59. package/packages/daemon/dist/tui/mirror/runtime/application-machine-sidebar.jsx +23 -18
  60. package/packages/daemon/dist/tui/mirror/runtime/application-machine-startup.js +31 -2
  61. package/packages/daemon/dist/tui/mirror/runtime/application-palette-search-owner.js +7 -3
  62. package/packages/daemon/dist/tui/mirror/runtime/application-performance-log.js +3 -0
  63. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-input-ingress.js +146 -2
  64. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-interaction-controller.js +201 -50
  65. package/packages/daemon/dist/tui/mirror/runtime/bounded-performance-record-writer.js +50 -10
  66. package/packages/daemon/dist/tui/mirror/runtime/terminal-fast-lane-renderer-adapter.js +6 -5
  67. package/packages/daemon/dist/tui/mirror/runtime/terminal-pane-input-router.js +3 -0
  68. package/packages/daemon/dist/tui/mirror/runtime/workspace-terminal-fast-lane.js +8 -2
  69. package/packages/daemon/dist/tui/mirror/terminal-text.js +35 -0
  70. package/packages/daemon/dist/tui/mirror/workspace/connection-feedback.js +5 -3
  71. package/packages/daemon/src/command-center/daemon-fleet-facts-observer.ts +100 -10
  72. package/packages/daemon/src/command-center/resources/saved-machine-route.ts +48 -1
  73. package/packages/daemon/src/command-center/ws-events.ts +5 -25
  74. package/packages/daemon/src/lib/canonical-daemon-bootstrap.ts +12 -0
  75. package/packages/daemon/src/lib/canonical-daemon.ts +44 -2
  76. package/packages/daemon/src/lib/daemon-embed.ts +1 -0
  77. package/packages/daemon/src/lib/daemon-service-manager.ts +152 -0
  78. package/packages/daemon/src/lib/daemon-service-plan.ts +153 -0
  79. package/packages/daemon/src/lib/daemon-service.ts +301 -0
  80. package/packages/daemon/src/lib/install-origin.ts +5 -0
  81. package/packages/daemon/src/lib/local-fleet-request.ts +19 -3
  82. package/packages/daemon/src/lib/log.ts +13 -9
  83. package/packages/daemon/src/lib/managed-installer-update.ts +79 -0
  84. package/packages/daemon/src/lib/{tui-download-lock.ts → private-operation-lock.ts} +15 -11
  85. package/packages/daemon/src/lib/remote-daemon-info.ts +3 -3
  86. package/packages/daemon/src/lib/remote-daemon-lifecycle.ts +4 -4
  87. package/packages/daemon/src/lib/remote-tmux-command.ts +12 -0
  88. package/packages/daemon/src/lib/runtime-namespace.ts +27 -18
  89. package/packages/daemon/src/lib/saved-machines.ts +40 -1
  90. package/packages/daemon/src/lib/ssh-daemon-transport.ts +25 -7
  91. package/packages/daemon/src/lib/tmux-server-owner.ts +1 -0
  92. package/packages/daemon/src/lib/tmux-server-registration.ts +21 -3
  93. package/packages/daemon/src/lib/tui-binary.ts +2 -2
  94. package/packages/daemon/src/lib/update.ts +24 -0
  95. package/packages/daemon/src/lib/workspace-multiplexer-verbs.ts +22 -0
  96. package/packages/daemon/src/machines.ts +53 -5
  97. package/packages/daemon/src/terminal/attachments/direct-websocket.ts +8 -2
  98. package/packages/daemon/src/terminal/attachments/native-runtime.ts +28 -13
  99. package/packages/daemon/src/terminal/mirror/mirror-service.ts +105 -3
  100. package/packages/daemon/src/terminal/mirror/registered-window-guard.ts +66 -0
  101. package/packages/daemon/src/terminal/mirror/session-channel.ts +92 -4
  102. package/packages/daemon/src/terminal/mirror/shared-window-index.ts +42 -0
  103. package/packages/daemon/src/terminal/pane-stream/pane-stream-websocket.ts +12 -1
  104. package/packages/daemon/src/terminal/session-runtime/multiplexer-backend.ts +2 -0
  105. package/packages/daemon/src/terminal/session-runtime/registry.ts +70 -8
  106. package/packages/daemon/src/terminal/session-runtime/semantic-mutation-executor.ts +3 -1
  107. package/packages/daemon/src/tui/mirror/dialog-model.ts +2 -32
  108. package/packages/daemon/src/tui/mirror/runtime/application-daemon-authority-owner.ts +8 -0
  109. package/packages/daemon/src/tui/mirror/runtime/application-home-fleet.ts +19 -2
  110. package/packages/daemon/src/tui/mirror/runtime/application-machine-agents.ts +6 -1
  111. package/packages/daemon/src/tui/mirror/runtime/application-machine-authority.ts +60 -11
  112. package/packages/daemon/src/tui/mirror/runtime/application-machine-navigation.ts +39 -33
  113. package/packages/daemon/src/tui/mirror/runtime/application-machine-sidebar.tsx +31 -23
  114. package/packages/daemon/src/tui/mirror/runtime/application-machine-startup.ts +38 -2
  115. package/packages/daemon/src/tui/mirror/runtime/application-palette-search-owner.ts +7 -4
  116. package/packages/daemon/src/tui/mirror/runtime/application-performance-log.ts +3 -0
  117. package/packages/daemon/src/tui/mirror/runtime/application-root-v2.tsx +1 -1
  118. package/packages/daemon/src/tui/mirror/runtime/application-shell-view.tsx +47 -46
  119. package/packages/daemon/src/tui/mirror/runtime/application-terminal-input-ingress.ts +165 -2
  120. package/packages/daemon/src/tui/mirror/runtime/application-terminal-interaction-controller.ts +207 -53
  121. package/packages/daemon/src/tui/mirror/runtime/bounded-performance-record-writer.ts +49 -9
  122. package/packages/daemon/src/tui/mirror/runtime/terminal-fast-lane-renderer-adapter.ts +6 -5
  123. package/packages/daemon/src/tui/mirror/runtime/terminal-pane-input-router.ts +4 -0
  124. package/packages/daemon/src/tui/mirror/runtime/workspace-terminal-fast-lane.ts +8 -3
  125. package/packages/daemon/src/tui/mirror/terminal-text.ts +32 -0
  126. package/packages/daemon/src/tui/mirror/workspace/connection-feedback.ts +6 -3
  127. package/packages/daemon-client/src/fleet-connection-status.ts +10 -1
  128. package/packages/daemon-client/src/workspace-client.ts +4 -1
  129. package/packages/contracts/src/__tests__/actions-contract.test.ts +0 -119
  130. package/packages/contracts/src/__tests__/agent-graph-overlay.test.ts +0 -428
  131. package/packages/contracts/src/__tests__/app-window-mutation.test.ts +0 -51
  132. package/packages/contracts/src/__tests__/app-window-state.test.ts +0 -34
  133. package/packages/contracts/src/__tests__/application-shell.test.ts +0 -645
  134. package/packages/contracts/src/__tests__/automation-operations.test.ts +0 -78
  135. package/packages/contracts/src/__tests__/causal-cell.test.ts +0 -47
  136. package/packages/contracts/src/__tests__/client-view-state.test.ts +0 -115
  137. package/packages/contracts/src/__tests__/cohesion-fixture.test.ts +0 -106
  138. package/packages/contracts/src/__tests__/commands.test.ts +0 -86
  139. package/packages/contracts/src/__tests__/control.test.ts +0 -154
  140. package/packages/contracts/src/__tests__/daemon-events.test.ts +0 -405
  141. package/packages/contracts/src/__tests__/daemon-resources.test.ts +0 -143
  142. package/packages/contracts/src/__tests__/daemon-wire.test.ts +0 -149
  143. package/packages/contracts/src/__tests__/desktop-host.test.ts +0 -269
  144. package/packages/contracts/src/__tests__/desktop-missions.test.ts +0 -215
  145. package/packages/contracts/src/__tests__/experience-conformance.test.ts +0 -153
  146. package/packages/contracts/src/__tests__/experience-kernel-boundary.test.ts +0 -113
  147. package/packages/contracts/src/__tests__/experience-shell.test.ts +0 -65
  148. package/packages/contracts/src/__tests__/fixtures/daemon-wire-v2.json +0 -35
  149. package/packages/contracts/src/__tests__/fixtures/daemon-wire-v3.json +0 -35
  150. package/packages/contracts/src/__tests__/fixtures/daemon-wire-v4.json +0 -35
  151. package/packages/contracts/src/__tests__/fixtures/scoped-receipt.ts +0 -62
  152. package/packages/contracts/src/__tests__/fleet-agent-graph.test.ts +0 -231
  153. package/packages/contracts/src/__tests__/fleet-catalog.test.ts +0 -270
  154. package/packages/contracts/src/__tests__/fleet-lifecycle.test.ts +0 -62
  155. package/packages/contracts/src/__tests__/focus-overlay.test.ts +0 -110
  156. package/packages/contracts/src/__tests__/ide-config.test.ts +0 -64
  157. package/packages/contracts/src/__tests__/interaction-evidence.test.ts +0 -288
  158. package/packages/contracts/src/__tests__/interaction-receipt-v2.test.ts +0 -72
  159. package/packages/contracts/src/__tests__/issue-error.test.ts +0 -78
  160. package/packages/contracts/src/__tests__/mission-projections.test.ts +0 -186
  161. package/packages/contracts/src/__tests__/missions.test.ts +0 -272
  162. package/packages/contracts/src/__tests__/multiplexer-verbs.test.ts +0 -242
  163. package/packages/contracts/src/__tests__/pane-appearance.test.ts +0 -146
  164. package/packages/contracts/src/__tests__/pane-read-result.test.ts +0 -55
  165. package/packages/contracts/src/__tests__/pane-stream.test.ts +0 -536
  166. package/packages/contracts/src/__tests__/pane-widget-marker.test.ts +0 -327
  167. package/packages/contracts/src/__tests__/performance-metrics.test.ts +0 -73
  168. package/packages/contracts/src/__tests__/performance-qualification.test.ts +0 -137
  169. package/packages/contracts/src/__tests__/rich-card-widget.test.ts +0 -29
  170. package/packages/contracts/src/__tests__/session-runtime.test.ts +0 -512
  171. package/packages/contracts/src/__tests__/startup-readiness.test.ts +0 -409
  172. package/packages/contracts/src/__tests__/terminal-attachment-stream.test.ts +0 -72
  173. package/packages/contracts/src/__tests__/terminal-attachments.test.ts +0 -329
  174. package/packages/contracts/src/__tests__/terminal-delivery.test.ts +0 -88
  175. package/packages/contracts/src/__tests__/terminal-runtime-inventory.test.ts +0 -68
  176. package/packages/contracts/src/__tests__/terminals.test.ts +0 -87
  177. package/packages/contracts/src/__tests__/tmux-server-scope.test.ts +0 -166
  178. package/packages/contracts/src/__tests__/transport-contract-loading.test.ts +0 -91
  179. package/packages/contracts/src/__tests__/visual-tokens.test.ts +0 -224
  180. package/packages/contracts/src/__tests__/window-links.test.ts +0 -243
  181. package/packages/contracts/src/__tests__/workspace-changes-resource.test.ts +0 -317
  182. package/packages/contracts/src/__tests__/workspace-changes-view.test.ts +0 -122
  183. package/packages/contracts/src/__tests__/workspace-config.test.ts +0 -294
  184. package/packages/contracts/src/__tests__/workspace-files-resource.test.ts +0 -261
  185. package/packages/contracts/src/__tests__/workspace-files-tree.test.ts +0 -147
  186. package/packages/contracts/src/__tests__/workspace-pane-creation.test.ts +0 -249
  187. package/packages/contracts/src/__tests__/workspace-promotion.test.ts +0 -94
  188. package/packages/contracts/src/__tests__/workspace-resource-identity.test.ts +0 -90
  189. package/packages/contracts/src/daemon-resource-request.test.ts +0 -192
  190. package/packages/contracts/src/native-operation-identity.test.ts +0 -23
  191. package/packages/contracts/src/workspace-admission.test.ts +0 -21
  192. package/packages/contracts/src/workspace-catalog-resource.test.ts +0 -146
  193. package/packages/core/src/agent-provisioning.test.ts +0 -42
  194. package/packages/core/src/application-shell-session.test.ts +0 -105
  195. package/packages/core/src/interaction-evidence.test.ts +0 -134
  196. package/packages/core/src/interaction-flow.test.ts +0 -66
  197. package/packages/core/src/interaction-receipts.test.ts +0 -671
  198. package/packages/core/src/navigator.test.ts +0 -34
  199. package/packages/core/src/optimistic-projection-conformance.test.ts +0 -75
  200. package/packages/core/src/optimistic-projection.test.ts +0 -118
  201. package/packages/core/src/performance-metrics.test.ts +0 -121
  202. package/packages/core/src/performance-qualification.test.ts +0 -283
  203. package/packages/core/src/saved-machines.test.ts +0 -80
  204. package/packages/core/src/terminal-compact-cold.test.ts +0 -87
  205. package/packages/core/src/terminal-conformance.test.ts +0 -48
  206. package/packages/core/src/terminal-delivery-cache-lifetime.test.ts +0 -167
  207. package/packages/core/src/terminal-delivery-encode-cooperative.test.ts +0 -140
  208. package/packages/core/src/terminal-delivery-representation-hash.test.ts +0 -77
  209. package/packages/core/src/terminal-delivery.test.ts +0 -1471
  210. package/packages/core/src/terminal-fnv64-wasm.test.ts +0 -61
  211. package/packages/core/src/terminal-replica-cold.test.ts +0 -31
  212. package/packages/core/src/terminal-replica-cooperative.test.ts +0 -170
  213. package/packages/core/src/terminal-replica-hash-cache.test.ts +0 -283
  214. package/packages/core/src/terminal-replica.test.ts +0 -347
  215. package/packages/core/src/workspace-selection.test.ts +0 -63
  216. package/packages/daemon/dist/__tests__/support.js +0 -33
  217. package/packages/daemon/dist/lib/__tests__/fixtures/workspace-state-writer.js +0 -58
  218. package/packages/daemon/dist/lib/__tests__/installed-recovery-fixture.js +0 -400
  219. package/packages/daemon/dist/terminal/__tests__/MockPtyAdapter.js +0 -182
  220. package/packages/daemon/dist/terminal/mirror/__tests__/scripted-channel.js +0 -98
  221. package/packages/daemon/dist/terminal/mirror/__tests__/simulated-channel.js +0 -156
  222. package/packages/daemon/src/tui/mirror/__snapshots__/activity-surface-renderer.test.tsx.snap +0 -42
  223. package/packages/daemon/src/tui/mirror/__snapshots__/changes-terminal-surface-renderer.test.tsx.snap +0 -267
  224. package/packages/daemon/src/tui/mirror/__snapshots__/home-files-surface-renderer.test.tsx.snap +0 -267
  225. package/packages/daemon/src/tui/mirror/__snapshots__/missions-surface-renderer.test.tsx.snap +0 -134
  226. package/packages/daemon/src/tui/mirror/__snapshots__/recipes-gallery-renderer.test.tsx.snap +0 -141
  227. package/packages/daemon/src/tui/mirror/__snapshots__/shell-chrome-renderer.test.tsx.snap +0 -134
  228. package/packages/daemon/src/tui/mirror/runtime/__snapshots__/application-shell-view-renderer.test.tsx.snap +0 -87
  229. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/agent-terminal-canvas-renderer.test.tsx.snap +0 -348
  230. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/application-shell-renderer.test.tsx.snap +0 -134
  231. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/command-palette-surface-renderer.test.tsx.snap +0 -255
  232. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/pane-frame-renderer.test.tsx.snap +0 -525
  233. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/terminal-pane-header-polish-renderer.test.tsx.snap +0 -31
  234. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/workbench-shell-renderer.test.tsx.snap +0 -134
  235. package/packages/daemon-client/src/application-shell-session.test.ts +0 -196
  236. package/packages/daemon-client/src/automation-client.test.ts +0 -214
  237. package/packages/daemon-client/src/bootstrap-coordinator.test.ts +0 -145
  238. package/packages/daemon-client/src/connection-supervisor.test.ts +0 -109
  239. package/packages/daemon-client/src/direct-application-shell-transport.test.ts +0 -941
  240. package/packages/daemon-client/src/first-latest-coordinator.test.ts +0 -175
  241. package/packages/daemon-client/src/fleet-dial-scheduler.test.ts +0 -114
  242. package/packages/daemon-client/src/fleet-environments.test.ts +0 -40
  243. package/packages/daemon-client/src/generation-bound-store-timers.test.ts +0 -74
  244. package/packages/daemon-client/src/owner-action-client.test.ts +0 -245
  245. package/packages/daemon-client/src/pane-stream-client.test.ts +0 -2841
  246. package/packages/daemon-client/src/pane-stream-clock-calibration.test.ts +0 -207
  247. package/packages/daemon-client/src/pane-stream-loopback-benchmark.test.ts +0 -51
  248. package/packages/daemon-client/src/push-resource-session.test.ts +0 -509
  249. package/packages/daemon-client/src/resource-replica.test.ts +0 -186
  250. package/packages/daemon-client/src/runtime-resource-ledger.test.ts +0 -18
  251. package/packages/daemon-client/src/scoped-tmux-server-transport.test.ts +0 -114
  252. package/packages/daemon-client/src/terminal-fast-lane.test.ts +0 -835
  253. package/packages/daemon-client/src/tmux-server-client.test.ts +0 -279
  254. package/packages/daemon-client/src/tmux-server-interaction-events.test.ts +0 -230
  255. package/packages/daemon-client/src/workspace-catalog-v2.test.ts +0 -109
  256. package/packages/daemon-client/src/workspace-client-boundaries.test.ts +0 -59
  257. package/packages/daemon-client/src/workspace-client-operations.test.ts +0 -96
  258. package/packages/daemon-client/src/workspace-client.test.ts +0 -2912
  259. package/packages/daemon-client/src/workspace-event-supervisor.test.ts +0 -1086
  260. package/packages/daemon-client/src/workspace-pane-client.test.ts +0 -80
  261. package/packages/presentation/src/presentation-contract.test.ts +0 -63
  262. package/packages/tmux-bridge/src/runner.test.ts +0 -614
  263. package/packages/tmux-bridge/src/targeting.test.ts +0 -107
@@ -1,405 +0,0 @@
1
- import { scopedReceiptFixture } from "./fixtures/scoped-receipt.ts";
2
- import { describe, expect, it } from "vitest";
3
- import { DaemonEventClientFrameSchemaZ, DaemonEventServerFrameSchemaZ } from "../daemon-events.ts";
4
-
5
- describe("daemon event contracts", () => {
6
- it("accepts strict privacy-safe interaction receipts and rejects literal input", () => {
7
- const receipt = scopedReceiptFixture({
8
- type: "interaction.receipt",
9
- sequence: 8,
10
- operationId: "10000000-0000-4000-8000-000000000001",
11
- origin: "sdk",
12
- workspaceName: "workspace.alpha",
13
- sourceSemanticPaneId: null,
14
- target: { kind: "pane", semanticPaneId: "pane.editor" },
15
- operationKind: "workspace.pane.send",
16
- phase: "observed",
17
- summary: {
18
- operationKind: "workspace.pane.send",
19
- characterCount: 14,
20
- byteCount: 14,
21
- submitted: true,
22
- },
23
- proof: {
24
- operationKind: "workspace.pane.send",
25
- observed: true,
26
- semanticPaneId: "pane.editor",
27
- },
28
- at: "2026-08-10T10:00:00.000Z",
29
- resourceRevision: null,
30
- } as const);
31
- expect(DaemonEventServerFrameSchemaZ.parse(receipt)).toEqual(receipt);
32
- expect(
33
- DaemonEventServerFrameSchemaZ.safeParse({ ...receipt, text: "private prompt" }).success,
34
- ).toBe(false);
35
- expect(
36
- DaemonEventServerFrameSchemaZ.safeParse({
37
- ...receipt,
38
- summary: { ...receipt.summary, prefix: "private" },
39
- }).success,
40
- ).toBe(false);
41
- expect(
42
- DaemonEventServerFrameSchemaZ.safeParse(
43
- scopedReceiptFixture({
44
- ...receipt,
45
- origin: "external",
46
- operationKind: "workspace.pane.read",
47
- phase: "observed",
48
- summary: { operationKind: "workspace.pane.read", observedOnly: true },
49
- proof: {
50
- operationKind: "workspace.pane.read",
51
- observed: true,
52
- semanticPaneId: "pane.editor",
53
- },
54
- }),
55
- ).success,
56
- ).toBe(true);
57
- expect(
58
- DaemonEventServerFrameSchemaZ.safeParse({
59
- ...receipt,
60
- operationKind: "workspace.pane.read",
61
- summary: receipt.summary,
62
- proof: {
63
- operationKind: "workspace.pane.read",
64
- observed: true,
65
- semanticPaneId: "pane.editor",
66
- },
67
- }).success,
68
- ).toBe(false);
69
- expect(
70
- DaemonEventServerFrameSchemaZ.safeParse(
71
- scopedReceiptFixture({
72
- ...receipt,
73
- origin: "external",
74
- phase: "observed",
75
- summary: { operationKind: "workspace.pane.send", observedOnly: true },
76
- }),
77
- ).success,
78
- ).toBe(true);
79
- expect(
80
- DaemonEventServerFrameSchemaZ.safeParse({
81
- ...receipt,
82
- origin: "external",
83
- sourceSemanticPaneId: "pane.source",
84
- phase: "observed",
85
- summary: { observedOnly: true },
86
- }).success,
87
- ).toBe(false);
88
- expect(
89
- DaemonEventServerFrameSchemaZ.safeParse({
90
- ...receipt,
91
- sourceSemanticPaneId: "pane.source",
92
- phase: "accepted",
93
- }).success,
94
- ).toBe(false);
95
- expect(
96
- DaemonEventServerFrameSchemaZ.safeParse({
97
- ...receipt,
98
- summary: { observedOnly: true, characterCount: 14 },
99
- }).success,
100
- ).toBe(false);
101
- });
102
- const daemon = {
103
- protocolVersion: 1,
104
- productVersion: "2.8.0",
105
- instanceId: "9bcf33b0-c837-4a94-b5e8-c0977f54464f",
106
- startedAt: "2026-07-21T00:00:00.000Z",
107
- } as const;
108
-
109
- it("accepts every client frame and rejects missing or extra fields", () => {
110
- expect(
111
- DaemonEventClientFrameSchemaZ.parse({ type: "subscribe", sessions: ["tmux-ide"] }),
112
- ).toEqual({ type: "subscribe", sessions: ["tmux-ide"] });
113
- expect(
114
- DaemonEventClientFrameSchemaZ.parse({
115
- type: "subscribe",
116
- sessions: ["tmux-ide"],
117
- afterSequence: 41,
118
- legacyEvents: false,
119
- interestRevision: 7,
120
- interests: [
121
- { resource: "application-shell", workspaceName: "tmux-ide" },
122
- { resource: "fleet-catalog", workspaceName: null },
123
- ],
124
- }),
125
- ).toEqual({
126
- type: "subscribe",
127
- sessions: ["tmux-ide"],
128
- afterSequence: 41,
129
- legacyEvents: false,
130
- interestRevision: 7,
131
- interests: [
132
- { resource: "application-shell", workspaceName: "tmux-ide" },
133
- { resource: "fleet-catalog", workspaceName: null },
134
- ],
135
- });
136
- expect(
137
- DaemonEventClientFrameSchemaZ.safeParse({ type: "unsubscribe", sessions: [] }).success,
138
- ).toBe(true);
139
- expect(
140
- DaemonEventClientFrameSchemaZ.safeParse({
141
- type: "unsubscribe",
142
- sessions: [],
143
- legacyEvents: true,
144
- interestRevision: 8,
145
- }).success,
146
- ).toBe(true);
147
- expect(DaemonEventClientFrameSchemaZ.safeParse({ type: "ping" }).success).toBe(true);
148
-
149
- expect(DaemonEventClientFrameSchemaZ.safeParse({ type: "subscribe" }).success).toBe(false);
150
- expect(
151
- DaemonEventClientFrameSchemaZ.safeParse({
152
- type: "subscribe",
153
- sessions: [],
154
- afterSequence: -1,
155
- }).success,
156
- ).toBe(false);
157
- expect(
158
- DaemonEventClientFrameSchemaZ.safeParse({
159
- type: "subscribe",
160
- sessions: [],
161
- typo: true,
162
- }).success,
163
- ).toBe(false);
164
- expect(DaemonEventClientFrameSchemaZ.safeParse({ type: "ping", sessions: [] }).success).toBe(
165
- false,
166
- );
167
- expect(
168
- DaemonEventClientFrameSchemaZ.safeParse({
169
- type: "subscribe",
170
- sessions: [],
171
- interests: [{ resource: "workspace-files", workspaceName: null }],
172
- }).success,
173
- ).toBe(false);
174
- expect(
175
- DaemonEventClientFrameSchemaZ.safeParse({
176
- type: "subscribe",
177
- sessions: [],
178
- interests: [{ resource: "fleet-catalog", workspaceName: "tmux-ide" }],
179
- }).success,
180
- ).toBe(false);
181
- });
182
-
183
- it("strictly parses replayable resource invalidations and gap recovery", () => {
184
- const changed = {
185
- type: "resource.changed",
186
- sequence: 42,
187
- workspaceName: "tmux-ide",
188
- resource: "application-shell",
189
- revision: 8,
190
- causeOperationId: "10000000-0000-4000-8000-000000000001",
191
- } as const;
192
- expect(DaemonEventServerFrameSchemaZ.parse(changed)).toEqual(changed);
193
- expect(DaemonEventServerFrameSchemaZ.safeParse({ ...changed, sequence: 0 }).success).toBe(
194
- false,
195
- );
196
- expect(
197
- DaemonEventServerFrameSchemaZ.safeParse({ ...changed, resource: "everything" }).success,
198
- ).toBe(false);
199
- expect(
200
- DaemonEventServerFrameSchemaZ.parse({ type: "resource.observed", sequence: 43 }),
201
- ).toEqual({ type: "resource.observed", sequence: 43 });
202
- const ack = {
203
- type: "resource.interests-ack",
204
- interestRevision: 9,
205
- sequence: 43,
206
- unavailableInterests: [{ resource: "workspace-missions", workspaceName: "tmux-ide" }],
207
- } as const;
208
- expect(DaemonEventServerFrameSchemaZ.parse(ack)).toEqual(ack);
209
- expect(DaemonEventServerFrameSchemaZ.safeParse({ ...ack, interestRevision: 0 }).success).toBe(
210
- false,
211
- );
212
- expect(
213
- DaemonEventServerFrameSchemaZ.safeParse({ ...changed, causeOperationId: null }).success,
214
- ).toBe(true);
215
-
216
- const gap = {
217
- type: "snapshot-required",
218
- afterSequence: 1,
219
- oldestAvailableSequence: 20,
220
- currentSequence: 42,
221
- reason: "journal-gap",
222
- } as const;
223
- expect(DaemonEventServerFrameSchemaZ.parse(gap)).toEqual(gap);
224
- expect(DaemonEventServerFrameSchemaZ.safeParse({ ...gap, reason: "unknown" }).success).toBe(
225
- false,
226
- );
227
- });
228
-
229
- it("strictly parses snapshots and protocol errors", () => {
230
- const snapshot = {
231
- type: "snapshot",
232
- sessionName: "tmux-ide",
233
- data: {
234
- project: {
235
- session: "tmux-ide",
236
- dir: "/repo/tmux-ide",
237
- panes: [],
238
- },
239
- },
240
- } as const;
241
- expect(DaemonEventServerFrameSchemaZ.parse(snapshot)).toEqual(snapshot);
242
- expect(DaemonEventServerFrameSchemaZ.safeParse({ ...snapshot, unexpected: true }).success).toBe(
243
- false,
244
- );
245
- expect(
246
- DaemonEventServerFrameSchemaZ.safeParse({
247
- ...snapshot,
248
- data: { project: { ...snapshot.data.project, unexpected: true } },
249
- }).success,
250
- ).toBe(false);
251
-
252
- expect(
253
- DaemonEventServerFrameSchemaZ.safeParse({
254
- type: "protocol.error",
255
- code: "invalid-frame",
256
- message: "Client frame does not match the daemon event protocol.",
257
- }).success,
258
- ).toBe(true);
259
- expect(
260
- DaemonEventServerFrameSchemaZ.safeParse({
261
- type: "protocol.error",
262
- code: "unknown",
263
- message: "nope",
264
- }).success,
265
- ).toBe(false);
266
- });
267
-
268
- it("keeps every historical server discriminator parseable", () => {
269
- const frames = [
270
- { type: "hello", daemon, sessions: [] },
271
- { type: "sessions.changed" },
272
- { type: "projects.changed" },
273
- { type: "init.output", jobId: "job-1", chunk: "working", done: false },
274
- { type: "init.error", jobId: "job-1", message: "failed" },
275
- { type: "pong" },
276
- { type: "action.complete", name: "project.launch", result: { ok: true } },
277
- { type: "config.changed", sessionName: "tmux-ide" },
278
- { type: "terminals.changed", sessionName: "tmux-ide" },
279
- { type: "agent-status.changed", sessionName: "tmux-ide" },
280
- {
281
- type: "agent.turn-completed",
282
- sessionName: "tmux-ide",
283
- agentId: "agent.0123456789abcdef0123",
284
- fromStatus: "working",
285
- toStatus: "done",
286
- at: "2026-07-23T12:00:00.000Z",
287
- },
288
- {
289
- type: "workspace.promotion-completed",
290
- workspaceName: "tmux-ide",
291
- outcome: "promoted",
292
- at: "2026-07-23T12:00:00.000Z",
293
- },
294
- {
295
- type: "workspace.added",
296
- workspace: {
297
- name: "tmux-ide",
298
- sessionName: "tmux-ide",
299
- projectDir: "/repo/tmux-ide",
300
- ideConfigPath: null,
301
- addedAt: "2026-07-21T12:00:00.000Z",
302
- },
303
- },
304
- { type: "workspace.removed", name: "tmux-ide" },
305
- ];
306
-
307
- for (const frame of frames) {
308
- expect(DaemonEventServerFrameSchemaZ.safeParse(frame).success, frame.type).toBe(true);
309
- }
310
- });
311
-
312
- it("requires a strict non-secret daemon generation on hello", () => {
313
- expect(
314
- DaemonEventServerFrameSchemaZ.safeParse({ type: "hello", daemon, sessions: [] }).success,
315
- ).toBe(true);
316
- expect(DaemonEventServerFrameSchemaZ.safeParse({ type: "hello", sessions: [] }).success).toBe(
317
- false,
318
- );
319
- expect(
320
- DaemonEventServerFrameSchemaZ.safeParse({
321
- type: "hello",
322
- daemon: { ...daemon, authToken: "must-not-cross-wire" },
323
- sessions: [],
324
- }).success,
325
- ).toBe(false);
326
- });
327
-
328
- it("strictly parses agent.turn-completed and rejects unsafe or unbounded shapes", () => {
329
- const receipt = {
330
- type: "agent.turn-completed",
331
- sessionName: "tmux-ide",
332
- agentId: "agent.0123456789abcdef0123",
333
- fromStatus: "working",
334
- toStatus: "idle",
335
- at: "2026-07-23T12:00:00.000Z",
336
- } as const;
337
- expect(DaemonEventServerFrameSchemaZ.parse(receipt)).toEqual(receipt);
338
- expect(DaemonEventServerFrameSchemaZ.safeParse({ ...receipt, agentId: null }).success).toBe(
339
- true,
340
- );
341
-
342
- // A raw tmux pane id, a raw durable stamp, or any non-digest value is
343
- // rejected — only the minted `agent.<digest>` identity crosses the wire.
344
- expect(DaemonEventServerFrameSchemaZ.safeParse({ ...receipt, agentId: "%1" }).success).toBe(
345
- false,
346
- );
347
- expect(
348
- DaemonEventServerFrameSchemaZ.safeParse({
349
- ...receipt,
350
- agentId: "pane.promoted.0123456789abcdef0123",
351
- }).success,
352
- ).toBe(false);
353
- // Completion is bounded to a finished turn: from working, to done|idle.
354
- expect(
355
- DaemonEventServerFrameSchemaZ.safeParse({ ...receipt, fromStatus: "blocked" }).success,
356
- ).toBe(false);
357
- expect(
358
- DaemonEventServerFrameSchemaZ.safeParse({ ...receipt, toStatus: "blocked" }).success,
359
- ).toBe(false);
360
- expect(DaemonEventServerFrameSchemaZ.safeParse({ ...receipt, at: "yesterday" }).success).toBe(
361
- false,
362
- );
363
- expect(DaemonEventServerFrameSchemaZ.safeParse({ ...receipt, unexpected: true }).success).toBe(
364
- false,
365
- );
366
- });
367
-
368
- it("strictly parses workspace.promotion-completed", () => {
369
- const receipt = {
370
- type: "workspace.promotion-completed",
371
- workspaceName: "tmux-ide",
372
- outcome: "replayed",
373
- at: "2026-07-23T12:00:00.000Z",
374
- } as const;
375
- expect(DaemonEventServerFrameSchemaZ.parse(receipt)).toEqual(receipt);
376
- expect(DaemonEventServerFrameSchemaZ.safeParse({ ...receipt, outcome: "failed" }).success).toBe(
377
- false,
378
- );
379
- expect(DaemonEventServerFrameSchemaZ.safeParse({ ...receipt, workspaceName: "" }).success).toBe(
380
- false,
381
- );
382
- expect(DaemonEventServerFrameSchemaZ.safeParse({ ...receipt, unexpected: true }).success).toBe(
383
- false,
384
- );
385
- });
386
-
387
- it("strictly parses agent-status.changed and rejects missing or extra fields", () => {
388
- expect(
389
- DaemonEventServerFrameSchemaZ.parse({
390
- type: "agent-status.changed",
391
- sessionName: "tmux-ide",
392
- }),
393
- ).toEqual({ type: "agent-status.changed", sessionName: "tmux-ide" });
394
- expect(DaemonEventServerFrameSchemaZ.safeParse({ type: "agent-status.changed" }).success).toBe(
395
- false,
396
- );
397
- expect(
398
- DaemonEventServerFrameSchemaZ.safeParse({
399
- type: "agent-status.changed",
400
- sessionName: "tmux-ide",
401
- unexpected: true,
402
- }).success,
403
- ).toBe(false);
404
- });
405
- });
@@ -1,143 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import {
3
- DaemonPanesResponseSchemaZ,
4
- DaemonProjectResponseSchemaZ,
5
- DaemonProjectsResponseSchemaZ,
6
- DaemonProjectTemplatesResponseSchemaZ,
7
- DaemonSessionsResponseSchemaZ,
8
- DaemonWorkspacesResponseSchemaZ,
9
- } from "../daemon-resources.ts";
10
- import {
11
- WORKSPACE_CATALOG_RESOURCE_VERSION,
12
- WorkspaceCatalogResourceV1SchemaZ,
13
- } from "../workspace-catalog-resource.ts";
14
-
15
- const daemon = {
16
- protocolVersion: 1,
17
- productVersion: "2.8.0",
18
- instanceId: "9bcf33b0-c837-4a94-b5e8-c0977f54464f",
19
- startedAt: "2026-07-21T12:00:00.000Z",
20
- };
21
-
22
- const pane = {
23
- id: "%7",
24
- index: 0,
25
- title: "Codex",
26
- currentCommand: "codex",
27
- width: 120,
28
- height: 40,
29
- active: true,
30
- role: "teammate" as const,
31
- name: "Implementer",
32
- type: null,
33
- };
34
-
35
- describe("daemon REST resources", () => {
36
- it("parses the current session, project, and pane response shapes", () => {
37
- expect(
38
- DaemonSessionsResponseSchemaZ.parse({
39
- sessions: [{ name: "tmux-ide", dir: "/repo/tmux-ide" }],
40
- }),
41
- ).toEqual({ sessions: [{ name: "tmux-ide", dir: "/repo/tmux-ide" }] });
42
-
43
- expect(
44
- DaemonProjectResponseSchemaZ.parse({
45
- session: "tmux-ide",
46
- dir: "/repo/tmux-ide",
47
- panes: [pane],
48
- }).panes,
49
- ).toEqual([pane]);
50
- expect(DaemonPanesResponseSchemaZ.parse({ panes: [pane] })).toEqual({ panes: [pane] });
51
- });
52
-
53
- it("parses workspace, registry, and project-template envelopes", () => {
54
- expect(
55
- DaemonWorkspacesResponseSchemaZ.safeParse({
56
- workspaces: [
57
- {
58
- name: "tmux-ide",
59
- sessionName: "tmux-ide",
60
- projectDir: "/repo/tmux-ide",
61
- ideConfigPath: null,
62
- configKind: "workspace",
63
- configPath: "/repo/tmux-ide/.tmux-ide/workspace.yml",
64
- hasWorkspaceConfig: true,
65
- addedAt: "2026-07-21T12:00:00.000Z",
66
- },
67
- ],
68
- }).success,
69
- ).toBe(true);
70
-
71
- expect(
72
- DaemonProjectsResponseSchemaZ.safeParse({
73
- projects: [
74
- {
75
- name: "tmux-ide",
76
- dir: "/repo/tmux-ide",
77
- hasIdeYml: false,
78
- hasWorkspaceConfig: true,
79
- configKind: "workspace",
80
- configPath: "/repo/tmux-ide/.tmux-ide/workspace.yml",
81
- ideConfigPath: null,
82
- gitOrigin: "git@github.com:wavyrai/tmux-ide.git",
83
- gitBranch: "main",
84
- registeredAt: "2026-07-21T12:00:00.000Z",
85
- },
86
- ],
87
- }).success,
88
- ).toBe(true);
89
-
90
- expect(
91
- DaemonProjectTemplatesResponseSchemaZ.parse({
92
- templates: [{ id: "default", label: "Default", description: "A balanced workspace" }],
93
- }).templates[0]?.id,
94
- ).toBe("default");
95
- });
96
-
97
- it("rejects unknown envelope and nested resource fields", () => {
98
- expect(DaemonSessionsResponseSchemaZ.safeParse({ sessions: [], typo: true }).success).toBe(
99
- false,
100
- );
101
- expect(
102
- DaemonSessionsResponseSchemaZ.safeParse({
103
- sessions: [{ name: "tmux-ide", dir: "/repo", typo: true }],
104
- }).success,
105
- ).toBe(false);
106
- expect(DaemonPanesResponseSchemaZ.safeParse({ panes: [{ ...pane, typo: true }] }).success).toBe(
107
- false,
108
- );
109
- expect(
110
- DaemonProjectsResponseSchemaZ.safeParse({
111
- projects: [
112
- {
113
- name: "tmux-ide",
114
- dir: "/repo",
115
- hasIdeYml: false,
116
- gitOrigin: null,
117
- gitBranch: null,
118
- registeredAt: "now",
119
- typo: true,
120
- },
121
- ],
122
- }).success,
123
- ).toBe(false);
124
- });
125
-
126
- it("strictly parses the generation-stamped workspace catalog resource", () => {
127
- const resource = {
128
- version: WORKSPACE_CATALOG_RESOURCE_VERSION,
129
- daemon,
130
- workspaces: [{ workspaceName: "tmux-ide", sessionName: "tmux-ide-live" }],
131
- };
132
- expect(WorkspaceCatalogResourceV1SchemaZ.parse(resource)).toEqual(resource);
133
- expect(
134
- WorkspaceCatalogResourceV1SchemaZ.safeParse({ ...resource, apiBaseUrl: "secret" }).success,
135
- ).toBe(false);
136
- expect(
137
- WorkspaceCatalogResourceV1SchemaZ.safeParse({
138
- ...resource,
139
- workspaces: [{ ...resource.workspaces[0], projectDir: "/private/project" }],
140
- }).success,
141
- ).toBe(false);
142
- });
143
- });
@@ -1,149 +0,0 @@
1
- import { readFileSync } from "node:fs";
2
- import { fileURLToPath } from "node:url";
3
- import { describe, expect, it } from "vitest";
4
- import {
5
- CanonicalDaemonInfoSchema,
6
- DAEMON_WIRE_PROTOCOL_VERSION,
7
- DaemonProvenanceSchema,
8
- DaemonHealthSchema,
9
- DaemonHealthzSchema,
10
- DaemonIdentitySchema,
11
- DaemonInstanceIdentitySchemaZ,
12
- isDaemonWireProtocolCompatible,
13
- } from "../daemon-wire.ts";
14
- import { WorkspaceCatalogResourceV1SchemaZ } from "../workspace-catalog-resource.ts";
15
-
16
- const fixturePath = fileURLToPath(new URL("./fixtures/daemon-wire-v4.json", import.meta.url));
17
-
18
- describe("daemon wire protocol", () => {
19
- it("validates the shared desktop/TypeScript v4 fixture", () => {
20
- const fixture = JSON.parse(readFileSync(fixturePath, "utf8")) as Record<string, unknown>;
21
-
22
- expect(CanonicalDaemonInfoSchema.parse(fixture.canonical).protocolVersion).toBe(
23
- DAEMON_WIRE_PROTOCOL_VERSION,
24
- );
25
- expect(DaemonHealthSchema.parse(fixture.health).protocolVersion).toBe(
26
- DAEMON_WIRE_PROTOCOL_VERSION,
27
- );
28
- expect(DaemonHealthzSchema.parse(fixture.healthz).productVersion).toBe("0.0.1");
29
- const identity = DaemonIdentitySchema.parse(fixture.identity);
30
- expect(identity.instanceId).toBe(CanonicalDaemonInfoSchema.parse(fixture.canonical).instanceId);
31
- });
32
-
33
- it("retains an unknown positive wire version for a separate compatibility decision", () => {
34
- const fixture = JSON.parse(readFileSync(fixturePath, "utf8")) as {
35
- canonical: Record<string, unknown>;
36
- health: Record<string, unknown>;
37
- };
38
- const unknownVersion = DAEMON_WIRE_PROTOCOL_VERSION + 1;
39
- const health = DaemonHealthSchema.parse({
40
- ...fixture.health,
41
- protocolVersion: unknownVersion,
42
- });
43
- const canonical = CanonicalDaemonInfoSchema.parse({
44
- ...fixture.canonical,
45
- protocolVersion: unknownVersion,
46
- });
47
-
48
- expect(health.protocolVersion).toBe(unknownVersion);
49
- expect(canonical.protocolVersion).toBe(unknownVersion);
50
- expect(isDaemonWireProtocolCompatible(unknownVersion)).toBe(false);
51
- expect(isDaemonWireProtocolCompatible(DAEMON_WIRE_PROTOCOL_VERSION)).toBe(true);
52
- });
53
- });
54
-
55
- describe("environment identity (additive, both directions)", () => {
56
- const ENVIRONMENT_ID = "0f4e9a7c-2f4a-4d55-9d2e-1f6cf3a3b210";
57
- const fixture = JSON.parse(readFileSync(fixturePath, "utf8")) as {
58
- canonical: Record<string, unknown>;
59
- identity: Record<string, unknown>;
60
- };
61
- const identityFields = {
62
- protocolVersion: DAEMON_WIRE_PROTOCOL_VERSION,
63
- productVersion: "0.0.1",
64
- instanceId: "9bcf33b0-c837-4a94-b5e8-c0977f54464f",
65
- startedAt: "2026-07-20T12:34:56.123Z",
66
- };
67
-
68
- it("parses pre-environment payloads unchanged (old daemon, new client)", () => {
69
- expect(CanonicalDaemonInfoSchema.parse(fixture.canonical).environmentId).toBeUndefined();
70
- expect(DaemonIdentitySchema.parse(fixture.identity).environmentId).toBeUndefined();
71
- expect(DaemonInstanceIdentitySchemaZ.parse(identityFields).environmentId).toBeUndefined();
72
- });
73
-
74
- it("carries the environment id on every identity surface when present", () => {
75
- const canonical = CanonicalDaemonInfoSchema.parse({
76
- ...fixture.canonical,
77
- environmentId: ENVIRONMENT_ID,
78
- });
79
- const identity = DaemonIdentitySchema.parse({
80
- ...fixture.identity,
81
- environmentId: ENVIRONMENT_ID,
82
- });
83
- const instanceIdentity = DaemonInstanceIdentitySchemaZ.parse({
84
- ...identityFields,
85
- environmentId: ENVIRONMENT_ID,
86
- });
87
- expect(canonical.environmentId).toBe(ENVIRONMENT_ID);
88
- expect(identity.environmentId).toBe(ENVIRONMENT_ID);
89
- expect(instanceIdentity.environmentId).toBe(ENVIRONMENT_ID);
90
- });
91
-
92
- it("rejects a non-UUID environment id but keeps other unknown-key strictness", () => {
93
- expect(
94
- DaemonInstanceIdentitySchemaZ.safeParse({ ...identityFields, environmentId: "nope" }).success,
95
- ).toBe(false);
96
- expect(
97
- DaemonInstanceIdentitySchemaZ.safeParse({ ...identityFields, machineId: ENVIRONMENT_ID })
98
- .success,
99
- ).toBe(false);
100
- });
101
-
102
- it("stamps generation-checked resource envelopes with and without the id", () => {
103
- const envelope = (daemon: Record<string, unknown>) => ({
104
- version: 1,
105
- daemon,
106
- workspaces: [{ workspaceName: "alpha", sessionName: "alpha" }],
107
- });
108
- const without = WorkspaceCatalogResourceV1SchemaZ.parse(envelope(identityFields));
109
- const withId = WorkspaceCatalogResourceV1SchemaZ.parse(
110
- envelope({ ...identityFields, environmentId: ENVIRONMENT_ID }),
111
- );
112
- expect(without.daemon.environmentId).toBeUndefined();
113
- expect(withId.daemon.environmentId).toBe(ENVIRONMENT_ID);
114
- // Generation identity is untouched by the additive field.
115
- expect(withId.daemon.instanceId).toBe(identityFields.instanceId);
116
- expect(withId.daemon.startedAt).toBe(identityFields.startedAt);
117
- });
118
- });
119
-
120
- describe("daemon provenance (additive)", () => {
121
- const fixture = JSON.parse(readFileSync(fixturePath, "utf8")) as {
122
- canonical: Record<string, unknown>;
123
- };
124
- const provenance = {
125
- launcher: "headless",
126
- supervisor: "systemd",
127
- parentPid: 1,
128
- stdout: { kind: "file", path: "/var/log/tmux-ide.out", dev: 1, ino: 2 },
129
- stderr: { kind: "socket" },
130
- warnings: ["stderr: path unresolved"],
131
- };
132
-
133
- it("parses records with and without provenance", () => {
134
- expect(CanonicalDaemonInfoSchema.parse(fixture.canonical).provenance).toBeUndefined();
135
- expect(
136
- CanonicalDaemonInfoSchema.parse({ ...fixture.canonical, provenance }).provenance,
137
- ).toEqual(provenance);
138
- expect(DaemonProvenanceSchema.parse(provenance)).toEqual(provenance);
139
- });
140
-
141
- it("rejects unknown supervisors and stream kinds", () => {
142
- expect(DaemonProvenanceSchema.safeParse({ ...provenance, supervisor: "cron" }).success).toBe(
143
- false,
144
- );
145
- expect(
146
- DaemonProvenanceSchema.safeParse({ ...provenance, stdout: { kind: "journal" } }).success,
147
- ).toBe(false);
148
- });
149
- });