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,87 +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("compact terminal delivery cold process", () => {
6
- it("adopts a unique-row 132x41 seed and 5000-history patch below the event-loop cap", () => {
7
- const fixture = fileURLToPath(
8
- new URL("../test-support/terminal-compact-cold-process.ts", import.meta.url),
9
- );
10
- const result = spawnSync(process.execPath, ["--experimental-strip-types", fixture], {
11
- encoding: "utf8",
12
- timeout: 30_000,
13
- });
14
- expect(result.status, result.stderr).toBe(0);
15
- const measurement = JSON.parse(result.stdout.trim()) as {
16
- durationMs: number;
17
- timerDelayMs: number;
18
- rssBytes: number;
19
- heapBytes: number;
20
- revision: number;
21
- uniqueHistoryRows: number;
22
- profiles: Array<Record<string, unknown>>;
23
- };
24
- expect(measurement).toMatchObject({ revision: 1, uniqueHistoryRows: 5_000 });
25
- expect(measurement.rssBytes).toBeLessThan(1_073_741_824);
26
- expect(measurement.heapBytes).toBeLessThan(536_870_912);
27
- expect(measurement.durationMs).toBeLessThan(30_000);
28
- expect(measurement.profiles).toHaveLength(2);
29
- expect(measurement.profiles).toEqual([
30
- expect.objectContaining({
31
- expandedRows: 4_137,
32
- expandedCells: 546_084,
33
- schemaTraversals: 1,
34
- hashTraversals: 1,
35
- applyTraversals: 0,
36
- trustedAdoption: true,
37
- retainedSnapshots: 0,
38
- }),
39
- expect.objectContaining({
40
- expandedRows: 904,
41
- expandedCells: 119_328,
42
- schemaTraversals: 1,
43
- hashTraversals: 1,
44
- applyTraversals: 1,
45
- trustedAdoption: true,
46
- retainedSnapshots: 0,
47
- }),
48
- ]);
49
- expect(measurement.timerDelayMs).toBeLessThanOrEqual(33);
50
- }, 35_000);
51
-
52
- it("bounds an 8MiB max-width high-run compact seed through final hash", () => {
53
- const fixture = fileURLToPath(
54
- new URL("../test-support/terminal-compact-max-cold-process.ts", import.meta.url),
55
- );
56
- const result = spawnSync(process.execPath, ["--experimental-strip-types", fixture], {
57
- encoding: "utf8",
58
- timeout: 35_000,
59
- });
60
- expect(result.status, result.stderr).toBe(0);
61
- const measurement = JSON.parse(result.stdout.trim()) as {
62
- timerDelayMs: number;
63
- maxSliceMs: number;
64
- maxSliceStage: string;
65
- representationBytes: number;
66
- denseRepresentationBytes: number;
67
- denseRejected: boolean;
68
- rssBytes: number;
69
- heapBytes: number;
70
- revision: number;
71
- hash: string;
72
- };
73
- expect(measurement).toMatchObject({ revision: 0, denseRejected: true });
74
- expect(measurement.hash).toMatch(/^[0-9a-f]{16}$/u);
75
- expect(measurement.representationBytes).toBeGreaterThan(8 * 1024 * 1024);
76
- expect(measurement.denseRepresentationBytes).toBeGreaterThan(14 * 1024 * 1024);
77
- expect(measurement.rssBytes).toBeLessThan(1_073_741_824);
78
- expect(measurement.heapBytes).toBeLessThan(536_870_912);
79
- // This max-width stress case also parses and rejects a deliberately dense
80
- // 15 MB legacy payload. Keep wall-clock scheduler jitter and the measured
81
- // CPU slice bounded without conflating this adversarial rejection path with
82
- // the 33 ms interactive budget enforced by performance qualification.
83
- expect(measurement.timerDelayMs).toBeLessThanOrEqual(60);
84
- expect(measurement.maxSliceMs).toBeLessThanOrEqual(150);
85
- expect(measurement.maxSliceStage).not.toBe("");
86
- }, 40_000);
87
- });
@@ -1,48 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
-
3
- import {
4
- TERMINAL_CONFORMANCE_FIXTURES,
5
- XTERM_PALETTE,
6
- XTERM_PALETTE_HEX,
7
- } from "./terminal-conformance.ts";
8
-
9
- describe("terminal conformance corpus", () => {
10
- it("defines one complete, byte-identical xterm palette for every renderer", () => {
11
- expect(XTERM_PALETTE).toHaveLength(256);
12
- expect(XTERM_PALETTE_HEX).toHaveLength(256);
13
- expect(XTERM_PALETTE[0]).toBe(0x000000);
14
- expect(XTERM_PALETTE[16]).toBe(0x000000);
15
- expect(XTERM_PALETTE[231]).toBe(0xffffff);
16
- expect(XTERM_PALETTE[232]).toBe(0x080808);
17
- expect(XTERM_PALETTE[255]).toBe(0xeeeeee);
18
- for (let index = 0; index < XTERM_PALETTE.length; index += 1) {
19
- expect(XTERM_PALETTE_HEX[index]).toBe(
20
- `#${XTERM_PALETTE[index]!.toString(16).padStart(6, "0")}`,
21
- );
22
- }
23
- });
24
-
25
- it("keeps fixture ids and asserted cell coordinates unique", () => {
26
- const ids = TERMINAL_CONFORMANCE_FIXTURES.map((fixture) => fixture.id);
27
- expect(new Set(ids).size).toBe(ids.length);
28
- for (const fixture of TERMINAL_CONFORMANCE_FIXTURES) {
29
- const cells = fixture.cells.map((cell) => `${cell.row}:${cell.column}`);
30
- expect(new Set(cells).size, fixture.id).toBe(cells.length);
31
- expect(fixture.writes.join("").length, fixture.id).toBeGreaterThan(0);
32
- for (const cell of fixture.cells) {
33
- expect(cell.row).toBeLessThan(fixture.rows);
34
- expect(cell.column).toBeLessThan(fixture.cols);
35
- }
36
- for (const row of fixture.wrappedRows ?? []) {
37
- expect(row, `${fixture.id} wrapped row`).toBeGreaterThanOrEqual(0);
38
- expect(row, `${fixture.id} wrapped row`).toBeLessThan(fixture.rows);
39
- }
40
- if (fixture.cursor) {
41
- expect(fixture.cursor.x, `${fixture.id} cursor x`).toBeLessThan(fixture.cols);
42
- expect(fixture.cursor.y, `${fixture.id} cursor y`).toBeLessThan(fixture.rows);
43
- }
44
- if (fixture.historyRows !== undefined)
45
- expect(fixture.historyRows, `${fixture.id} history`).toBeGreaterThanOrEqual(0);
46
- }
47
- });
48
- });
@@ -1,167 +0,0 @@
1
- import { execFileSync } from "node:child_process";
2
- import { mkdtempSync, rmSync } from "node:fs";
3
- import { tmpdir } from "node:os";
4
- import { join } from "node:path";
5
- import { fileURLToPath } from "node:url";
6
- import { build } from "esbuild";
7
- import { afterAll, beforeAll, describe, expect, it } from "vitest";
8
- import {
9
- applyTerminalReplicaPatch,
10
- blankTerminalReplicaSnapshot,
11
- hashTerminalReplicaSnapshot,
12
- } from "./terminal-replica.ts";
13
- import {
14
- decodeVerifiedCompactSemanticTerminalUpdateCooperatively as decode,
15
- encodeCompactSemanticTerminalUpdate,
16
- } from "./terminal-delivery.ts";
17
-
18
- const yieldControl = async () => {};
19
-
20
- async function decodedBlank() {
21
- const input = blankTerminalReplicaSnapshot(8, 2);
22
- return (
23
- await decode(
24
- encodeCompactSemanticTerminalUpdate({ frame: "seed", revision: 0, snapshot: input }),
25
- null,
26
- hashTerminalReplicaSnapshot(input),
27
- { yieldControl },
28
- )
29
- ).canonicalSnapshot!;
30
- }
31
-
32
- describe("compact baseline index lifetime", () => {
33
- it("reuses a row that entered the current baseline after the first index was built", async () => {
34
- let baseline = await decodedBlank();
35
- for (let revision = 1; revision <= 3; revision += 1) {
36
- const row = structuredClone(baseline.grid[0]!);
37
- row.cells[0]!.grapheme = "X";
38
- const patch = { rows: [{ index: 1, row }], cursor: { ...baseline.cursor, x: revision } };
39
- const expected = applyTerminalReplicaPatch(baseline, patch);
40
- let counts: { allocatedCells: number; reusedRows: number } | undefined;
41
- const result = await decode(
42
- encodeCompactSemanticTerminalUpdate({
43
- frame: "patch",
44
- baseRevision: revision - 1,
45
- revision,
46
- patch,
47
- }),
48
- baseline,
49
- hashTerminalReplicaSnapshot(expected),
50
- {
51
- yieldControl,
52
- onComplete: (profile) => {
53
- counts = profile;
54
- },
55
- },
56
- );
57
- expect(result.canonicalSnapshot).toEqual(expected);
58
- expect(counts).toMatchObject(
59
- revision === 1
60
- ? { allocatedCells: 8, reusedRows: 0 }
61
- : { allocatedCells: 0, reusedRows: 1 },
62
- );
63
- if (revision > 1) expect(result.canonicalSnapshot!.grid[1]).toBe(baseline.grid[1]);
64
- baseline = result.canonicalSnapshot!;
65
- }
66
- });
67
-
68
- it("checks history when a same-hash grid candidate has different bytes", async () => {
69
- const blank = blankTerminalReplicaSnapshot(1, 1);
70
- const row = (grapheme: string) => ({
71
- wrapped: false,
72
- cells: [{ ...blank.grid[0]!.cells[0]!, grapheme }],
73
- });
74
- // These encoded rows collide in the raw FNV32 cache, but differ canonically.
75
- const input = { ...blank, grid: [row("dkzbb9")], history: [row("1mu5745")] };
76
- const baseline = (
77
- await decode(
78
- encodeCompactSemanticTerminalUpdate({ frame: "seed", revision: 0, snapshot: input }),
79
- null,
80
- hashTerminalReplicaSnapshot(input),
81
- { yieldControl },
82
- )
83
- ).canonicalSnapshot!;
84
- const patch = { rows: [{ index: 0, row: baseline.history[0]! }] };
85
- const expected = applyTerminalReplicaPatch(baseline, patch);
86
- let counts: { allocatedCells: number; reusedRows: number } | undefined;
87
- const result = await decode(
88
- encodeCompactSemanticTerminalUpdate({ frame: "patch", baseRevision: 0, revision: 1, patch }),
89
- baseline,
90
- hashTerminalReplicaSnapshot(expected),
91
- {
92
- yieldControl,
93
- onComplete: (profile) => {
94
- counts = profile;
95
- },
96
- },
97
- );
98
- expect(result.canonicalSnapshot).toEqual(expected);
99
- expect(result.canonicalSnapshot!.grid[0]).toBe(baseline.history[0]);
100
- expect(counts).toMatchObject({ allocatedCells: 0, reusedRows: 1 });
101
- });
102
-
103
- // An isolated Node process provides explicit GC without sharing Vitest's
104
- // retained assertions, module jobs or heap with the weak-reference probe.
105
- let directory: string;
106
- let probe: string;
107
- beforeAll(async () => {
108
- directory = mkdtempSync(join(tmpdir(), "tmux-compact-lifetime-"));
109
- probe = join(directory, "probe.mjs");
110
- const replica = fileURLToPath(new URL("./terminal-replica.ts", import.meta.url));
111
- const delivery = fileURLToPath(new URL("./terminal-delivery.ts", import.meta.url));
112
- await build({
113
- stdin: {
114
- contents: `
115
- import {blankTerminalReplicaSnapshot,hashTerminalReplicaSnapshot,applyTerminalReplicaPatch} from ${JSON.stringify(replica)};
116
- import {encodeCompactSemanticTerminalUpdate,decodeVerifiedCompactSemanticTerminalUpdateCooperatively as decode} from ${JSON.stringify(delivery)};
117
- const yieldControl=async()=>{};
118
- const blank=blankTerminalReplicaSnapshot(8,1);
119
- function row(label){const r=structuredClone(blank.grid[0]);r.cells[0].grapheme=label;return r;}
120
- async function setup(){
121
- const chain=process.argv[2]==='chain';
122
- const input={...blank,grid:[row('A')],history:chain?[row('B')]:Array.from({length:2000},(_,i)=>row('old-'+i))};
123
- let state=(await decode(encodeCompactSemanticTerminalUpdate({frame:'seed',revision:0,snapshot:input}),null,hashTerminalReplicaSnapshot(input),{yieldControl})).canonicalSnapshot;
124
- const anchor=state.grid[0];const refs=[];let revision=0;
125
- async function patch(p){const next=applyTerminalReplicaPatch(state,p);state=(await decode(encodeCompactSemanticTerminalUpdate({frame:'patch',baseRevision:revision,revision:++revision,patch:p}),state,hashTerminalReplicaSnapshot(next),{yieldControl})).canonicalSnapshot;}
126
- if(chain){
127
- for(let i=0;i<50;i++){
128
- await patch({rows:[{index:0,row:state.history[0]}],history:[row('next-'+i)]});
129
- await patch({rows:[],cursor:{...state.cursor,x:0}});
130
- refs.push(new WeakRef(state.history[0]));
131
- }
132
- }else{
133
- refs.push(new WeakRef(state.history[1000]));
134
- await patch({rows:[],historyDelta:{trim:2000,append:[]}});
135
- }
136
- return {anchor,refs,current:chain?null:state};
137
- }
138
- const result=await setup();
139
- for(let i=0;i<12;i++){await new Promise(r=>setImmediate(r));global.gc();}
140
- console.log(JSON.stringify({anchor:result.anchor.cells[0].grapheme,retained:result.refs.filter(r=>r.deref()).length,history:result.current?.history.length??null}));
141
- `,
142
- resolveDir: process.cwd(),
143
- loader: "ts",
144
- },
145
- bundle: true,
146
- platform: "node",
147
- format: "esm",
148
- outfile: probe,
149
- });
150
- });
151
- afterAll(() => {
152
- if (directory) rmSync(directory, { recursive: true, force: true });
153
- });
154
-
155
- it.each(["trim", "chain"])(
156
- "releases obsolete rows after %s while one old row remains alive",
157
- (mode) => {
158
- const result = JSON.parse(
159
- execFileSync(process.execPath, ["--expose-gc", probe, mode], {
160
- encoding: "utf8",
161
- timeout: 15_000,
162
- }),
163
- );
164
- expect(result).toEqual({ anchor: "A", retained: 0, history: mode === "trim" ? 0 : null });
165
- },
166
- );
167
- });
@@ -1,140 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import {
3
- encodeCompactSemanticTerminalUpdate,
4
- encodeCompactSemanticTerminalUpdateCooperatively,
5
- terminalSemanticUpdateNeedsCooperativeEncoding,
6
- TerminalDeliveryStateTooLargeError,
7
- } from "./terminal-delivery.ts";
8
- import { blankTerminalReplicaSnapshot } from "./terminal-replica.ts";
9
- import type { TerminalSemanticDeliveryPayload } from "@tmux-ide/contracts";
10
- function seed(cols = 128, rows = 64) {
11
- return {
12
- frame: "seed" as const,
13
- revision: 2,
14
- snapshot: structuredClone(blankTerminalReplicaSnapshot(cols, rows)),
15
- };
16
- }
17
- const yielding = { yieldControl: async () => {} };
18
- describe("cooperative compact seed encoding", () => {
19
- it("emits byte-identical dense style, Unicode, wide and history representations", async () => {
20
- const input = seed();
21
- for (let y = 0; y < input.snapshot.grid.length; y++) {
22
- const row = input.snapshot.grid[y]!;
23
- row.wrapped = y % 2 === 0;
24
- for (let x = 0; x < row.cells.length; x++)
25
- row.cells[x] = {
26
- ...row.cells[x]!,
27
- grapheme: x % 3 === 0 ? '界é🙂\\"\n' : String(x % 10),
28
- foreground: { kind: "rgb", value: 0x124578 + x },
29
- background: { kind: "indexed", index: y },
30
- attributes: x % 256,
31
- };
32
- row.cells[0]!.width = 2;
33
- row.cells[1]!.width = 0;
34
- }
35
- input.snapshot.history = input.snapshot.grid.slice(0, 3);
36
- input.snapshot.placements = [
37
- {
38
- id: "widget",
39
- kind: "plot",
40
- row: 0,
41
- column: 0,
42
- rows: 1,
43
- columns: 1,
44
- contentDigest: "digest",
45
- },
46
- ];
47
- expect(await encodeCompactSemanticTerminalUpdateCooperatively(input, yielding)).toEqual(
48
- encodeCompactSemanticTerminalUpdate(input),
49
- );
50
- });
51
- it("joins runs across validation slices and retains exact key order", async () => {
52
- const input = seed(4096, 2);
53
- expect(await encodeCompactSemanticTerminalUpdateCooperatively(input, yielding)).toEqual(
54
- encodeCompactSemanticTerminalUpdate(input),
55
- );
56
- });
57
- it.each(["envelope", "snapshot", "row", "width", "attributes", "color", "cursor", "placement"])(
58
- "rejects malformed %s with the strict schema",
59
- async (kind) => {
60
- const input = seed();
61
- if (kind === "envelope") Object.assign(input, { unknown: true });
62
- if (kind === "snapshot") Object.assign(input.snapshot, { unknown: true });
63
- if (kind === "row") Object.assign(input.snapshot.grid[0]!, { unknown: true });
64
- if (kind === "width") Object.assign(input.snapshot.grid[0]!.cells[0]!, { width: 3 });
65
- if (kind === "attributes") input.snapshot.grid[0]!.cells[0]!.attributes = 256;
66
- if (kind === "color")
67
- Object.assign(input.snapshot.grid[0]!.cells[0]!, {
68
- foreground: { kind: "indexed", index: 256 },
69
- });
70
- if (kind === "cursor") input.snapshot.cursor.x = -1;
71
- if (kind === "placement")
72
- input.snapshot.placements = [
73
- { id: "", kind: "x", row: 0, column: 0, rows: 1, columns: 1, contentDigest: "x" },
74
- ];
75
- expect(() => encodeCompactSemanticTerminalUpdate(input)).toThrow();
76
- await expect(
77
- encodeCompactSemanticTerminalUpdateCooperatively(input, yielding),
78
- ).rejects.toThrow();
79
- },
80
- );
81
- it("checks aggregate row/cell and representation limits", async () => {
82
- const rows = seed();
83
- rows.snapshot.history = Array.from({ length: 10001 }, () => rows.snapshot.grid[0]!);
84
- await expect(
85
- encodeCompactSemanticTerminalUpdateCooperatively(rows, yielding),
86
- ).rejects.toBeInstanceOf(TerminalDeliveryStateTooLargeError);
87
- const bytes = seed();
88
- for (const row of bytes.snapshot.grid)
89
- for (let i = 0; i < row.cells.length; i++)
90
- row.cells[i]!.grapheme = (i % 2 ? "a" : "b").repeat(4096);
91
- expect(() => encodeCompactSemanticTerminalUpdate(bytes)).toThrow(
92
- TerminalDeliveryStateTooLargeError,
93
- );
94
- await expect(
95
- encodeCompactSemanticTerminalUpdateCooperatively(bytes, yielding),
96
- ).rejects.toBeInstanceOf(TerminalDeliveryStateTooLargeError);
97
- });
98
- it("yields during validation before reading a whole seed and aborts without bytes", async () => {
99
- const input = seed();
100
- let reads = 0;
101
- for (const row of input.snapshot.grid)
102
- for (const cell of row.cells)
103
- Object.defineProperty(cell, "grapheme", {
104
- enumerable: true,
105
- get: () => {
106
- reads++;
107
- return "";
108
- },
109
- });
110
- const controller = new AbortController(),
111
- reason = new Error("client retired");
112
- await expect(
113
- encodeCompactSemanticTerminalUpdateCooperatively(input, {
114
- signal: controller.signal,
115
- yieldControl: async () => {
116
- expect(reads).toBe(256);
117
- controller.abort(reason);
118
- },
119
- }),
120
- ).rejects.toBe(reason);
121
- expect(reads).toBe(256);
122
- });
123
- it("keeps small updates on ordinary encoding with no task yield", async () => {
124
- let yields = 0;
125
- for (const input of [
126
- seed(4, 2),
127
- { frame: "patch", baseRevision: 0, revision: 1, patch: { rows: [] } },
128
- ] satisfies TerminalSemanticDeliveryPayload[]) {
129
- expect(terminalSemanticUpdateNeedsCooperativeEncoding(input)).toBe(false);
130
- expect(
131
- await encodeCompactSemanticTerminalUpdateCooperatively(input, {
132
- yieldControl: async () => {
133
- yields++;
134
- },
135
- }),
136
- ).toEqual(encodeCompactSemanticTerminalUpdate(input));
137
- }
138
- expect(yields).toBe(0);
139
- });
140
- });
@@ -1,77 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import {
3
- hashTerminalDeliveryRepresentation,
4
- splitTerminalDeliveryChunks,
5
- TerminalDeliveryAssembler,
6
- } from "./terminal-delivery.ts";
7
- import type { TerminalDeliveryEnvelope } from "@tmux-ide/contracts";
8
-
9
- // Independent integer arithmetic oracle for the existing two-lane wire digest.
10
- function referenceHash(bytes: Uint8Array): string {
11
- let high = 0x811c9dc5n;
12
- let low = 0x9e3779b9n;
13
- for (const byte of bytes) {
14
- high = ((high ^ BigInt(byte)) * 0x01000193n) & 0xffffffffn;
15
- low = ((low ^ BigInt(byte)) * 0x85ebca6bn) & 0xffffffffn;
16
- }
17
- return high.toString(16).padStart(8, "0") + low.toString(16).padStart(8, "0");
18
- }
19
- function slicedBytes(length: number): Uint8Array {
20
- const backing = Uint8Array.from({ length: length + 19 }, (_, index) => (index * 131 + 17) % 256);
21
- return backing.subarray(7, length + 7);
22
- }
23
- function envelope(bytes: Uint8Array, hash: string): TerminalDeliveryEnvelope {
24
- return {
25
- type: "terminal.delivery",
26
- workspaceName: "hash-parity",
27
- semanticPaneId: "pane-a",
28
- generation: "00000000-0000-4000-8000-000000000001",
29
- incarnation: "00000000-0000-4000-8000-000000000001:0",
30
- deliveryNonce: "00000000-0000-4000-8000-000000000002",
31
- transactionId: "00000000-0000-4000-8000-000000000003",
32
- protocolVersion: 1,
33
- encoding: "semantic-v1",
34
- frame: "seed",
35
- baseRevision: null,
36
- canonicalRevision: 0,
37
- canonicalStateHash: "0000000000000000",
38
- representationHash: hash,
39
- representationBytes: bytes.byteLength,
40
- chunkCount: Math.ceil(bytes.byteLength / (256 * 1024)),
41
- canonicalEquivalent: true,
42
- history: "complete",
43
- richPlacements: false,
44
- };
45
- }
46
-
47
- describe("terminal delivery wire hash parity", () => {
48
- it("preserves unsigned lane arithmetic for empty, sliced and chunk-boundary bytes", () => {
49
- expect(hashTerminalDeliveryRepresentation(new Uint8Array())).toBe("811c9dc59e3779b9");
50
- for (const length of [1, 255, 256, 65_537, 262_143, 262_144, 262_145]) {
51
- const bytes = slicedBytes(length);
52
- expect(bytes.byteOffset).toBe(7);
53
- expect(hashTerminalDeliveryRepresentation(bytes)).toBe(referenceHash(bytes));
54
- }
55
- });
56
-
57
- it("preserves incremental assembly across full and partial chunks and refuses corruption", () => {
58
- const bytes = slicedBytes(2 * 256 * 1024 + 17);
59
- const expected = referenceHash(bytes);
60
- const metadata = envelope(bytes, expected);
61
- const chunks = splitTerminalDeliveryChunks(metadata.transactionId, bytes);
62
- expect(chunks.map((chunk) => chunk.bytes.length)).toEqual([262_144, 262_144, 17]);
63
- const valid = new TerminalDeliveryAssembler(metadata);
64
- for (const chunk of chunks) valid.write(chunk);
65
- expect(valid.complete()).toEqual(bytes);
66
- expect(hashTerminalDeliveryRepresentation(valid.complete())).toBe(expected);
67
-
68
- const corrupt = new TerminalDeliveryAssembler(metadata);
69
- for (const chunk of chunks) {
70
- const changed = new Uint8Array(chunk.bytes.length + 9).subarray(9);
71
- changed.set(chunk.bytes);
72
- if (chunk.index === 1) changed[changed.length - 1]! ^= 1;
73
- corrupt.write({ ...chunk, bytes: changed });
74
- }
75
- expect(() => corrupt.complete()).toThrow("representation hash mismatch");
76
- });
77
- });