tmux-ide 2.9.2 → 2.9.4

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 (267) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +121 -140
  3. package/bin/cli.js +2457 -727
  4. package/package.json +23 -8
  5. package/packages/contracts/src/desktop-host.ts +3 -0
  6. package/packages/contracts/src/saved-machines.ts +19 -0
  7. package/packages/contracts/src/terminal-replica.ts +1 -1
  8. package/packages/core/package.json +3 -2
  9. package/packages/core/src/terminal-delivery.ts +51 -3
  10. package/packages/core/src/terminal-fnv64-wasm.ts +4 -3
  11. package/packages/core/src/terminal-replica-hash-cache.ts +129 -31
  12. package/packages/core/src/terminal-replica-owned-row.ts +27 -0
  13. package/packages/core/src/terminal-replica.ts +13 -28
  14. package/packages/daemon/dist/command-center/daemon-fleet-facts-observer.js +96 -10
  15. package/packages/daemon/dist/command-center/resources/saved-machine-route.js +40 -1
  16. package/packages/daemon/dist/command-center/ws-events.js +5 -24
  17. package/packages/daemon/dist/lib/canonical-daemon-bootstrap.js +8 -0
  18. package/packages/daemon/dist/lib/canonical-daemon.js +28 -2
  19. package/packages/daemon/dist/lib/daemon-embed.js +1 -1
  20. package/packages/daemon/dist/lib/daemon-service-manager.js +122 -0
  21. package/packages/daemon/dist/lib/daemon-service-plan.js +127 -0
  22. package/packages/daemon/dist/lib/daemon-service.js +259 -0
  23. package/packages/daemon/dist/lib/install-origin.js +2 -0
  24. package/packages/daemon/dist/lib/local-fleet-request.js +9 -3
  25. package/packages/daemon/dist/lib/log.js +6 -10
  26. package/packages/daemon/dist/lib/managed-installer-update.js +67 -0
  27. package/packages/daemon/dist/lib/{tui-download-lock.js → private-operation-lock.js} +11 -11
  28. package/packages/daemon/dist/lib/remote-daemon-info.js +3 -2
  29. package/packages/daemon/dist/lib/remote-daemon-lifecycle.js +4 -4
  30. package/packages/daemon/dist/lib/remote-tmux-command.js +10 -0
  31. package/packages/daemon/dist/lib/runtime-namespace.js +28 -16
  32. package/packages/daemon/dist/lib/saved-machines.js +40 -2
  33. package/packages/daemon/dist/lib/ssh-daemon-transport.js +24 -9
  34. package/packages/daemon/dist/lib/tmux-server-owner.js +1 -1
  35. package/packages/daemon/dist/lib/tmux-server-registration.js +21 -3
  36. package/packages/daemon/dist/lib/tui-binary.js +2 -2
  37. package/packages/daemon/dist/lib/update.js +18 -0
  38. package/packages/daemon/dist/lib/workspace-multiplexer-verbs.js +24 -1
  39. package/packages/daemon/dist/machines.js +40 -4
  40. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Info.plist +2 -2
  41. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/MacOS/tmux-ide-notifier +0 -0
  42. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/Resources/Assets.car +0 -0
  43. package/packages/daemon/dist/native/TmuxIdeNotifier.app/Contents/_CodeSignature/CodeResources +2 -2
  44. package/packages/daemon/dist/terminal/attachments/direct-websocket.js +4 -1
  45. package/packages/daemon/dist/terminal/attachments/native-runtime.js +22 -13
  46. package/packages/daemon/dist/terminal/mirror/mirror-service.js +101 -3
  47. package/packages/daemon/dist/terminal/mirror/registered-window-guard.js +62 -0
  48. package/packages/daemon/dist/terminal/mirror/session-channel.js +75 -4
  49. package/packages/daemon/dist/terminal/mirror/shared-window-index.js +45 -0
  50. package/packages/daemon/dist/terminal/pane-stream/pane-stream-websocket.js +11 -1
  51. package/packages/daemon/dist/terminal/session-runtime/multiplexer-backend.js +1 -0
  52. package/packages/daemon/dist/terminal/session-runtime/registry.js +56 -7
  53. package/packages/daemon/dist/terminal/session-runtime/semantic-mutation-executor.js +3 -1
  54. package/packages/daemon/dist/tui/integrations/claude-agent-teams.js +264 -0
  55. package/packages/daemon/dist/tui/mirror/dialog-model.js +2 -35
  56. package/packages/daemon/dist/tui/mirror/runtime/application-daemon-authority-owner.js +8 -0
  57. package/packages/daemon/dist/tui/mirror/runtime/application-home-fleet.js +20 -2
  58. package/packages/daemon/dist/tui/mirror/runtime/application-machine-agents.js +7 -1
  59. package/packages/daemon/dist/tui/mirror/runtime/application-machine-authority.js +59 -9
  60. package/packages/daemon/dist/tui/mirror/runtime/application-machine-navigation.js +27 -19
  61. package/packages/daemon/dist/tui/mirror/runtime/application-machine-sidebar.jsx +23 -18
  62. package/packages/daemon/dist/tui/mirror/runtime/application-machine-startup.js +31 -2
  63. package/packages/daemon/dist/tui/mirror/runtime/application-palette-search-owner.js +7 -3
  64. package/packages/daemon/dist/tui/mirror/runtime/application-performance-log.js +3 -0
  65. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-input-ingress.js +146 -2
  66. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-interaction-controller.js +201 -50
  67. package/packages/daemon/dist/tui/mirror/runtime/bounded-performance-record-writer.js +50 -10
  68. package/packages/daemon/dist/tui/mirror/runtime/terminal-fast-lane-renderer-adapter.js +6 -5
  69. package/packages/daemon/dist/tui/mirror/runtime/terminal-pane-input-router.js +3 -0
  70. package/packages/daemon/dist/tui/mirror/runtime/workspace-terminal-fast-lane.js +8 -2
  71. package/packages/daemon/dist/tui/mirror/terminal-text.js +35 -0
  72. package/packages/daemon/dist/tui/mirror/workspace/connection-feedback.js +5 -3
  73. package/packages/daemon/src/command-center/daemon-fleet-facts-observer.ts +100 -10
  74. package/packages/daemon/src/command-center/resources/saved-machine-route.ts +48 -1
  75. package/packages/daemon/src/command-center/ws-events.ts +5 -25
  76. package/packages/daemon/src/lib/canonical-daemon-bootstrap.ts +12 -0
  77. package/packages/daemon/src/lib/canonical-daemon.ts +44 -2
  78. package/packages/daemon/src/lib/daemon-embed.ts +1 -0
  79. package/packages/daemon/src/lib/daemon-service-manager.ts +152 -0
  80. package/packages/daemon/src/lib/daemon-service-plan.ts +153 -0
  81. package/packages/daemon/src/lib/daemon-service.ts +301 -0
  82. package/packages/daemon/src/lib/install-origin.ts +5 -0
  83. package/packages/daemon/src/lib/local-fleet-request.ts +19 -3
  84. package/packages/daemon/src/lib/log.ts +13 -9
  85. package/packages/daemon/src/lib/managed-installer-update.ts +79 -0
  86. package/packages/daemon/src/lib/{tui-download-lock.ts → private-operation-lock.ts} +15 -11
  87. package/packages/daemon/src/lib/remote-daemon-info.ts +3 -3
  88. package/packages/daemon/src/lib/remote-daemon-lifecycle.ts +4 -4
  89. package/packages/daemon/src/lib/remote-tmux-command.ts +12 -0
  90. package/packages/daemon/src/lib/runtime-namespace.ts +27 -18
  91. package/packages/daemon/src/lib/saved-machines.ts +40 -1
  92. package/packages/daemon/src/lib/ssh-daemon-transport.ts +25 -7
  93. package/packages/daemon/src/lib/tmux-server-owner.ts +1 -0
  94. package/packages/daemon/src/lib/tmux-server-registration.ts +21 -3
  95. package/packages/daemon/src/lib/tui-binary.ts +2 -2
  96. package/packages/daemon/src/lib/update.ts +24 -0
  97. package/packages/daemon/src/lib/workspace-multiplexer-verbs.ts +22 -0
  98. package/packages/daemon/src/machines.ts +53 -5
  99. package/packages/daemon/src/terminal/attachments/direct-websocket.ts +8 -2
  100. package/packages/daemon/src/terminal/attachments/native-runtime.ts +28 -13
  101. package/packages/daemon/src/terminal/mirror/mirror-service.ts +105 -3
  102. package/packages/daemon/src/terminal/mirror/registered-window-guard.ts +66 -0
  103. package/packages/daemon/src/terminal/mirror/session-channel.ts +92 -4
  104. package/packages/daemon/src/terminal/mirror/shared-window-index.ts +42 -0
  105. package/packages/daemon/src/terminal/pane-stream/pane-stream-websocket.ts +12 -1
  106. package/packages/daemon/src/terminal/session-runtime/multiplexer-backend.ts +2 -0
  107. package/packages/daemon/src/terminal/session-runtime/registry.ts +70 -8
  108. package/packages/daemon/src/terminal/session-runtime/semantic-mutation-executor.ts +3 -1
  109. package/packages/daemon/src/tui/integrations/claude-agent-teams.ts +334 -0
  110. package/packages/daemon/src/tui/mirror/dialog-model.ts +2 -32
  111. package/packages/daemon/src/tui/mirror/runtime/application-daemon-authority-owner.ts +8 -0
  112. package/packages/daemon/src/tui/mirror/runtime/application-home-fleet.ts +19 -2
  113. package/packages/daemon/src/tui/mirror/runtime/application-machine-agents.ts +6 -1
  114. package/packages/daemon/src/tui/mirror/runtime/application-machine-authority.ts +60 -11
  115. package/packages/daemon/src/tui/mirror/runtime/application-machine-navigation.ts +39 -33
  116. package/packages/daemon/src/tui/mirror/runtime/application-machine-sidebar.tsx +31 -23
  117. package/packages/daemon/src/tui/mirror/runtime/application-machine-startup.ts +38 -2
  118. package/packages/daemon/src/tui/mirror/runtime/application-palette-search-owner.ts +7 -4
  119. package/packages/daemon/src/tui/mirror/runtime/application-performance-log.ts +3 -0
  120. package/packages/daemon/src/tui/mirror/runtime/application-root-v2.tsx +1 -1
  121. package/packages/daemon/src/tui/mirror/runtime/application-shell-view.tsx +47 -46
  122. package/packages/daemon/src/tui/mirror/runtime/application-terminal-input-ingress.ts +165 -2
  123. package/packages/daemon/src/tui/mirror/runtime/application-terminal-interaction-controller.ts +207 -53
  124. package/packages/daemon/src/tui/mirror/runtime/bounded-performance-record-writer.ts +49 -9
  125. package/packages/daemon/src/tui/mirror/runtime/terminal-fast-lane-renderer-adapter.ts +6 -5
  126. package/packages/daemon/src/tui/mirror/runtime/terminal-pane-input-router.ts +4 -0
  127. package/packages/daemon/src/tui/mirror/runtime/workspace-terminal-fast-lane.ts +8 -3
  128. package/packages/daemon/src/tui/mirror/terminal-text.ts +32 -0
  129. package/packages/daemon/src/tui/mirror/workspace/connection-feedback.ts +6 -3
  130. package/packages/daemon-client/src/fleet-connection-status.ts +10 -1
  131. package/packages/daemon-client/src/workspace-client.ts +4 -1
  132. package/skill/SKILL.md +30 -30
  133. package/packages/contracts/src/__tests__/actions-contract.test.ts +0 -119
  134. package/packages/contracts/src/__tests__/agent-graph-overlay.test.ts +0 -428
  135. package/packages/contracts/src/__tests__/app-window-mutation.test.ts +0 -51
  136. package/packages/contracts/src/__tests__/app-window-state.test.ts +0 -34
  137. package/packages/contracts/src/__tests__/application-shell.test.ts +0 -645
  138. package/packages/contracts/src/__tests__/automation-operations.test.ts +0 -78
  139. package/packages/contracts/src/__tests__/causal-cell.test.ts +0 -47
  140. package/packages/contracts/src/__tests__/client-view-state.test.ts +0 -115
  141. package/packages/contracts/src/__tests__/cohesion-fixture.test.ts +0 -106
  142. package/packages/contracts/src/__tests__/commands.test.ts +0 -86
  143. package/packages/contracts/src/__tests__/control.test.ts +0 -154
  144. package/packages/contracts/src/__tests__/daemon-events.test.ts +0 -405
  145. package/packages/contracts/src/__tests__/daemon-resources.test.ts +0 -143
  146. package/packages/contracts/src/__tests__/daemon-wire.test.ts +0 -149
  147. package/packages/contracts/src/__tests__/desktop-host.test.ts +0 -269
  148. package/packages/contracts/src/__tests__/desktop-missions.test.ts +0 -215
  149. package/packages/contracts/src/__tests__/experience-conformance.test.ts +0 -153
  150. package/packages/contracts/src/__tests__/experience-kernel-boundary.test.ts +0 -113
  151. package/packages/contracts/src/__tests__/experience-shell.test.ts +0 -65
  152. package/packages/contracts/src/__tests__/fixtures/daemon-wire-v2.json +0 -35
  153. package/packages/contracts/src/__tests__/fixtures/daemon-wire-v3.json +0 -35
  154. package/packages/contracts/src/__tests__/fixtures/daemon-wire-v4.json +0 -35
  155. package/packages/contracts/src/__tests__/fixtures/scoped-receipt.ts +0 -62
  156. package/packages/contracts/src/__tests__/fleet-agent-graph.test.ts +0 -231
  157. package/packages/contracts/src/__tests__/fleet-catalog.test.ts +0 -270
  158. package/packages/contracts/src/__tests__/fleet-lifecycle.test.ts +0 -62
  159. package/packages/contracts/src/__tests__/focus-overlay.test.ts +0 -110
  160. package/packages/contracts/src/__tests__/ide-config.test.ts +0 -64
  161. package/packages/contracts/src/__tests__/interaction-evidence.test.ts +0 -288
  162. package/packages/contracts/src/__tests__/interaction-receipt-v2.test.ts +0 -72
  163. package/packages/contracts/src/__tests__/issue-error.test.ts +0 -78
  164. package/packages/contracts/src/__tests__/mission-projections.test.ts +0 -186
  165. package/packages/contracts/src/__tests__/missions.test.ts +0 -272
  166. package/packages/contracts/src/__tests__/multiplexer-verbs.test.ts +0 -242
  167. package/packages/contracts/src/__tests__/pane-appearance.test.ts +0 -146
  168. package/packages/contracts/src/__tests__/pane-read-result.test.ts +0 -55
  169. package/packages/contracts/src/__tests__/pane-stream.test.ts +0 -536
  170. package/packages/contracts/src/__tests__/pane-widget-marker.test.ts +0 -327
  171. package/packages/contracts/src/__tests__/performance-metrics.test.ts +0 -73
  172. package/packages/contracts/src/__tests__/performance-qualification.test.ts +0 -137
  173. package/packages/contracts/src/__tests__/rich-card-widget.test.ts +0 -29
  174. package/packages/contracts/src/__tests__/session-runtime.test.ts +0 -512
  175. package/packages/contracts/src/__tests__/startup-readiness.test.ts +0 -409
  176. package/packages/contracts/src/__tests__/terminal-attachment-stream.test.ts +0 -72
  177. package/packages/contracts/src/__tests__/terminal-attachments.test.ts +0 -329
  178. package/packages/contracts/src/__tests__/terminal-delivery.test.ts +0 -88
  179. package/packages/contracts/src/__tests__/terminal-runtime-inventory.test.ts +0 -68
  180. package/packages/contracts/src/__tests__/terminals.test.ts +0 -87
  181. package/packages/contracts/src/__tests__/tmux-server-scope.test.ts +0 -166
  182. package/packages/contracts/src/__tests__/transport-contract-loading.test.ts +0 -91
  183. package/packages/contracts/src/__tests__/visual-tokens.test.ts +0 -224
  184. package/packages/contracts/src/__tests__/window-links.test.ts +0 -243
  185. package/packages/contracts/src/__tests__/workspace-changes-resource.test.ts +0 -317
  186. package/packages/contracts/src/__tests__/workspace-changes-view.test.ts +0 -122
  187. package/packages/contracts/src/__tests__/workspace-config.test.ts +0 -294
  188. package/packages/contracts/src/__tests__/workspace-files-resource.test.ts +0 -261
  189. package/packages/contracts/src/__tests__/workspace-files-tree.test.ts +0 -147
  190. package/packages/contracts/src/__tests__/workspace-pane-creation.test.ts +0 -249
  191. package/packages/contracts/src/__tests__/workspace-promotion.test.ts +0 -94
  192. package/packages/contracts/src/__tests__/workspace-resource-identity.test.ts +0 -90
  193. package/packages/contracts/src/daemon-resource-request.test.ts +0 -192
  194. package/packages/contracts/src/native-operation-identity.test.ts +0 -23
  195. package/packages/contracts/src/workspace-admission.test.ts +0 -21
  196. package/packages/contracts/src/workspace-catalog-resource.test.ts +0 -146
  197. package/packages/core/src/agent-provisioning.test.ts +0 -42
  198. package/packages/core/src/application-shell-session.test.ts +0 -105
  199. package/packages/core/src/interaction-evidence.test.ts +0 -134
  200. package/packages/core/src/interaction-flow.test.ts +0 -66
  201. package/packages/core/src/interaction-receipts.test.ts +0 -671
  202. package/packages/core/src/navigator.test.ts +0 -34
  203. package/packages/core/src/optimistic-projection-conformance.test.ts +0 -75
  204. package/packages/core/src/optimistic-projection.test.ts +0 -118
  205. package/packages/core/src/performance-metrics.test.ts +0 -121
  206. package/packages/core/src/performance-qualification.test.ts +0 -283
  207. package/packages/core/src/saved-machines.test.ts +0 -80
  208. package/packages/core/src/terminal-compact-cold.test.ts +0 -87
  209. package/packages/core/src/terminal-conformance.test.ts +0 -48
  210. package/packages/core/src/terminal-delivery-cache-lifetime.test.ts +0 -167
  211. package/packages/core/src/terminal-delivery-encode-cooperative.test.ts +0 -140
  212. package/packages/core/src/terminal-delivery-representation-hash.test.ts +0 -77
  213. package/packages/core/src/terminal-delivery.test.ts +0 -1471
  214. package/packages/core/src/terminal-fnv64-wasm.test.ts +0 -61
  215. package/packages/core/src/terminal-replica-cold.test.ts +0 -31
  216. package/packages/core/src/terminal-replica-cooperative.test.ts +0 -170
  217. package/packages/core/src/terminal-replica-hash-cache.test.ts +0 -283
  218. package/packages/core/src/terminal-replica.test.ts +0 -347
  219. package/packages/core/src/workspace-selection.test.ts +0 -63
  220. package/packages/daemon/dist/__tests__/support.js +0 -33
  221. package/packages/daemon/dist/lib/__tests__/fixtures/workspace-state-writer.js +0 -58
  222. package/packages/daemon/dist/lib/__tests__/installed-recovery-fixture.js +0 -400
  223. package/packages/daemon/dist/terminal/__tests__/MockPtyAdapter.js +0 -182
  224. package/packages/daemon/dist/terminal/mirror/__tests__/scripted-channel.js +0 -98
  225. package/packages/daemon/dist/terminal/mirror/__tests__/simulated-channel.js +0 -156
  226. package/packages/daemon/src/tui/mirror/__snapshots__/activity-surface-renderer.test.tsx.snap +0 -42
  227. package/packages/daemon/src/tui/mirror/__snapshots__/changes-terminal-surface-renderer.test.tsx.snap +0 -267
  228. package/packages/daemon/src/tui/mirror/__snapshots__/home-files-surface-renderer.test.tsx.snap +0 -267
  229. package/packages/daemon/src/tui/mirror/__snapshots__/missions-surface-renderer.test.tsx.snap +0 -134
  230. package/packages/daemon/src/tui/mirror/__snapshots__/recipes-gallery-renderer.test.tsx.snap +0 -141
  231. package/packages/daemon/src/tui/mirror/__snapshots__/shell-chrome-renderer.test.tsx.snap +0 -134
  232. package/packages/daemon/src/tui/mirror/runtime/__snapshots__/application-shell-view-renderer.test.tsx.snap +0 -87
  233. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/agent-terminal-canvas-renderer.test.tsx.snap +0 -348
  234. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/application-shell-renderer.test.tsx.snap +0 -134
  235. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/command-palette-surface-renderer.test.tsx.snap +0 -255
  236. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/pane-frame-renderer.test.tsx.snap +0 -525
  237. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/terminal-pane-header-polish-renderer.test.tsx.snap +0 -31
  238. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/workbench-shell-renderer.test.tsx.snap +0 -134
  239. package/packages/daemon-client/src/application-shell-session.test.ts +0 -196
  240. package/packages/daemon-client/src/automation-client.test.ts +0 -214
  241. package/packages/daemon-client/src/bootstrap-coordinator.test.ts +0 -145
  242. package/packages/daemon-client/src/connection-supervisor.test.ts +0 -109
  243. package/packages/daemon-client/src/direct-application-shell-transport.test.ts +0 -941
  244. package/packages/daemon-client/src/first-latest-coordinator.test.ts +0 -175
  245. package/packages/daemon-client/src/fleet-dial-scheduler.test.ts +0 -114
  246. package/packages/daemon-client/src/fleet-environments.test.ts +0 -40
  247. package/packages/daemon-client/src/generation-bound-store-timers.test.ts +0 -74
  248. package/packages/daemon-client/src/owner-action-client.test.ts +0 -245
  249. package/packages/daemon-client/src/pane-stream-client.test.ts +0 -2841
  250. package/packages/daemon-client/src/pane-stream-clock-calibration.test.ts +0 -207
  251. package/packages/daemon-client/src/pane-stream-loopback-benchmark.test.ts +0 -51
  252. package/packages/daemon-client/src/push-resource-session.test.ts +0 -509
  253. package/packages/daemon-client/src/resource-replica.test.ts +0 -186
  254. package/packages/daemon-client/src/runtime-resource-ledger.test.ts +0 -18
  255. package/packages/daemon-client/src/scoped-tmux-server-transport.test.ts +0 -114
  256. package/packages/daemon-client/src/terminal-fast-lane.test.ts +0 -835
  257. package/packages/daemon-client/src/tmux-server-client.test.ts +0 -279
  258. package/packages/daemon-client/src/tmux-server-interaction-events.test.ts +0 -230
  259. package/packages/daemon-client/src/workspace-catalog-v2.test.ts +0 -109
  260. package/packages/daemon-client/src/workspace-client-boundaries.test.ts +0 -59
  261. package/packages/daemon-client/src/workspace-client-operations.test.ts +0 -96
  262. package/packages/daemon-client/src/workspace-client.test.ts +0 -2912
  263. package/packages/daemon-client/src/workspace-event-supervisor.test.ts +0 -1086
  264. package/packages/daemon-client/src/workspace-pane-client.test.ts +0 -80
  265. package/packages/presentation/src/presentation-contract.test.ts +0 -63
  266. package/packages/tmux-bridge/src/runner.test.ts +0 -614
  267. package/packages/tmux-bridge/src/targeting.test.ts +0 -107
@@ -1,61 +0,0 @@
1
- import { afterEach, expect, it, vi } from "vitest";
2
- import { createBufferedFnv64 } from "./terminal-fnv64-wasm.ts";
3
-
4
- const reference = (bytes: Uint8Array): string => {
5
- let state = 0xcbf29ce484222325n;
6
- for (const byte of bytes) state = BigInt.asUintN(64, (state ^ BigInt(byte)) * 0x100000001b3n);
7
- return state.toString(16).padStart(16, "0");
8
- };
9
-
10
- afterEach(() => {
11
- vi.unstubAllGlobals();
12
- vi.resetModules();
13
- });
14
-
15
- it("matches exact FNV across scratch boundaries, UTF-8 and every byte value", () => {
16
- for (const length of [0, 1, 4095, 4096, 4097, 16385]) {
17
- const bytes = Uint8Array.from({ length }, (_, index) => index % 256);
18
- const writer = createBufferedFnv64();
19
- expect(writer).not.toBeNull();
20
- writer!.bytes(bytes);
21
- expect(writer!.digest()).toBe(reference(bytes));
22
- expect(writer!.digest()).toBe(reference(bytes));
23
- }
24
- for (const text of ["é", "😀", "\ud800", "a\udc00z"]) {
25
- const writer = createBufferedFnv64()!;
26
- const bytes = new TextEncoder().encode(text);
27
- writer.ascii("prefix");
28
- writer.bytes(bytes);
29
- writer.boolean(true);
30
- expect(writer.digest()).toBe(reference(new TextEncoder().encode(`prefix${text}b1;`)));
31
- }
32
- });
33
-
34
- it("keeps concurrent partially buffered writers independent across async yields", async () => {
35
- await Promise.all(
36
- Array.from({ length: 16 }, async (_, index) => {
37
- const writer = createBufferedFnv64()!;
38
- const parts = Array.from({ length: 20 }, (_, part) => `${index}:${part}:`.repeat(150));
39
- for (const part of parts) {
40
- expect(writer.ascii(part)).toBe(part.length);
41
- await Promise.resolve();
42
- }
43
- expect(writer.digest()).toBe(reference(new TextEncoder().encode(parts.join(""))));
44
- }),
45
- );
46
- });
47
-
48
- it("returns the JS-fallback signal when WASM is unavailable or initialization is blocked", async () => {
49
- vi.stubGlobal("WebAssembly", undefined);
50
- vi.resetModules();
51
- expect((await import("./terminal-fnv64-wasm.ts")).createBufferedFnv64()).toBeNull();
52
- const blocked = vi.fn(function () {
53
- throw new Error("WASM blocked");
54
- });
55
- vi.stubGlobal("WebAssembly", { Module: blocked });
56
- vi.resetModules();
57
- const module = await import("./terminal-fnv64-wasm.ts");
58
- expect(module.createBufferedFnv64()).toBeNull();
59
- expect(module.createBufferedFnv64()).toBeNull();
60
- expect(blocked).toHaveBeenCalledTimes(1);
61
- });
@@ -1,31 +0,0 @@
1
- import { spawnSync } from "node:child_process";
2
- import { fileURLToPath } from "node:url";
3
- import { describe, expect, it } from "vitest";
4
-
5
- describe("terminal replica cold Bun process", () => {
6
- it("applies the first 132x41 last-column patch inside one frame", () => {
7
- const fixture = fileURLToPath(
8
- new URL("../test-support/terminal-replica-cold-process.ts", import.meta.url),
9
- );
10
- const result = spawnSync("bun", [fixture], { encoding: "utf8", timeout: 10_000 });
11
- expect(result.status, result.stderr).toBe(0);
12
- const measurement = JSON.parse(result.stdout.trim()) as {
13
- durationMs: number;
14
- profile: {
15
- reusedAuthenticatedFrameHash: boolean;
16
- phaseMicros: Record<string, number>;
17
- counts: Record<string, number>;
18
- };
19
- };
20
- expect(measurement.durationMs).toBeLessThanOrEqual(16.67);
21
- expect(measurement.profile.reusedAuthenticatedFrameHash).toBe(true);
22
- expect(measurement.profile.phaseMicros.updateHash).toBe(0);
23
- expect(measurement.profile.counts).toMatchObject({
24
- patchedRows: 1,
25
- validatedCells: 132,
26
- frozenCells: 132,
27
- comparedCells: 132,
28
- rowHashMisses: 1,
29
- });
30
- });
31
- });
@@ -1,170 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import type { CanonicalTerminalReplicaSeed } from "@tmux-ide/contracts";
3
- import {
4
- applyTerminalReplicaUpdate,
5
- applyTerminalReplicaUpdateCooperatively,
6
- blankTerminalReplicaSnapshot,
7
- hashTerminalReplicaSnapshot,
8
- terminalReplicaUpdateNeedsCooperativeReduction,
9
- } from "./terminal-replica.ts";
10
- import {
11
- decodeVerifiedCompactSemanticTerminalUpdate,
12
- encodeCompactSemanticTerminalUpdate,
13
- } from "./terminal-delivery.ts";
14
-
15
- function seed(cols = 128, rows = 64): CanonicalTerminalReplicaSeed {
16
- const snapshot = blankTerminalReplicaSnapshot(cols, rows);
17
- return {
18
- type: "terminal.seed",
19
- workspaceName: "workspace",
20
- semanticPaneId: "pane",
21
- generation: "00000000-0000-4000-8000-000000000001",
22
- incarnation: "00000000-0000-4000-8000-000000000001:0",
23
- revision: 0,
24
- cols,
25
- rows,
26
- snapshot,
27
- stateHash: hashTerminalReplicaSnapshot(snapshot),
28
- hashAlgorithm: "fnv1a64-v1",
29
- };
30
- }
31
- const yielding = { yieldControl: async () => {} };
32
- describe("cooperative terminal seed reduction", () => {
33
- it("matches ordinary state and exact frame hash for large seeds and replay", async () => {
34
- const update = seed();
35
- const sync = applyTerminalReplicaUpdate(null, update);
36
- const asyncResult = await applyTerminalReplicaUpdateCooperatively(null, update, yielding);
37
- expect(asyncResult).toEqual(sync);
38
- expect(Object.isFrozen(asyncResult.state!.snapshot!.grid[0]!.cells[0])).toBe(true);
39
- expect(
40
- await applyTerminalReplicaUpdateCooperatively(asyncResult.state, update, yielding),
41
- ).toEqual(applyTerminalReplicaUpdate(sync.state, update));
42
- });
43
- it.each([
44
- "hash",
45
- "dimensions",
46
- "cursor",
47
- "wide",
48
- "placement",
49
- "generation",
50
- "incarnation",
51
- "stale",
52
- ])("preserves %s rejection/order semantics", async (kind) => {
53
- const initial = seed();
54
- const current = applyTerminalReplicaUpdate(null, initial).state;
55
- const update = { ...structuredClone(initial) };
56
- update.revision = 1;
57
- if (kind === "hash") update.stateHash = "0000000000000000";
58
- if (kind === "dimensions") update.cols++;
59
- if (kind === "cursor") update.snapshot.cursor.x = update.cols;
60
- if (kind === "wide") update.snapshot.grid[0]!.cells[0]!.width = 2;
61
- if (kind === "placement")
62
- update.snapshot.placements.push({
63
- id: "p",
64
- kind: "test",
65
- row: 1000,
66
- column: 0,
67
- rows: 1,
68
- columns: 1,
69
- contentDigest: "x",
70
- });
71
- if (kind === "generation") update.generation = "00000000-0000-4000-8000-000000000002";
72
- if (kind === "incarnation") update.incarnation = "other";
73
- const baseline = kind === "stale" ? { ...current!, revision: 5 } : current;
74
- expect(await applyTerminalReplicaUpdateCooperatively(baseline, update, yielding)).toEqual(
75
- applyTerminalReplicaUpdate(baseline, update),
76
- );
77
- });
78
- it("preserves existing upstream-validated boundary rather than silently changing schemas", async () => {
79
- const update = { ...structuredClone(seed()) };
80
- update.snapshot.cursor.x = -1;
81
- update.stateHash = hashTerminalReplicaSnapshot(update.snapshot);
82
- expect(await applyTerminalReplicaUpdateCooperatively(null, update, yielding)).toEqual(
83
- applyTerminalReplicaUpdate(null, update),
84
- );
85
- });
86
- it("yields during cell copying before traversing the complete snapshot and aborts cleanly", async () => {
87
- const update = { ...structuredClone(seed()) };
88
- let reads = 0;
89
- for (const row of update.snapshot.grid)
90
- for (const cell of row.cells)
91
- Object.defineProperty(cell, "grapheme", {
92
- enumerable: true,
93
- get: () => {
94
- reads++;
95
- return "";
96
- },
97
- });
98
- update.stateHash = hashTerminalReplicaSnapshot(update.snapshot);
99
- reads = 0;
100
- const controller = new AbortController();
101
- const reason = new Error("owner retired");
102
- await expect(
103
- applyTerminalReplicaUpdateCooperatively(null, update, {
104
- signal: controller.signal,
105
- yieldControl: async () => {
106
- expect(reads).toBe(256);
107
- controller.abort(reason);
108
- },
109
- }),
110
- ).rejects.toBe(reason);
111
- expect(reads).toBe(256);
112
- });
113
- it("permits actual I/O turns while reducing wide rows and supports cancellation during hashing", async () => {
114
- const update = seed(4096, 2);
115
- let turns = 0;
116
- const result = await applyTerminalReplicaUpdateCooperatively(null, update, {
117
- yieldControl: () =>
118
- new Promise<void>((resolve) =>
119
- setImmediate(() => {
120
- turns++;
121
- resolve();
122
- }),
123
- ),
124
- });
125
- expect(result.status).toBe("applied");
126
- expect(turns).toBeGreaterThan(32);
127
- const controller = new AbortController();
128
- let slices = 0;
129
- await expect(
130
- applyTerminalReplicaUpdateCooperatively(null, update, {
131
- signal: controller.signal,
132
- yieldControl: async () => {
133
- if (++slices === 40) controller.abort();
134
- },
135
- }),
136
- ).rejects.toMatchObject({ name: "AbortError" });
137
- });
138
- it("keeps small seed/patch reduction synchronous within the wrapper", async () => {
139
- const update = seed(4, 2);
140
- let yields = 0;
141
- expect(terminalReplicaUpdateNeedsCooperativeReduction(update)).toBe(false);
142
- const result = await applyTerminalReplicaUpdateCooperatively(null, update, {
143
- yieldControl: async () => {
144
- yields++;
145
- },
146
- });
147
- expect(result).toEqual(applyTerminalReplicaUpdate(null, update));
148
- expect(yields).toBe(0);
149
- });
150
- it("preserves verified compact adoption and authenticated frame hash", async () => {
151
- const original = seed();
152
- const verified = decodeVerifiedCompactSemanticTerminalUpdate(
153
- encodeCompactSemanticTerminalUpdate({
154
- frame: "seed",
155
- revision: 0,
156
- snapshot: original.snapshot,
157
- }),
158
- null,
159
- original.stateHash,
160
- { grantReducerAdoption: true },
161
- );
162
- const update = { ...original, snapshot: verified.canonicalSnapshot! };
163
- const result = await applyTerminalReplicaUpdateCooperatively(null, update, {
164
- ...yielding,
165
- authenticatedFrameHash: "1234567890abcdef",
166
- });
167
- expect(result.state!.snapshot).toBe(verified.canonicalSnapshot);
168
- expect(result.state!.frameHash).toBe("1234567890abcdef");
169
- });
170
- });
@@ -1,283 +0,0 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- import * as bufferedHash from "./terminal-fnv64-wasm.ts";
3
- import type { TerminalReplicaRow, TerminalReplicaSnapshot } from "@tmux-ide/contracts";
4
- import { blankTerminalReplicaSnapshot, hashTerminalReplicaSnapshot } from "./terminal-replica.ts";
5
- import {
6
- hashCanonicalTerminalValue,
7
- hashTerminalReplicaRowCached,
8
- hashTerminalReplicaRowRunsCooperatively,
9
- TerminalReplicaRunEncodingCache,
10
- } from "./terminal-replica-hash-cache.ts";
11
-
12
- const canonicalEncode = (value: unknown): string => {
13
- if (value === null) return "n;";
14
- if (typeof value === "boolean") return value ? "b1;" : "b0;";
15
- if (typeof value === "number") return `d${String(value).length}:${String(value)};`;
16
- if (typeof value === "string") {
17
- const length = new TextEncoder().encode(value).length;
18
- return `s${length}:${value};`;
19
- }
20
- if (Array.isArray(value)) return `a${value.length}:${value.map(canonicalEncode).join("")};`;
21
- const record = value as Record<string, unknown>;
22
- const keys = Object.keys(record).sort();
23
- return `o${keys.length}:${keys
24
- .map((key) => `${canonicalEncode(key)}${canonicalEncode(record[key])}`)
25
- .join("")};`;
26
- };
27
-
28
- const referenceHash = (value: unknown): string => {
29
- const bytes = new TextEncoder().encode(canonicalEncode(value));
30
- let hash = 0xcbf29ce484222325n;
31
- for (const byte of bytes) {
32
- hash ^= BigInt(byte);
33
- hash = BigInt.asUintN(64, hash * 0x100000001b3n);
34
- }
35
- return hash.toString(16).padStart(16, "0");
36
- };
37
-
38
- describe("terminal canonical hash cache", () => {
39
- it("accelerates substantial transactions without changing hashes or cooperative checkpoints", async () => {
40
- const cache = new TerminalReplicaRunEncodingCache();
41
- const factory = vi.spyOn(bufferedHash, "createBufferedFnv64");
42
- const cell = {
43
- ...blankTerminalReplicaSnapshot(1, 1).grid[0]!.cells[0]!,
44
- grapheme: "界e\u0301\ud800",
45
- };
46
- const row = { wrapped: true, cells: Array.from({ length: 1_024 }, () => cell) };
47
- const expected = hashTerminalReplicaRowCached(row);
48
- const decode = async (encodingCache: TerminalReplicaRunEncodingCache) => {
49
- let checkpoints = 0;
50
- const digest = await hashTerminalReplicaRowRunsCooperatively(
51
- true,
52
- row.cells.length,
53
- [[row.cells.length, cell]],
54
- async () => {
55
- checkpoints += 1;
56
- },
57
- 64,
58
- undefined,
59
- encodingCache,
60
- );
61
- expect(digest).toBe(expected);
62
- expect(checkpoints).toBe(16);
63
- };
64
- try {
65
- await decode(cache);
66
- expect(factory).not.toHaveBeenCalled();
67
- await Promise.all([decode(cache), decode(cache)]);
68
- expect(factory).toHaveBeenCalledTimes(2);
69
- expect(factory.mock.results.every((result) => result.value !== null)).toBe(true);
70
- // A separate client/delivery does not inherit another transaction's work.
71
- await decode(new TerminalReplicaRunEncodingCache());
72
- expect(factory).toHaveBeenCalledTimes(2);
73
- factory.mockReturnValue(null);
74
- await decode(cache);
75
- expect(factory).toHaveBeenCalledTimes(3);
76
- } finally {
77
- factory.mockRestore();
78
- }
79
- });
80
-
81
- it("preserves carries and wraparound over every indexed color and RGB byte extreme", () => {
82
- const colors = [
83
- { kind: "default" },
84
- ...Array.from({ length: 256 }, (_, index) => ({ kind: "indexed", index })),
85
- ...[0, 0xff, 0xff00, 0xff0000, 0xffffff].map((value) => ({ kind: "rgb", value })),
86
- ];
87
- const values = colors.map((foreground, index) => [
88
- String.fromCharCode(index % 128),
89
- index % 3,
90
- foreground,
91
- colors[colors.length - index - 1],
92
- index * 257,
93
- ]);
94
- expect(hashCanonicalTerminalValue([true, values])).toBe(referenceHash([true, values]));
95
- });
96
-
97
- it("preserves exact UTF-8 hashes across ASCII boundaries and malformed surrogates", () => {
98
- const values = [
99
- "",
100
- " ",
101
- Array.from({ length: 128 }, (_, index) => String.fromCharCode(index)).join(""),
102
- "a".repeat(1024),
103
- "\u007f\u0080",
104
- "ASCII界",
105
- "e\u0301",
106
- "😀",
107
- "\ud800",
108
- "\udc00",
109
- "a\ud800z",
110
- ];
111
- for (const value of values) {
112
- expect(hashCanonicalTerminalValue(value)).toBe(referenceHash(value));
113
- expect(hashCanonicalTerminalValue({ [value]: [value, "", "tail"] })).toBe(
114
- referenceHash({ [value]: [value, "", "tail"] }),
115
- );
116
- }
117
- });
118
-
119
- it("matches the prior canonical BigInt hash for nested UTF-8 values", () => {
120
- const corpus = [
121
- null,
122
- true,
123
- false,
124
- 0,
125
- -17,
126
- "ASCII",
127
- "界e\u0301\ud800",
128
- [null, true, 17, "wide界"],
129
- { z: [1, 2], a: { kind: "rgb", value: 0xff00aa } },
130
- ];
131
- for (const value of corpus)
132
- expect(hashCanonicalTerminalValue(value)).toBe(referenceHash(value));
133
- });
134
-
135
- it("matches the prior row hash for indexed, RGB, wide and combining cells", () => {
136
- const blank = blankTerminalReplicaSnapshot(3, 1);
137
- const row = Object.freeze({
138
- wrapped: true,
139
- cells: Object.freeze([
140
- Object.freeze({
141
- ...blank.grid[0]!.cells[0]!,
142
- grapheme: "界",
143
- width: 2 as const,
144
- foreground: Object.freeze({ kind: "indexed" as const, index: 75 }),
145
- }),
146
- Object.freeze({
147
- ...blank.grid[0]!.cells[1]!,
148
- grapheme: "",
149
- width: 0 as const,
150
- background: Object.freeze({ kind: "rgb" as const, value: 0x112233 }),
151
- }),
152
- Object.freeze({ ...blank.grid[0]!.cells[2]!, grapheme: "e\u0301", attributes: 7 }),
153
- ]),
154
- }) as unknown as TerminalReplicaRow;
155
- const projected = [
156
- row.wrapped,
157
- row.cells.map((cell) => [
158
- cell.grapheme,
159
- cell.width,
160
- cell.foreground,
161
- cell.background,
162
- cell.attributes,
163
- ]),
164
- ];
165
- expect(hashTerminalReplicaRowCached(row)).toBe(referenceHash(projected));
166
- expect(hashTerminalReplicaRowCached(row)).toBe(referenceHash(projected));
167
- });
168
-
169
- it("replays one UTF-8 encoding per compact run with exhaustive row-hash parity", async () => {
170
- const blank = blankTerminalReplicaSnapshot(5, 1);
171
- const cells = [
172
- Object.freeze({
173
- ...blank.grid[0]!.cells[0]!,
174
- grapheme: "界",
175
- width: 2 as const,
176
- foreground: Object.freeze({ kind: "indexed" as const, index: 75 }),
177
- }),
178
- Object.freeze({
179
- ...blank.grid[0]!.cells[0]!,
180
- grapheme: "",
181
- width: 0 as const,
182
- background: Object.freeze({ kind: "rgb" as const, value: 0x112233 }),
183
- }),
184
- Object.freeze({
185
- ...blank.grid[0]!.cells[0]!,
186
- grapheme: "e\u0301",
187
- attributes: 0xff,
188
- }),
189
- ];
190
- const row = Object.freeze({
191
- wrapped: true,
192
- cells: Object.freeze([cells[0]!, cells[1]!, cells[2]!, cells[2]!, cells[2]!]),
193
- }) as unknown as TerminalReplicaRow;
194
- const encodedRuns: number[] = [];
195
- const digest = await hashTerminalReplicaRowRunsCooperatively(
196
- true,
197
- 5,
198
- [
199
- [1, cells[0]!],
200
- [1, cells[1]!],
201
- [3, cells[2]!],
202
- ],
203
- async () => {},
204
- 2,
205
- (bytes) => encodedRuns.push(bytes),
206
- );
207
- expect(digest).toBe(hashTerminalReplicaRowCached(row));
208
- expect(encodedRuns).toEqual([3, 0, 3]);
209
- });
210
-
211
- it("never caches a shallow-frozen snapshot whose nested canonical state remains mutable", () => {
212
- const blank = blankTerminalReplicaSnapshot(2, 1);
213
- const cursor = { ...blank.cursor };
214
- const modes = { ...blank.modes };
215
- const placements = [
216
- {
217
- id: "placement-a",
218
- kind: "image",
219
- row: 0,
220
- column: 0,
221
- columns: 1,
222
- rows: 1,
223
- contentDigest: "digest-a",
224
- },
225
- ];
226
- const history: TerminalReplicaRow[] = [];
227
- const snapshot = Object.freeze({
228
- ...blank,
229
- grid: [...blank.grid],
230
- history,
231
- cursor,
232
- modes,
233
- placements,
234
- }) as unknown as TerminalReplicaSnapshot;
235
- const initial = hashTerminalReplicaSnapshot(snapshot);
236
- cursor.x = 1;
237
- const cursorChanged = hashTerminalReplicaSnapshot(snapshot);
238
- expect(cursorChanged).not.toBe(initial);
239
- modes.insert = true;
240
- const modesChanged = hashTerminalReplicaSnapshot(snapshot);
241
- expect(modesChanged).not.toBe(cursorChanged);
242
- placements[0]!.contentDigest = "digest-b";
243
- const placementChanged = hashTerminalReplicaSnapshot(snapshot);
244
- expect(placementChanged).not.toBe(modesChanged);
245
- history.push(blank.grid[0]!);
246
- expect(hashTerminalReplicaSnapshot(snapshot)).not.toBe(placementChanged);
247
- });
248
-
249
- it("never caches frozen row arrays or rows with mutable nested cells and colors", () => {
250
- const blank = blankTerminalReplicaSnapshot(1, 1);
251
- const foreground = { kind: "rgb" as const, value: 0x112233 };
252
- const background = { kind: "rgb" as const, value: 0x445566 };
253
- const cell = {
254
- ...blank.grid[0]!.cells[0]!,
255
- foreground,
256
- background,
257
- };
258
- const row = Object.freeze({ wrapped: false, cells: Object.freeze([cell]) });
259
- const snapshot = Object.freeze({
260
- ...blank,
261
- grid: Object.freeze([row]),
262
- }) as unknown as TerminalReplicaSnapshot;
263
- const initial = hashTerminalReplicaSnapshot(snapshot);
264
- cell.grapheme = "x";
265
- const graphemeChanged = hashTerminalReplicaSnapshot(snapshot);
266
- expect(graphemeChanged).not.toBe(initial);
267
- cell.attributes = 7;
268
- const styleChanged = hashTerminalReplicaSnapshot(snapshot);
269
- expect(styleChanged).not.toBe(graphemeChanged);
270
- foreground.value = 0xaabbcc;
271
- const colorChanged = hashTerminalReplicaSnapshot(snapshot);
272
- expect(colorChanged).not.toBe(styleChanged);
273
-
274
- const mutableRow = { wrapped: false, cells: blank.grid[0]!.cells };
275
- const mutableRowSnapshot = Object.freeze({
276
- ...blank,
277
- grid: Object.freeze([mutableRow]),
278
- }) as unknown as TerminalReplicaSnapshot;
279
- const rowInitial = hashTerminalReplicaSnapshot(mutableRowSnapshot);
280
- mutableRow.wrapped = true;
281
- expect(hashTerminalReplicaSnapshot(mutableRowSnapshot)).not.toBe(rowInitial);
282
- });
283
- });