tmux-ide 2.7.0 → 2.9.0-beta.5

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 (1746) hide show
  1. package/README.md +95 -115
  2. package/bin/cli.js +69987 -11819
  3. package/bin/cli.ts +772 -114
  4. package/package.json +64 -30
  5. package/packages/contracts/package.json +3 -2
  6. package/packages/contracts/src/__tests__/actions-contract.test.ts +119 -0
  7. package/packages/contracts/src/__tests__/agent-graph-overlay.test.ts +428 -0
  8. package/packages/contracts/src/__tests__/app-window-mutation.test.ts +51 -0
  9. package/packages/contracts/src/__tests__/app-window-state.test.ts +34 -0
  10. package/packages/contracts/src/__tests__/application-shell.test.ts +635 -0
  11. package/packages/contracts/src/__tests__/causal-cell.test.ts +47 -0
  12. package/packages/contracts/src/__tests__/client-view-state.test.ts +115 -0
  13. package/packages/contracts/src/__tests__/cohesion-fixture.test.ts +106 -0
  14. package/packages/contracts/src/__tests__/commands.test.ts +86 -0
  15. package/packages/contracts/src/__tests__/control.test.ts +154 -0
  16. package/packages/contracts/src/__tests__/daemon-events.test.ts +400 -0
  17. package/packages/contracts/src/__tests__/daemon-resources.test.ts +143 -0
  18. package/packages/contracts/src/__tests__/daemon-wire.test.ts +117 -0
  19. package/packages/contracts/src/__tests__/desktop-host.test.ts +269 -0
  20. package/packages/contracts/src/__tests__/desktop-missions.test.ts +211 -0
  21. package/packages/contracts/src/__tests__/experience-conformance.test.ts +153 -0
  22. package/packages/contracts/src/__tests__/experience-kernel-boundary.test.ts +109 -0
  23. package/packages/contracts/src/__tests__/experience-shell.test.ts +65 -0
  24. package/packages/contracts/src/__tests__/fixtures/daemon-wire-v2.json +35 -0
  25. package/packages/contracts/src/__tests__/fleet-agent-graph.test.ts +231 -0
  26. package/packages/contracts/src/__tests__/fleet-catalog.test.ts +268 -0
  27. package/packages/contracts/src/__tests__/fleet-lifecycle.test.ts +62 -0
  28. package/packages/contracts/src/__tests__/focus-overlay.test.ts +110 -0
  29. package/packages/contracts/src/__tests__/ide-config.test.ts +18 -0
  30. package/packages/contracts/src/__tests__/issue-error.test.ts +78 -0
  31. package/packages/contracts/src/__tests__/mission-projections.test.ts +186 -0
  32. package/packages/contracts/src/__tests__/missions.test.ts +272 -0
  33. package/packages/contracts/src/__tests__/multiplexer-verbs.test.ts +240 -0
  34. package/packages/contracts/src/__tests__/pane-appearance.test.ts +146 -0
  35. package/packages/contracts/src/__tests__/pane-stream.test.ts +466 -0
  36. package/packages/contracts/src/__tests__/pane-widget-marker.test.ts +327 -0
  37. package/packages/contracts/src/__tests__/performance-metrics.test.ts +73 -0
  38. package/packages/contracts/src/__tests__/performance-qualification.test.ts +137 -0
  39. package/packages/contracts/src/__tests__/rich-card-widget.test.ts +29 -0
  40. package/packages/contracts/src/__tests__/session-runtime.test.ts +490 -0
  41. package/packages/contracts/src/__tests__/startup-readiness.test.ts +409 -0
  42. package/packages/contracts/src/__tests__/terminal-attachment-stream.test.ts +72 -0
  43. package/packages/contracts/src/__tests__/terminal-attachments.test.ts +329 -0
  44. package/packages/contracts/src/__tests__/terminal-delivery.test.ts +88 -0
  45. package/packages/contracts/src/__tests__/terminal-runtime-inventory.test.ts +68 -0
  46. package/packages/contracts/src/__tests__/visual-tokens.test.ts +224 -0
  47. package/packages/contracts/src/__tests__/workspace-changes-resource.test.ts +317 -0
  48. package/packages/contracts/src/__tests__/workspace-changes-view.test.ts +122 -0
  49. package/packages/contracts/src/__tests__/workspace-config.test.ts +294 -0
  50. package/packages/contracts/src/__tests__/workspace-files-resource.test.ts +261 -0
  51. package/packages/contracts/src/__tests__/workspace-files-tree.test.ts +147 -0
  52. package/packages/contracts/src/__tests__/workspace-pane-creation.test.ts +249 -0
  53. package/packages/contracts/src/__tests__/workspace-promotion.test.ts +94 -0
  54. package/packages/contracts/src/__tests__/workspace-resource-identity.test.ts +90 -0
  55. package/packages/contracts/src/actions-contract.ts +205 -0
  56. package/packages/contracts/src/actions-errors.ts +20 -0
  57. package/packages/contracts/src/agent-graph-overlay.ts +425 -0
  58. package/packages/contracts/src/app-window-mutation.ts +103 -0
  59. package/packages/contracts/src/app-window-state.ts +446 -0
  60. package/packages/contracts/src/application-shell-resource.ts +54 -0
  61. package/packages/contracts/src/application-shell.ts +1094 -0
  62. package/packages/contracts/src/causal-cell.ts +168 -0
  63. package/packages/contracts/src/client-view-state.ts +156 -0
  64. package/packages/contracts/src/cohesion-fixture.ts +647 -0
  65. package/packages/contracts/src/commands.ts +153 -0
  66. package/packages/contracts/src/control.ts +217 -0
  67. package/packages/contracts/src/daemon-events.ts +374 -0
  68. package/packages/contracts/src/daemon-resource-request.test.ts +192 -0
  69. package/packages/contracts/src/daemon-resource-request.ts +397 -0
  70. package/packages/contracts/src/daemon-resources.ts +108 -0
  71. package/packages/contracts/src/daemon-wire.ts +100 -0
  72. package/packages/contracts/src/desktop-daemon-issue.ts +83 -0
  73. package/packages/contracts/src/desktop-host.ts +746 -0
  74. package/packages/contracts/src/desktop-missions.ts +159 -0
  75. package/packages/contracts/src/desktop-update.ts +48 -0
  76. package/packages/contracts/src/desktop-workspace-name.ts +18 -0
  77. package/packages/contracts/src/domain.ts +493 -0
  78. package/packages/contracts/src/experience-identifiers.ts +53 -0
  79. package/packages/contracts/src/experience-shell.ts +249 -0
  80. package/packages/contracts/src/fleet-agent-graph.ts +171 -0
  81. package/packages/contracts/src/fleet-catalog.ts +190 -0
  82. package/packages/contracts/src/fleet-lifecycle.ts +136 -0
  83. package/packages/contracts/src/focus-overlay.ts +175 -0
  84. package/packages/contracts/src/ide-config.ts +40 -20
  85. package/packages/contracts/src/index.ts +60 -0
  86. package/packages/contracts/src/interaction-receipts.ts +438 -0
  87. package/packages/contracts/src/issue-error.ts +107 -0
  88. package/packages/contracts/src/mission-projections.ts +269 -0
  89. package/packages/contracts/src/multiplexer-verbs.ts +447 -0
  90. package/packages/contracts/src/pane-appearance.ts +248 -0
  91. package/packages/contracts/src/pane-stream.ts +709 -0
  92. package/packages/contracts/src/pane-widget-descriptor.ts +62 -0
  93. package/packages/contracts/src/pane-widget-marker.ts +301 -0
  94. package/packages/contracts/src/performance-metrics.ts +128 -0
  95. package/packages/contracts/src/performance-qualification.ts +276 -0
  96. package/packages/contracts/src/rich-card-widget.ts +72 -0
  97. package/packages/contracts/src/semantic-identity.ts +39 -0
  98. package/packages/contracts/src/session-runtime.ts +351 -0
  99. package/packages/contracts/src/shared-monotonic-clock.ts +18 -0
  100. package/packages/contracts/src/startup-readiness.ts +432 -0
  101. package/packages/contracts/src/terminal-attachment-stream.ts +119 -0
  102. package/packages/contracts/src/terminal-attachments.ts +347 -0
  103. package/packages/contracts/src/terminal-delivery.ts +245 -0
  104. package/packages/contracts/src/terminal-replica.ts +133 -0
  105. package/packages/contracts/src/terminal-runtime-inventory.ts +42 -0
  106. package/packages/contracts/src/visual-recipes.ts +126 -0
  107. package/packages/contracts/src/visual-tokens.ts +883 -0
  108. package/packages/contracts/src/widget-asset.ts +43 -0
  109. package/packages/contracts/src/workspace-catalog-resource.test.ts +146 -0
  110. package/packages/contracts/src/workspace-catalog-resource.ts +180 -0
  111. package/packages/contracts/src/workspace-changes-resource.ts +405 -0
  112. package/packages/contracts/src/workspace-changes-view.ts +195 -0
  113. package/packages/contracts/src/workspace-config.ts +303 -0
  114. package/packages/contracts/src/workspace-files-resource.ts +310 -0
  115. package/packages/contracts/src/workspace-files-tree.ts +167 -0
  116. package/packages/contracts/src/workspace-missions-resource.ts +32 -0
  117. package/packages/contracts/src/workspace-multiplexer.ts +373 -0
  118. package/packages/contracts/src/workspace-open-handoff.ts +99 -0
  119. package/packages/contracts/src/workspace-open.ts +64 -0
  120. package/packages/contracts/src/workspace-pane-creation.ts +223 -0
  121. package/packages/contracts/src/workspace-promotion.ts +109 -0
  122. package/packages/contracts/src/workspace-resource-identity.ts +81 -0
  123. package/packages/contracts/src/workspace-state.ts +530 -0
  124. package/packages/contracts/src/workspace.ts +14 -2
  125. package/packages/core/package.json +35 -0
  126. package/packages/core/src/agent-provisioning.test.ts +42 -0
  127. package/packages/core/src/agent-provisioning.ts +112 -0
  128. package/packages/core/src/app-window-identity.ts +33 -0
  129. package/packages/core/src/application-shell-session.test.ts +105 -0
  130. package/packages/core/src/application-shell-session.ts +195 -0
  131. package/packages/core/src/index.ts +15 -0
  132. package/packages/core/src/interaction-flow.test.ts +66 -0
  133. package/packages/core/src/interaction-flow.ts +159 -0
  134. package/packages/core/src/interaction-receipts.test.ts +361 -0
  135. package/packages/core/src/interaction-receipts.ts +335 -0
  136. package/packages/core/src/navigator.test.ts +34 -0
  137. package/packages/core/src/navigator.ts +74 -0
  138. package/packages/core/src/optimistic-projection-conformance.test.ts +75 -0
  139. package/packages/core/src/optimistic-projection-conformance.ts +61 -0
  140. package/packages/core/src/optimistic-projection-store.ts +71 -0
  141. package/packages/core/src/optimistic-projection.test.ts +118 -0
  142. package/packages/core/src/optimistic-projection.ts +194 -0
  143. package/packages/core/src/performance-metrics.test.ts +121 -0
  144. package/packages/core/src/performance-metrics.ts +241 -0
  145. package/packages/core/src/performance-qualification.test.ts +283 -0
  146. package/packages/core/src/performance-qualification.ts +360 -0
  147. package/packages/core/src/terminal-compact-capability.ts +31 -0
  148. package/packages/core/src/terminal-compact-cold.test.ts +87 -0
  149. package/packages/core/src/terminal-conformance.test.ts +48 -0
  150. package/packages/core/src/terminal-conformance.ts +405 -0
  151. package/packages/core/src/terminal-delivery.test.ts +1196 -0
  152. package/packages/core/src/terminal-delivery.ts +2918 -0
  153. package/packages/core/src/terminal-replica-cold.test.ts +31 -0
  154. package/packages/core/src/terminal-replica-hash-cache.test.ts +201 -0
  155. package/packages/core/src/terminal-replica-hash-cache.ts +367 -0
  156. package/packages/core/src/terminal-replica.test.ts +282 -0
  157. package/packages/core/src/terminal-replica.ts +943 -0
  158. package/packages/core/src/workspace-selection.test.ts +63 -0
  159. package/packages/core/src/workspace-selection.ts +97 -0
  160. package/packages/daemon/dist/attach.js +2 -2
  161. package/packages/daemon/dist/canonical.d.ts +2 -2
  162. package/packages/daemon/dist/canonical.js +1 -1
  163. package/packages/daemon/dist/cli.js +37 -36
  164. package/packages/daemon/dist/command-center/actions/command-definitions.d.ts +4 -0
  165. package/packages/daemon/dist/command-center/actions/command-definitions.js +70 -0
  166. package/packages/daemon/dist/command-center/actions/dispatcher.d.ts +29 -0
  167. package/packages/daemon/dist/command-center/actions/dispatcher.js +228 -10
  168. package/packages/daemon/dist/command-center/actions/errors.d.ts +1 -1
  169. package/packages/daemon/dist/command-center/actions/handlers/_project-context.d.ts +1 -1
  170. package/packages/daemon/dist/command-center/actions/handlers/_project-context.js +3 -4
  171. package/packages/daemon/dist/command-center/actions/handlers/app-window-mutate.d.ts +8 -0
  172. package/packages/daemon/dist/command-center/actions/handlers/app-window-mutate.js +39 -0
  173. package/packages/daemon/dist/command-center/actions/handlers/config-actions.d.ts +6 -6
  174. package/packages/daemon/dist/command-center/actions/handlers/config-actions.js +44 -20
  175. package/packages/daemon/dist/command-center/actions/handlers/daemon-shutdown.d.ts +2 -1
  176. package/packages/daemon/dist/command-center/actions/handlers/daemon-shutdown.js +11 -1
  177. package/packages/daemon/dist/command-center/actions/handlers/fleet-lifecycle.d.ts +10 -0
  178. package/packages/daemon/dist/command-center/actions/handlers/fleet-lifecycle.js +56 -0
  179. package/packages/daemon/dist/command-center/actions/handlers/project-launch.js +16 -4
  180. package/packages/daemon/dist/command-center/actions/handlers/workspace-multiplexer.d.ts +186 -0
  181. package/packages/daemon/dist/command-center/actions/handlers/workspace-multiplexer.js +55 -0
  182. package/packages/daemon/dist/command-center/actions/handlers/workspace-open.d.ts +16 -0
  183. package/packages/daemon/dist/command-center/actions/handlers/workspace-open.js +89 -0
  184. package/packages/daemon/dist/command-center/actions/handlers/workspace-pane-create.d.ts +8 -0
  185. package/packages/daemon/dist/command-center/actions/handlers/workspace-pane-create.js +34 -0
  186. package/packages/daemon/dist/command-center/actions/handlers/workspace-promote.d.ts +8 -0
  187. package/packages/daemon/dist/command-center/actions/handlers/workspace-promote.js +34 -0
  188. package/packages/daemon/dist/command-center/actions/registry.d.ts +33 -2
  189. package/packages/daemon/dist/command-center/actions/registry.js +126 -0
  190. package/packages/daemon/dist/command-center/actions/semantic-multiplexer-actions.d.ts +3 -0
  191. package/packages/daemon/dist/command-center/actions/semantic-multiplexer-actions.js +16 -0
  192. package/packages/daemon/dist/command-center/agent-status-watch.d.ts +100 -0
  193. package/packages/daemon/dist/command-center/agent-status-watch.js +170 -0
  194. package/packages/daemon/dist/command-center/daemon-fleet-facts-observer.d.ts +57 -0
  195. package/packages/daemon/dist/command-center/daemon-fleet-facts-observer.js +395 -0
  196. package/packages/daemon/dist/command-center/discovery.d.ts +98 -1
  197. package/packages/daemon/dist/command-center/discovery.js +262 -3
  198. package/packages/daemon/dist/command-center/owner-authority.d.ts +71 -0
  199. package/packages/daemon/dist/command-center/owner-authority.js +46 -0
  200. package/packages/daemon/dist/command-center/pane-stream-issue.d.ts +26 -0
  201. package/packages/daemon/dist/command-center/pane-stream-issue.js +185 -0
  202. package/packages/daemon/dist/command-center/resources/agent-graph-overlay.d.ts +45 -0
  203. package/packages/daemon/dist/command-center/resources/agent-graph-overlay.js +234 -0
  204. package/packages/daemon/dist/command-center/resources/application-shell.d.ts +201 -0
  205. package/packages/daemon/dist/command-center/resources/application-shell.js +641 -0
  206. package/packages/daemon/dist/command-center/resources/desktop-missions.d.ts +10 -0
  207. package/packages/daemon/dist/command-center/resources/desktop-missions.js +132 -0
  208. package/packages/daemon/dist/command-center/resources/fleet-catalog.d.ts +25 -0
  209. package/packages/daemon/dist/command-center/resources/fleet-catalog.js +163 -0
  210. package/packages/daemon/dist/command-center/resources/fleet-resource-route.d.ts +25 -0
  211. package/packages/daemon/dist/command-center/resources/fleet-resource-route.js +46 -0
  212. package/packages/daemon/dist/command-center/resources/startup-readiness-route.d.ts +38 -0
  213. package/packages/daemon/dist/command-center/resources/startup-readiness-route.js +121 -0
  214. package/packages/daemon/dist/command-center/resources/startup-readiness.d.ts +57 -0
  215. package/packages/daemon/dist/command-center/resources/startup-readiness.js +183 -0
  216. package/packages/daemon/dist/command-center/resources/terminal-runtime-inventory.d.ts +5 -0
  217. package/packages/daemon/dist/command-center/resources/terminal-runtime-inventory.js +24 -0
  218. package/packages/daemon/dist/command-center/resources/workspace-changes-authority.d.ts +39 -0
  219. package/packages/daemon/dist/command-center/resources/workspace-changes-authority.js +451 -0
  220. package/packages/daemon/dist/command-center/resources/workspace-changes-git.d.ts +63 -0
  221. package/packages/daemon/dist/command-center/resources/workspace-changes-git.js +222 -0
  222. package/packages/daemon/dist/command-center/resources/workspace-files-authority.d.ts +44 -0
  223. package/packages/daemon/dist/command-center/resources/workspace-files-authority.js +493 -0
  224. package/packages/daemon/dist/command-center/resources/workspace-missions-route.d.ts +22 -0
  225. package/packages/daemon/dist/command-center/resources/workspace-missions-route.js +75 -0
  226. package/packages/daemon/dist/command-center/resources/workspace-resource-ids.d.ts +24 -0
  227. package/packages/daemon/dist/command-center/resources/workspace-resource-ids.js +69 -0
  228. package/packages/daemon/dist/command-center/resources/workspace-resource-routes.d.ts +17 -0
  229. package/packages/daemon/dist/command-center/resources/workspace-resource-routes.js +116 -0
  230. package/packages/daemon/dist/command-center/schemas.d.ts +1 -1
  231. package/packages/daemon/dist/command-center/server.d.ts +57 -1
  232. package/packages/daemon/dist/command-center/server.js +540 -51
  233. package/packages/daemon/dist/command-center/terminal-attachment-issue.d.ts +22 -0
  234. package/packages/daemon/dist/command-center/terminal-attachment-issue.js +191 -0
  235. package/packages/daemon/dist/command-center/workspace-resource-observer.d.ts +50 -0
  236. package/packages/daemon/dist/command-center/workspace-resource-observer.js +453 -0
  237. package/packages/daemon/dist/command-center/ws-events.d.ts +82 -7
  238. package/packages/daemon/dist/command-center/ws-events.js +681 -63
  239. package/packages/daemon/dist/config.js +31 -25
  240. package/packages/daemon/dist/control/client.d.ts +23 -0
  241. package/packages/daemon/dist/control/client.js +105 -0
  242. package/packages/daemon/dist/control/dispatch.d.ts +34 -0
  243. package/packages/daemon/dist/control/dispatch.js +83 -0
  244. package/packages/daemon/dist/control/fanout.d.ts +19 -0
  245. package/packages/daemon/dist/control/fanout.js +37 -0
  246. package/packages/daemon/dist/control/frames.d.ts +23 -0
  247. package/packages/daemon/dist/control/frames.js +37 -0
  248. package/packages/daemon/dist/control/lifecycle.d.ts +45 -0
  249. package/packages/daemon/dist/control/lifecycle.js +124 -0
  250. package/packages/daemon/dist/control/server.d.ts +16 -0
  251. package/packages/daemon/dist/control/server.js +214 -0
  252. package/packages/daemon/dist/control/verbs.d.ts +11 -0
  253. package/packages/daemon/dist/control/verbs.js +91 -0
  254. package/packages/daemon/dist/detect.js +23 -20
  255. package/packages/daemon/dist/doctor.d.ts +18 -0
  256. package/packages/daemon/dist/doctor.js +127 -21
  257. package/packages/daemon/dist/index.d.ts +21 -2
  258. package/packages/daemon/dist/index.js +20 -1
  259. package/packages/daemon/dist/init.js +24 -22
  260. package/packages/daemon/dist/inspect.d.ts +7 -1
  261. package/packages/daemon/dist/inspect.js +33 -8
  262. package/packages/daemon/dist/launch.d.ts +2 -0
  263. package/packages/daemon/dist/launch.js +38 -26
  264. package/packages/daemon/dist/lib/__tests__/fixtures/workspace-state-writer.js +58 -0
  265. package/packages/daemon/dist/lib/agent-discovery.d.ts +27 -2
  266. package/packages/daemon/dist/lib/agent-discovery.js +29 -14
  267. package/packages/daemon/dist/lib/agent-kind.d.ts +7 -0
  268. package/packages/daemon/dist/lib/agent-kind.js +24 -0
  269. package/packages/daemon/dist/lib/app-config.d.ts +111 -0
  270. package/packages/daemon/dist/lib/app-config.js +130 -5
  271. package/packages/daemon/dist/lib/app-window-kernel.d.ts +64 -0
  272. package/packages/daemon/dist/lib/app-window-kernel.js +556 -0
  273. package/packages/daemon/dist/lib/app-window-mutation.d.ts +28 -0
  274. package/packages/daemon/dist/lib/app-window-mutation.js +139 -0
  275. package/packages/daemon/dist/lib/app-window-repository.d.ts +81 -0
  276. package/packages/daemon/dist/lib/app-window-repository.js +368 -0
  277. package/packages/daemon/dist/lib/app-window-state.d.ts +57 -0
  278. package/packages/daemon/dist/lib/app-window-state.js +415 -0
  279. package/packages/daemon/dist/lib/application-shell-app-windows.d.ts +16 -0
  280. package/packages/daemon/dist/lib/application-shell-app-windows.js +285 -0
  281. package/packages/daemon/dist/lib/auth/middleware.d.ts +1 -1
  282. package/packages/daemon/dist/lib/auth/middleware.js +7 -3
  283. package/packages/daemon/dist/lib/canonical-daemon-bootstrap.d.ts +25 -0
  284. package/packages/daemon/dist/lib/canonical-daemon-bootstrap.js +174 -0
  285. package/packages/daemon/dist/lib/canonical-daemon.d.ts +80 -14
  286. package/packages/daemon/dist/lib/canonical-daemon.js +507 -70
  287. package/packages/daemon/dist/lib/chrome-front-door.d.ts +7 -0
  288. package/packages/daemon/dist/lib/chrome-front-door.js +13 -0
  289. package/packages/daemon/dist/lib/cli-action-bridge.d.ts +8 -3
  290. package/packages/daemon/dist/lib/cli-action-bridge.js +112 -82
  291. package/packages/daemon/dist/lib/command-registry.d.ts +37 -0
  292. package/packages/daemon/dist/lib/command-registry.js +107 -0
  293. package/packages/daemon/dist/lib/config-context.d.ts +18 -0
  294. package/packages/daemon/dist/lib/config-context.js +34 -0
  295. package/packages/daemon/dist/lib/daemon-embed.d.ts +30 -0
  296. package/packages/daemon/dist/lib/daemon-embed.js +1060 -356
  297. package/packages/daemon/dist/lib/daemon-session-monitor.d.ts +50 -0
  298. package/packages/daemon/dist/lib/daemon-session-monitor.js +194 -0
  299. package/packages/daemon/dist/lib/daemon.js +3 -47
  300. package/packages/daemon/dist/lib/directory-watcher.d.ts +12 -0
  301. package/packages/daemon/dist/lib/directory-watcher.js +118 -0
  302. package/packages/daemon/dist/lib/environment-identity.d.ts +9 -0
  303. package/packages/daemon/dist/lib/environment-identity.js +79 -0
  304. package/packages/daemon/dist/lib/errors.d.ts +1 -1
  305. package/packages/daemon/dist/lib/fleet-agent-lifecycle.d.ts +8 -0
  306. package/packages/daemon/dist/lib/fleet-agent-lifecycle.js +65 -0
  307. package/packages/daemon/dist/lib/fleet-lifecycle-authority.d.ts +21 -0
  308. package/packages/daemon/dist/lib/fleet-lifecycle-authority.js +437 -0
  309. package/packages/daemon/dist/lib/headless-daemon.d.ts +33 -0
  310. package/packages/daemon/dist/lib/headless-daemon.js +306 -0
  311. package/packages/daemon/dist/lib/launch-plan.d.ts +20 -1
  312. package/packages/daemon/dist/lib/launch-plan.js +96 -1
  313. package/packages/daemon/dist/lib/legacy-config-adapter.d.ts +12 -0
  314. package/packages/daemon/dist/lib/legacy-config-adapter.js +19 -0
  315. package/packages/daemon/dist/lib/legacy-config-migration.d.ts +15 -0
  316. package/packages/daemon/dist/lib/legacy-config-migration.js +110 -0
  317. package/packages/daemon/dist/lib/legacy-theme-compat.d.ts +14 -0
  318. package/packages/daemon/dist/lib/legacy-theme-compat.js +25 -0
  319. package/packages/daemon/dist/lib/manifest-pack.d.ts +79 -0
  320. package/packages/daemon/dist/lib/manifest-pack.js +232 -0
  321. package/packages/daemon/dist/lib/mission-projections.d.ts +24 -0
  322. package/packages/daemon/dist/lib/mission-projections.js +615 -0
  323. package/packages/daemon/dist/lib/mission-repository.d.ts +941 -0
  324. package/packages/daemon/dist/lib/mission-repository.js +775 -0
  325. package/packages/daemon/dist/lib/onboarding-marker.d.ts +13 -0
  326. package/packages/daemon/dist/lib/onboarding-marker.js +51 -0
  327. package/packages/daemon/dist/lib/pane-chrome.d.ts +12 -0
  328. package/packages/daemon/dist/lib/pane-chrome.js +12 -0
  329. package/packages/daemon/dist/lib/pane-source-credentials.d.ts +32 -0
  330. package/packages/daemon/dist/lib/pane-source-credentials.js +178 -0
  331. package/packages/daemon/dist/lib/pane-widget.d.ts +61 -0
  332. package/packages/daemon/dist/lib/pane-widget.js +126 -0
  333. package/packages/daemon/dist/lib/project-inspect.js +4 -0
  334. package/packages/daemon/dist/lib/project-onboard.d.ts +5 -5
  335. package/packages/daemon/dist/lib/project-onboard.js +17 -21
  336. package/packages/daemon/dist/lib/project-probe.d.ts +9 -3
  337. package/packages/daemon/dist/lib/project-probe.js +28 -22
  338. package/packages/daemon/dist/lib/project-readiness-probe.d.ts +60 -0
  339. package/packages/daemon/dist/lib/project-readiness-probe.js +425 -0
  340. package/packages/daemon/dist/lib/project-readiness.d.ts +157 -0
  341. package/packages/daemon/dist/lib/project-readiness.js +680 -0
  342. package/packages/daemon/dist/lib/project-registry.d.ts +8 -0
  343. package/packages/daemon/dist/lib/project-registry.js +42 -9
  344. package/packages/daemon/dist/lib/project-resolver.d.ts +77 -0
  345. package/packages/daemon/dist/lib/project-resolver.js +245 -0
  346. package/packages/daemon/dist/lib/project-runtime-errors.d.ts +13 -0
  347. package/packages/daemon/dist/lib/project-runtime-errors.js +21 -0
  348. package/packages/daemon/dist/lib/project-runtime-repository.d.ts +193 -0
  349. package/packages/daemon/dist/lib/project-runtime-repository.js +876 -0
  350. package/packages/daemon/dist/lib/resolved-config.d.ts +48 -0
  351. package/packages/daemon/dist/lib/resolved-config.js +318 -0
  352. package/packages/daemon/dist/lib/runtime-namespace.d.ts +34 -0
  353. package/packages/daemon/dist/lib/runtime-namespace.js +136 -0
  354. package/packages/daemon/dist/lib/semantic-resource-id.d.ts +7 -0
  355. package/packages/daemon/dist/lib/semantic-resource-id.js +14 -0
  356. package/packages/daemon/dist/lib/session-monitor.d.ts +2 -0
  357. package/packages/daemon/dist/lib/session-monitor.js +29 -23
  358. package/packages/daemon/dist/lib/session-options.js +3 -10
  359. package/packages/daemon/dist/lib/state-home.d.ts +2 -0
  360. package/packages/daemon/dist/lib/state-home.js +11 -0
  361. package/packages/daemon/dist/lib/theme-mode.d.ts +10 -0
  362. package/packages/daemon/dist/lib/theme-mode.js +9 -0
  363. package/packages/daemon/dist/lib/tmux-external-interaction-observer.d.ts +88 -0
  364. package/packages/daemon/dist/lib/tmux-external-interaction-observer.js +534 -0
  365. package/packages/daemon/dist/lib/tmux-interaction-options.d.ts +34 -0
  366. package/packages/daemon/dist/lib/tmux-interaction-options.js +126 -0
  367. package/packages/daemon/dist/lib/tmux-terminal-color.d.ts +18 -0
  368. package/packages/daemon/dist/lib/tmux-terminal-color.js +37 -0
  369. package/packages/daemon/dist/lib/tui-binary.d.ts +30 -5
  370. package/packages/daemon/dist/lib/tui-binary.js +291 -28
  371. package/packages/daemon/dist/lib/unix-socket-authority.d.ts +9 -0
  372. package/packages/daemon/dist/lib/unix-socket-authority.js +48 -0
  373. package/packages/daemon/dist/lib/update-check.js +5 -0
  374. package/packages/daemon/dist/lib/widget-asset-policy.d.ts +3 -0
  375. package/packages/daemon/dist/lib/widget-asset-policy.js +3 -0
  376. package/packages/daemon/dist/lib/widget-asset-store.d.ts +22 -0
  377. package/packages/daemon/dist/lib/widget-asset-store.js +166 -0
  378. package/packages/daemon/dist/lib/workspace-config-loader.d.ts +68 -0
  379. package/packages/daemon/dist/lib/workspace-config-loader.js +280 -0
  380. package/packages/daemon/dist/lib/workspace-multiplexer-verbs.d.ts +109 -0
  381. package/packages/daemon/dist/lib/workspace-multiplexer-verbs.js +1138 -0
  382. package/packages/daemon/dist/lib/workspace-open-handoff.d.ts +41 -0
  383. package/packages/daemon/dist/lib/workspace-open-handoff.js +219 -0
  384. package/packages/daemon/dist/lib/workspace-open.d.ts +44 -0
  385. package/packages/daemon/dist/lib/workspace-open.js +740 -0
  386. package/packages/daemon/dist/lib/workspace-pane-creation.d.ts +64 -0
  387. package/packages/daemon/dist/lib/workspace-pane-creation.js +1107 -0
  388. package/packages/daemon/dist/lib/workspace-promotion.d.ts +41 -0
  389. package/packages/daemon/dist/lib/workspace-promotion.js +804 -0
  390. package/packages/daemon/dist/lib/workspace-registry.d.ts +49 -2
  391. package/packages/daemon/dist/lib/workspace-registry.js +150 -23
  392. package/packages/daemon/dist/lib/workspace-state-repository.d.ts +139 -0
  393. package/packages/daemon/dist/lib/workspace-state-repository.js +790 -0
  394. package/packages/daemon/dist/lib/workspace-state.d.ts +37 -0
  395. package/packages/daemon/dist/lib/workspace-state.js +765 -0
  396. package/packages/daemon/dist/lib/yaml-io.js +4 -18
  397. package/packages/daemon/dist/migrate.d.ts +11 -0
  398. package/packages/daemon/dist/migrate.js +105 -0
  399. package/packages/daemon/dist/restart.js +2 -2
  400. package/packages/daemon/dist/restore.d.ts +40 -13
  401. package/packages/daemon/dist/restore.js +62 -21
  402. package/packages/daemon/dist/schemas/inspect.d.ts +8 -0
  403. package/packages/daemon/dist/schemas/inspect.js +9 -1
  404. package/packages/daemon/dist/schemas/registry.d.ts +18 -4
  405. package/packages/daemon/dist/schemas/registry.js +5 -19
  406. package/packages/daemon/dist/schemas/ws-events.d.ts +5 -69
  407. package/packages/daemon/dist/schemas/ws-events.js +4 -107
  408. package/packages/daemon/dist/send.d.ts +41 -1
  409. package/packages/daemon/dist/send.js +136 -20
  410. package/packages/daemon/dist/server/pane-stream-upgrade.d.ts +12 -0
  411. package/packages/daemon/dist/server/pane-stream-upgrade.js +117 -0
  412. package/packages/daemon/dist/server/terminal-attachment-upgrade.d.ts +11 -0
  413. package/packages/daemon/dist/server/terminal-attachment-upgrade.js +121 -0
  414. package/packages/daemon/dist/status.js +11 -8
  415. package/packages/daemon/dist/stop.js +2 -2
  416. package/packages/daemon/dist/terminal/MonotonicPtyInput.d.ts +30 -0
  417. package/packages/daemon/dist/terminal/MonotonicPtyInput.js +130 -0
  418. package/packages/daemon/dist/terminal/NodePtyAdapter.d.ts +9 -3
  419. package/packages/daemon/dist/terminal/NodePtyAdapter.js +37 -10
  420. package/packages/daemon/dist/terminal/PtyAdapter.d.ts +93 -3
  421. package/packages/daemon/dist/terminal/PtyAdapter.js +18 -0
  422. package/packages/daemon/dist/terminal/__tests__/MockPtyAdapter.d.ts +14 -4
  423. package/packages/daemon/dist/terminal/__tests__/MockPtyAdapter.js +33 -6
  424. package/packages/daemon/dist/terminal/attachments/admission-util.d.ts +14 -0
  425. package/packages/daemon/dist/terminal/attachments/admission-util.js +87 -0
  426. package/packages/daemon/dist/terminal/attachments/agent-status-probe.d.ts +102 -0
  427. package/packages/daemon/dist/terminal/attachments/agent-status-probe.js +325 -0
  428. package/packages/daemon/dist/terminal/attachments/direct-websocket.d.ts +141 -0
  429. package/packages/daemon/dist/terminal/attachments/direct-websocket.js +1069 -0
  430. package/packages/daemon/dist/terminal/attachments/grouped-tmux.d.ts +106 -0
  431. package/packages/daemon/dist/terminal/attachments/grouped-tmux.js +213 -0
  432. package/packages/daemon/dist/terminal/attachments/lease-manager.d.ts +188 -0
  433. package/packages/daemon/dist/terminal/attachments/lease-manager.js +655 -0
  434. package/packages/daemon/dist/terminal/attachments/native-runtime.d.ts +196 -0
  435. package/packages/daemon/dist/terminal/attachments/native-runtime.js +1564 -0
  436. package/packages/daemon/dist/terminal/attachments/pty-tmux-attachment-launcher.d.ts +66 -0
  437. package/packages/daemon/dist/terminal/attachments/pty-tmux-attachment-launcher.js +607 -0
  438. package/packages/daemon/dist/terminal/attachments/semantic-pane-catalog.d.ts +81 -0
  439. package/packages/daemon/dist/terminal/attachments/semantic-pane-catalog.js +208 -0
  440. package/packages/daemon/dist/terminal/attachments/tmux-view-executor.d.ts +111 -0
  441. package/packages/daemon/dist/terminal/attachments/tmux-view-executor.js +825 -0
  442. package/packages/daemon/dist/terminal/mirror/__tests__/scripted-channel.d.ts +25 -0
  443. package/packages/daemon/dist/terminal/mirror/__tests__/scripted-channel.js +80 -0
  444. package/packages/daemon/dist/terminal/mirror/__tests__/simulated-channel.d.ts +66 -0
  445. package/packages/daemon/dist/terminal/mirror/__tests__/simulated-channel.js +133 -0
  446. package/packages/daemon/dist/terminal/mirror/control-channel.d.ts +188 -0
  447. package/packages/daemon/dist/terminal/mirror/control-channel.js +624 -0
  448. package/packages/daemon/dist/terminal/mirror/control-mode-ownership.d.ts +14 -0
  449. package/packages/daemon/dist/terminal/mirror/control-mode-ownership.js +30 -0
  450. package/packages/daemon/dist/terminal/mirror/events.d.ts +115 -0
  451. package/packages/daemon/dist/terminal/mirror/events.js +18 -0
  452. package/packages/daemon/dist/terminal/mirror/flow-ledger.d.ts +40 -0
  453. package/packages/daemon/dist/terminal/mirror/flow-ledger.js +56 -0
  454. package/packages/daemon/dist/terminal/mirror/mirror-service.d.ts +137 -0
  455. package/packages/daemon/dist/terminal/mirror/mirror-service.js +329 -0
  456. package/packages/daemon/dist/terminal/mirror/pane-feed.d.ts +90 -0
  457. package/packages/daemon/dist/terminal/mirror/pane-feed.js +140 -0
  458. package/packages/daemon/dist/terminal/mirror/session-channel.d.ts +216 -0
  459. package/packages/daemon/dist/terminal/mirror/session-channel.js +2301 -0
  460. package/packages/daemon/dist/terminal/mirror/trusted-inventory.d.ts +28 -0
  461. package/packages/daemon/dist/terminal/pane-stream/lease-manager.d.ts +72 -0
  462. package/packages/daemon/dist/terminal/pane-stream/lease-manager.js +245 -0
  463. package/packages/daemon/dist/terminal/pane-stream/pane-stream-websocket.d.ts +208 -0
  464. package/packages/daemon/dist/terminal/pane-stream/pane-stream-websocket.js +2058 -0
  465. package/packages/daemon/dist/terminal/pane-stream/runtime.d.ts +26 -0
  466. package/packages/daemon/dist/terminal/pane-stream/runtime.js +53 -0
  467. package/packages/daemon/dist/terminal/pane-stream/wire-ledger.d.ts +59 -0
  468. package/packages/daemon/dist/terminal/pane-stream/wire-ledger.js +110 -0
  469. package/packages/daemon/dist/terminal/protocol/chunk-bytes.d.ts +3 -0
  470. package/packages/daemon/dist/terminal/protocol/chunk-bytes.js +21 -0
  471. package/packages/daemon/dist/terminal/protocol/control.d.ts +66 -0
  472. package/packages/daemon/dist/terminal/protocol/control.js +111 -0
  473. package/packages/daemon/dist/terminal/protocol/input-coalescer.d.ts +55 -0
  474. package/packages/daemon/dist/terminal/protocol/input-coalescer.js +111 -0
  475. package/packages/daemon/dist/terminal/protocol/layout-parse.d.ts +68 -0
  476. package/packages/daemon/dist/terminal/protocol/layout-parse.js +127 -0
  477. package/packages/daemon/dist/terminal/protocol/pane-display-name.d.ts +16 -0
  478. package/packages/daemon/dist/terminal/protocol/pane-display-name.js +153 -0
  479. package/packages/daemon/dist/terminal/protocol/session-descriptor-discovery.d.ts +78 -0
  480. package/packages/daemon/dist/terminal/protocol/session-descriptor-discovery.js +294 -0
  481. package/packages/daemon/dist/terminal/protocol/workspace-tmux-adapter.d.ts +90 -0
  482. package/packages/daemon/dist/terminal/protocol/workspace-tmux-adapter.js +213 -0
  483. package/packages/daemon/dist/terminal/session-runtime/authority-arbiter.d.ts +36 -0
  484. package/packages/daemon/dist/terminal/session-runtime/authority-arbiter.js +260 -0
  485. package/packages/daemon/dist/terminal/session-runtime/causal-cell-ledger.d.ts +29 -0
  486. package/packages/daemon/dist/terminal/session-runtime/causal-cell-ledger.js +278 -0
  487. package/packages/daemon/dist/terminal/session-runtime/interaction-receipt-facts.d.ts +12 -0
  488. package/packages/daemon/dist/terminal/session-runtime/interaction-receipt-facts.js +147 -0
  489. package/packages/daemon/dist/terminal/session-runtime/multiplexer-backend.d.ts +16 -0
  490. package/packages/daemon/dist/terminal/session-runtime/multiplexer-backend.js +116 -0
  491. package/packages/daemon/dist/terminal/session-runtime/registry.d.ts +148 -0
  492. package/packages/daemon/dist/terminal/session-runtime/registry.js +1368 -0
  493. package/packages/daemon/dist/terminal/session-runtime/runtime-observability.d.ts +118 -0
  494. package/packages/daemon/dist/terminal/session-runtime/runtime-observability.js +72 -0
  495. package/packages/daemon/dist/terminal/session-runtime/runtime-scheduler.d.ts +11 -0
  496. package/packages/daemon/dist/terminal/session-runtime/runtime-scheduler.js +10 -0
  497. package/packages/daemon/dist/terminal/session-runtime/runtime-trace-correlator.d.ts +18 -0
  498. package/packages/daemon/dist/terminal/session-runtime/runtime-trace-correlator.js +48 -0
  499. package/packages/daemon/dist/terminal/session-runtime/semantic-mutation-executor.d.ts +69 -0
  500. package/packages/daemon/dist/terminal/session-runtime/semantic-mutation-executor.js +353 -0
  501. package/packages/daemon/dist/terminal/session-runtime/semantic-mutation-resource-changes.d.ts +8 -0
  502. package/packages/daemon/dist/terminal/session-runtime/semantic-mutation-resource-changes.js +32 -0
  503. package/packages/daemon/dist/terminal/session-runtime/terminal-delivery-hub.d.ts +91 -0
  504. package/packages/daemon/dist/terminal/session-runtime/terminal-delivery-hub.js +1362 -0
  505. package/packages/daemon/dist/terminal/session-runtime/terminal-delivery-observation-identity.d.ts +3 -0
  506. package/packages/daemon/dist/terminal/session-runtime/terminal-delivery-observation-identity.js +9 -0
  507. package/packages/daemon/dist/terminal/session-runtime/terminal-interpreter-backend.d.ts +55 -0
  508. package/packages/daemon/dist/terminal/session-runtime/terminal-replica-interpreter.d.ts +91 -0
  509. package/packages/daemon/dist/terminal/session-runtime/terminal-replica-interpreter.js +528 -0
  510. package/packages/daemon/dist/terminal/session-runtime/terminal-replica-owner.d.ts +50 -0
  511. package/packages/daemon/dist/terminal/session-runtime/terminal-replica-owner.js +387 -0
  512. package/packages/daemon/dist/terminal/session-runtime/terminal-replica-shadow-projections.d.ts +37 -0
  513. package/packages/daemon/dist/terminal/session-runtime/terminal-replica-shadow-projections.js +21 -0
  514. package/packages/daemon/dist/terminal/session-runtime/transport-binding.d.ts +75 -0
  515. package/packages/daemon/dist/terminal/session-runtime/transport-binding.js +474 -0
  516. package/packages/daemon/dist/terminal/session-runtime/xterm-terminal-interpreter-backend.d.ts +26 -0
  517. package/packages/daemon/dist/terminal/session-runtime/xterm-terminal-interpreter-backend.js +276 -0
  518. package/packages/daemon/dist/tui/async-disposable-slot.d.ts +18 -0
  519. package/packages/daemon/dist/tui/async-disposable-slot.js +57 -0
  520. package/packages/daemon/dist/tui/chrome/cheatsheet.d.ts +59 -0
  521. package/packages/daemon/dist/tui/chrome/cheatsheet.js +211 -0
  522. package/packages/daemon/dist/tui/chrome/chip.d.ts +21 -0
  523. package/packages/daemon/dist/tui/chrome/chip.js +25 -0
  524. package/packages/daemon/dist/tui/chrome/events.d.ts +51 -0
  525. package/packages/daemon/dist/tui/chrome/events.js +94 -0
  526. package/packages/daemon/dist/tui/chrome/front-door.d.ts +16 -0
  527. package/packages/daemon/dist/tui/chrome/front-door.js +16 -0
  528. package/packages/daemon/dist/tui/chrome/kitty-keys.d.ts +41 -0
  529. package/packages/daemon/dist/tui/chrome/kitty-keys.js +54 -0
  530. package/packages/daemon/dist/tui/chrome/menu.d.ts +92 -0
  531. package/packages/daemon/dist/tui/chrome/menu.js +251 -0
  532. package/packages/daemon/dist/tui/chrome/notify-prefs.d.ts +47 -0
  533. package/packages/daemon/dist/tui/chrome/notify-prefs.js +13 -0
  534. package/packages/daemon/dist/tui/chrome/notify-state.d.ts +13 -0
  535. package/packages/daemon/dist/tui/chrome/notify-state.js +77 -0
  536. package/packages/daemon/dist/tui/chrome/notify.d.ts +361 -0
  537. package/packages/daemon/dist/tui/chrome/notify.js +711 -0
  538. package/packages/daemon/dist/tui/chrome/panels.d.ts +72 -0
  539. package/packages/daemon/dist/tui/chrome/panels.js +60 -0
  540. package/packages/daemon/dist/tui/chrome/sidebar.d.ts +77 -0
  541. package/packages/daemon/dist/tui/chrome/sidebar.js +183 -0
  542. package/packages/daemon/dist/tui/chrome/snapshot.d.ts +110 -0
  543. package/packages/daemon/dist/tui/chrome/snapshot.js +290 -0
  544. package/packages/daemon/dist/tui/chrome/statusline.d.ts +237 -0
  545. package/packages/daemon/dist/tui/chrome/statusline.js +552 -0
  546. package/packages/daemon/dist/tui/chrome/updater.d.ts +230 -0
  547. package/packages/daemon/dist/tui/chrome/updater.js +651 -0
  548. package/packages/daemon/dist/tui/chrome/welcome.d.ts +41 -0
  549. package/packages/daemon/dist/tui/chrome/welcome.js +117 -0
  550. package/packages/daemon/dist/tui/compiled.d.ts +86 -0
  551. package/packages/daemon/dist/tui/compiled.js +165 -0
  552. package/packages/daemon/dist/tui/detect/agent-resolution.d.ts +56 -0
  553. package/packages/daemon/dist/tui/detect/agent-resolution.js +60 -0
  554. package/packages/daemon/dist/tui/detect/classify.d.ts +107 -0
  555. package/packages/daemon/dist/tui/detect/classify.js +184 -0
  556. package/packages/daemon/dist/tui/detect/manifest-loader.d.ts +54 -0
  557. package/packages/daemon/dist/tui/detect/manifest-loader.js +242 -0
  558. package/packages/daemon/dist/tui/detect/manifest.d.ts +111 -0
  559. package/packages/daemon/dist/tui/detect/manifest.js +126 -0
  560. package/packages/daemon/dist/tui/detect/manifests.d.ts +40 -0
  561. package/packages/daemon/dist/tui/detect/manifests.js +535 -0
  562. package/packages/daemon/dist/tui/detect/process-tree.d.ts +96 -0
  563. package/packages/daemon/dist/tui/detect/process-tree.js +194 -0
  564. package/packages/daemon/dist/tui/detect/session-id.d.ts +110 -0
  565. package/packages/daemon/dist/tui/detect/session-id.js +414 -0
  566. package/packages/daemon/dist/tui/detect/snapshot.d.ts +27 -0
  567. package/packages/daemon/dist/tui/detect/snapshot.js +81 -0
  568. package/packages/daemon/dist/tui/integrations/claude.d.ts +65 -0
  569. package/packages/daemon/dist/tui/integrations/claude.js +151 -0
  570. package/packages/daemon/dist/tui/integrations/offer.d.ts +47 -0
  571. package/packages/daemon/dist/tui/integrations/offer.js +134 -0
  572. package/packages/daemon/dist/tui/integrations/opencode.d.ts +37 -0
  573. package/packages/daemon/dist/tui/integrations/opencode.js +117 -0
  574. package/packages/daemon/dist/tui/mirror/ack-writer.d.ts +36 -0
  575. package/packages/daemon/dist/tui/mirror/ack-writer.js +78 -0
  576. package/packages/daemon/dist/tui/mirror/activity-surface-view.d.ts +8 -0
  577. package/packages/daemon/dist/tui/mirror/activity-surface-view.jsx +69 -0
  578. package/packages/daemon/dist/tui/mirror/activity-surface.d.ts +103 -0
  579. package/packages/daemon/dist/tui/mirror/activity-surface.js +271 -0
  580. package/packages/daemon/dist/tui/mirror/agent-chip.d.ts +76 -0
  581. package/packages/daemon/dist/tui/mirror/agent-chip.js +84 -0
  582. package/packages/daemon/dist/tui/mirror/agent-lifecycle.d.ts +217 -0
  583. package/packages/daemon/dist/tui/mirror/agent-lifecycle.js +372 -0
  584. package/packages/daemon/dist/tui/mirror/agent-provisioning-executor.d.ts +42 -0
  585. package/packages/daemon/dist/tui/mirror/agent-provisioning-executor.js +86 -0
  586. package/packages/daemon/dist/tui/mirror/agent-rows.d.ts +119 -0
  587. package/packages/daemon/dist/tui/mirror/agent-rows.js +126 -0
  588. package/packages/daemon/dist/tui/mirror/ansi-palette.d.ts +3 -0
  589. package/packages/daemon/dist/tui/mirror/ansi-palette.js +3 -0
  590. package/packages/daemon/dist/tui/mirror/app-state.d.ts +114 -0
  591. package/packages/daemon/dist/tui/mirror/app-state.js +294 -0
  592. package/packages/daemon/dist/tui/mirror/application-keybindings.d.ts +18 -0
  593. package/packages/daemon/dist/tui/mirror/application-keybindings.js +33 -0
  594. package/packages/daemon/dist/tui/mirror/application-shell-daemon-connection.d.ts +53 -0
  595. package/packages/daemon/dist/tui/mirror/application-shell-daemon-connection.js +253 -0
  596. package/packages/daemon/dist/tui/mirror/application-shell-daemon-session.d.ts +22 -0
  597. package/packages/daemon/dist/tui/mirror/application-shell-daemon-session.js +45 -0
  598. package/packages/daemon/dist/tui/mirror/attention.d.ts +63 -0
  599. package/packages/daemon/dist/tui/mirror/attention.js +59 -0
  600. package/packages/daemon/dist/tui/mirror/blit.d.ts +82 -0
  601. package/packages/daemon/dist/tui/mirror/blit.js +120 -0
  602. package/packages/daemon/dist/tui/mirror/canonical-workspace-routing.d.ts +11 -0
  603. package/packages/daemon/dist/tui/mirror/canonical-workspace-routing.js +45 -0
  604. package/packages/daemon/dist/tui/mirror/changes-surface-view.d.ts +19 -0
  605. package/packages/daemon/dist/tui/mirror/changes-surface-view.jsx +92 -0
  606. package/packages/daemon/dist/tui/mirror/changes-surface.d.ts +115 -0
  607. package/packages/daemon/dist/tui/mirror/changes-surface.js +210 -0
  608. package/packages/daemon/dist/tui/mirror/composite-layout.d.ts +91 -0
  609. package/packages/daemon/dist/tui/mirror/composite-layout.js +539 -0
  610. package/packages/daemon/dist/tui/mirror/configless-session-bootstrap.d.ts +39 -0
  611. package/packages/daemon/dist/tui/mirror/configless-session-bootstrap.js +133 -0
  612. package/packages/daemon/dist/tui/mirror/dialog-model.d.ts +154 -0
  613. package/packages/daemon/dist/tui/mirror/dialog-model.js +183 -0
  614. package/packages/daemon/dist/tui/mirror/dialog-stack-core.d.ts +45 -0
  615. package/packages/daemon/dist/tui/mirror/dialog-stack-core.js +232 -0
  616. package/packages/daemon/dist/tui/mirror/dialog-stack.d.ts +2 -0
  617. package/packages/daemon/dist/tui/mirror/dialog-stack.js +2 -0
  618. package/packages/daemon/dist/tui/mirror/diff-model.d.ts +169 -0
  619. package/packages/daemon/dist/tui/mirror/diff-model.js +332 -0
  620. package/packages/daemon/dist/tui/mirror/editor-buffer.d.ts +24 -0
  621. package/packages/daemon/dist/tui/mirror/editor-buffer.js +47 -0
  622. package/packages/daemon/dist/tui/mirror/editor-open-policy.d.ts +9 -0
  623. package/packages/daemon/dist/tui/mirror/editor-open-policy.js +9 -0
  624. package/packages/daemon/dist/tui/mirror/features/changes/contract.d.ts +75 -0
  625. package/packages/daemon/dist/tui/mirror/features/changes/controller.d.ts +10 -0
  626. package/packages/daemon/dist/tui/mirror/features/changes/controller.js +454 -0
  627. package/packages/daemon/dist/tui/mirror/features/changes/feature.d.ts +10 -0
  628. package/packages/daemon/dist/tui/mirror/features/changes/feature.jsx +9 -0
  629. package/packages/daemon/dist/tui/mirror/features/dialogs/contract.d.ts +47 -0
  630. package/packages/daemon/dist/tui/mirror/features/dialogs/contract.js +1 -0
  631. package/packages/daemon/dist/tui/mirror/features/dialogs/feature.d.ts +12 -0
  632. package/packages/daemon/dist/tui/mirror/features/dialogs/feature.jsx +123 -0
  633. package/packages/daemon/dist/tui/mirror/features/dialogs/session.d.ts +9 -0
  634. package/packages/daemon/dist/tui/mirror/features/dialogs/session.js +160 -0
  635. package/packages/daemon/dist/tui/mirror/features/files/feature.d.ts +16 -0
  636. package/packages/daemon/dist/tui/mirror/features/files/feature.jsx +15 -0
  637. package/packages/daemon/dist/tui/mirror/features/files/session.d.ts +133 -0
  638. package/packages/daemon/dist/tui/mirror/features/files/session.js +617 -0
  639. package/packages/daemon/dist/tui/mirror/features/home/feature.d.ts +28 -0
  640. package/packages/daemon/dist/tui/mirror/features/home/feature.jsx +122 -0
  641. package/packages/daemon/dist/tui/mirror/features/missions-activity/contract.d.ts +84 -0
  642. package/packages/daemon/dist/tui/mirror/features/missions-activity/contract.js +3 -0
  643. package/packages/daemon/dist/tui/mirror/features/missions-activity/feature.d.ts +6 -0
  644. package/packages/daemon/dist/tui/mirror/features/missions-activity/feature.jsx +5 -0
  645. package/packages/daemon/dist/tui/mirror/features/missions-activity/session.d.ts +5 -0
  646. package/packages/daemon/dist/tui/mirror/features/missions-activity/session.js +377 -0
  647. package/packages/daemon/dist/tui/mirror/features/palette/contract.d.ts +116 -0
  648. package/packages/daemon/dist/tui/mirror/features/palette/contract.js +9 -0
  649. package/packages/daemon/dist/tui/mirror/features/palette/feature.d.ts +4 -0
  650. package/packages/daemon/dist/tui/mirror/features/palette/feature.js +3 -0
  651. package/packages/daemon/dist/tui/mirror/features/palette/session.d.ts +2 -0
  652. package/packages/daemon/dist/tui/mirror/features/palette/session.js +393 -0
  653. package/packages/daemon/dist/tui/mirror/features/palette/surface.d.ts +7 -0
  654. package/packages/daemon/dist/tui/mirror/features/palette/surface.jsx +48 -0
  655. package/packages/daemon/dist/tui/mirror/features/performance-hud/contract.d.ts +17 -0
  656. package/packages/daemon/dist/tui/mirror/features/performance-hud/contract.js +1 -0
  657. package/packages/daemon/dist/tui/mirror/features/performance-hud/feature.d.ts +3 -0
  658. package/packages/daemon/dist/tui/mirror/features/performance-hud/feature.jsx +2 -0
  659. package/packages/daemon/dist/tui/mirror/features/performance-hud/session.d.ts +8 -0
  660. package/packages/daemon/dist/tui/mirror/features/performance-hud/session.js +148 -0
  661. package/packages/daemon/dist/tui/mirror/features/performance-hud/surface.d.ts +17 -0
  662. package/packages/daemon/dist/tui/mirror/features/performance-hud/surface.jsx +64 -0
  663. package/packages/daemon/dist/tui/mirror/features/rich-preview/asset-loader.d.ts +9 -0
  664. package/packages/daemon/dist/tui/mirror/features/rich-preview/asset-loader.js +125 -0
  665. package/packages/daemon/dist/tui/mirror/features/rich-preview/contract.d.ts +71 -0
  666. package/packages/daemon/dist/tui/mirror/features/rich-preview/contract.js +1 -0
  667. package/packages/daemon/dist/tui/mirror/features/rich-preview/feature.d.ts +23 -0
  668. package/packages/daemon/dist/tui/mirror/features/rich-preview/feature.jsx +103 -0
  669. package/packages/daemon/dist/tui/mirror/features/rich-preview/session.d.ts +23 -0
  670. package/packages/daemon/dist/tui/mirror/features/rich-preview/session.js +310 -0
  671. package/packages/daemon/dist/tui/mirror/features/settings/catalog.d.ts +7 -0
  672. package/packages/daemon/dist/tui/mirror/features/settings/catalog.js +10 -0
  673. package/packages/daemon/dist/tui/mirror/features/settings/contract.d.ts +35 -0
  674. package/packages/daemon/dist/tui/mirror/features/settings/contract.js +1 -0
  675. package/packages/daemon/dist/tui/mirror/features/settings/feature.d.ts +3 -0
  676. package/packages/daemon/dist/tui/mirror/features/settings/feature.js +2 -0
  677. package/packages/daemon/dist/tui/mirror/features/settings/session.d.ts +3 -0
  678. package/packages/daemon/dist/tui/mirror/features/settings/session.js +309 -0
  679. package/packages/daemon/dist/tui/mirror/file-tree.d.ts +142 -0
  680. package/packages/daemon/dist/tui/mirror/file-tree.js +283 -0
  681. package/packages/daemon/dist/tui/mirror/files-surface-view.d.ts +17 -0
  682. package/packages/daemon/dist/tui/mirror/files-surface-view.jsx +92 -0
  683. package/packages/daemon/dist/tui/mirror/files-surface.d.ts +123 -0
  684. package/packages/daemon/dist/tui/mirror/files-surface.js +237 -0
  685. package/packages/daemon/dist/tui/mirror/focus-projection.d.ts +20 -0
  686. package/packages/daemon/dist/tui/mirror/focus-projection.js +80 -0
  687. package/packages/daemon/dist/tui/mirror/folder-picker.d.ts +38 -0
  688. package/packages/daemon/dist/tui/mirror/folder-picker.js +114 -0
  689. package/packages/daemon/dist/tui/mirror/frame-coalescer.d.ts +29 -0
  690. package/packages/daemon/dist/tui/mirror/frame-coalescer.js +74 -0
  691. package/packages/daemon/dist/tui/mirror/home-model.d.ts +81 -0
  692. package/packages/daemon/dist/tui/mirror/home-model.js +125 -0
  693. package/packages/daemon/dist/tui/mirror/home-surface-model.d.ts +113 -0
  694. package/packages/daemon/dist/tui/mirror/home-surface-model.js +297 -0
  695. package/packages/daemon/dist/tui/mirror/home-surface.d.ts +11 -0
  696. package/packages/daemon/dist/tui/mirror/home-surface.jsx +110 -0
  697. package/packages/daemon/dist/tui/mirror/host-terminal.d.ts +28 -0
  698. package/packages/daemon/dist/tui/mirror/host-terminal.js +33 -0
  699. package/packages/daemon/dist/tui/mirror/hosted.d.ts +179 -0
  700. package/packages/daemon/dist/tui/mirror/hosted.js +239 -0
  701. package/packages/daemon/dist/tui/mirror/input-lifecycle.d.ts +140 -0
  702. package/packages/daemon/dist/tui/mirror/input-lifecycle.js +147 -0
  703. package/packages/daemon/dist/tui/mirror/interaction-flow.d.ts +30 -0
  704. package/packages/daemon/dist/tui/mirror/interaction-flow.js +41 -0
  705. package/packages/daemon/dist/tui/mirror/legacy/missions-workspace-loader.d.ts +19 -0
  706. package/packages/daemon/dist/tui/mirror/legacy/missions-workspace-loader.js +84 -0
  707. package/packages/daemon/dist/tui/mirror/menu-model.d.ts +89 -0
  708. package/packages/daemon/dist/tui/mirror/menu-model.js +143 -0
  709. package/packages/daemon/dist/tui/mirror/missions-dashboard.d.ts +68 -0
  710. package/packages/daemon/dist/tui/mirror/missions-dashboard.js +261 -0
  711. package/packages/daemon/dist/tui/mirror/missions-render-fixtures.d.ts +13 -0
  712. package/packages/daemon/dist/tui/mirror/missions-render-fixtures.js +330 -0
  713. package/packages/daemon/dist/tui/mirror/missions-surface-controller.d.ts +84 -0
  714. package/packages/daemon/dist/tui/mirror/missions-surface-controller.js +314 -0
  715. package/packages/daemon/dist/tui/mirror/missions-surface.d.ts +17 -0
  716. package/packages/daemon/dist/tui/mirror/missions-surface.jsx +239 -0
  717. package/packages/daemon/dist/tui/mirror/missions-workspace.d.ts +341 -0
  718. package/packages/daemon/dist/tui/mirror/missions-workspace.js +1399 -0
  719. package/packages/daemon/dist/tui/mirror/multiplexer-action-executor.d.ts +71 -0
  720. package/packages/daemon/dist/tui/mirror/multiplexer-action-executor.js +233 -0
  721. package/packages/daemon/dist/tui/mirror/open-tui-pane-stream-socket.d.ts +16 -0
  722. package/packages/daemon/dist/tui/mirror/open-tui-pane-stream-socket.js +32 -0
  723. package/packages/daemon/dist/tui/mirror/open-tui-verified-routing.d.ts +19 -0
  724. package/packages/daemon/dist/tui/mirror/open-tui-verified-routing.js +45 -0
  725. package/packages/daemon/dist/tui/mirror/open-tui-workspace-runtime-port.d.ts +36 -0
  726. package/packages/daemon/dist/tui/mirror/open-tui-workspace-runtime-port.js +1069 -0
  727. package/packages/daemon/dist/tui/mirror/palette-surface-adapter.d.ts +58 -0
  728. package/packages/daemon/dist/tui/mirror/palette-surface-adapter.js +384 -0
  729. package/packages/daemon/dist/tui/mirror/palette.d.ts +315 -0
  730. package/packages/daemon/dist/tui/mirror/palette.js +522 -0
  731. package/packages/daemon/dist/tui/mirror/pane-frame-state.d.ts +68 -0
  732. package/packages/daemon/dist/tui/mirror/pane-frame-state.js +124 -0
  733. package/packages/daemon/dist/tui/mirror/pane-mirror.d.ts +205 -0
  734. package/packages/daemon/dist/tui/mirror/pane-mirror.js +584 -0
  735. package/packages/daemon/dist/tui/mirror/pane-surface.d.ts +257 -0
  736. package/packages/daemon/dist/tui/mirror/pane-surface.jsx +855 -0
  737. package/packages/daemon/dist/tui/mirror/panel-host-reactive.d.ts +7 -0
  738. package/packages/daemon/dist/tui/mirror/panel-host-reactive.js +13 -0
  739. package/packages/daemon/dist/tui/mirror/panel-host.d.ts +69 -0
  740. package/packages/daemon/dist/tui/mirror/panel-host.js +242 -0
  741. package/packages/daemon/dist/tui/mirror/perf-tap.d.ts +13 -0
  742. package/packages/daemon/dist/tui/mirror/perf-tap.js +32 -0
  743. package/packages/daemon/dist/tui/mirror/performance-events.d.ts +404 -0
  744. package/packages/daemon/dist/tui/mirror/performance-events.js +46 -0
  745. package/packages/daemon/dist/tui/mirror/recipe-components.d.ts +93 -0
  746. package/packages/daemon/dist/tui/mirror/recipe-components.jsx +135 -0
  747. package/packages/daemon/dist/tui/mirror/recipes.d.ts +90 -0
  748. package/packages/daemon/dist/tui/mirror/recipes.js +395 -0
  749. package/packages/daemon/dist/tui/mirror/reference-performance-trace.d.ts +80 -0
  750. package/packages/daemon/dist/tui/mirror/reference-performance-trace.js +597 -0
  751. package/packages/daemon/dist/tui/mirror/renderer-commands.d.ts +60 -0
  752. package/packages/daemon/dist/tui/mirror/renderer-commands.js +250 -0
  753. package/packages/daemon/dist/tui/mirror/resize-model.d.ts +76 -0
  754. package/packages/daemon/dist/tui/mirror/resize-model.js +105 -0
  755. package/packages/daemon/dist/tui/mirror/resize-transaction.d.ts +102 -0
  756. package/packages/daemon/dist/tui/mirror/resize-transaction.js +221 -0
  757. package/packages/daemon/dist/tui/mirror/rich-placement-projection.d.ts +64 -0
  758. package/packages/daemon/dist/tui/mirror/rich-placement-projection.js +80 -0
  759. package/packages/daemon/dist/tui/mirror/runtime/application-appearance-owner.d.ts +22 -0
  760. package/packages/daemon/dist/tui/mirror/runtime/application-appearance-owner.js +79 -0
  761. package/packages/daemon/dist/tui/mirror/runtime/application-bootstrap.d.ts +61 -0
  762. package/packages/daemon/dist/tui/mirror/runtime/application-bootstrap.js +51 -0
  763. package/packages/daemon/dist/tui/mirror/runtime/application-generation-starter.d.ts +26 -0
  764. package/packages/daemon/dist/tui/mirror/runtime/application-generation-starter.js +80 -0
  765. package/packages/daemon/dist/tui/mirror/runtime/application-home-catalog-owner.d.ts +21 -0
  766. package/packages/daemon/dist/tui/mirror/runtime/application-home-catalog-owner.js +88 -0
  767. package/packages/daemon/dist/tui/mirror/runtime/application-home-catalog.d.ts +60 -0
  768. package/packages/daemon/dist/tui/mirror/runtime/application-home-catalog.js +320 -0
  769. package/packages/daemon/dist/tui/mirror/runtime/application-host-focus-control-binding.d.ts +28 -0
  770. package/packages/daemon/dist/tui/mirror/runtime/application-host-focus-control-binding.js +111 -0
  771. package/packages/daemon/dist/tui/mirror/runtime/application-host-focus-control-capability.d.ts +16 -0
  772. package/packages/daemon/dist/tui/mirror/runtime/application-host-focus-control-capability.js +25 -0
  773. package/packages/daemon/dist/tui/mirror/runtime/application-host-focus-presentation.d.ts +38 -0
  774. package/packages/daemon/dist/tui/mirror/runtime/application-host-focus-presentation.js +129 -0
  775. package/packages/daemon/dist/tui/mirror/runtime/application-host-focus-test-control.d.ts +43 -0
  776. package/packages/daemon/dist/tui/mirror/runtime/application-host-focus-test-control.js +242 -0
  777. package/packages/daemon/dist/tui/mirror/runtime/application-input-readiness.d.ts +5 -0
  778. package/packages/daemon/dist/tui/mirror/runtime/application-input-readiness.js +20 -0
  779. package/packages/daemon/dist/tui/mirror/runtime/application-lifecycle.d.ts +72 -0
  780. package/packages/daemon/dist/tui/mirror/runtime/application-lifecycle.js +297 -0
  781. package/packages/daemon/dist/tui/mirror/runtime/application-optional-features.d.ts +14 -0
  782. package/packages/daemon/dist/tui/mirror/runtime/application-optional-features.js +12 -0
  783. package/packages/daemon/dist/tui/mirror/runtime/application-palette-command-owner.d.ts +23 -0
  784. package/packages/daemon/dist/tui/mirror/runtime/application-palette-command-owner.js +61 -0
  785. package/packages/daemon/dist/tui/mirror/runtime/application-palette-input.d.ts +31 -0
  786. package/packages/daemon/dist/tui/mirror/runtime/application-palette-input.js +60 -0
  787. package/packages/daemon/dist/tui/mirror/runtime/application-pane-rename-input.d.ts +22 -0
  788. package/packages/daemon/dist/tui/mirror/runtime/application-pane-rename-input.js +30 -0
  789. package/packages/daemon/dist/tui/mirror/runtime/application-pane-rename-owner.d.ts +14 -0
  790. package/packages/daemon/dist/tui/mirror/runtime/application-pane-rename-owner.js +38 -0
  791. package/packages/daemon/dist/tui/mirror/runtime/application-pending-terminal-input.d.ts +53 -0
  792. package/packages/daemon/dist/tui/mirror/runtime/application-pending-terminal-input.js +74 -0
  793. package/packages/daemon/dist/tui/mirror/runtime/application-performance-log.d.ts +20 -0
  794. package/packages/daemon/dist/tui/mirror/runtime/application-performance-log.js +81 -0
  795. package/packages/daemon/dist/tui/mirror/runtime/application-post-render-runtime.d.ts +37 -0
  796. package/packages/daemon/dist/tui/mirror/runtime/application-post-render-runtime.js +117 -0
  797. package/packages/daemon/dist/tui/mirror/runtime/application-root-configuration.d.ts +21 -0
  798. package/packages/daemon/dist/tui/mirror/runtime/application-root-configuration.js +21 -0
  799. package/packages/daemon/dist/tui/mirror/runtime/application-root-renderer.d.ts +9 -0
  800. package/packages/daemon/dist/tui/mirror/runtime/application-root-renderer.js +27 -0
  801. package/packages/daemon/dist/tui/mirror/runtime/application-session-focus-owner.d.ts +14 -0
  802. package/packages/daemon/dist/tui/mirror/runtime/application-session-focus-owner.js +65 -0
  803. package/packages/daemon/dist/tui/mirror/runtime/application-shell-binding.d.ts +34 -0
  804. package/packages/daemon/dist/tui/mirror/runtime/application-shell-binding.js +307 -0
  805. package/packages/daemon/dist/tui/mirror/runtime/application-shell-viewport.d.ts +8 -0
  806. package/packages/daemon/dist/tui/mirror/runtime/application-shell-viewport.js +14 -0
  807. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-frame-readiness-owner.d.ts +6 -0
  808. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-frame-readiness-owner.js +20 -0
  809. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-host-focus-owner.d.ts +3 -0
  810. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-host-focus-owner.js +25 -0
  811. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-input-ingress.d.ts +15 -0
  812. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-input-ingress.js +96 -0
  813. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-interaction-controller.d.ts +65 -0
  814. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-interaction-controller.js +1326 -0
  815. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-palette-owner.d.ts +65 -0
  816. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-palette-owner.js +217 -0
  817. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-paste.d.ts +4 -0
  818. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-paste.js +22 -0
  819. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-renderer-sources.d.ts +15 -0
  820. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-renderer-sources.js +31 -0
  821. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-selection-owner.d.ts +47 -0
  822. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-selection-owner.js +161 -0
  823. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-workspace-policy.d.ts +44 -0
  824. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-workspace-policy.js +177 -0
  825. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-workspace.d.ts +103 -0
  826. package/packages/daemon/dist/tui/mirror/runtime/application-terminal-workspace.jsx +720 -0
  827. package/packages/daemon/dist/tui/mirror/runtime/application-theme-repaint.d.ts +24 -0
  828. package/packages/daemon/dist/tui/mirror/runtime/application-theme-repaint.js +34 -0
  829. package/packages/daemon/dist/tui/mirror/runtime/application-transient-note-owner.d.ts +15 -0
  830. package/packages/daemon/dist/tui/mirror/runtime/application-transient-note-owner.js +29 -0
  831. package/packages/daemon/dist/tui/mirror/runtime/bounded-performance-record-writer.d.ts +17 -0
  832. package/packages/daemon/dist/tui/mirror/runtime/bounded-performance-record-writer.js +67 -0
  833. package/packages/daemon/dist/tui/mirror/runtime/causal-cell-client-ledger.d.ts +64 -0
  834. package/packages/daemon/dist/tui/mirror/runtime/causal-cell-client-ledger.js +271 -0
  835. package/packages/daemon/dist/tui/mirror/runtime/causal-cell-input-fixture.d.ts +12 -0
  836. package/packages/daemon/dist/tui/mirror/runtime/causal-cell-input-fixture.js +43 -0
  837. package/packages/daemon/dist/tui/mirror/runtime/changes-deferred-identity.d.ts +15 -0
  838. package/packages/daemon/dist/tui/mirror/runtime/changes-deferred-identity.js +17 -0
  839. package/packages/daemon/dist/tui/mirror/runtime/daemon-authority-rebind.d.ts +29 -0
  840. package/packages/daemon/dist/tui/mirror/runtime/daemon-authority-rebind.js +128 -0
  841. package/packages/daemon/dist/tui/mirror/runtime/deferred-intent-queue.d.ts +12 -0
  842. package/packages/daemon/dist/tui/mirror/runtime/deferred-intent-queue.js +40 -0
  843. package/packages/daemon/dist/tui/mirror/runtime/editor-primitives.d.ts +23 -0
  844. package/packages/daemon/dist/tui/mirror/runtime/editor-primitives.js +39 -0
  845. package/packages/daemon/dist/tui/mirror/runtime/file-content-primitives.d.ts +3 -0
  846. package/packages/daemon/dist/tui/mirror/runtime/file-content-primitives.js +9 -0
  847. package/packages/daemon/dist/tui/mirror/runtime/fleet-lifecycle-client.d.ts +4 -0
  848. package/packages/daemon/dist/tui/mirror/runtime/fleet-lifecycle-client.js +27 -0
  849. package/packages/daemon/dist/tui/mirror/runtime/focus-framebuffer-projection.d.ts +16 -0
  850. package/packages/daemon/dist/tui/mirror/runtime/focus-framebuffer-projection.js +53 -0
  851. package/packages/daemon/dist/tui/mirror/runtime/generation-bound-slot.d.ts +7 -0
  852. package/packages/daemon/dist/tui/mirror/runtime/generation-bound-slot.js +23 -0
  853. package/packages/daemon/dist/tui/mirror/runtime/host-local-tmux-adapter.d.ts +17 -0
  854. package/packages/daemon/dist/tui/mirror/runtime/host-local-tmux-adapter.js +90 -0
  855. package/packages/daemon/dist/tui/mirror/runtime/hosted-tty-size-bridge.d.ts +55 -0
  856. package/packages/daemon/dist/tui/mirror/runtime/hosted-tty-size-bridge.js +166 -0
  857. package/packages/daemon/dist/tui/mirror/runtime/latest-intent-fence.d.ts +11 -0
  858. package/packages/daemon/dist/tui/mirror/runtime/latest-intent-fence.js +14 -0
  859. package/packages/daemon/dist/tui/mirror/runtime/local-view-controller.d.ts +30 -0
  860. package/packages/daemon/dist/tui/mirror/runtime/local-view-controller.js +58 -0
  861. package/packages/daemon/dist/tui/mirror/runtime/modal-admission-coordinator.d.ts +44 -0
  862. package/packages/daemon/dist/tui/mirror/runtime/modal-admission-coordinator.js +118 -0
  863. package/packages/daemon/dist/tui/mirror/runtime/modal-pointer-capture.d.ts +13 -0
  864. package/packages/daemon/dist/tui/mirror/runtime/modal-pointer-capture.js +12 -0
  865. package/packages/daemon/dist/tui/mirror/runtime/open-tui-generation-host.d.ts +68 -0
  866. package/packages/daemon/dist/tui/mirror/runtime/open-tui-generation-host.js +834 -0
  867. package/packages/daemon/dist/tui/mirror/runtime/open-tui-session-owner.d.ts +19 -0
  868. package/packages/daemon/dist/tui/mirror/runtime/open-tui-session-owner.js +146 -0
  869. package/packages/daemon/dist/tui/mirror/runtime/optional-feature-registry.d.ts +45 -0
  870. package/packages/daemon/dist/tui/mirror/runtime/optional-feature-registry.js +178 -0
  871. package/packages/daemon/dist/tui/mirror/runtime/optional-feature-registry.typecheck.d.ts +11 -0
  872. package/packages/daemon/dist/tui/mirror/runtime/optional-feature-registry.typecheck.js +1 -0
  873. package/packages/daemon/dist/tui/mirror/runtime/palette-production-controller.d.ts +55 -0
  874. package/packages/daemon/dist/tui/mirror/runtime/palette-production-controller.js +126 -0
  875. package/packages/daemon/dist/tui/mirror/runtime/pane-resize-geometry.d.ts +11 -0
  876. package/packages/daemon/dist/tui/mirror/runtime/pane-resize-geometry.js +13 -0
  877. package/packages/daemon/dist/tui/mirror/runtime/pane-scoped-terminal-surface.d.ts +42 -0
  878. package/packages/daemon/dist/tui/mirror/runtime/pane-scoped-terminal-surface.jsx +67 -0
  879. package/packages/daemon/dist/tui/mirror/runtime/product-surface-policy.d.ts +11 -0
  880. package/packages/daemon/dist/tui/mirror/runtime/product-surface-policy.js +12 -0
  881. package/packages/daemon/dist/tui/mirror/runtime/renderer-cadence.d.ts +4 -0
  882. package/packages/daemon/dist/tui/mirror/runtime/renderer-cadence.js +4 -0
  883. package/packages/daemon/dist/tui/mirror/runtime/resize-terminal-pane.d.ts +35 -0
  884. package/packages/daemon/dist/tui/mirror/runtime/resize-terminal-pane.js +91 -0
  885. package/packages/daemon/dist/tui/mirror/runtime/rich-preview-demand.d.ts +14 -0
  886. package/packages/daemon/dist/tui/mirror/runtime/rich-preview-demand.js +14 -0
  887. package/packages/daemon/dist/tui/mirror/runtime/runtime-layout-presentation.d.ts +20 -0
  888. package/packages/daemon/dist/tui/mirror/runtime/runtime-layout-presentation.js +111 -0
  889. package/packages/daemon/dist/tui/mirror/runtime/select-terminal-pane.d.ts +25 -0
  890. package/packages/daemon/dist/tui/mirror/runtime/select-terminal-pane.js +90 -0
  891. package/packages/daemon/dist/tui/mirror/runtime/semantic-pane-publication.d.ts +10 -0
  892. package/packages/daemon/dist/tui/mirror/runtime/semantic-pane-publication.js +14 -0
  893. package/packages/daemon/dist/tui/mirror/runtime/semantic-shell-viewport-resize.d.ts +15 -0
  894. package/packages/daemon/dist/tui/mirror/runtime/semantic-shell-viewport-resize.js +56 -0
  895. package/packages/daemon/dist/tui/mirror/runtime/terminal-dimensions-owner.d.ts +9 -0
  896. package/packages/daemon/dist/tui/mirror/runtime/terminal-dimensions-owner.js +9 -0
  897. package/packages/daemon/dist/tui/mirror/runtime/terminal-fast-lane-renderer-adapter.d.ts +52 -0
  898. package/packages/daemon/dist/tui/mirror/runtime/terminal-fast-lane-renderer-adapter.js +610 -0
  899. package/packages/daemon/dist/tui/mirror/runtime/terminal-frame-readiness.d.ts +16 -0
  900. package/packages/daemon/dist/tui/mirror/runtime/terminal-frame-readiness.js +84 -0
  901. package/packages/daemon/dist/tui/mirror/runtime/terminal-host-focus.d.ts +41 -0
  902. package/packages/daemon/dist/tui/mirror/runtime/terminal-host-focus.js +347 -0
  903. package/packages/daemon/dist/tui/mirror/runtime/terminal-host-frame-diagnostics.d.ts +3 -0
  904. package/packages/daemon/dist/tui/mirror/runtime/terminal-host-frame-diagnostics.js +37 -0
  905. package/packages/daemon/dist/tui/mirror/runtime/terminal-input-adapter.d.ts +10 -0
  906. package/packages/daemon/dist/tui/mirror/runtime/terminal-input-adapter.js +50 -0
  907. package/packages/daemon/dist/tui/mirror/runtime/terminal-layout-projection.d.ts +22 -0
  908. package/packages/daemon/dist/tui/mirror/runtime/terminal-layout-projection.js +28 -0
  909. package/packages/daemon/dist/tui/mirror/runtime/terminal-pane-input-router.d.ts +23 -0
  910. package/packages/daemon/dist/tui/mirror/runtime/terminal-pane-input-router.js +82 -0
  911. package/packages/daemon/dist/tui/mirror/runtime/terminal-selection.d.ts +66 -0
  912. package/packages/daemon/dist/tui/mirror/runtime/terminal-selection.js +141 -0
  913. package/packages/daemon/dist/tui/mirror/runtime/terminal-session-handoff.d.ts +50 -0
  914. package/packages/daemon/dist/tui/mirror/runtime/terminal-session-handoff.js +89 -0
  915. package/packages/daemon/dist/tui/mirror/runtime/terminal-tool-readiness.d.ts +31 -0
  916. package/packages/daemon/dist/tui/mirror/runtime/terminal-tool-readiness.js +64 -0
  917. package/packages/daemon/dist/tui/mirror/runtime/tool-resource-controller.d.ts +92 -0
  918. package/packages/daemon/dist/tui/mirror/runtime/tool-resource-controller.js +636 -0
  919. package/packages/daemon/dist/tui/mirror/runtime/tool-resource-projection.d.ts +59 -0
  920. package/packages/daemon/dist/tui/mirror/runtime/tool-resource-projection.js +169 -0
  921. package/packages/daemon/dist/tui/mirror/runtime/viewport-fit-coordinator.d.ts +8 -0
  922. package/packages/daemon/dist/tui/mirror/runtime/viewport-fit-coordinator.js +7 -0
  923. package/packages/daemon/dist/tui/mirror/runtime/workspace-terminal-fast-lane.d.ts +22 -0
  924. package/packages/daemon/dist/tui/mirror/runtime/workspace-terminal-fast-lane.js +498 -0
  925. package/packages/daemon/dist/tui/mirror/scrollbar-model.d.ts +35 -0
  926. package/packages/daemon/dist/tui/mirror/scrollbar-model.js +64 -0
  927. package/packages/daemon/dist/tui/mirror/search-model.d.ts +41 -0
  928. package/packages/daemon/dist/tui/mirror/search-model.js +62 -0
  929. package/packages/daemon/dist/tui/mirror/selection.d.ts +175 -0
  930. package/packages/daemon/dist/tui/mirror/selection.js +264 -0
  931. package/packages/daemon/dist/tui/mirror/semantic-pane-render-source.d.ts +147 -0
  932. package/packages/daemon/dist/tui/mirror/semantic-pane-render-source.js +562 -0
  933. package/packages/daemon/dist/tui/mirror/semantic-session-view.d.ts +86 -0
  934. package/packages/daemon/dist/tui/mirror/semantic-session-view.js +269 -0
  935. package/packages/daemon/dist/tui/mirror/settings-model.d.ts +108 -0
  936. package/packages/daemon/dist/tui/mirror/settings-model.js +304 -0
  937. package/packages/daemon/dist/tui/mirror/shell-chrome.d.ts +151 -0
  938. package/packages/daemon/dist/tui/mirror/shell-chrome.js +313 -0
  939. package/packages/daemon/dist/tui/mirror/size-truth.d.ts +92 -0
  940. package/packages/daemon/dist/tui/mirror/size-truth.js +104 -0
  941. package/packages/daemon/dist/tui/mirror/spans.d.ts +26 -0
  942. package/packages/daemon/dist/tui/mirror/spans.js +31 -0
  943. package/packages/daemon/dist/tui/mirror/status-grammar.d.ts +18 -0
  944. package/packages/daemon/dist/tui/mirror/status-grammar.js +29 -0
  945. package/packages/daemon/dist/tui/mirror/terminal-surface.d.ts +55 -0
  946. package/packages/daemon/dist/tui/mirror/terminal-surface.js +92 -0
  947. package/packages/daemon/dist/tui/mirror/terminal-text.d.ts +9 -0
  948. package/packages/daemon/dist/tui/mirror/terminal-text.js +38 -0
  949. package/packages/daemon/dist/tui/mirror/theme.d.ts +207 -0
  950. package/packages/daemon/dist/tui/mirror/theme.js +744 -0
  951. package/packages/daemon/dist/tui/mirror/ui/agent-badge.d.ts +11 -0
  952. package/packages/daemon/dist/tui/mirror/ui/agent-badge.jsx +14 -0
  953. package/packages/daemon/dist/tui/mirror/ui/badge.d.ts +13 -0
  954. package/packages/daemon/dist/tui/mirror/ui/badge.jsx +15 -0
  955. package/packages/daemon/dist/tui/mirror/ui/button.d.ts +26 -0
  956. package/packages/daemon/dist/tui/mirror/ui/button.jsx +66 -0
  957. package/packages/daemon/dist/tui/mirror/ui/dialog.d.ts +19 -0
  958. package/packages/daemon/dist/tui/mirror/ui/dialog.jsx +8 -0
  959. package/packages/daemon/dist/tui/mirror/ui/index.d.ts +16 -0
  960. package/packages/daemon/dist/tui/mirror/ui/index.js +16 -0
  961. package/packages/daemon/dist/tui/mirror/ui/key-hint.d.ts +13 -0
  962. package/packages/daemon/dist/tui/mirror/ui/key-hint.jsx +39 -0
  963. package/packages/daemon/dist/tui/mirror/ui/keyboard-router.d.ts +25 -0
  964. package/packages/daemon/dist/tui/mirror/ui/keyboard-router.jsx +46 -0
  965. package/packages/daemon/dist/tui/mirror/ui/menu.d.ts +24 -0
  966. package/packages/daemon/dist/tui/mirror/ui/menu.jsx +15 -0
  967. package/packages/daemon/dist/tui/mirror/ui/navigation-row.d.ts +21 -0
  968. package/packages/daemon/dist/tui/mirror/ui/navigation-row.jsx +62 -0
  969. package/packages/daemon/dist/tui/mirror/ui/overlay-frame.d.ts +25 -0
  970. package/packages/daemon/dist/tui/mirror/ui/overlay-frame.jsx +52 -0
  971. package/packages/daemon/dist/tui/mirror/ui/overlay-host.d.ts +24 -0
  972. package/packages/daemon/dist/tui/mirror/ui/overlay-host.jsx +33 -0
  973. package/packages/daemon/dist/tui/mirror/ui/overlay-list-row.d.ts +13 -0
  974. package/packages/daemon/dist/tui/mirror/ui/overlay-list-row.jsx +23 -0
  975. package/packages/daemon/dist/tui/mirror/ui/overlay-model.d.ts +29 -0
  976. package/packages/daemon/dist/tui/mirror/ui/overlay-model.js +45 -0
  977. package/packages/daemon/dist/tui/mirror/ui/state.d.ts +27 -0
  978. package/packages/daemon/dist/tui/mirror/ui/state.js +171 -0
  979. package/packages/daemon/dist/tui/mirror/ui/status-bar.d.ts +43 -0
  980. package/packages/daemon/dist/tui/mirror/ui/status-bar.jsx +102 -0
  981. package/packages/daemon/dist/tui/mirror/ui/surface.d.ts +14 -0
  982. package/packages/daemon/dist/tui/mirror/ui/surface.jsx +45 -0
  983. package/packages/daemon/dist/tui/mirror/ui/tabs.d.ts +26 -0
  984. package/packages/daemon/dist/tui/mirror/ui/tabs.jsx +88 -0
  985. package/packages/daemon/dist/tui/mirror/widget-fallback.d.ts +15 -0
  986. package/packages/daemon/dist/tui/mirror/widget-fallback.js +52 -0
  987. package/packages/daemon/dist/tui/mirror/widget-surface-model.d.ts +26 -0
  988. package/packages/daemon/dist/tui/mirror/widget-surface-model.js +145 -0
  989. package/packages/daemon/dist/tui/mirror/widget-surface.d.ts +13 -0
  990. package/packages/daemon/dist/tui/mirror/widget-surface.jsx +31 -0
  991. package/packages/daemon/dist/tui/mirror/workspace/agent-terminal-canvas.d.ts +53 -0
  992. package/packages/daemon/dist/tui/mirror/workspace/agent-terminal-canvas.js +77 -0
  993. package/packages/daemon/dist/tui/mirror/workspace/application-root-controller.d.ts +266 -0
  994. package/packages/daemon/dist/tui/mirror/workspace/application-root-controller.js +99 -0
  995. package/packages/daemon/dist/tui/mirror/workspace/application-shell-controller.d.ts +83 -0
  996. package/packages/daemon/dist/tui/mirror/workspace/application-shell-controller.js +292 -0
  997. package/packages/daemon/dist/tui/mirror/workspace/application-shell-surface-commands.d.ts +5 -0
  998. package/packages/daemon/dist/tui/mirror/workspace/application-shell-surface-commands.js +28 -0
  999. package/packages/daemon/dist/tui/mirror/workspace/application-shell.d.ts +49 -0
  1000. package/packages/daemon/dist/tui/mirror/workspace/application-shell.js +97 -0
  1001. package/packages/daemon/dist/tui/mirror/workspace/command-palette-surface-view.d.ts +11 -0
  1002. package/packages/daemon/dist/tui/mirror/workspace/command-palette-surface-view.jsx +158 -0
  1003. package/packages/daemon/dist/tui/mirror/workspace/command-palette-surface.d.ts +128 -0
  1004. package/packages/daemon/dist/tui/mirror/workspace/command-palette-surface.js +342 -0
  1005. package/packages/daemon/dist/tui/mirror/workspace/icons.d.ts +154 -0
  1006. package/packages/daemon/dist/tui/mirror/workspace/icons.js +43 -0
  1007. package/packages/daemon/dist/tui/mirror/workspace/pane-action-menu.d.ts +24 -0
  1008. package/packages/daemon/dist/tui/mirror/workspace/pane-action-menu.jsx +20 -0
  1009. package/packages/daemon/dist/tui/mirror/workspace/pane-frame.d.ts +143 -0
  1010. package/packages/daemon/dist/tui/mirror/workspace/pane-frame.js +452 -0
  1011. package/packages/daemon/dist/tui/mirror/workspace/terminal-pane-chrome.d.ts +152 -0
  1012. package/packages/daemon/dist/tui/mirror/workspace/terminal-pane-chrome.js +555 -0
  1013. package/packages/daemon/dist/tui/mirror/workspace/terminal-pane-header.d.ts +58 -0
  1014. package/packages/daemon/dist/tui/mirror/workspace/terminal-pane-header.jsx +93 -0
  1015. package/packages/daemon/dist/tui/mirror/workspace/terminal-window-strip.d.ts +75 -0
  1016. package/packages/daemon/dist/tui/mirror/workspace/terminal-window-strip.jsx +253 -0
  1017. package/packages/daemon/dist/tui/mirror/workspace/text.d.ts +2 -0
  1018. package/packages/daemon/dist/tui/mirror/workspace/text.js +27 -0
  1019. package/packages/daemon/dist/tui/mirror/workspace/workbench-controller.d.ts +23 -0
  1020. package/packages/daemon/dist/tui/mirror/workspace/workbench-controller.js +34 -0
  1021. package/packages/daemon/dist/tui/mirror/workspace/workbench-shell.d.ts +123 -0
  1022. package/packages/daemon/dist/tui/mirror/workspace/workbench-shell.js +286 -0
  1023. package/packages/daemon/dist/tui/mirror/workspace-ui-state.d.ts +174 -0
  1024. package/packages/daemon/dist/tui/mirror/workspace-ui-state.js +885 -0
  1025. package/packages/daemon/dist/tui/readiness.d.ts +22 -0
  1026. package/packages/daemon/dist/tui/readiness.js +34 -0
  1027. package/packages/daemon/dist/tui/team/entry.d.ts +37 -0
  1028. package/packages/daemon/dist/tui/team/entry.js +20 -0
  1029. package/packages/daemon/dist/tui/team/fuzzy.d.ts +38 -0
  1030. package/packages/daemon/dist/tui/team/fuzzy.js +141 -0
  1031. package/packages/daemon/dist/tui/team/home.d.ts +94 -0
  1032. package/packages/daemon/dist/tui/team/home.js +115 -0
  1033. package/packages/daemon/dist/tui/team/input.d.ts +22 -0
  1034. package/packages/daemon/dist/tui/team/input.js +21 -0
  1035. package/packages/daemon/dist/tui/team/keymap.d.ts +33 -0
  1036. package/packages/daemon/dist/tui/team/keymap.js +99 -0
  1037. package/packages/daemon/dist/tui/team/mouse.d.ts +18 -0
  1038. package/packages/daemon/dist/tui/team/mouse.js +17 -0
  1039. package/packages/daemon/dist/tui/team/nav.d.ts +21 -0
  1040. package/packages/daemon/dist/tui/team/nav.js +33 -0
  1041. package/packages/daemon/dist/tui/team/preview.d.ts +19 -0
  1042. package/packages/daemon/dist/tui/team/preview.js +35 -0
  1043. package/packages/daemon/dist/tui/team/projects.d.ts +52 -0
  1044. package/packages/daemon/dist/tui/team/projects.js +159 -0
  1045. package/packages/daemon/dist/tui/team/report.d.ts +51 -0
  1046. package/packages/daemon/dist/tui/team/report.js +37 -0
  1047. package/packages/daemon/dist/tui/team/sessions.d.ts +235 -0
  1048. package/packages/daemon/dist/tui/team/sessions.js +292 -0
  1049. package/packages/daemon/dist/tui/team/tree.d.ts +41 -0
  1050. package/packages/daemon/dist/tui/team/tree.js +42 -0
  1051. package/packages/daemon/dist/tui/team/wait-receipts.d.ts +60 -0
  1052. package/packages/daemon/dist/tui/team/wait-receipts.js +153 -0
  1053. package/packages/daemon/dist/tui/team/wait.d.ts +62 -0
  1054. package/packages/daemon/dist/tui/team/wait.js +90 -0
  1055. package/packages/daemon/dist/validate.js +16 -10
  1056. package/packages/daemon/dist/widgets/lib/watcher.d.ts +5 -9
  1057. package/packages/daemon/dist/widgets/lib/watcher.js +5 -92
  1058. package/packages/daemon/dist/widgets/resolve.js +10 -7
  1059. package/packages/daemon/dist/widgets/setup/setup-model.js +7 -9
  1060. package/packages/daemon/src/attach.ts +2 -2
  1061. package/packages/daemon/src/canonical.ts +19 -2
  1062. package/packages/daemon/src/cli.ts +38 -36
  1063. package/packages/daemon/src/command-center/actions/command-definitions.ts +91 -0
  1064. package/packages/daemon/src/command-center/actions/dispatcher.ts +291 -10
  1065. package/packages/daemon/src/command-center/actions/errors.ts +40 -0
  1066. package/packages/daemon/src/command-center/actions/handlers/_project-context.ts +4 -5
  1067. package/packages/daemon/src/command-center/actions/handlers/app-window-mutate.ts +54 -0
  1068. package/packages/daemon/src/command-center/actions/handlers/config-actions.ts +59 -29
  1069. package/packages/daemon/src/command-center/actions/handlers/daemon-shutdown.ts +12 -0
  1070. package/packages/daemon/src/command-center/actions/handlers/fleet-lifecycle.ts +104 -0
  1071. package/packages/daemon/src/command-center/actions/handlers/project-launch.ts +20 -4
  1072. package/packages/daemon/src/command-center/actions/handlers/workspace-multiplexer.ts +96 -0
  1073. package/packages/daemon/src/command-center/actions/handlers/workspace-open.ts +141 -0
  1074. package/packages/daemon/src/command-center/actions/handlers/workspace-pane-create.ts +48 -0
  1075. package/packages/daemon/src/command-center/actions/handlers/workspace-promote.ts +48 -0
  1076. package/packages/daemon/src/command-center/actions/registry.ts +200 -1
  1077. package/packages/daemon/src/command-center/actions/semantic-multiplexer-actions.ts +26 -0
  1078. package/packages/daemon/src/command-center/agent-status-watch.ts +222 -0
  1079. package/packages/daemon/src/command-center/daemon-fleet-facts-observer.ts +465 -0
  1080. package/packages/daemon/src/command-center/discovery.ts +310 -5
  1081. package/packages/daemon/src/command-center/owner-authority.ts +118 -0
  1082. package/packages/daemon/src/command-center/pane-stream-issue.ts +247 -0
  1083. package/packages/daemon/src/command-center/resources/agent-graph-overlay.ts +270 -0
  1084. package/packages/daemon/src/command-center/resources/application-shell.ts +909 -0
  1085. package/packages/daemon/src/command-center/resources/desktop-missions.ts +171 -0
  1086. package/packages/daemon/src/command-center/resources/fleet-catalog.ts +200 -0
  1087. package/packages/daemon/src/command-center/resources/fleet-resource-route.ts +61 -0
  1088. package/packages/daemon/src/command-center/resources/startup-readiness-route.ts +172 -0
  1089. package/packages/daemon/src/command-center/resources/startup-readiness.ts +250 -0
  1090. package/packages/daemon/src/command-center/resources/terminal-runtime-inventory.ts +45 -0
  1091. package/packages/daemon/src/command-center/resources/workspace-changes-authority.ts +594 -0
  1092. package/packages/daemon/src/command-center/resources/workspace-changes-git.ts +278 -0
  1093. package/packages/daemon/src/command-center/resources/workspace-files-authority.ts +583 -0
  1094. package/packages/daemon/src/command-center/resources/workspace-missions-route.ts +125 -0
  1095. package/packages/daemon/src/command-center/resources/workspace-resource-ids.ts +81 -0
  1096. package/packages/daemon/src/command-center/resources/workspace-resource-routes.ts +147 -0
  1097. package/packages/daemon/src/command-center/server.ts +732 -59
  1098. package/packages/daemon/src/command-center/terminal-attachment-issue.ts +257 -0
  1099. package/packages/daemon/src/command-center/workspace-resource-observer.ts +560 -0
  1100. package/packages/daemon/src/command-center/ws-events.ts +853 -66
  1101. package/packages/daemon/src/config.ts +35 -25
  1102. package/packages/daemon/src/control/client.ts +128 -0
  1103. package/packages/daemon/src/control/dispatch.ts +107 -0
  1104. package/packages/daemon/src/control/fanout.ts +44 -0
  1105. package/packages/daemon/src/control/frames.ts +40 -0
  1106. package/packages/daemon/src/control/lifecycle.ts +163 -0
  1107. package/packages/daemon/src/control/server.ts +237 -0
  1108. package/packages/daemon/src/control/verbs.ts +118 -0
  1109. package/packages/daemon/src/detect.ts +25 -20
  1110. package/packages/daemon/src/doctor.ts +133 -33
  1111. package/packages/daemon/src/index.ts +244 -2
  1112. package/packages/daemon/src/init.ts +23 -22
  1113. package/packages/daemon/src/inspect.ts +41 -8
  1114. package/packages/daemon/src/launch.ts +56 -28
  1115. package/packages/daemon/src/lib/agent-discovery.ts +53 -13
  1116. package/packages/daemon/src/lib/agent-kind.ts +23 -0
  1117. package/packages/daemon/src/lib/app-config.ts +143 -9
  1118. package/packages/daemon/src/lib/app-window-kernel.ts +777 -0
  1119. package/packages/daemon/src/lib/app-window-mutation.ts +178 -0
  1120. package/packages/daemon/src/lib/app-window-repository.ts +650 -0
  1121. package/packages/daemon/src/lib/app-window-state.ts +599 -0
  1122. package/packages/daemon/src/lib/application-shell-app-windows.ts +357 -0
  1123. package/packages/daemon/src/lib/auth/middleware.ts +9 -3
  1124. package/packages/daemon/src/lib/canonical-daemon-bootstrap.ts +266 -0
  1125. package/packages/daemon/src/lib/canonical-daemon.ts +695 -73
  1126. package/packages/daemon/src/lib/chrome-front-door.ts +17 -0
  1127. package/packages/daemon/src/lib/cli-action-bridge.ts +127 -91
  1128. package/packages/daemon/src/lib/command-registry.ts +152 -0
  1129. package/packages/daemon/src/lib/config-context.ts +61 -0
  1130. package/packages/daemon/src/lib/daemon-embed.ts +1347 -387
  1131. package/packages/daemon/src/lib/daemon-session-monitor.ts +274 -0
  1132. package/packages/daemon/src/lib/daemon.ts +3 -46
  1133. package/packages/daemon/src/lib/directory-watcher.ts +166 -0
  1134. package/packages/daemon/src/lib/environment-identity.ts +82 -0
  1135. package/packages/daemon/src/lib/errors.ts +7 -1
  1136. package/packages/daemon/src/lib/fleet-agent-lifecycle.ts +74 -0
  1137. package/packages/daemon/src/lib/fleet-lifecycle-authority.ts +535 -0
  1138. package/packages/daemon/src/lib/headless-daemon.ts +406 -0
  1139. package/packages/daemon/src/lib/launch-plan.ts +123 -4
  1140. package/packages/daemon/src/lib/legacy-config-adapter.ts +28 -0
  1141. package/packages/daemon/src/lib/legacy-config-migration.ts +145 -0
  1142. package/packages/daemon/src/lib/legacy-theme-compat.ts +40 -0
  1143. package/packages/daemon/src/lib/manifest-pack.ts +255 -0
  1144. package/packages/daemon/src/lib/mission-projections.ts +775 -0
  1145. package/packages/daemon/src/lib/mission-repository.ts +1311 -0
  1146. package/packages/daemon/src/lib/onboarding-marker.ts +51 -0
  1147. package/packages/daemon/src/lib/pane-chrome.ts +14 -0
  1148. package/packages/daemon/src/lib/pane-source-credentials.ts +200 -0
  1149. package/packages/daemon/src/lib/pane-widget.ts +182 -0
  1150. package/packages/daemon/src/lib/project-inspect.ts +4 -0
  1151. package/packages/daemon/src/lib/project-onboard.ts +19 -24
  1152. package/packages/daemon/src/lib/project-probe.ts +38 -30
  1153. package/packages/daemon/src/lib/project-readiness-probe.ts +578 -0
  1154. package/packages/daemon/src/lib/project-readiness.ts +1034 -0
  1155. package/packages/daemon/src/lib/project-registry.ts +45 -9
  1156. package/packages/daemon/src/lib/project-resolver.ts +350 -0
  1157. package/packages/daemon/src/lib/project-runtime-errors.ts +41 -0
  1158. package/packages/daemon/src/lib/project-runtime-repository.ts +1194 -0
  1159. package/packages/daemon/src/lib/resolved-config.ts +425 -0
  1160. package/packages/daemon/src/lib/runtime-namespace.ts +186 -0
  1161. package/packages/daemon/src/lib/semantic-resource-id.ts +17 -0
  1162. package/packages/daemon/src/lib/session-monitor.ts +28 -20
  1163. package/packages/daemon/src/lib/session-options.ts +3 -10
  1164. package/packages/daemon/src/lib/state-home.ts +12 -0
  1165. package/packages/daemon/src/lib/theme-mode.ts +11 -0
  1166. package/packages/daemon/src/lib/tmux-external-interaction-observer.ts +632 -0
  1167. package/packages/daemon/src/lib/tmux-interaction-options.ts +171 -0
  1168. package/packages/daemon/src/lib/tmux-terminal-color.ts +44 -0
  1169. package/packages/daemon/src/lib/tui-binary.ts +354 -34
  1170. package/packages/daemon/src/lib/unix-socket-authority.ts +65 -0
  1171. package/packages/daemon/src/lib/update-check.ts +5 -0
  1172. package/packages/daemon/src/lib/widget-asset-policy.ts +3 -0
  1173. package/packages/daemon/src/lib/widget-asset-store.ts +218 -0
  1174. package/packages/daemon/src/lib/workspace-config-loader.ts +378 -0
  1175. package/packages/daemon/src/lib/workspace-multiplexer-verbs.ts +1362 -0
  1176. package/packages/daemon/src/lib/workspace-open-handoff.ts +340 -0
  1177. package/packages/daemon/src/lib/workspace-open.ts +983 -0
  1178. package/packages/daemon/src/lib/workspace-pane-creation.ts +1406 -0
  1179. package/packages/daemon/src/lib/workspace-promotion.ts +1031 -0
  1180. package/packages/daemon/src/lib/workspace-registry.ts +193 -25
  1181. package/packages/daemon/src/lib/workspace-state-repository.ts +1204 -0
  1182. package/packages/daemon/src/lib/workspace-state.ts +960 -0
  1183. package/packages/daemon/src/lib/yaml-io.ts +8 -17
  1184. package/packages/daemon/src/migrate.ts +134 -0
  1185. package/packages/daemon/src/restart.ts +2 -2
  1186. package/packages/daemon/src/restore.ts +67 -24
  1187. package/packages/daemon/src/schemas/inspect.ts +9 -1
  1188. package/packages/daemon/src/schemas/registry.ts +12 -22
  1189. package/packages/daemon/src/schemas/ws-events.ts +14 -131
  1190. package/packages/daemon/src/send.ts +191 -22
  1191. package/packages/daemon/src/server/pane-stream-upgrade.ts +141 -0
  1192. package/packages/daemon/src/server/terminal-attachment-upgrade.ts +153 -0
  1193. package/packages/daemon/src/status.ts +13 -8
  1194. package/packages/daemon/src/stop.ts +2 -2
  1195. package/packages/daemon/src/terminal/MonotonicPtyInput.ts +153 -0
  1196. package/packages/daemon/src/terminal/NodePtyAdapter.ts +53 -11
  1197. package/packages/daemon/src/terminal/PtyAdapter.ts +111 -3
  1198. package/packages/daemon/src/terminal/README.md +34 -16
  1199. package/packages/daemon/src/terminal/attachments/admission-util.ts +97 -0
  1200. package/packages/daemon/src/terminal/attachments/agent-status-probe.ts +474 -0
  1201. package/packages/daemon/src/terminal/attachments/direct-websocket.ts +1482 -0
  1202. package/packages/daemon/src/terminal/attachments/grouped-tmux.ts +293 -0
  1203. package/packages/daemon/src/terminal/attachments/lease-manager.ts +1042 -0
  1204. package/packages/daemon/src/terminal/attachments/native-runtime.ts +2206 -0
  1205. package/packages/daemon/src/terminal/attachments/pty-tmux-attachment-launcher.ts +750 -0
  1206. package/packages/daemon/src/terminal/attachments/semantic-pane-catalog.ts +365 -0
  1207. package/packages/daemon/src/terminal/attachments/tmux-view-executor.ts +1095 -0
  1208. package/packages/daemon/src/terminal/mirror/control-channel.ts +827 -0
  1209. package/packages/daemon/src/terminal/mirror/control-mode-ownership.ts +34 -0
  1210. package/packages/daemon/src/terminal/mirror/events.ts +128 -0
  1211. package/packages/daemon/src/terminal/mirror/flow-ledger.ts +65 -0
  1212. package/packages/daemon/src/terminal/mirror/mirror-service.ts +480 -0
  1213. package/packages/daemon/src/terminal/mirror/pane-feed.ts +193 -0
  1214. package/packages/daemon/src/terminal/mirror/session-channel.ts +2820 -0
  1215. package/packages/daemon/src/terminal/mirror/trusted-inventory.ts +29 -0
  1216. package/packages/daemon/src/terminal/pane-stream/lease-manager.ts +375 -0
  1217. package/packages/daemon/src/terminal/pane-stream/pane-stream-websocket.ts +2612 -0
  1218. package/packages/daemon/src/terminal/pane-stream/runtime.ts +78 -0
  1219. package/packages/daemon/src/terminal/pane-stream/wire-ledger.ts +155 -0
  1220. package/packages/daemon/src/terminal/protocol/README.md +14 -0
  1221. package/packages/daemon/src/terminal/protocol/chunk-bytes.ts +20 -0
  1222. package/packages/daemon/src/{tui/mirror → terminal/protocol}/control.ts +39 -6
  1223. package/packages/daemon/src/{tui/mirror → terminal/protocol}/input-coalescer.ts +18 -7
  1224. package/packages/daemon/src/terminal/protocol/layout-parse.ts +154 -0
  1225. package/packages/daemon/src/terminal/protocol/pane-display-name.ts +185 -0
  1226. package/packages/daemon/src/terminal/protocol/session-descriptor-discovery.ts +382 -0
  1227. package/packages/daemon/src/terminal/protocol/workspace-tmux-adapter.ts +470 -0
  1228. package/packages/daemon/src/terminal/session-runtime/authority-arbiter.ts +312 -0
  1229. package/packages/daemon/src/terminal/session-runtime/causal-cell-ledger.ts +359 -0
  1230. package/packages/daemon/src/terminal/session-runtime/interaction-receipt-facts.ts +173 -0
  1231. package/packages/daemon/src/terminal/session-runtime/multiplexer-backend.ts +194 -0
  1232. package/packages/daemon/src/terminal/session-runtime/registry.ts +2047 -0
  1233. package/packages/daemon/src/terminal/session-runtime/runtime-observability.ts +267 -0
  1234. package/packages/daemon/src/terminal/session-runtime/runtime-scheduler.ts +22 -0
  1235. package/packages/daemon/src/terminal/session-runtime/runtime-trace-correlator.ts +58 -0
  1236. package/packages/daemon/src/terminal/session-runtime/semantic-mutation-executor.ts +555 -0
  1237. package/packages/daemon/src/terminal/session-runtime/semantic-mutation-resource-changes.ts +48 -0
  1238. package/packages/daemon/src/terminal/session-runtime/terminal-delivery-hub.ts +1806 -0
  1239. package/packages/daemon/src/terminal/session-runtime/terminal-delivery-observation-identity.ts +18 -0
  1240. package/packages/daemon/src/terminal/session-runtime/terminal-interpreter-backend.ts +64 -0
  1241. package/packages/daemon/src/terminal/session-runtime/terminal-replica-interpreter.ts +690 -0
  1242. package/packages/daemon/src/terminal/session-runtime/terminal-replica-owner.ts +498 -0
  1243. package/packages/daemon/src/terminal/session-runtime/terminal-replica-shadow-projections.ts +36 -0
  1244. package/packages/daemon/src/terminal/session-runtime/transport-binding.ts +682 -0
  1245. package/packages/daemon/src/terminal/session-runtime/xterm-headless-provenance.json +25 -0
  1246. package/packages/daemon/src/terminal/session-runtime/xterm-terminal-interpreter-backend.ts +379 -0
  1247. package/packages/daemon/src/tui/async-disposable-slot.ts +60 -0
  1248. package/packages/daemon/src/tui/chrome/events.ts +4 -4
  1249. package/packages/daemon/src/tui/chrome/front-door.ts +27 -0
  1250. package/packages/daemon/src/tui/chrome/notify-prefs.ts +58 -0
  1251. package/packages/daemon/src/tui/chrome/notify-state.ts +76 -0
  1252. package/packages/daemon/src/tui/chrome/notify.ts +582 -84
  1253. package/packages/daemon/src/tui/chrome/sidebar.ts +9 -4
  1254. package/packages/daemon/src/tui/chrome/statusline.ts +15 -6
  1255. package/packages/daemon/src/tui/chrome/updater.ts +367 -64
  1256. package/packages/daemon/src/tui/compiled.ts +102 -6
  1257. package/packages/daemon/src/tui/detect/agent-resolution.ts +85 -0
  1258. package/packages/daemon/src/tui/detect/classify.ts +34 -0
  1259. package/packages/daemon/src/tui/detect/manifest-loader.ts +54 -5
  1260. package/packages/daemon/src/tui/detect/manifest.ts +24 -3
  1261. package/packages/daemon/src/tui/detect/manifests.ts +240 -6
  1262. package/packages/daemon/src/tui/detect/process-tree.ts +30 -4
  1263. package/packages/daemon/src/tui/detect/session-id.ts +503 -0
  1264. package/packages/daemon/src/tui/detect/snapshot.ts +38 -3
  1265. package/packages/daemon/src/tui/integrations/claude.ts +1 -0
  1266. package/packages/daemon/src/tui/integrations/opencode.ts +121 -0
  1267. package/packages/daemon/src/tui/main.ts +53 -0
  1268. package/packages/daemon/src/tui/mirror/RECIPES.md +59 -0
  1269. package/packages/daemon/src/tui/mirror/SHELL_CHROME.md +39 -0
  1270. package/packages/daemon/src/tui/mirror/THEME.md +48 -0
  1271. package/packages/daemon/src/tui/mirror/__snapshots__/activity-surface-renderer.test.tsx.snap +42 -0
  1272. package/packages/daemon/src/tui/mirror/__snapshots__/changes-terminal-surface-renderer.test.tsx.snap +267 -0
  1273. package/packages/daemon/src/tui/mirror/__snapshots__/home-files-surface-renderer.test.tsx.snap +267 -0
  1274. package/packages/daemon/src/tui/mirror/__snapshots__/missions-surface-renderer.test.tsx.snap +134 -0
  1275. package/packages/daemon/src/tui/mirror/__snapshots__/recipes-gallery-renderer.test.tsx.snap +141 -0
  1276. package/packages/daemon/src/tui/mirror/__snapshots__/shell-chrome-renderer.test.tsx.snap +134 -0
  1277. package/packages/daemon/src/tui/mirror/activity-surface-view.tsx +169 -0
  1278. package/packages/daemon/src/tui/mirror/activity-surface.ts +430 -0
  1279. package/packages/daemon/src/tui/mirror/agent-chip.ts +40 -11
  1280. package/packages/daemon/src/tui/mirror/agent-lifecycle.ts +468 -0
  1281. package/packages/daemon/src/tui/mirror/agent-provisioning-executor.ts +151 -0
  1282. package/packages/daemon/src/tui/mirror/agent-rows.ts +61 -5
  1283. package/packages/daemon/src/tui/mirror/ansi-palette.ts +3 -0
  1284. package/packages/daemon/src/tui/mirror/app-state.ts +185 -9
  1285. package/packages/daemon/src/tui/mirror/app.tsx +2 -5264
  1286. package/packages/daemon/src/tui/mirror/application-keybindings.ts +54 -0
  1287. package/packages/daemon/src/tui/mirror/application-shell-daemon-connection.ts +344 -0
  1288. package/packages/daemon/src/tui/mirror/application-shell-daemon-session.ts +74 -0
  1289. package/packages/daemon/src/tui/mirror/attention.ts +110 -0
  1290. package/packages/daemon/src/tui/mirror/canonical-workspace-routing.ts +63 -0
  1291. package/packages/daemon/src/tui/mirror/changes-surface-view.tsx +263 -0
  1292. package/packages/daemon/src/tui/mirror/changes-surface.ts +338 -0
  1293. package/packages/daemon/src/tui/mirror/composite-layout.ts +710 -0
  1294. package/packages/daemon/src/tui/mirror/configless-session-bootstrap.ts +192 -0
  1295. package/packages/daemon/src/tui/mirror/dialog-model.ts +2 -2
  1296. package/packages/daemon/src/tui/mirror/dialog-stack-core.ts +264 -0
  1297. package/packages/daemon/src/tui/mirror/dialog-stack.ts +2 -354
  1298. package/packages/daemon/src/tui/mirror/diff-model.ts +279 -4
  1299. package/packages/daemon/src/tui/mirror/editor-buffer.ts +9 -70
  1300. package/packages/daemon/src/tui/mirror/editor-open-policy.ts +16 -0
  1301. package/packages/daemon/src/tui/mirror/features/changes/contract.ts +84 -0
  1302. package/packages/daemon/src/tui/mirror/features/changes/controller.ts +470 -0
  1303. package/packages/daemon/src/tui/mirror/features/changes/feature.tsx +19 -0
  1304. package/packages/daemon/src/tui/mirror/features/dialogs/contract.ts +64 -0
  1305. package/packages/daemon/src/tui/mirror/features/dialogs/feature.tsx +227 -0
  1306. package/packages/daemon/src/tui/mirror/features/dialogs/session.ts +186 -0
  1307. package/packages/daemon/src/tui/mirror/features/files/feature.tsx +54 -0
  1308. package/packages/daemon/src/tui/mirror/features/files/session.ts +694 -0
  1309. package/packages/daemon/src/tui/mirror/features/home/feature.tsx +172 -0
  1310. package/packages/daemon/src/tui/mirror/features/missions-activity/contract.ts +106 -0
  1311. package/packages/daemon/src/tui/mirror/features/missions-activity/feature.tsx +19 -0
  1312. package/packages/daemon/src/tui/mirror/features/missions-activity/session.ts +470 -0
  1313. package/packages/daemon/src/tui/mirror/features/palette/contract.ts +121 -0
  1314. package/packages/daemon/src/tui/mirror/features/palette/feature.ts +14 -0
  1315. package/packages/daemon/src/tui/mirror/features/palette/session.ts +427 -0
  1316. package/packages/daemon/src/tui/mirror/features/palette/surface.tsx +92 -0
  1317. package/packages/daemon/src/tui/mirror/features/performance-hud/contract.ts +20 -0
  1318. package/packages/daemon/src/tui/mirror/features/performance-hud/feature.tsx +8 -0
  1319. package/packages/daemon/src/tui/mirror/features/performance-hud/session.ts +152 -0
  1320. package/packages/daemon/src/tui/mirror/features/performance-hud/surface.tsx +137 -0
  1321. package/packages/daemon/src/tui/mirror/features/rich-preview/asset-loader.ts +153 -0
  1322. package/packages/daemon/src/tui/mirror/features/rich-preview/contract.ts +94 -0
  1323. package/packages/daemon/src/tui/mirror/features/rich-preview/feature.tsx +141 -0
  1324. package/packages/daemon/src/tui/mirror/features/rich-preview/session.ts +387 -0
  1325. package/packages/daemon/src/tui/mirror/features/settings/catalog.ts +26 -0
  1326. package/packages/daemon/src/tui/mirror/features/settings/contract.ts +41 -0
  1327. package/packages/daemon/src/tui/mirror/features/settings/feature.ts +3 -0
  1328. package/packages/daemon/src/tui/mirror/features/settings/session.ts +375 -0
  1329. package/packages/daemon/src/tui/mirror/file-tree.ts +231 -6
  1330. package/packages/daemon/src/tui/mirror/files-surface-view.tsx +242 -0
  1331. package/packages/daemon/src/tui/mirror/files-surface.ts +371 -0
  1332. package/packages/daemon/src/tui/mirror/focus-projection.ts +113 -0
  1333. package/packages/daemon/src/tui/mirror/frame-coalescer.ts +87 -0
  1334. package/packages/daemon/src/tui/mirror/home-model.ts +1 -1
  1335. package/packages/daemon/src/tui/mirror/home-surface-model.ts +440 -0
  1336. package/packages/daemon/src/tui/mirror/home-surface.tsx +254 -0
  1337. package/packages/daemon/src/tui/mirror/host-terminal.ts +49 -0
  1338. package/packages/daemon/src/tui/mirror/hosted.ts +286 -0
  1339. package/packages/daemon/src/tui/mirror/input-lifecycle.ts +248 -0
  1340. package/packages/daemon/src/tui/mirror/interaction-flow.ts +83 -0
  1341. package/packages/daemon/src/tui/mirror/legacy/missions-workspace-loader.ts +117 -0
  1342. package/packages/daemon/src/tui/mirror/menu-model.ts +28 -18
  1343. package/packages/daemon/src/tui/mirror/missions-dashboard.ts +451 -0
  1344. package/packages/daemon/src/tui/mirror/missions-render-fixtures.ts +371 -0
  1345. package/packages/daemon/src/tui/mirror/missions-surface-controller.ts +530 -0
  1346. package/packages/daemon/src/tui/mirror/missions-surface.tsx +434 -0
  1347. package/packages/daemon/src/tui/mirror/missions-workspace.ts +1996 -0
  1348. package/packages/daemon/src/tui/mirror/multiplexer-action-executor.ts +379 -0
  1349. package/packages/daemon/src/tui/mirror/open-tui-pane-stream-socket.ts +47 -0
  1350. package/packages/daemon/src/tui/mirror/open-tui-verified-routing.ts +83 -0
  1351. package/packages/daemon/src/tui/mirror/open-tui-workspace-runtime-port.ts +1314 -0
  1352. package/packages/daemon/src/tui/mirror/palette-surface-adapter.ts +465 -0
  1353. package/packages/daemon/src/tui/mirror/palette.ts +485 -34
  1354. package/packages/daemon/src/tui/mirror/pane-frame-state.ts +209 -0
  1355. package/packages/daemon/src/tui/mirror/pane-mirror.ts +215 -50
  1356. package/packages/daemon/src/tui/mirror/pane-surface.tsx +720 -51
  1357. package/packages/daemon/src/tui/mirror/panel-host-reactive.ts +17 -0
  1358. package/packages/daemon/src/tui/mirror/panel-host.ts +384 -0
  1359. package/packages/daemon/src/tui/mirror/perf-tap.ts +1 -122
  1360. package/packages/daemon/src/tui/mirror/performance-events.ts +488 -0
  1361. package/packages/daemon/src/tui/mirror/recipe-components.tsx +310 -0
  1362. package/packages/daemon/src/tui/mirror/recipes-gallery.tsx +256 -0
  1363. package/packages/daemon/src/tui/mirror/recipes.ts +543 -0
  1364. package/packages/daemon/src/tui/mirror/reference-performance-trace.ts +726 -0
  1365. package/packages/daemon/src/tui/mirror/renderer-commands.ts +344 -0
  1366. package/packages/daemon/src/tui/mirror/resize-model.ts +74 -9
  1367. package/packages/daemon/src/tui/mirror/resize-transaction.ts +342 -0
  1368. package/packages/daemon/src/tui/mirror/rich-placement-projection.ts +173 -0
  1369. package/packages/daemon/src/tui/mirror/runtime/__snapshots__/application-shell-view-renderer.test.tsx.snap +87 -0
  1370. package/packages/daemon/src/tui/mirror/runtime/application-appearance-owner.ts +121 -0
  1371. package/packages/daemon/src/tui/mirror/runtime/application-bootstrap.ts +118 -0
  1372. package/packages/daemon/src/tui/mirror/runtime/application-entry.ts +194 -0
  1373. package/packages/daemon/src/tui/mirror/runtime/application-generation-starter.ts +116 -0
  1374. package/packages/daemon/src/tui/mirror/runtime/application-home-catalog-owner.ts +112 -0
  1375. package/packages/daemon/src/tui/mirror/runtime/application-home-catalog.ts +440 -0
  1376. package/packages/daemon/src/tui/mirror/runtime/application-host-focus-control-binding.ts +143 -0
  1377. package/packages/daemon/src/tui/mirror/runtime/application-host-focus-control-capability.ts +46 -0
  1378. package/packages/daemon/src/tui/mirror/runtime/application-host-focus-presentation.ts +176 -0
  1379. package/packages/daemon/src/tui/mirror/runtime/application-host-focus-test-control.ts +313 -0
  1380. package/packages/daemon/src/tui/mirror/runtime/application-input-readiness.ts +28 -0
  1381. package/packages/daemon/src/tui/mirror/runtime/application-lifecycle.ts +374 -0
  1382. package/packages/daemon/src/tui/mirror/runtime/application-optional-features.ts +25 -0
  1383. package/packages/daemon/src/tui/mirror/runtime/application-palette-command-owner.ts +87 -0
  1384. package/packages/daemon/src/tui/mirror/runtime/application-palette-input.ts +105 -0
  1385. package/packages/daemon/src/tui/mirror/runtime/application-pane-rename-input.ts +43 -0
  1386. package/packages/daemon/src/tui/mirror/runtime/application-pane-rename-owner.ts +43 -0
  1387. package/packages/daemon/src/tui/mirror/runtime/application-pending-terminal-input.ts +117 -0
  1388. package/packages/daemon/src/tui/mirror/runtime/application-performance-log.ts +110 -0
  1389. package/packages/daemon/src/tui/mirror/runtime/application-post-render-runtime.ts +163 -0
  1390. package/packages/daemon/src/tui/mirror/runtime/application-root-configuration.ts +47 -0
  1391. package/packages/daemon/src/tui/mirror/runtime/application-root-renderer.ts +32 -0
  1392. package/packages/daemon/src/tui/mirror/runtime/application-root-v2.tsx +506 -0
  1393. package/packages/daemon/src/tui/mirror/runtime/application-session-focus-owner.ts +80 -0
  1394. package/packages/daemon/src/tui/mirror/runtime/application-shell-binding.ts +365 -0
  1395. package/packages/daemon/src/tui/mirror/runtime/application-shell-catalog.tsx +372 -0
  1396. package/packages/daemon/src/tui/mirror/runtime/application-shell-home.tsx +161 -0
  1397. package/packages/daemon/src/tui/mirror/runtime/application-shell-overlay-stack.tsx +42 -0
  1398. package/packages/daemon/src/tui/mirror/runtime/application-shell-overlays.tsx +154 -0
  1399. package/packages/daemon/src/tui/mirror/runtime/application-shell-sidebar.tsx +140 -0
  1400. package/packages/daemon/src/tui/mirror/runtime/application-shell-view.tsx +425 -0
  1401. package/packages/daemon/src/tui/mirror/runtime/application-shell-viewport.ts +18 -0
  1402. package/packages/daemon/src/tui/mirror/runtime/application-terminal-frame-readiness-owner.ts +33 -0
  1403. package/packages/daemon/src/tui/mirror/runtime/application-terminal-host-focus-owner.ts +36 -0
  1404. package/packages/daemon/src/tui/mirror/runtime/application-terminal-input-ingress.ts +133 -0
  1405. package/packages/daemon/src/tui/mirror/runtime/application-terminal-interaction-controller.ts +1630 -0
  1406. package/packages/daemon/src/tui/mirror/runtime/application-terminal-palette-owner.ts +302 -0
  1407. package/packages/daemon/src/tui/mirror/runtime/application-terminal-paste.ts +33 -0
  1408. package/packages/daemon/src/tui/mirror/runtime/application-terminal-renderer-sources.ts +33 -0
  1409. package/packages/daemon/src/tui/mirror/runtime/application-terminal-selection-owner.ts +218 -0
  1410. package/packages/daemon/src/tui/mirror/runtime/application-terminal-workspace-policy.ts +285 -0
  1411. package/packages/daemon/src/tui/mirror/runtime/application-terminal-workspace.tsx +1150 -0
  1412. package/packages/daemon/src/tui/mirror/runtime/application-theme-repaint.ts +45 -0
  1413. package/packages/daemon/src/tui/mirror/runtime/application-transient-note-owner.ts +42 -0
  1414. package/packages/daemon/src/tui/mirror/runtime/bounded-performance-record-writer.ts +75 -0
  1415. package/packages/daemon/src/tui/mirror/runtime/causal-cell-client-ledger.ts +394 -0
  1416. package/packages/daemon/src/tui/mirror/runtime/causal-cell-input-fixture.ts +55 -0
  1417. package/packages/daemon/src/tui/mirror/runtime/changes-deferred-identity.ts +34 -0
  1418. package/packages/daemon/src/tui/mirror/runtime/daemon-authority-rebind.ts +163 -0
  1419. package/packages/daemon/src/tui/mirror/runtime/deferred-intent-queue.ts +45 -0
  1420. package/packages/daemon/src/tui/mirror/runtime/editor-primitives.ts +56 -0
  1421. package/packages/daemon/src/tui/mirror/runtime/file-content-primitives.ts +8 -0
  1422. package/packages/daemon/src/tui/mirror/runtime/fleet-lifecycle-client.ts +61 -0
  1423. package/packages/daemon/src/tui/mirror/runtime/focus-framebuffer-projection.ts +71 -0
  1424. package/packages/daemon/src/tui/mirror/runtime/generation-bound-slot.ts +23 -0
  1425. package/packages/daemon/src/tui/mirror/runtime/host-local-tmux-adapter.ts +105 -0
  1426. package/packages/daemon/src/tui/mirror/runtime/hosted-tty-size-bridge.ts +213 -0
  1427. package/packages/daemon/src/tui/mirror/runtime/latest-intent-fence.ts +22 -0
  1428. package/packages/daemon/src/tui/mirror/runtime/local-view-controller.ts +95 -0
  1429. package/packages/daemon/src/tui/mirror/runtime/modal-admission-coordinator.ts +158 -0
  1430. package/packages/daemon/src/tui/mirror/runtime/modal-pointer-capture.ts +23 -0
  1431. package/packages/daemon/src/tui/mirror/runtime/open-tui-generation-host.ts +996 -0
  1432. package/packages/daemon/src/tui/mirror/runtime/open-tui-session-owner.ts +195 -0
  1433. package/packages/daemon/src/tui/mirror/runtime/optional-feature-registry.ts +234 -0
  1434. package/packages/daemon/src/tui/mirror/runtime/optional-feature-registry.typecheck.ts +14 -0
  1435. package/packages/daemon/src/tui/mirror/runtime/palette-production-controller.ts +170 -0
  1436. package/packages/daemon/src/tui/mirror/runtime/palette-production-overlay.tsx +65 -0
  1437. package/packages/daemon/src/tui/mirror/runtime/pane-resize-geometry.ts +22 -0
  1438. package/packages/daemon/src/tui/mirror/runtime/pane-scoped-terminal-surface.tsx +146 -0
  1439. package/packages/daemon/src/tui/mirror/runtime/product-surface-policy.ts +16 -0
  1440. package/packages/daemon/src/tui/mirror/runtime/renderer-cadence.ts +4 -0
  1441. package/packages/daemon/src/tui/mirror/runtime/resize-terminal-pane.ts +134 -0
  1442. package/packages/daemon/src/tui/mirror/runtime/rich-preview-demand.ts +26 -0
  1443. package/packages/daemon/src/tui/mirror/runtime/rich-preview-overlay.tsx +54 -0
  1444. package/packages/daemon/src/tui/mirror/runtime/runtime-layout-presentation.ts +119 -0
  1445. package/packages/daemon/src/tui/mirror/runtime/select-terminal-pane.ts +127 -0
  1446. package/packages/daemon/src/tui/mirror/runtime/semantic-pane-publication.ts +26 -0
  1447. package/packages/daemon/src/tui/mirror/runtime/semantic-shell-viewport-resize.ts +78 -0
  1448. package/packages/daemon/src/tui/mirror/runtime/terminal-dimensions-owner.ts +20 -0
  1449. package/packages/daemon/src/tui/mirror/runtime/terminal-fast-lane-renderer-adapter.ts +719 -0
  1450. package/packages/daemon/src/tui/mirror/runtime/terminal-frame-readiness.ts +100 -0
  1451. package/packages/daemon/src/tui/mirror/runtime/terminal-host-focus.ts +519 -0
  1452. package/packages/daemon/src/tui/mirror/runtime/terminal-host-frame-diagnostics.ts +47 -0
  1453. package/packages/daemon/src/tui/mirror/runtime/terminal-input-adapter.ts +69 -0
  1454. package/packages/daemon/src/tui/mirror/runtime/terminal-layout-projection.ts +45 -0
  1455. package/packages/daemon/src/tui/mirror/runtime/terminal-pane-input-router.ts +94 -0
  1456. package/packages/daemon/src/tui/mirror/runtime/terminal-selection.ts +218 -0
  1457. package/packages/daemon/src/tui/mirror/runtime/terminal-session-handoff.ts +143 -0
  1458. package/packages/daemon/src/tui/mirror/runtime/terminal-tool-readiness.ts +72 -0
  1459. package/packages/daemon/src/tui/mirror/runtime/tool-resource-controller.ts +799 -0
  1460. package/packages/daemon/src/tui/mirror/runtime/tool-resource-projection.ts +223 -0
  1461. package/packages/daemon/src/tui/mirror/runtime/viewport-fit-coordinator.ts +12 -0
  1462. package/packages/daemon/src/tui/mirror/runtime/workspace-terminal-fast-lane.ts +597 -0
  1463. package/packages/daemon/src/tui/mirror/selection.ts +122 -29
  1464. package/packages/daemon/src/tui/mirror/semantic-pane-render-source.ts +767 -0
  1465. package/packages/daemon/src/tui/mirror/semantic-session-view.ts +366 -0
  1466. package/packages/daemon/src/tui/mirror/settings-model.ts +95 -57
  1467. package/packages/daemon/src/tui/mirror/shell-chrome-view.tsx +346 -0
  1468. package/packages/daemon/src/tui/mirror/shell-chrome.ts +508 -0
  1469. package/packages/daemon/src/tui/mirror/sidebar.tsx +321 -0
  1470. package/packages/daemon/src/tui/mirror/size-truth.ts +53 -0
  1471. package/packages/daemon/src/tui/mirror/terminal-surface.ts +157 -0
  1472. package/packages/daemon/src/tui/mirror/terminal-surface.tsx +84 -0
  1473. package/packages/daemon/src/tui/mirror/terminal-text.ts +42 -0
  1474. package/packages/daemon/src/tui/mirror/theme.ts +1059 -0
  1475. package/packages/daemon/src/tui/mirror/ui/agent-badge.tsx +41 -0
  1476. package/packages/daemon/src/tui/mirror/ui/badge.tsx +42 -0
  1477. package/packages/daemon/src/tui/mirror/ui/button.tsx +127 -0
  1478. package/packages/daemon/src/tui/mirror/ui/dialog.tsx +45 -0
  1479. package/packages/daemon/src/tui/mirror/ui/index.ts +59 -0
  1480. package/packages/daemon/src/tui/mirror/ui/key-hint.tsx +63 -0
  1481. package/packages/daemon/src/tui/mirror/ui/keyboard-router.tsx +72 -0
  1482. package/packages/daemon/src/tui/mirror/ui/menu.tsx +68 -0
  1483. package/packages/daemon/src/tui/mirror/ui/navigation-row.tsx +114 -0
  1484. package/packages/daemon/src/tui/mirror/ui/overlay-frame.tsx +115 -0
  1485. package/packages/daemon/src/tui/mirror/ui/overlay-host.tsx +71 -0
  1486. package/packages/daemon/src/tui/mirror/ui/overlay-list-row.tsx +59 -0
  1487. package/packages/daemon/src/tui/mirror/ui/overlay-model.ts +75 -0
  1488. package/packages/daemon/src/tui/mirror/ui/state.ts +218 -0
  1489. package/packages/daemon/src/tui/mirror/ui/status-bar.tsx +208 -0
  1490. package/packages/daemon/src/tui/mirror/ui/surface.tsx +71 -0
  1491. package/packages/daemon/src/tui/mirror/ui/tabs.tsx +168 -0
  1492. package/packages/daemon/src/tui/mirror/widget-fallback.ts +66 -0
  1493. package/packages/daemon/src/tui/mirror/widget-surface-model.ts +170 -0
  1494. package/packages/daemon/src/tui/mirror/widget-surface.tsx +79 -0
  1495. package/packages/daemon/src/tui/mirror/workspace/README.md +79 -0
  1496. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/agent-terminal-canvas-renderer.test.tsx.snap +348 -0
  1497. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/application-shell-renderer.test.tsx.snap +134 -0
  1498. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/command-palette-surface-renderer.test.tsx.snap +255 -0
  1499. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/pane-frame-renderer.test.tsx.snap +525 -0
  1500. package/packages/daemon/src/tui/mirror/workspace/__snapshots__/workbench-shell-renderer.test.tsx.snap +134 -0
  1501. package/packages/daemon/src/tui/mirror/workspace/agent-terminal-canvas-view.tsx +61 -0
  1502. package/packages/daemon/src/tui/mirror/workspace/agent-terminal-canvas.ts +131 -0
  1503. package/packages/daemon/src/tui/mirror/workspace/application-root-controller.ts +169 -0
  1504. package/packages/daemon/src/tui/mirror/workspace/application-shell-controller.ts +430 -0
  1505. package/packages/daemon/src/tui/mirror/workspace/application-shell-surface-commands.ts +64 -0
  1506. package/packages/daemon/src/tui/mirror/workspace/application-shell-view.tsx +169 -0
  1507. package/packages/daemon/src/tui/mirror/workspace/application-shell.ts +179 -0
  1508. package/packages/daemon/src/tui/mirror/workspace/command-palette-surface-view.tsx +356 -0
  1509. package/packages/daemon/src/tui/mirror/workspace/command-palette-surface.ts +544 -0
  1510. package/packages/daemon/src/tui/mirror/workspace/icons.ts +56 -0
  1511. package/packages/daemon/src/tui/mirror/workspace/pane-action-menu.tsx +68 -0
  1512. package/packages/daemon/src/tui/mirror/workspace/pane-frame.ts +675 -0
  1513. package/packages/daemon/src/tui/mirror/workspace/pane-frame.tsx +490 -0
  1514. package/packages/daemon/src/tui/mirror/workspace/terminal-pane-chrome-view.tsx +125 -0
  1515. package/packages/daemon/src/tui/mirror/workspace/terminal-pane-chrome.ts +833 -0
  1516. package/packages/daemon/src/tui/mirror/workspace/terminal-pane-header.tsx +225 -0
  1517. package/packages/daemon/src/tui/mirror/workspace/terminal-window-strip.tsx +466 -0
  1518. package/packages/daemon/src/tui/mirror/workspace/text.ts +28 -0
  1519. package/packages/daemon/src/tui/mirror/workspace/workbench-controller.ts +75 -0
  1520. package/packages/daemon/src/tui/mirror/workspace/workbench-dock-opentui.tsx +224 -0
  1521. package/packages/daemon/src/tui/mirror/workspace/workbench-shell.ts +486 -0
  1522. package/packages/daemon/src/tui/mirror/workspace/workbench-shell.tsx +95 -0
  1523. package/packages/daemon/src/tui/mirror/workspace-ui-state.ts +1278 -0
  1524. package/packages/daemon/src/tui/readiness.ts +52 -0
  1525. package/packages/daemon/src/tui/team/entry.ts +23 -13
  1526. package/packages/daemon/src/tui/team/fuzzy.ts +20 -0
  1527. package/packages/daemon/src/tui/team/home.ts +1 -1
  1528. package/packages/daemon/src/tui/team/index.tsx +27 -8
  1529. package/packages/daemon/src/tui/team/projects.ts +12 -0
  1530. package/packages/daemon/src/tui/team/sessions.ts +119 -46
  1531. package/packages/daemon/src/tui/team/wait-receipts.ts +192 -0
  1532. package/packages/daemon/src/tui/team/wait.ts +144 -0
  1533. package/packages/daemon/src/ui/pane-frame/fixture.ts +43 -0
  1534. package/packages/daemon/src/ui/workbench-dock/fixture.ts +61 -0
  1535. package/packages/daemon/src/validate.ts +21 -9
  1536. package/packages/daemon/src/widgets/config/README.md +1 -1
  1537. package/packages/daemon/src/widgets/config/index.tsx +15 -115
  1538. package/packages/daemon/src/widgets/lib/watcher.ts +3 -130
  1539. package/packages/daemon/src/widgets/resolve.ts +15 -7
  1540. package/packages/daemon/src/widgets/setup/footer.tsx +0 -7
  1541. package/packages/daemon/src/widgets/setup/index.tsx +18 -20
  1542. package/packages/daemon/src/widgets/setup/review-panel.tsx +15 -10
  1543. package/packages/daemon/src/widgets/setup/setup-model.ts +7 -10
  1544. package/packages/daemon-client/package.json +42 -0
  1545. package/packages/daemon-client/src/application-shell-session.test.ts +196 -0
  1546. package/packages/daemon-client/src/application-shell-session.ts +450 -0
  1547. package/packages/daemon-client/src/bootstrap-coordinator.test.ts +122 -0
  1548. package/packages/daemon-client/src/bootstrap-coordinator.ts +293 -0
  1549. package/packages/daemon-client/src/connection-supervisor.test.ts +109 -0
  1550. package/packages/daemon-client/src/connection-supervisor.ts +216 -0
  1551. package/packages/daemon-client/src/direct-application-shell-transport.test.ts +939 -0
  1552. package/packages/daemon-client/src/direct-application-shell-transport.ts +1144 -0
  1553. package/packages/daemon-client/src/first-latest-coordinator.test.ts +175 -0
  1554. package/packages/daemon-client/src/first-latest-coordinator.ts +82 -0
  1555. package/packages/daemon-client/src/generation-bound-store-timers.test.ts +74 -0
  1556. package/packages/daemon-client/src/generation-bound-store.ts +908 -0
  1557. package/packages/daemon-client/src/index.ts +25 -0
  1558. package/packages/daemon-client/src/owner-action-client.test.ts +180 -0
  1559. package/packages/daemon-client/src/owner-action-client.ts +113 -0
  1560. package/packages/daemon-client/src/pane-stream-client.test.ts +2754 -0
  1561. package/packages/daemon-client/src/pane-stream-client.ts +1665 -0
  1562. package/packages/daemon-client/src/pane-stream-clock-calibration.test.ts +207 -0
  1563. package/packages/daemon-client/src/pane-stream-clock-calibration.ts +161 -0
  1564. package/packages/daemon-client/src/pane-stream-loopback-benchmark.test.ts +51 -0
  1565. package/packages/daemon-client/src/push-resource-session.test.ts +509 -0
  1566. package/packages/daemon-client/src/push-resource-session.ts +797 -0
  1567. package/packages/daemon-client/src/resource-replica.test.ts +186 -0
  1568. package/packages/daemon-client/src/resource-replica.ts +280 -0
  1569. package/packages/daemon-client/src/runtime-resource-ledger.test.ts +18 -0
  1570. package/packages/daemon-client/src/runtime-resource-ledger.ts +69 -0
  1571. package/packages/daemon-client/src/terminal-fast-lane.test.ts +817 -0
  1572. package/packages/daemon-client/src/terminal-fast-lane.ts +817 -0
  1573. package/packages/daemon-client/src/terminal-fast-lane.typecheck.ts +16 -0
  1574. package/packages/daemon-client/src/workspace-catalog-v2.test.ts +109 -0
  1575. package/packages/daemon-client/src/workspace-catalog-v2.ts +66 -0
  1576. package/packages/daemon-client/src/workspace-client-boundaries.test.ts +59 -0
  1577. package/packages/daemon-client/src/workspace-client-conformance.ts +67 -0
  1578. package/packages/daemon-client/src/workspace-client-operations.ts +203 -0
  1579. package/packages/daemon-client/src/workspace-client-types.ts +302 -0
  1580. package/packages/daemon-client/src/workspace-client.test.ts +2626 -0
  1581. package/packages/daemon-client/src/workspace-client.ts +1421 -0
  1582. package/packages/daemon-client/src/workspace-event-supervisor.test.ts +1086 -0
  1583. package/packages/daemon-client/src/workspace-event-supervisor.ts +719 -0
  1584. package/packages/daemon-client/src/workspace-pane-client.test.ts +80 -0
  1585. package/packages/daemon-client/src/workspace-pane-client.ts +63 -0
  1586. package/packages/presentation/package.json +28 -0
  1587. package/packages/presentation/src/index.ts +2 -0
  1588. package/packages/presentation/src/pane-frame/action-state.ts +72 -0
  1589. package/packages/presentation/src/pane-frame/index.ts +3 -0
  1590. package/packages/presentation/src/pane-frame/model.ts +517 -0
  1591. package/packages/presentation/src/pane-frame/presenter.tsx +335 -0
  1592. package/packages/presentation/src/pane-frame/web-entry.tsx +22 -0
  1593. package/packages/presentation/src/pane-frame/web-host-unstyled.tsx +280 -0
  1594. package/packages/presentation/src/pane-frame/web-host.css +388 -0
  1595. package/packages/presentation/src/pane-frame/web-host.tsx +3 -0
  1596. package/packages/presentation/src/presentation-contract.test.ts +63 -0
  1597. package/packages/presentation/src/workbench-dock/index.ts +2 -0
  1598. package/packages/presentation/src/workbench-dock/navigation.ts +54 -0
  1599. package/packages/presentation/src/workbench-dock/presenter.tsx +252 -0
  1600. package/packages/presentation/src/workbench-dock/web-entry.tsx +19 -0
  1601. package/packages/presentation/src/workbench-dock/web-host-unstyled.tsx +198 -0
  1602. package/packages/presentation/src/workbench-dock/web-host.css +204 -0
  1603. package/packages/presentation/src/workbench-dock/web-host.tsx +3 -0
  1604. package/packages/tmux-bridge/src/index.ts +9 -1
  1605. package/packages/tmux-bridge/src/panes.ts +4 -0
  1606. package/packages/tmux-bridge/src/runner.test.ts +72 -0
  1607. package/packages/tmux-bridge/src/runner.ts +43 -2
  1608. package/packages/tmux-bridge/src/sessions.ts +8 -1
  1609. package/scripts/architecture-debt-budget.json +10 -0
  1610. package/scripts/architecture-debt-inventory.mjs +98 -0
  1611. package/scripts/build-cli.mjs +22 -1
  1612. package/scripts/build-macos-notifier.mjs +160 -0
  1613. package/scripts/build-tui.mjs +59 -3
  1614. package/scripts/check-control-bytes.mjs +70 -0
  1615. package/scripts/dev-web.mjs +66 -0
  1616. package/scripts/lib/bounded-child-command.mjs +59 -0
  1617. package/scripts/lib/bounded-child-command.test.mjs +148 -0
  1618. package/scripts/lib/bounded-diagnostic-tail.mjs +82 -0
  1619. package/scripts/lib/bounded-diagnostic-tail.test.mjs +97 -0
  1620. package/scripts/lib/npm-release-tag.mjs +27 -0
  1621. package/scripts/lib/npm-release-tag.test.mjs +116 -0
  1622. package/scripts/lib/packed-opentui-frame.mjs +18 -0
  1623. package/scripts/lib/packed-opentui-frame.test.mjs +40 -0
  1624. package/scripts/lib/performance-reference-budgets.mjs +36 -0
  1625. package/scripts/lib/performance-reference-report.mjs +157 -0
  1626. package/scripts/lib/performance-reference-report.test.mjs +62 -0
  1627. package/scripts/lib/portable-performance-evidence.mjs +210 -0
  1628. package/scripts/lib/portable-performance-evidence.test.mjs +208 -0
  1629. package/scripts/lib/product-ansi-cursor-alt-screen-fixture.mjs +132 -0
  1630. package/scripts/lib/product-ansi-cursor-alt-screen.mjs +4618 -0
  1631. package/scripts/lib/product-ansi-cursor-alt-screen.test.mjs +4120 -0
  1632. package/scripts/lib/product-ansi-tmux-precondition.mjs +159 -0
  1633. package/scripts/lib/product-ansi-tmux-precondition.test.mjs +147 -0
  1634. package/scripts/lib/product-card5-host-topology.mjs +873 -0
  1635. package/scripts/lib/product-card5-host-topology.test.mjs +1070 -0
  1636. package/scripts/lib/product-card5-production-host-owner.mjs +4864 -0
  1637. package/scripts/lib/product-card5-production-host-owner.test.mjs +5051 -0
  1638. package/scripts/lib/product-configless-owner.mjs +1578 -0
  1639. package/scripts/lib/product-configless-owner.test.mjs +2169 -0
  1640. package/scripts/lib/product-cross-client-handoff.mjs +1165 -0
  1641. package/scripts/lib/product-cross-client-handoff.test.mjs +1062 -0
  1642. package/scripts/lib/product-cross-client-host-evidence.mjs +4780 -0
  1643. package/scripts/lib/product-cross-client-host-evidence.test.mjs +3897 -0
  1644. package/scripts/lib/product-first-input.mjs +1546 -0
  1645. package/scripts/lib/product-first-input.test.mjs +1731 -0
  1646. package/scripts/lib/product-focus-tmux.mjs +46 -0
  1647. package/scripts/lib/product-focus.mjs +1198 -0
  1648. package/scripts/lib/product-focus.test.mjs +1504 -0
  1649. package/scripts/lib/product-idle-process-proof.mjs +270 -0
  1650. package/scripts/lib/product-idle-process-proof.test.mjs +210 -0
  1651. package/scripts/lib/product-keyboard-pointer-resize.mjs +471 -0
  1652. package/scripts/lib/product-keyboard-pointer-resize.test.mjs +363 -0
  1653. package/scripts/lib/product-rig-causal-cell-fixture.mjs +91 -0
  1654. package/scripts/lib/product-rig-causal-fixture-geometry.mjs +27 -0
  1655. package/scripts/lib/product-rig-causal-fixture-geometry.test.mjs +45 -0
  1656. package/scripts/lib/product-rig-sleep-assertion.mjs +179 -0
  1657. package/scripts/lib/product-selection-copy-app-mouse.mjs +1585 -0
  1658. package/scripts/lib/product-selection-copy-app-mouse.test.mjs +1602 -0
  1659. package/scripts/lib/product-tui-host-readiness.mjs +133 -0
  1660. package/scripts/lib/product-tui-host-readiness.test.mjs +258 -0
  1661. package/scripts/lib/product-window-lifecycle.mjs +1351 -0
  1662. package/scripts/lib/product-window-lifecycle.test.mjs +1305 -0
  1663. package/scripts/lib/release-source-state.mjs +28 -0
  1664. package/scripts/lib/release-source-state.test.mjs +26 -0
  1665. package/scripts/lib/tui-diagnostics.mjs +159 -0
  1666. package/scripts/lib/tui-host-publication.mjs +38 -0
  1667. package/scripts/lib/tui-testdrive-clipboard-hook.mjs +543 -0
  1668. package/scripts/lib/tui-testdrive-clipboard-hook.test.mjs +626 -0
  1669. package/scripts/lib/tui-testdrive-input.mjs +1940 -0
  1670. package/scripts/lib/tui-testdrive-input.test.mjs +3434 -0
  1671. package/scripts/lib/tui-testdrive-launch.mjs +180 -0
  1672. package/scripts/lib/tui-testdrive-launch.test.mjs +294 -0
  1673. package/scripts/opentui-release-check.mjs +209 -0
  1674. package/scripts/pack-check-run.mjs +1779 -30
  1675. package/scripts/pack-tui-check.mjs +73 -0
  1676. package/scripts/pack-web-check.mjs +19 -0
  1677. package/scripts/performance-portable-evidence.mjs +419 -0
  1678. package/scripts/performance-qualification.mjs +456 -0
  1679. package/scripts/performance-reference-memory.ts +177 -0
  1680. package/scripts/performance-reference-pane-stream.ts +74 -0
  1681. package/scripts/performance-reference.mjs +681 -0
  1682. package/scripts/postinstall.js +14 -6
  1683. package/scripts/prepublish-check.mjs +37 -1
  1684. package/scripts/prepublish-opentui-check.mjs +24 -0
  1685. package/scripts/product-test-rig-journeys.mjs +2700 -0
  1686. package/scripts/product-test-rig-journeys.test.mjs +3959 -0
  1687. package/scripts/product-test-rig-lib.mjs +2359 -0
  1688. package/scripts/product-test-rig-multiclient.ts +434 -0
  1689. package/scripts/product-test-rig-native-client.mjs +45 -0
  1690. package/scripts/product-test-rig.mjs +20260 -0
  1691. package/scripts/product-test-rig.test.mjs +3634 -0
  1692. package/scripts/publish-tap.sh +55 -0
  1693. package/scripts/smoke-tui-missions.mjs +329 -0
  1694. package/scripts/tui-diagnose.mjs +258 -0
  1695. package/scripts/tui-diagnose.test.mjs +200 -0
  1696. package/scripts/tui-testdrive-capture.test.mjs +161 -0
  1697. package/scripts/tui-testdrive.mjs +1955 -0
  1698. package/skill/SKILL.md +115 -30
  1699. package/templates/agent-team-monorepo.yml +28 -30
  1700. package/templates/agent-team-nextjs.yml +24 -26
  1701. package/templates/agent-team.yml +24 -24
  1702. package/templates/convex.yml +24 -16
  1703. package/templates/default.yml +26 -21
  1704. package/templates/go.yml +21 -14
  1705. package/templates/missions.yml +25 -40
  1706. package/templates/nextjs.yml +24 -16
  1707. package/templates/python.yml +21 -14
  1708. package/templates/vite.yml +21 -14
  1709. package/packages/daemon/dist/widgets/changes/index.jsx +0 -575
  1710. package/packages/daemon/dist/widgets/config/index.d.ts +0 -1
  1711. package/packages/daemon/dist/widgets/config/index.jsx +0 -395
  1712. package/packages/daemon/dist/widgets/explorer/breadcrumbs.d.ts +0 -10
  1713. package/packages/daemon/dist/widgets/explorer/breadcrumbs.jsx +0 -51
  1714. package/packages/daemon/dist/widgets/explorer/footer.d.ts +0 -6
  1715. package/packages/daemon/dist/widgets/explorer/footer.jsx +0 -11
  1716. package/packages/daemon/dist/widgets/explorer/index.jsx +0 -393
  1717. package/packages/daemon/dist/widgets/explorer/tree.d.ts +0 -13
  1718. package/packages/daemon/dist/widgets/explorer/tree.jsx +0 -108
  1719. package/packages/daemon/dist/widgets/lib/help-overlay.d.ts +0 -19
  1720. package/packages/daemon/dist/widgets/lib/help-overlay.jsx +0 -69
  1721. package/packages/daemon/dist/widgets/preview/index.jsx +0 -371
  1722. package/packages/daemon/dist/widgets/setup/agent-naming.d.ts +0 -9
  1723. package/packages/daemon/dist/widgets/setup/agent-naming.jsx +0 -81
  1724. package/packages/daemon/dist/widgets/setup/config-tree.d.ts +0 -13
  1725. package/packages/daemon/dist/widgets/setup/config-tree.jsx +0 -203
  1726. package/packages/daemon/dist/widgets/setup/detect-panel.d.ts +0 -14
  1727. package/packages/daemon/dist/widgets/setup/detect-panel.jsx +0 -48
  1728. package/packages/daemon/dist/widgets/setup/field-editor.d.ts +0 -12
  1729. package/packages/daemon/dist/widgets/setup/field-editor.jsx +0 -163
  1730. package/packages/daemon/dist/widgets/setup/footer.d.ts +0 -17
  1731. package/packages/daemon/dist/widgets/setup/footer.jsx +0 -64
  1732. package/packages/daemon/dist/widgets/setup/index.d.ts +0 -1
  1733. package/packages/daemon/dist/widgets/setup/index.jsx +0 -261
  1734. package/packages/daemon/dist/widgets/setup/layout-picker.d.ts +0 -9
  1735. package/packages/daemon/dist/widgets/setup/layout-picker.jsx +0 -69
  1736. package/packages/daemon/dist/widgets/sidebar/index.jsx +0 -462
  1737. package/packages/daemon/src/tui/mirror/control-client.ts +0 -214
  1738. package/packages/daemon/src/tui/mirror/focus-border.ts +0 -57
  1739. package/packages/daemon/src/tui/mirror/session-mirror.ts +0 -443
  1740. package/packages/daemon/src/widgets/setup/orchestrator-panel.tsx +0 -200
  1741. package/scripts/perf-mirror.mjs +0 -313
  1742. package/scripts/verify-endpoints.sh +0 -90
  1743. /package/packages/daemon/dist/{widgets/changes/index.d.ts → lib/__tests__/fixtures/workspace-state-writer.d.ts} +0 -0
  1744. /package/packages/daemon/dist/{widgets/explorer/index.d.ts → terminal/mirror/trusted-inventory.js} +0 -0
  1745. /package/packages/daemon/dist/{widgets/preview/index.d.ts → terminal/session-runtime/terminal-interpreter-backend.js} +0 -0
  1746. /package/packages/daemon/dist/{widgets/sidebar/index.d.ts → tui/mirror/features/changes/contract.js} +0 -0
@@ -0,0 +1,4864 @@
1
+ import { isAbsolute, resolve } from "node:path";
2
+ import { execFileSync } from "node:child_process";
3
+ import { createHmac } from "node:crypto";
4
+
5
+ import { card5ProductionHostTopology } from "./product-card5-host-topology.mjs";
6
+
7
+ const HASH = /^[0-9a-f]{64}$/u;
8
+ const DAEMON_INSTANCE_ID_PATTERN =
9
+ "(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)";
10
+ const DAEMON_INSTANCE_ID = new RegExp(`^${DAEMON_INSTANCE_ID_PATTERN}$`, "iu");
11
+ const TERMINAL_ATTACHMENT_PANE_ID_PATTERN = "[A-Za-z0-9][A-Za-z0-9._-]{0,127}";
12
+ const TERMINAL_ATTACHMENT_PANE_ID_RESERVED = Object.freeze([
13
+ "__proto__",
14
+ "prototype",
15
+ "constructor",
16
+ ]);
17
+ const TERMINAL_ATTACHMENT_PANE_ID_DISCOVERED_PREFIX = "terminal.discovered.";
18
+ const exactDaemonInstanceId = (value) =>
19
+ typeof value === "string" && value.length === 36 && DAEMON_INSTANCE_ID.test(value);
20
+ const CARD5_PROBE_QUERY = "tmuxIdeCard5Evidence";
21
+ const CARD5_ACTIVE_TERMINAL_PANEL = "#workspace-panel-terminals:not([hidden])";
22
+ const CARD5_MAX_READINESS_CANDIDATES = 64;
23
+ const CARD5_MAX_PAGE_EVENTS = 16;
24
+ const CARD5_READINESS_OBSERVATION_TIMEOUT_MS = 1_000;
25
+ const CARD5_INPUT_PRODUCT_PATH_RESERVE_MS = 4_000;
26
+ const CARD5_INPUT_PREFLIGHT_MARGIN_MS = 250;
27
+ const CLOSE_GRACE_MS = 2_000;
28
+ const CLOSE_TERM_MS = 500;
29
+ const qualifiedTerminalIdentities = new WeakMap();
30
+
31
+ const boundedInputGuardCount = (value, cap) =>
32
+ Number.isSafeInteger(value) && value >= 0 ? Math.min(value, cap) : null;
33
+
34
+ export function boundedCard5InputGuardAxes(
35
+ outcome,
36
+ { deadlineValid = false, settled = false } = {},
37
+ ) {
38
+ const beforeInputCount = boundedInputGuardCount(outcome?.beforeInputCount, 8);
39
+ const inputCount = boundedInputGuardCount(outcome?.inputCount, 8);
40
+ const eventCount = boundedInputGuardCount(outcome?.eventCount, 16);
41
+ const mutationCount = boundedInputGuardCount(outcome?.mutationCount, 64);
42
+ const exactBoolean = (value) => (typeof value === "boolean" ? value : null);
43
+ return Object.freeze({
44
+ beforeInputCount,
45
+ beforeInputCountOverflow:
46
+ Number.isSafeInteger(outcome?.beforeInputCount) && outcome.beforeInputCount > 8,
47
+ inputCount,
48
+ inputCountOverflow: Number.isSafeInteger(outcome?.inputCount) && outcome.inputCount > 8,
49
+ eventCount,
50
+ eventCountOverflow: Number.isSafeInteger(outcome?.eventCount) && outcome.eventCount > 16,
51
+ eventOverflow: exactBoolean(outcome?.eventOverflow),
52
+ mutationCount,
53
+ mutationCountOverflow:
54
+ Number.isSafeInteger(outcome?.mutationCount) && outcome.mutationCount > 64,
55
+ mutationOverflow: exactBoolean(outcome?.mutationOverflow),
56
+ trusted: exactBoolean(outcome?.trusted),
57
+ exactTarget: exactBoolean(outcome?.exactTarget),
58
+ exactData: exactBoolean(outcome?.exactData),
59
+ exactInputType: exactBoolean(outcome?.exactInputType),
60
+ cancelableBeforeInput: exactBoolean(outcome?.cancelableBeforeInput),
61
+ restorationExact: exactBoolean(outcome?.restorationExact),
62
+ rejected: exactBoolean(outcome?.rejected),
63
+ currentExact: exactBoolean(outcome?.exact),
64
+ deadlineValid: deadlineValid === true,
65
+ settled: settled === true,
66
+ });
67
+ }
68
+
69
+ export function card5InputGuardFailureReason(axes) {
70
+ if (axes?.inputCount !== 1) return "input-count-invalid";
71
+ if (axes.beforeInputCount !== 1) return "beforeinput-count-invalid";
72
+ if (axes.eventCount !== axes.inputCount + axes.beforeInputCount) return "event-count-invalid";
73
+ if (axes.eventOverflow !== false) return "event-overflow";
74
+ if (axes.mutationCount !== 0) return "mutation-count-invalid";
75
+ if (axes.mutationOverflow !== false) return "mutation-overflow";
76
+ if (axes.trusted !== true) return "event-untrusted";
77
+ if (axes.exactTarget !== true) return "event-target-invalid";
78
+ if (axes.exactData !== true) return "event-data-invalid";
79
+ if (axes.exactInputType !== true) return "event-input-type-invalid";
80
+ if (axes.cancelableBeforeInput !== true) return "beforeinput-not-cancelable";
81
+ if (axes.restorationExact !== true) return "restoration-invalid";
82
+ if (axes.rejected !== false) return "guard-rejected";
83
+ if (axes.currentExact !== true) return "guard-current-invalid";
84
+ return null;
85
+ }
86
+
87
+ export function boundedCard5PointerDispatchAxes(outcome) {
88
+ const count = (value, cap) =>
89
+ Number.isSafeInteger(value) && value >= 0 ? Math.min(value, cap) : null;
90
+ const bool = (value) => (typeof value === "boolean" ? value : null);
91
+ const mutationCategories = outcome?.mutationCategories ?? {};
92
+ return Object.freeze({
93
+ dispatched: bool(outcome?.dispatched),
94
+ trusted: bool(outcome?.trusted),
95
+ buttonExact: bool(outcome?.buttonExact),
96
+ pathExact: bool(outcome?.pathExact),
97
+ allowed: bool(outcome?.allowed),
98
+ rejected: bool(outcome?.rejected),
99
+ eventCount: count(outcome?.eventCount, 8),
100
+ eventOverflow: bool(outcome?.eventOverflow),
101
+ mutationCount: count(outcome?.mutationCount, 64),
102
+ mutationOverflow: bool(outcome?.mutationOverflow),
103
+ mutationCategories: Object.freeze({
104
+ identityNode: count(mutationCategories.identityNode, 64),
105
+ areaDescendant: count(mutationCategories.areaDescendant, 64),
106
+ terminalAttribute: count(mutationCategories.terminalAttribute, 64),
107
+ paneAttribute: count(mutationCategories.paneAttribute, 64),
108
+ childList: count(mutationCategories.childList, 64),
109
+ inspectionOverflow: count(mutationCategories.inspectionOverflow, 64),
110
+ }),
111
+ mutationTail: Object.freeze(
112
+ Array.isArray(outcome?.mutationTail)
113
+ ? outcome.mutationTail.slice(-2).map((entry) =>
114
+ Object.freeze({
115
+ type: ["attributes", "childList"].includes(entry?.type) ? entry.type : "invalid",
116
+ attribute:
117
+ typeof entry?.attribute === "string" && entry.attribute.length <= 32
118
+ ? entry.attribute
119
+ : null,
120
+ relevanceHmac: HASH.test(entry?.relevanceHmac ?? "") ? entry.relevanceHmac : null,
121
+ }),
122
+ )
123
+ : [],
124
+ ),
125
+ current: Object.freeze({
126
+ areaConnected: bool(outcome?.current?.areaConnected),
127
+ surfaceConnected: bool(outcome?.current?.surfaceConnected),
128
+ targetConnected: bool(outcome?.current?.targetConnected),
129
+ surfaceAreaExact: bool(outcome?.current?.surfaceAreaExact),
130
+ targetAreaExact: bool(outcome?.current?.targetAreaExact),
131
+ surfaceCardinalityExact: bool(outcome?.current?.surfaceCardinalityExact),
132
+ compositorExact: bool(outcome?.current?.compositorExact),
133
+ topologyExact: bool(outcome?.current?.topologyExact),
134
+ }),
135
+ });
136
+ }
137
+
138
+ export function card5PointerDispatchFailureReason(axes) {
139
+ if (axes?.dispatched !== true) return "pointer-not-dispatched";
140
+ if (axes.trusted !== true) return "pointer-untrusted";
141
+ if (axes.buttonExact !== true) return "pointer-button-invalid";
142
+ if (axes.pathExact !== true) return "pointer-path-invalid";
143
+ if (axes.eventOverflow !== false) return "pointer-event-overflow";
144
+ if (axes.mutationOverflow !== false) return "pointer-mutation-overflow";
145
+ if (axes.mutationCount !== 0) return "pointer-mutation-detected";
146
+ for (const [field, reason] of [
147
+ ["areaConnected", "pointer-area-disconnected"],
148
+ ["surfaceConnected", "pointer-surface-disconnected"],
149
+ ["targetConnected", "pointer-target-disconnected"],
150
+ ["surfaceAreaExact", "pointer-surface-area-changed"],
151
+ ["targetAreaExact", "pointer-target-area-changed"],
152
+ ["surfaceCardinalityExact", "pointer-surface-cardinality-changed"],
153
+ ["compositorExact", "pointer-compositor-changed"],
154
+ ["topologyExact", "pointer-topology-changed"],
155
+ ])
156
+ if (axes.current?.[field] !== true) return reason;
157
+ if (axes.allowed !== true) return "pointer-not-allowed";
158
+ if (axes.rejected !== false) return "pointer-rejected";
159
+ return null;
160
+ }
161
+
162
+ export function boundedCard5InputReceiptAxes(outcome, keyHex = null) {
163
+ const boundedCount = (value, cap = 8) =>
164
+ Number.isSafeInteger(value) && value >= 0 ? Math.min(value, cap) : null;
165
+ const exactBoolean = (value) => (typeof value === "boolean" ? value : null);
166
+ return Object.freeze({
167
+ status: [
168
+ "pending",
169
+ "accepted",
170
+ "input-receipt-invalid",
171
+ "input-receipt-timeout",
172
+ "input-authority-unobserved-timeout",
173
+ "input-authority-rejected",
174
+ "input-authority-timeout",
175
+ "input-authority-unavailable",
176
+ "input-authority-foreign",
177
+ "input-ack-timeout",
178
+ ].includes(outcome?.status)
179
+ ? outcome.status
180
+ : "invalid",
181
+ baselineCount: boundedCount(outcome?.baselineCount),
182
+ currentCount: boundedCount(outcome?.currentCount),
183
+ candidateCount: boundedCount(outcome?.candidateCount),
184
+ countRegressed: exactBoolean(outcome?.countRegressed),
185
+ countAdvanced: exactBoolean(outcome?.countAdvanced),
186
+ surfaceExact: exactBoolean(outcome?.surfaceExact),
187
+ textareaExact: exactBoolean(outcome?.textareaExact),
188
+ focusExact: exactBoolean(outcome?.focusExact),
189
+ bindingExact: exactBoolean(outcome?.bindingExact),
190
+ generationExact: exactBoolean(outcome?.generationExact),
191
+ sessionExact: exactBoolean(outcome?.sessionExact),
192
+ workspaceExact: exactBoolean(outcome?.workspaceExact),
193
+ paneExact: exactBoolean(outcome?.paneExact),
194
+ clientExact: exactBoolean(outcome?.clientExact),
195
+ requestExact: exactBoolean(outcome?.requestExact),
196
+ epochExact: exactBoolean(outcome?.epochExact),
197
+ clientGenerationExact: exactBoolean(outcome?.clientGenerationExact),
198
+ targetExact: exactBoolean(outcome?.targetExact),
199
+ mutationCount: boundedCount(outcome?.mutationCount, 32),
200
+ mutationOverflow: exactBoolean(outcome?.mutationOverflow),
201
+ authorityState: ["null", "expected", "foreign", "invalid"].includes(outcome?.authorityState)
202
+ ? outcome.authorityState
203
+ : "invalid",
204
+ timerCleared: exactBoolean(outcome?.timerCleared),
205
+ settled: exactBoolean(outcome?.settled),
206
+ operationCount: boundedCount(outcome?.operationCount, 64),
207
+ operationOverflow: exactBoolean(outcome?.operationOverflow),
208
+ operationTail: Object.freeze(
209
+ Array.isArray(outcome?.operationTail)
210
+ ? outcome.operationTail.slice(-2).map((event) =>
211
+ Object.freeze({
212
+ ordinal: boundedCount(event?.ordinal, 0xffff_ffff),
213
+ stage: [
214
+ "xterm-enqueue",
215
+ "surface-write",
216
+ "authority-request",
217
+ "authority-result",
218
+ "input-send",
219
+ "input-ack",
220
+ "receipt-published",
221
+ ].includes(event?.stage)
222
+ ? event.stage
223
+ : "invalid",
224
+ outcome: [
225
+ "attempt",
226
+ "ok",
227
+ "sent",
228
+ "send-failed",
229
+ "granted",
230
+ "rejected",
231
+ "authority-timeout",
232
+ "ack-timeout",
233
+ "closed",
234
+ "unavailable",
235
+ "failed",
236
+ ].includes(event?.outcome)
237
+ ? event.outcome
238
+ : "invalid",
239
+ identityHmac:
240
+ typeof keyHex === "string" && /^[0-9a-f]{64}$/u.test(keyHex)
241
+ ? createHmac("sha256", Buffer.from(keyHex, "hex"))
242
+ .update(
243
+ `input-operation\0${event?.generation ?? ""}\0${event?.lifecycleRequestId ?? ""}\0${event?.authorityRequestId ?? ""}\0${event?.clientId ?? ""}\0${event?.pane ?? ""}\0${event?.seq ?? ""}`,
244
+ )
245
+ .digest("hex")
246
+ : null,
247
+ }),
248
+ )
249
+ : [],
250
+ ),
251
+ });
252
+ }
253
+
254
+ export function boundedCard5InputReceiptStartAxes(result) {
255
+ const bool = (value) => (typeof value === "boolean" ? value : null);
256
+ const boundedMilliseconds = (value) =>
257
+ Number.isFinite(value) && value >= 0 ? Math.min(10_000, Math.floor(value)) : null;
258
+ const initial = result?.initial ?? {};
259
+ return Object.freeze({
260
+ status: [
261
+ "started",
262
+ "initial-invalid",
263
+ "already-started",
264
+ "deadline-invalid",
265
+ "reserve-insufficient",
266
+ ].includes(result?.status)
267
+ ? result.status
268
+ : "invalid",
269
+ settledStatus:
270
+ typeof result?.settledStatus === "string" && result.settledStatus.length <= 32
271
+ ? result.settledStatus
272
+ : "invalid",
273
+ fixedDeadlineInstalled: bool(result?.fixedDeadlineInstalled),
274
+ fixedDeadlineFinite: bool(result?.fixedDeadlineFinite),
275
+ browserRemainingMs: boundedMilliseconds(result?.browserRemainingMs),
276
+ reserveMs: boundedMilliseconds(result?.reserveMs),
277
+ dispatchFresh: bool(result?.dispatchFresh),
278
+ initial: Object.freeze({
279
+ surfaceExact: bool(initial.surfaceExact),
280
+ textareaExact: bool(initial.textareaExact),
281
+ focusExact: bool(initial.focusExact),
282
+ bindingEpochExact: bool(initial.bindingEpochExact),
283
+ bindingGenerationExact: bool(initial.bindingGenerationExact),
284
+ bindingSessionExact: bool(initial.bindingSessionExact),
285
+ bindingWorkspaceExact: bool(initial.bindingWorkspaceExact),
286
+ bindingPaneExact: bool(initial.bindingPaneExact),
287
+ bindingPaneSetHmacExact: bool(initial.bindingPaneSetHmacExact),
288
+ bindingStageExact: bool(initial.bindingStageExact),
289
+ bindingClientExact: bool(initial.bindingClientExact),
290
+ bindingRequestExact: bool(initial.bindingRequestExact),
291
+ authorityGenerationExact: bool(initial.authorityGenerationExact),
292
+ authoritySessionExact: bool(initial.authoritySessionExact),
293
+ clientGenerationExact: bool(initial.clientGenerationExact),
294
+ targetExact: bool(initial.targetExact),
295
+ baselineCountSafe: bool(initial.baselineCountSafe),
296
+ currentCountSafe: bool(initial.currentCountSafe),
297
+ currentCountExact: bool(initial.currentCountExact),
298
+ operationBoundarySafe: bool(initial.operationBoundarySafe),
299
+ }),
300
+ });
301
+ }
302
+
303
+ function processAlive(pid) {
304
+ try {
305
+ process.kill(pid, 0);
306
+ return true;
307
+ } catch {
308
+ return false;
309
+ }
310
+ }
311
+
312
+ function descendantPids(rootPid) {
313
+ const rows = execFileSync("ps", ["-axo", "pid=,ppid="], { encoding: "utf8" })
314
+ .trim()
315
+ .split("\n")
316
+ .map((line) => line.trim().split(/\s+/u).map(Number))
317
+ .filter(([pid, ppid]) => Number.isSafeInteger(pid) && Number.isSafeInteger(ppid));
318
+ const found = new Set();
319
+ let frontier = [rootPid];
320
+ while (frontier.length > 0) {
321
+ const parents = new Set(frontier);
322
+ frontier = rows
323
+ .filter(([pid, ppid]) => parents.has(ppid) && !found.has(pid))
324
+ .map(([pid]) => pid);
325
+ for (const pid of frontier) found.add(pid);
326
+ }
327
+ return [...found];
328
+ }
329
+
330
+ function processRows() {
331
+ try {
332
+ return execFileSync("ps", ["-axo", "pid=,ppid=,pgid=,stat=,lstart=,command="], {
333
+ encoding: "utf8",
334
+ })
335
+ .trim()
336
+ .split("\n")
337
+ .map((line) =>
338
+ /^(\d+)\s+(\d+)\s+(\d+)\s+(\S+)\s+(\w{3}\s+\w{3}\s+\d+\s+\d+:\d+:\d+\s+\d+)\s+(.*)$/u.exec(
339
+ line.trim(),
340
+ ),
341
+ )
342
+ .filter(Boolean)
343
+ .map((match) => ({
344
+ pid: Number(match[1]),
345
+ ppid: Number(match[2]),
346
+ pgid: Number(match[3]),
347
+ state: match[4],
348
+ startToken: match[5],
349
+ command: match[6],
350
+ }));
351
+ } catch {
352
+ return [];
353
+ }
354
+ }
355
+
356
+ function lsofCount(args, predicate = () => true) {
357
+ try {
358
+ return execFileSync("lsof", args, {
359
+ encoding: "utf8",
360
+ stdio: ["ignore", "pipe", "ignore"],
361
+ })
362
+ .trim()
363
+ .split("\n")
364
+ .slice(1)
365
+ .filter((line) => line && predicate(line)).length;
366
+ } catch (error) {
367
+ return error?.status === 1 ? 0 : null;
368
+ }
369
+ }
370
+
371
+ function abortError() {
372
+ const error = new Error("Card5 production host launch was aborted");
373
+ error.name = "AbortError";
374
+ return error;
375
+ }
376
+
377
+ function abortable(promise, signal) {
378
+ if (!signal) return promise;
379
+ if (signal.aborted) return Promise.reject(abortError());
380
+ return new Promise((resolvePromise, rejectPromise) => {
381
+ const abort = () => rejectPromise(abortError());
382
+ signal.addEventListener("abort", abort, { once: true });
383
+ Promise.resolve(promise).then(
384
+ (value) => {
385
+ signal.removeEventListener("abort", abort);
386
+ resolvePromise(value);
387
+ },
388
+ (error) => {
389
+ signal.removeEventListener("abort", abort);
390
+ rejectPromise(error);
391
+ },
392
+ );
393
+ });
394
+ }
395
+
396
+ async function bounded(promise, milliseconds) {
397
+ let timer;
398
+ try {
399
+ return await Promise.race([
400
+ Promise.resolve(promise),
401
+ new Promise((_, reject) => {
402
+ timer = setTimeout(
403
+ () => reject(new Error("Card5 host close deadline expired")),
404
+ milliseconds,
405
+ );
406
+ }),
407
+ ]);
408
+ } finally {
409
+ clearTimeout(timer);
410
+ }
411
+ }
412
+
413
+ function exactOwnedFile(path, root, label) {
414
+ if (!isAbsolute(path)) throw new TypeError(`${label} must be absolute`);
415
+ const exact = resolve(path);
416
+ const base = resolve(root);
417
+ if (exact !== base && !exact.startsWith(`${base}/`)) {
418
+ throw new TypeError(`${label} must be ProductRig-owned`);
419
+ }
420
+ return exact;
421
+ }
422
+
423
+ async function preparePage(page, pageUrl, signal, evidenceKey) {
424
+ await page.addInitScript(() => {
425
+ globalThis.__TMUX_IDE_ANSI_RENDITION_PROBE_ENABLED__ = true;
426
+ globalThis.__TMUX_IDE_CARD5_EVIDENCE_ENABLED__ = true;
427
+ });
428
+ await abortable(page.goto(pageUrl, { waitUntil: "domcontentloaded" }), signal);
429
+ await abortable(
430
+ page.locator(".app[data-shell-source='runtime']").waitFor({ timeout: 60_000 }),
431
+ signal,
432
+ );
433
+ await abortable(waitForQualifiedTerminal(page), signal);
434
+ await qualifiedTerminalIdentity(page, evidenceKey);
435
+ }
436
+
437
+ function installReadinessPageEvents(page) {
438
+ const counts = { pageError: 0, close: 0, crash: 0 };
439
+ const events = [];
440
+ const record = (kind) => {
441
+ counts[kind] = Math.min(0xffff, counts[kind] + 1);
442
+ if (events.length < CARD5_MAX_PAGE_EVENTS) events.push(kind);
443
+ };
444
+ page.on?.("pageerror", () => record("pageError"));
445
+ page.on?.("close", () => record("close"));
446
+ page.on?.("crash", () => record("crash"));
447
+ return () =>
448
+ Object.freeze({
449
+ pageErrorCount: counts.pageError,
450
+ closeCount: counts.close,
451
+ crashCount: counts.crash,
452
+ events: Object.freeze([...events]),
453
+ eventOverflow: Math.min(
454
+ 0xffff,
455
+ Math.max(0, counts.pageError + counts.close + counts.crash - events.length),
456
+ ),
457
+ });
458
+ }
459
+
460
+ async function waitForQualifiedTerminal(page) {
461
+ await page.waitForFunction(
462
+ () => Boolean(globalThis.__TMUX_IDE_CARD5_QUALIFIED_TERMINAL__?.()),
463
+ undefined,
464
+ { timeout: 60_000 },
465
+ );
466
+ }
467
+
468
+ async function qualifiedTerminalIdentity(page, evidenceKey) {
469
+ if (!HASH.test(evidenceKey ?? "")) throw new TypeError("Card5 evidence key is malformed");
470
+ const surfaceHandle = await page.evaluateHandle(
471
+ () => globalThis.__TMUX_IDE_CARD5_QUALIFIED_TERMINAL__?.() ?? null,
472
+ );
473
+ const identity = await page.evaluate(
474
+ async ({ exactKey, exactSurface }) => {
475
+ const surface = globalThis.__TMUX_IDE_CARD5_QUALIFIED_TERMINAL__?.() ?? null;
476
+ if (!surface || surface !== exactSurface) return null;
477
+ const bytes = Uint8Array.from(
478
+ exactKey.match(/../gu).map((pair) => Number.parseInt(pair, 16)),
479
+ );
480
+ const key = await globalThis.crypto.subtle.importKey(
481
+ "raw",
482
+ bytes,
483
+ { name: "HMAC", hash: "SHA-256" },
484
+ false,
485
+ ["sign"],
486
+ );
487
+ const hmac = async (domain, value) => {
488
+ if (typeof value !== "string" || value.length === 0 || value.length > 512) return null;
489
+ const signed = await globalThis.crypto.subtle.sign(
490
+ "HMAC",
491
+ key,
492
+ new TextEncoder().encode(`${domain}\0${value}`),
493
+ );
494
+ return [...new Uint8Array(signed)]
495
+ .map((byte) => byte.toString(16).padStart(2, "0"))
496
+ .join("");
497
+ };
498
+ return {
499
+ workspaceHmac: await hmac("workspace", surface.getAttribute("data-workspace-name")),
500
+ paneHmac: await hmac("pane", surface.getAttribute("data-semantic-pane-id")),
501
+ };
502
+ },
503
+ { exactKey: evidenceKey, exactSurface: surfaceHandle },
504
+ );
505
+ if (!HASH.test(identity?.workspaceHmac ?? "") || !HASH.test(identity?.paneHmac ?? "")) {
506
+ await surfaceHandle.dispose();
507
+ throw new Error("Card5 qualified terminal identity was unavailable");
508
+ }
509
+ const prior = qualifiedTerminalIdentities.get(page);
510
+ await prior?.surfaceHandle.dispose();
511
+ const authority = Object.freeze({ ...identity, surfaceHandle });
512
+ qualifiedTerminalIdentities.set(page, authority);
513
+ const retire = () => {
514
+ if (qualifiedTerminalIdentities.get(page) !== authority) return;
515
+ qualifiedTerminalIdentities.delete(page);
516
+ void surfaceHandle.dispose().catch(() => undefined);
517
+ };
518
+ page.on?.("close", retire);
519
+ page.on?.("crash", retire);
520
+ page.on?.("framenavigated", (frame) => {
521
+ if (typeof page.mainFrame !== "function" || frame === page.mainFrame()) retire();
522
+ });
523
+ return authority;
524
+ }
525
+
526
+ async function waitForElectronReadyTerminal(page, signal, evidenceKey) {
527
+ await abortable(waitForQualifiedTerminal(page), signal);
528
+ await qualifiedTerminalIdentity(page, evidenceKey);
529
+ }
530
+
531
+ async function observeHostReadiness(page, evidenceKey, pageEvents) {
532
+ if (!HASH.test(evidenceKey ?? "")) throw new TypeError("Card5 evidence key is malformed");
533
+ const observation = await page.evaluate(
534
+ async ({
535
+ evidenceKey: exactKey,
536
+ panelSelector,
537
+ maxCandidates,
538
+ maxSocketEvents,
539
+ maxLifecycleEvents,
540
+ }) => {
541
+ const boundedInteger = (value, ceiling = 0xffff) => {
542
+ if (typeof value !== "string" || !/^\d{1,10}$/u.test(value)) return null;
543
+ const number = Number(value);
544
+ return Number.isSafeInteger(number) && number >= 0 ? Math.min(number, ceiling) : null;
545
+ };
546
+ const boundedDimension = (value) =>
547
+ Number.isFinite(value) && value >= 0 ? Math.min(0xffff, Math.round(value)) : null;
548
+ const exactDimension = (value) =>
549
+ /^[1-9]\d{0,4}x[1-9]\d{0,4}$/u.test(value ?? "") ? value : null;
550
+ const phase = (value) =>
551
+ ["unavailable", "measuring", "connecting", "connected", "disconnected", "error"].includes(
552
+ value,
553
+ )
554
+ ? value
555
+ : "unknown";
556
+ const attachPhase = (value) =>
557
+ [
558
+ "unavailable",
559
+ "renderer-loading",
560
+ "renderer-ready",
561
+ "waiting-for-viewport",
562
+ "attach-requested",
563
+ "transport-ready",
564
+ "attachment-ready",
565
+ "awaiting-first-output",
566
+ "first-output-received",
567
+ "painting-first-frame",
568
+ "live",
569
+ "disconnected",
570
+ "failed",
571
+ ].includes(value)
572
+ ? value
573
+ : "unknown";
574
+ const failureCode = (value) =>
575
+ [
576
+ "none",
577
+ "geometry-authority-conflict",
578
+ "resize-rejected",
579
+ "resize-exception",
580
+ "attach-failed",
581
+ "input-failed",
582
+ "renderer-failed",
583
+ "output-failed",
584
+ ].includes(value)
585
+ ? value
586
+ : "unknown";
587
+ const resizeOutcome = (value) =>
588
+ [
589
+ "none",
590
+ "geometry-authority-conflict",
591
+ "authority-timeout",
592
+ "viewport-timeout",
593
+ "stream-closed",
594
+ "lifecycle-retired",
595
+ "failed",
596
+ ].includes(value)
597
+ ? value
598
+ : "unknown";
599
+ const reason = (surfacePhase, surfaceAttachPhase, preservesFrame) => {
600
+ if (surfacePhase === "connected") return preservesFrame ? "none" : "frame-unavailable";
601
+ if (surfacePhase === "unavailable") return "transport-unavailable";
602
+ if (surfacePhase === "measuring")
603
+ return surfaceAttachPhase === "waiting-for-viewport"
604
+ ? "viewport-unavailable"
605
+ : "renderer-pending";
606
+ if (surfacePhase === "connecting")
607
+ return surfaceAttachPhase === "transport-ready"
608
+ ? "attachment-handle-pending"
609
+ : "transport-pending";
610
+ if (surfacePhase === "disconnected") return "transport-disconnected";
611
+ if (surfacePhase === "error") return "terminal-failed";
612
+ return "unknown";
613
+ };
614
+ const bytes = Uint8Array.from(
615
+ exactKey.match(/../gu).map((pair) => Number.parseInt(pair, 16)),
616
+ );
617
+ const key = await globalThis.crypto.subtle.importKey(
618
+ "raw",
619
+ bytes,
620
+ { name: "HMAC", hash: "SHA-256" },
621
+ false,
622
+ ["sign"],
623
+ );
624
+ const hmac = async (domain, value) => {
625
+ if (typeof value !== "string" || value.length === 0 || value.length > 512) return null;
626
+ const signed = await globalThis.crypto.subtle.sign(
627
+ "HMAC",
628
+ key,
629
+ new TextEncoder().encode(`${domain}\0${value}`),
630
+ );
631
+ return [...new Uint8Array(signed)]
632
+ .map((byte) => byte.toString(16).padStart(2, "0"))
633
+ .join("");
634
+ };
635
+ const panel = globalThis.document.querySelector(panelSelector);
636
+ const surfaces = panel ? [...panel.querySelectorAll(".terminal-surface")] : [];
637
+ const qualifiedSurface = globalThis.__TMUX_IDE_CARD5_QUALIFIED_TERMINAL__?.() ?? null;
638
+ const candidates = await Promise.all(
639
+ surfaces.slice(0, maxCandidates).map(async (surface) => {
640
+ const style = globalThis.getComputedStyle(surface);
641
+ const rect = surface.getBoundingClientRect();
642
+ const surfacePhase = phase(surface.getAttribute("data-phase"));
643
+ const surfaceAttachPhase = attachPhase(surface.getAttribute("data-attach-phase"));
644
+ const preservesFrame = surface.getAttribute("data-preserves-frame") === "true";
645
+ const visible =
646
+ globalThis.document.visibilityState === "visible" &&
647
+ style.display !== "none" &&
648
+ style.visibility !== "hidden" &&
649
+ style.visibility !== "collapse" &&
650
+ rect.width > 0 &&
651
+ rect.height > 0 &&
652
+ surface.getClientRects().length > 0;
653
+ return {
654
+ phase: surfacePhase,
655
+ attachPhase: surfaceAttachPhase,
656
+ failureCode: failureCode(surface.getAttribute("data-attach-failure-code")),
657
+ resizeOutcome: resizeOutcome(surface.getAttribute("data-resize-outcome")),
658
+ resizeOrdinal: boundedInteger(surface.getAttribute("data-resize-ordinal")),
659
+ attempt: boundedInteger(surface.getAttribute("data-attach-attempt")),
660
+ reason: reason(surfacePhase, surfaceAttachPhase, preservesFrame),
661
+ qualified: surface === qualifiedSurface,
662
+ visible,
663
+ bbox: Object.freeze({
664
+ width: boundedDimension(rect.width),
665
+ height: boundedDimension(rect.height),
666
+ }),
667
+ hasXterm: surface.querySelector(".xterm") !== null,
668
+ preservesFrame,
669
+ sourceDimensions: exactDimension(surface.getAttribute("data-source-grid")),
670
+ clientDimensions: exactDimension(surface.getAttribute("data-client-viewport")),
671
+ workspaceHmac: await hmac("workspace", surface.getAttribute("data-workspace-name")),
672
+ paneHmac: await hmac("pane", surface.getAttribute("data-semantic-pane-id")),
673
+ };
674
+ }),
675
+ );
676
+ const app = globalThis.document.querySelector(".app");
677
+ const workspaceEvidence =
678
+ typeof globalThis.__TMUX_IDE_CARD5_WORKSPACE_EVIDENCE__ === "function"
679
+ ? globalThis.__TMUX_IDE_CARD5_WORKSPACE_EVIDENCE__()
680
+ : null;
681
+ const clientPhase = workspaceEvidence?.snapshot?.phase;
682
+ const envelopeEvidence =
683
+ typeof globalThis.__TMUX_IDE_CARD5_ENVELOPE_EVIDENCE__ === "function"
684
+ ? globalThis.__TMUX_IDE_CARD5_ENVELOPE_EVIDENCE__()
685
+ : null;
686
+ const boundedCount = (value, ceiling = 0xffff) =>
687
+ Number.isSafeInteger(value) && value >= 0 ? Math.min(value, ceiling) : null;
688
+ const socketEvents = Array.isArray(envelopeEvidence?.socketEvents)
689
+ ? envelopeEvidence.socketEvents.slice(-maxSocketEvents)
690
+ : [];
691
+ const socketOutcomes = await Promise.all(
692
+ socketEvents.map(async (event) => ({
693
+ outcome: ["open", "closed", "failed"].includes(event?.outcome)
694
+ ? event.outcome
695
+ : "unknown",
696
+ ordinal: boundedCount(event?.ordinal, 0xffff_ffff),
697
+ generationHmac: await hmac("generation", event?.generation),
698
+ })),
699
+ );
700
+ const socketEventCount = boundedCount(envelopeEvidence?.socketEventCount, 0xffff_ffff);
701
+ const lifecycleEvents = Array.isArray(envelopeEvidence?.lifecycleEvents)
702
+ ? envelopeEvidence.lifecycleEvents.slice(-maxLifecycleEvents)
703
+ : [];
704
+ const lifecycle = await Promise.all(
705
+ lifecycleEvents.map(async (event) => ({
706
+ stage: [
707
+ "issued",
708
+ "socket-open",
709
+ "server-ready",
710
+ "layout-validated",
711
+ "delivery-open",
712
+ "first-seed",
713
+ "terminal",
714
+ ].includes(event?.stage)
715
+ ? event.stage
716
+ : "unknown",
717
+ code:
718
+ typeof event?.code === "string" && /^[a-z][a-z0-9-]{0,63}$/u.test(event.code)
719
+ ? event.code
720
+ : "unknown",
721
+ origin: ["client", "peer", "dispose", "unknown"].includes(event?.origin)
722
+ ? event.origin
723
+ : "unknown",
724
+ closeCode:
725
+ Number.isSafeInteger(event?.closeCode) &&
726
+ event.closeCode >= 1000 &&
727
+ event.closeCode <= 4999
728
+ ? event.closeCode
729
+ : null,
730
+ closeReason:
731
+ typeof event?.closeReason === "string" &&
732
+ /^[a-z][a-z0-9-]{0,63}$/u.test(event.closeReason)
733
+ ? event.closeReason
734
+ : "unknown",
735
+ ordinal: boundedCount(event?.ordinal, 0xffff_ffff),
736
+ generationHmac: await hmac("generation", event?.generation),
737
+ requestHmac: await hmac("request", event?.requestId),
738
+ })),
739
+ );
740
+ const lifecycleEventCount = boundedCount(envelopeEvidence?.lifecycleEventCount, 0xffff_ffff);
741
+ const descriptorEventCount = boundedCount(
742
+ envelopeEvidence?.descriptorEventCount,
743
+ 0xffff_ffff,
744
+ );
745
+ const replacementCount = boundedCount(envelopeEvidence?.replacementCount, 0xffff);
746
+ const predecessorAcceptedAfterReplacement = boundedCount(
747
+ envelopeEvidence?.predecessorAcceptedAfterReplacement,
748
+ 0xffff,
749
+ );
750
+ const reconnectOutcome =
751
+ predecessorAcceptedAfterReplacement === null || replacementCount === null
752
+ ? "unknown"
753
+ : predecessorAcceptedAfterReplacement > 0
754
+ ? "replacement-violation"
755
+ : replacementCount > 0
756
+ ? "replacement-observed"
757
+ : descriptorEventCount !== null &&
758
+ descriptorEventCount > 0 &&
759
+ socketOutcomes.length === 0
760
+ ? "issued-without-socket"
761
+ : "none";
762
+ return {
763
+ probeInstalled: typeof globalThis.__TMUX_IDE_CARD5_QUALIFIED_TERMINAL__ === "function",
764
+ candidateCount: Math.min(surfaces.length, 0xffff),
765
+ candidateOverflow: Math.min(0xffff, Math.max(0, surfaces.length - candidates.length)),
766
+ candidates,
767
+ documentVisibility:
768
+ globalThis.document.visibilityState === "visible" ? "visible" : "hidden",
769
+ activePanelPresent: panel !== null,
770
+ shellPresent: app?.getAttribute("data-shell-source") === "runtime",
771
+ bootstrapPhase: app?.getAttribute("data-daemon-generation") ? "connected" : "pending",
772
+ clientPhase: [
773
+ "loading",
774
+ "live",
775
+ "stale",
776
+ "degraded",
777
+ "unavailable",
778
+ "error",
779
+ "disposed",
780
+ ].includes(clientPhase)
781
+ ? clientPhase
782
+ : "unknown",
783
+ transport: Object.freeze({
784
+ descriptorEventCount,
785
+ socketEventCount,
786
+ socketEventOverflow:
787
+ socketEventCount === null
788
+ ? null
789
+ : Math.max(0, socketEventCount - socketOutcomes.length),
790
+ socketOutcomes,
791
+ lifecycleEventCount,
792
+ lifecycleEventOverflow:
793
+ lifecycleEventCount === null
794
+ ? null
795
+ : Math.max(0, lifecycleEventCount - lifecycle.length),
796
+ lifecycle,
797
+ replacementCount,
798
+ predecessorAcceptedAfterReplacement,
799
+ reconnectOutcome,
800
+ }),
801
+ };
802
+ },
803
+ {
804
+ evidenceKey,
805
+ panelSelector: CARD5_ACTIVE_TERMINAL_PANEL,
806
+ maxCandidates: CARD5_MAX_READINESS_CANDIDATES,
807
+ maxSocketEvents: CARD5_MAX_PAGE_EVENTS,
808
+ maxLifecycleEvents: 64,
809
+ },
810
+ );
811
+ return Object.freeze({ ...observation, pageEvents: pageEvents() });
812
+ }
813
+
814
+ function unavailableReadinessObservation(readReason, pageEvents) {
815
+ return Object.freeze({
816
+ readReason,
817
+ probeInstalled: null,
818
+ candidateCount: null,
819
+ candidateOverflow: null,
820
+ candidates: Object.freeze([]),
821
+ documentVisibility: "unknown",
822
+ activePanelPresent: null,
823
+ shellPresent: null,
824
+ bootstrapPhase: "unknown",
825
+ clientPhase: "unknown",
826
+ transport: Object.freeze({
827
+ descriptorEventCount: null,
828
+ socketEventCount: null,
829
+ socketEventOverflow: null,
830
+ socketOutcomes: Object.freeze([]),
831
+ lifecycleEventCount: null,
832
+ lifecycleEventOverflow: null,
833
+ lifecycle: Object.freeze([]),
834
+ replacementCount: null,
835
+ predecessorAcceptedAfterReplacement: null,
836
+ reconnectOutcome: "unknown",
837
+ }),
838
+ pageEvents: pageEvents(),
839
+ });
840
+ }
841
+
842
+ async function captureFailedReadiness(
843
+ page,
844
+ evidenceKey,
845
+ pageEvents,
846
+ signal,
847
+ timeoutMs,
848
+ scheduleTimeout,
849
+ ) {
850
+ if (page?.isClosed?.() === true) {
851
+ return unavailableReadinessObservation("page-closed", pageEvents);
852
+ }
853
+ const observation = observeHostReadiness(page, evidenceKey, pageEvents);
854
+ return await new Promise((resolveObservation) => {
855
+ let settled = false;
856
+ let cancelTimeout = () => undefined;
857
+ let onAbort = () => undefined;
858
+ const finish = (value) => {
859
+ if (settled) return;
860
+ settled = true;
861
+ cancelTimeout();
862
+ signal?.removeEventListener("abort", onAbort);
863
+ resolveObservation(value);
864
+ };
865
+ onAbort = () => finish(unavailableReadinessObservation("read-aborted", pageEvents));
866
+ Promise.resolve(observation).then(
867
+ (value) => finish(value),
868
+ () => finish(unavailableReadinessObservation("read-failed", pageEvents)),
869
+ );
870
+ signal?.addEventListener("abort", onAbort, { once: true });
871
+ if (signal?.aborted) {
872
+ onAbort();
873
+ return;
874
+ }
875
+ try {
876
+ const cancel = scheduleTimeout(
877
+ () => finish(unavailableReadinessObservation("read-timeout", pageEvents)),
878
+ timeoutMs,
879
+ );
880
+ if (typeof cancel === "function") cancelTimeout = cancel;
881
+ } catch {
882
+ finish(unavailableReadinessObservation("read-failed", pageEvents));
883
+ }
884
+ });
885
+ }
886
+
887
+ /**
888
+ * A synchronously-created cleanup authority for a possibly partial Card5 host
889
+ * launch. The owner can abort/retire it before any awaited acquisition returns.
890
+ */
891
+ export function createCard5ProductionWebHostLease(input) {
892
+ const cleanupRuntime = input.cleanupRuntime ?? {};
893
+ const isAlive = cleanupRuntime.processAlive ?? processAlive;
894
+ const readProcessRows = cleanupRuntime.processRows ?? processRows;
895
+ const signalProcess =
896
+ cleanupRuntime.signalProcess ?? ((pid, signal) => process.kill(pid, signal));
897
+ const inspectLsof = cleanupRuntime.lsofCount ?? lsofCount;
898
+ const sleep =
899
+ cleanupRuntime.sleep ??
900
+ ((milliseconds) => new Promise((resolveWait) => setTimeout(resolveWait, milliseconds)));
901
+ const closeGraceMs = cleanupRuntime.closeGraceMs ?? CLOSE_GRACE_MS;
902
+ const closeTermMs = cleanupRuntime.closeTermMs ?? CLOSE_TERM_MS;
903
+ const readinessObservationTimeoutMs =
904
+ cleanupRuntime.readinessObservationTimeoutMs ?? CARD5_READINESS_OBSERVATION_TIMEOUT_MS;
905
+ if (
906
+ !Number.isSafeInteger(readinessObservationTimeoutMs) ||
907
+ readinessObservationTimeoutMs < 1 ||
908
+ readinessObservationTimeoutMs > CARD5_READINESS_OBSERVATION_TIMEOUT_MS
909
+ ) {
910
+ throw new TypeError("Card5 readiness observation timeout is invalid");
911
+ }
912
+ const scheduleReadinessObservationTimeout =
913
+ cleanupRuntime.scheduleReadinessObservationTimeout ??
914
+ ((callback, milliseconds) => {
915
+ const timer = setTimeout(callback, milliseconds);
916
+ return () => clearTimeout(timer);
917
+ });
918
+ const controller = new AbortController();
919
+ const externallyAborted = () => controller.abort();
920
+ input.signal?.addEventListener("abort", externallyAborted, { once: true });
921
+ const resources = {
922
+ stage: "created",
923
+ browser: null,
924
+ chromiumContext: null,
925
+ chromiumPage: null,
926
+ chromiumPageEvents: () =>
927
+ Object.freeze({
928
+ pageErrorCount: 0,
929
+ closeCount: 0,
930
+ crashCount: 0,
931
+ events: Object.freeze([]),
932
+ eventOverflow: 0,
933
+ }),
934
+ chromiumReadinessObservation: null,
935
+ chromiumPid: null,
936
+ chromiumIdentityObserved: false,
937
+ electronApp: null,
938
+ electronPage: null,
939
+ electronPageEvents: () =>
940
+ Object.freeze({
941
+ pageErrorCount: 0,
942
+ closeCount: 0,
943
+ crashCount: 0,
944
+ events: Object.freeze([]),
945
+ eventOverflow: 0,
946
+ }),
947
+ electronReadinessObservation: null,
948
+ electronPid: null,
949
+ electronIdentityObserved: false,
950
+ knownChromium: new Set(),
951
+ knownElectron: new Set(),
952
+ chromiumIdentities: new Map(),
953
+ electronIdentities: new Map(),
954
+ chromiumCloseObserved: false,
955
+ electronCloseObserved: false,
956
+ };
957
+ let launchSettled = false;
958
+ let closePromise = null;
959
+ let retiredReceipt = null;
960
+ const pendingAcquisitions = new Set();
961
+ const acquisition = (promise, assign) => {
962
+ const tracked = Promise.resolve(promise).then((value) => {
963
+ assign(value);
964
+ if (controller.signal.aborted) void close();
965
+ return value;
966
+ });
967
+ pendingAcquisitions.add(tracked);
968
+ void tracked.finally(() => pendingAcquisitions.delete(tracked)).catch(() => {});
969
+ return tracked;
970
+ };
971
+ const waitRetired = async (pids, milliseconds = closeGraceMs) => {
972
+ const deadline = performance.now() + milliseconds;
973
+ while (performance.now() < deadline && pids.some(isAlive)) await sleep(10);
974
+ };
975
+
976
+ const ownedProcessRows = (rootPid, known, identities, ownedPath) => {
977
+ const rows = readProcessRows();
978
+ const rowByPid = new Map(rows.map((row) => [row.pid, row]));
979
+ const identity = (row) => `${row.startToken}\0${row.pgid}\0${row.command}`;
980
+ const register = (pid) => {
981
+ const row = rowByPid.get(pid);
982
+ if (!row) return;
983
+ if (identities.has(pid)) {
984
+ if (identities.get(pid) === identity(row)) known.add(pid);
985
+ return;
986
+ }
987
+ known.add(pid);
988
+ identities.set(pid, identity(row));
989
+ };
990
+ if (Number.isSafeInteger(rootPid) && !known.has(rootPid)) register(rootPid);
991
+ for (const pid of [...known]) {
992
+ if (!identities.has(pid)) register(pid);
993
+ const row = rowByPid.get(pid);
994
+ if (!row || identities.get(pid) !== identity(row)) known.delete(pid);
995
+ }
996
+ let changed = true;
997
+ while (changed) {
998
+ changed = false;
999
+ for (const row of rows) {
1000
+ if (
1001
+ !known.has(row.pid) &&
1002
+ known.has(row.ppid) &&
1003
+ (!ownedPath ||
1004
+ row.command.includes(ownedPath) ||
1005
+ row.pgid === rowByPid.get(row.ppid)?.pgid)
1006
+ ) {
1007
+ register(row.pid);
1008
+ changed = true;
1009
+ }
1010
+ }
1011
+ }
1012
+ return [...known].map((pid) => rowByPid.get(pid)).filter((row) => row && isAlive(row.pid));
1013
+ };
1014
+ const terminalProcessState = (row) => typeof row?.state === "string" && /[EZ]/u.test(row.state);
1015
+ const boundedProcessEvidence = (rows, host) =>
1016
+ Object.freeze(
1017
+ rows.slice(0, 32).map((row) =>
1018
+ Object.freeze({
1019
+ identityHmac: createHmac("sha256", Buffer.from(input.evidenceKey, "hex"))
1020
+ .update(`${host}\0${row.pid}\0${row.startToken}\0${row.pgid}\0${row.command}`)
1021
+ .digest("hex"),
1022
+ terminalState: terminalProcessState(row),
1023
+ }),
1024
+ ),
1025
+ );
1026
+ const receipt = (reason = null) => {
1027
+ const chromiumRows = ownedProcessRows(
1028
+ resources.chromiumPid,
1029
+ resources.knownChromium,
1030
+ resources.chromiumIdentities,
1031
+ null,
1032
+ );
1033
+ const electronRows = ownedProcessRows(
1034
+ resources.electronPid,
1035
+ resources.knownElectron,
1036
+ resources.electronIdentities,
1037
+ input.electronUserData,
1038
+ );
1039
+ const chromium = chromiumRows.filter((row) => !terminalProcessState(row));
1040
+ const electron = electronRows.filter((row) => !terminalProcessState(row));
1041
+ const chromiumTerminal = chromiumRows.filter(terminalProcessState);
1042
+ const electronTerminal = electronRows.filter(terminalProcessState);
1043
+ const chromiumMain = chromium.some(({ pid }) => pid === resources.chromiumPid) ? 1 : 0;
1044
+ const electronMain = electron.some(({ pid }) => pid === resources.electronPid) ? 1 : 0;
1045
+ const inspectedCount = (pids, inspect) => {
1046
+ const values = pids.map(inspect);
1047
+ return values.some((value) => value === null)
1048
+ ? null
1049
+ : values.reduce((sum, value) => sum + value, 0);
1050
+ };
1051
+ const electronOpenHandleCount = inspectedCount(electronRows, ({ pid }) =>
1052
+ inspectLsof(["-n", "-P", "-a", "-p", String(pid)], (line) =>
1053
+ line.includes(input.runtimeRoot),
1054
+ ),
1055
+ );
1056
+ const chromiumListenerCount = inspectedCount(chromiumRows, ({ pid }) =>
1057
+ inspectLsof(["-n", "-P", "-a", "-p", String(pid), "-iTCP", "-sTCP:LISTEN"]),
1058
+ );
1059
+ const electronListenerCount = inspectedCount(electronRows, ({ pid }) =>
1060
+ inspectLsof(["-n", "-P", "-a", "-p", String(pid), "-iTCP", "-sTCP:LISTEN"]),
1061
+ );
1062
+ return Object.freeze({
1063
+ launchStage: resources.stage,
1064
+ reason: reason ?? (controller.signal.aborted ? "graceful-retirement" : "active"),
1065
+ chromiumReason:
1066
+ resources.browser === null ? "not-acquired" : (reason ?? "graceful-retirement"),
1067
+ electronReason:
1068
+ resources.electronApp === null ? "not-acquired" : (reason ?? "graceful-retirement"),
1069
+ acquisitionPendingCount: pendingAcquisitions.size,
1070
+ chromiumOwned: resources.browser !== null || Number.isSafeInteger(resources.chromiumPid),
1071
+ chromiumRetired:
1072
+ pendingAcquisitions.size === 0 &&
1073
+ chromium.length === 0 &&
1074
+ (resources.browser === null ||
1075
+ (resources.chromiumIdentityObserved && resources.chromiumCloseObserved)) &&
1076
+ resources.chromiumPage?.isClosed?.() !== false &&
1077
+ resources.browser?.isConnected?.() !== true &&
1078
+ chromiumListenerCount === 0,
1079
+ chromiumProcessCount: chromiumMain,
1080
+ chromiumDescendantCount: Math.max(0, chromium.length - chromiumMain),
1081
+ chromiumTerminalProcessCount: chromiumTerminal.length,
1082
+ chromiumProcessEvidence: boundedProcessEvidence(chromiumRows, "chromium"),
1083
+ chromiumProcessEvidenceOverflow: chromiumRows.length > 32,
1084
+ chromiumPageCount: resources.chromiumPage?.isClosed?.() === false ? 1 : 0,
1085
+ chromiumContextCount: resources.browser?.isConnected?.() === true ? 1 : 0,
1086
+ chromiumListenerCount,
1087
+ electronOwned: resources.electronApp !== null || Number.isSafeInteger(resources.electronPid),
1088
+ electronRetired:
1089
+ pendingAcquisitions.size === 0 &&
1090
+ electron.length === 0 &&
1091
+ (resources.electronApp === null ||
1092
+ (resources.electronIdentityObserved && resources.electronCloseObserved)) &&
1093
+ resources.electronPage?.isClosed?.() !== false &&
1094
+ electronOpenHandleCount === 0 &&
1095
+ electronListenerCount === 0,
1096
+ electronProcessCount: electronMain,
1097
+ electronDescendantCount: Math.max(0, electron.length - electronMain),
1098
+ electronTerminalProcessCount: electronTerminal.length,
1099
+ electronProcessEvidence: boundedProcessEvidence(electronRows, "electron"),
1100
+ electronProcessEvidenceOverflow: electronRows.length > 32,
1101
+ retainedProcessIdentities: Object.freeze(
1102
+ [
1103
+ ...chromiumTerminal.map((row) => ({ ...row, host: "chromium" })),
1104
+ ...electronTerminal.map((row) => ({ ...row, host: "electron" })),
1105
+ ].map(({ host, pid, ppid, pgid, state, startToken, command }) =>
1106
+ Object.freeze({ host, pid, ppid, pgid, state, startToken, command }),
1107
+ ),
1108
+ ),
1109
+ electronWindowCount: resources.electronPage?.isClosed?.() === false ? 1 : 0,
1110
+ electronListenerCount,
1111
+ electronOpenHandleCount,
1112
+ });
1113
+ };
1114
+ const close = async () => {
1115
+ controller.abort();
1116
+ if (retiredReceipt) return retiredReceipt;
1117
+ if (closePromise) return closePromise;
1118
+ closePromise = (async () => {
1119
+ if (!launchSettled)
1120
+ await bounded(
1121
+ ready.catch(() => undefined),
1122
+ closeGraceMs,
1123
+ ).catch(() => {});
1124
+ await bounded(Promise.allSettled([...pendingAcquisitions]), closeGraceMs).catch(() => {});
1125
+ if (!Number.isSafeInteger(resources.chromiumPid) && resources.browser) {
1126
+ await bounded(
1127
+ Promise.resolve()
1128
+ .then(() => resources.browser.newBrowserCDPSession())
1129
+ .then((session) => session.send("SystemInfo.getProcessInfo"))
1130
+ .then((system) => {
1131
+ resources.chromiumPid =
1132
+ system.processInfo.find(({ type }) => type === "browser")?.id ?? null;
1133
+ if (Number.isSafeInteger(resources.chromiumPid)) {
1134
+ resources.chromiumIdentityObserved = true;
1135
+ resources.knownChromium.add(resources.chromiumPid);
1136
+ ownedProcessRows(
1137
+ resources.chromiumPid,
1138
+ resources.knownChromium,
1139
+ resources.chromiumIdentities,
1140
+ null,
1141
+ );
1142
+ }
1143
+ }),
1144
+ closeGraceMs,
1145
+ ).catch(() => {});
1146
+ }
1147
+ const graceful = await Promise.allSettled([
1148
+ bounded(
1149
+ Promise.resolve().then(() => resources.electronApp?.close?.()),
1150
+ closeGraceMs,
1151
+ ),
1152
+ bounded(
1153
+ Promise.resolve().then(() => resources.browser?.close?.()),
1154
+ closeGraceMs,
1155
+ ),
1156
+ ]);
1157
+ resources.electronCloseObserved = graceful[0]?.status === "fulfilled";
1158
+ resources.chromiumCloseObserved = graceful[1]?.status === "fulfilled";
1159
+ await waitRetired([...resources.knownChromium, ...resources.knownElectron]);
1160
+ let current = receipt(
1161
+ graceful.some(({ status }) => status === "rejected") ? "graceful-close-failed" : null,
1162
+ );
1163
+ if (!current.chromiumRetired || !current.electronRetired) {
1164
+ const ownedRows = [
1165
+ ...ownedProcessRows(
1166
+ resources.chromiumPid,
1167
+ resources.knownChromium,
1168
+ resources.chromiumIdentities,
1169
+ null,
1170
+ ).map((row) => ({ ...row, host: "chromium" })),
1171
+ ...ownedProcessRows(
1172
+ resources.electronPid,
1173
+ resources.knownElectron,
1174
+ resources.electronIdentities,
1175
+ input.electronUserData,
1176
+ ).map((row) => ({ ...row, host: "electron" })),
1177
+ ].filter((row) => !terminalProcessState(row));
1178
+ const ownedPidSet = new Set(ownedRows.map(({ pid }) => pid));
1179
+ const depth = (row) => {
1180
+ let value = 0;
1181
+ let parent = row.ppid;
1182
+ while (ownedPidSet.has(parent) && value <= ownedRows.length) {
1183
+ value += 1;
1184
+ parent = ownedRows.find(({ pid }) => pid === parent)?.ppid;
1185
+ }
1186
+ return value;
1187
+ };
1188
+ const childrenFirst = [...ownedRows].sort((a, b) => depth(b) - depth(a));
1189
+ const exactCurrentRow = (row) => {
1190
+ const chromium = row.host === "chromium";
1191
+ return ownedProcessRows(
1192
+ chromium ? resources.chromiumPid : resources.electronPid,
1193
+ chromium ? resources.knownChromium : resources.knownElectron,
1194
+ chromium ? resources.chromiumIdentities : resources.electronIdentities,
1195
+ chromium ? null : input.electronUserData,
1196
+ ).find(({ pid }) => pid === row.pid);
1197
+ };
1198
+ for (const row of childrenFirst) {
1199
+ const exactRow = exactCurrentRow(row);
1200
+ if (!exactRow || terminalProcessState(exactRow)) continue;
1201
+ try {
1202
+ signalProcess(row.pid, "SIGTERM");
1203
+ } catch {
1204
+ // The identity-validated owned process may retire after observation.
1205
+ }
1206
+ }
1207
+ await waitRetired(childrenFirst.map(({ pid }) => pid));
1208
+ const remaining = childrenFirst.filter(({ pid }) => isAlive(pid));
1209
+ await sleep(closeTermMs);
1210
+ for (const row of remaining) {
1211
+ const exactRow = exactCurrentRow(row);
1212
+ if (!exactRow || terminalProcessState(exactRow)) continue;
1213
+ try {
1214
+ signalProcess(row.pid, "SIGKILL");
1215
+ } catch {
1216
+ // The identity-validated owned process may retire after observation.
1217
+ }
1218
+ }
1219
+ await waitRetired(remaining.map(({ pid }) => pid));
1220
+ current = receipt("owner-scoped-escalation");
1221
+ }
1222
+ if (current.chromiumRetired && current.electronRetired) retiredReceipt = current;
1223
+ return current;
1224
+ })().finally(() => {
1225
+ closePromise = null;
1226
+ });
1227
+ return closePromise;
1228
+ };
1229
+
1230
+ const ready = (async () => {
1231
+ if (!HASH.test(input.evidenceKey ?? "")) throw new TypeError("Card5 evidence key is malformed");
1232
+ const detailedUrl = new URL(input.pageUrl);
1233
+ detailedUrl.searchParams.set("performanceHud", "1");
1234
+ detailedUrl.searchParams.set("tmuxIdeResourceTelemetry", "1");
1235
+ detailedUrl.searchParams.set(CARD5_PROBE_QUERY, "1");
1236
+ const topology = card5ProductionHostTopology({ ...input, pageUrl: detailedUrl.toString() });
1237
+ const electronEntry = exactOwnedFile(input.electronEntry, input.repoRoot, "Electron entry");
1238
+ const environment = { ...input.environment };
1239
+ for (const name of [
1240
+ "TMUX_IDE_RIG_OWNER_TOKEN",
1241
+ "TMUX_IDE_OWNER_TOKEN",
1242
+ "TMUX_IDE_AUTH_TOKEN",
1243
+ "TMUX_IDE_CAPABILITY",
1244
+ ])
1245
+ delete environment[name];
1246
+ try {
1247
+ resources.stage = "chromium-launch";
1248
+ resources.browser = await abortable(
1249
+ acquisition(input.chromium.launch({ headless: true }), (value) => {
1250
+ resources.browser = value;
1251
+ }),
1252
+ controller.signal,
1253
+ );
1254
+ resources.stage = "chromium-identity";
1255
+ const chromiumSystem = await abortable(
1256
+ resources.browser
1257
+ .newBrowserCDPSession()
1258
+ .then((session) => session.send("SystemInfo.getProcessInfo")),
1259
+ controller.signal,
1260
+ );
1261
+ resources.chromiumPid =
1262
+ chromiumSystem.processInfo.find(({ type }) => type === "browser")?.id ?? null;
1263
+ if (Number.isSafeInteger(resources.chromiumPid)) {
1264
+ resources.chromiumIdentityObserved = true;
1265
+ resources.knownChromium.add(resources.chromiumPid);
1266
+ ownedProcessRows(
1267
+ resources.chromiumPid,
1268
+ resources.knownChromium,
1269
+ resources.chromiumIdentities,
1270
+ null,
1271
+ );
1272
+ }
1273
+ resources.stage = "chromium-context";
1274
+ resources.chromiumContext = await abortable(
1275
+ resources.browser.newContext({ viewport: { width: 1440, height: 900 } }),
1276
+ controller.signal,
1277
+ );
1278
+ resources.chromiumPage = await abortable(
1279
+ resources.chromiumContext.newPage(),
1280
+ controller.signal,
1281
+ );
1282
+ resources.chromiumPageEvents = installReadinessPageEvents(resources.chromiumPage);
1283
+ resources.stage = "chromium-readiness";
1284
+ await preparePage(
1285
+ resources.chromiumPage,
1286
+ topology.chromium.pageUrl,
1287
+ controller.signal,
1288
+ input.evidenceKey,
1289
+ );
1290
+ resources.stage = "electron-launch";
1291
+ resources.electronApp = await abortable(
1292
+ acquisition(
1293
+ input.electron.launch({
1294
+ args: [electronEntry, `--user-data-dir=${topology.electron.userData}`],
1295
+ env: {
1296
+ ...environment,
1297
+ TMUX_IDE_RENDERER_URL: topology.electron.rendererUrl,
1298
+ TMUX_IDE_DAEMON_INFO_DIR: resolve(input.daemonInfoDir),
1299
+ TMUX_IDE_HOME: topology.ownership.runtimeRoot,
1300
+ TMUX_IDE_REGISTRY_DIR: exactOwnedFile(
1301
+ input.registryDir,
1302
+ topology.ownership.runtimeRoot,
1303
+ "Electron registry directory",
1304
+ ),
1305
+ TMUX_IDE_SETTINGS_DIR: exactOwnedFile(
1306
+ input.settingsDir,
1307
+ topology.ownership.runtimeRoot,
1308
+ "Electron settings directory",
1309
+ ),
1310
+ },
1311
+ }),
1312
+ (value) => {
1313
+ resources.electronApp = value;
1314
+ resources.electronPid = value.process()?.pid ?? null;
1315
+ if (Number.isSafeInteger(resources.electronPid)) {
1316
+ resources.electronIdentityObserved = true;
1317
+ resources.knownElectron.add(resources.electronPid);
1318
+ ownedProcessRows(
1319
+ resources.electronPid,
1320
+ resources.knownElectron,
1321
+ resources.electronIdentities,
1322
+ input.electronUserData,
1323
+ );
1324
+ }
1325
+ },
1326
+ ),
1327
+ controller.signal,
1328
+ );
1329
+ resources.electronPid = resources.electronApp.process()?.pid ?? null;
1330
+ if (Number.isSafeInteger(resources.electronPid))
1331
+ resources.knownElectron.add(resources.electronPid);
1332
+ resources.stage = "electron-window";
1333
+ const electronPageEvents = new WeakMap();
1334
+ const registerElectronPage = (page) => {
1335
+ if (!electronPageEvents.has(page))
1336
+ electronPageEvents.set(page, installReadinessPageEvents(page));
1337
+ };
1338
+ resources.electronApp.on?.("window", registerElectronPage);
1339
+ resources.electronPage = await abortable(
1340
+ resources.electronApp.firstWindow({ timeout: 60_000 }),
1341
+ controller.signal,
1342
+ );
1343
+ registerElectronPage(resources.electronPage);
1344
+ resources.electronPageEvents = electronPageEvents.get(resources.electronPage);
1345
+ await resources.electronPage.addInitScript(() => {
1346
+ globalThis.__TMUX_IDE_ANSI_RENDITION_PROBE_ENABLED__ = true;
1347
+ globalThis.__TMUX_IDE_CARD5_EVIDENCE_ENABLED__ = true;
1348
+ });
1349
+ resources.stage = "electron-readiness";
1350
+ await abortable(
1351
+ resources.electronPage
1352
+ .locator(".app[data-shell-source='runtime']")
1353
+ .waitFor({ timeout: 60_000 }),
1354
+ controller.signal,
1355
+ );
1356
+ await waitForElectronReadyTerminal(
1357
+ resources.electronPage,
1358
+ controller.signal,
1359
+ input.evidenceKey,
1360
+ );
1361
+ if (
1362
+ !Number.isSafeInteger(resources.chromiumPid) ||
1363
+ !Number.isSafeInteger(resources.electronPid)
1364
+ )
1365
+ throw new Error("Card5 production host process identities were unavailable");
1366
+ resources.knownChromium = new Set([
1367
+ resources.chromiumPid,
1368
+ ...descendantPids(resources.chromiumPid),
1369
+ ]);
1370
+ resources.knownElectron = new Set([
1371
+ resources.electronPid,
1372
+ ...descendantPids(resources.electronPid),
1373
+ ]);
1374
+ resources.stage = "ready";
1375
+ return Object.freeze({
1376
+ topology,
1377
+ chromiumPage: resources.chromiumPage,
1378
+ electronPage: resources.electronPage,
1379
+ chromiumProcessIdentity: `chromium:${resources.chromiumPid}`,
1380
+ electronProcessIdentity: `electron:${resources.electronPid}`,
1381
+ lifecycle: Object.freeze({
1382
+ chromiumPid: resources.chromiumPid,
1383
+ electronPid: resources.electronPid,
1384
+ chromiumDescendants: Object.freeze(
1385
+ [...resources.knownChromium].filter((pid) => pid !== resources.chromiumPid),
1386
+ ),
1387
+ electronDescendants: Object.freeze(
1388
+ [...resources.knownElectron].filter((pid) => pid !== resources.electronPid),
1389
+ ),
1390
+ }),
1391
+ setElectronSlowHidden: async (rate = 4) => {
1392
+ if (!Number.isSafeInteger(rate) || rate < 1 || rate > 20)
1393
+ throw new TypeError("Electron throttle rate is outside the bounded Card5 range");
1394
+ const session = await resources.electronPage
1395
+ .context()
1396
+ .newCDPSession(resources.electronPage);
1397
+ await session.send("Emulation.setCPUThrottlingRate", { rate });
1398
+ await resources.electronApp.evaluate(({ BrowserWindow }) => {
1399
+ const windows = BrowserWindow.getAllWindows();
1400
+ if (windows.length !== 1) throw new Error("Card5 expected one Electron BrowserWindow");
1401
+ windows[0].hide();
1402
+ });
1403
+ await resources.electronPage.waitForFunction(
1404
+ () => globalThis.document.visibilityState === "hidden",
1405
+ );
1406
+ return Object.freeze({ hidden: true, throttled: rate > 1, session });
1407
+ },
1408
+ setElectronSinkBlocked: async (blocked) =>
1409
+ resources.electronPage.evaluate((next) => {
1410
+ const control = globalThis.__TMUX_IDE_CARD5_SINK_CONTROL__;
1411
+ if (!control) throw new Error("Card5 detailed sink control is unavailable");
1412
+ control.setBlocked(next);
1413
+ return control.snapshot();
1414
+ }, blocked === true),
1415
+ observeElectronSink: async () =>
1416
+ resources.electronPage.evaluate(() => {
1417
+ const control = globalThis.__TMUX_IDE_CARD5_SINK_CONTROL__;
1418
+ if (!control) throw new Error("Card5 detailed sink control is unavailable");
1419
+ return control.snapshot();
1420
+ }),
1421
+ restoreElectron: async (slow) => {
1422
+ await resources.electronPage.evaluate(() =>
1423
+ globalThis.__TMUX_IDE_CARD5_SINK_CONTROL__?.setBlocked(false),
1424
+ );
1425
+ await slow.session.send("Emulation.setCPUThrottlingRate", { rate: 1 });
1426
+ await resources.electronApp.evaluate(({ BrowserWindow }) => {
1427
+ const windows = BrowserWindow.getAllWindows();
1428
+ if (windows.length !== 1) throw new Error("Card5 expected one Electron BrowserWindow");
1429
+ windows[0].show();
1430
+ });
1431
+ },
1432
+ close,
1433
+ });
1434
+ } catch (error) {
1435
+ if (resources.stage === "chromium-readiness" && resources.chromiumPage)
1436
+ resources.chromiumReadinessObservation = await captureFailedReadiness(
1437
+ resources.chromiumPage,
1438
+ input.evidenceKey,
1439
+ resources.chromiumPageEvents,
1440
+ controller.signal,
1441
+ readinessObservationTimeoutMs,
1442
+ scheduleReadinessObservationTimeout,
1443
+ );
1444
+ if (resources.stage === "electron-readiness" && resources.electronPage)
1445
+ resources.electronReadinessObservation = await captureFailedReadiness(
1446
+ resources.electronPage,
1447
+ input.evidenceKey,
1448
+ resources.electronPageEvents,
1449
+ controller.signal,
1450
+ readinessObservationTimeoutMs,
1451
+ scheduleReadinessObservationTimeout,
1452
+ );
1453
+ resources.stage = `${resources.stage}:failed`;
1454
+ launchSettled = true;
1455
+ if (!closePromise) await close();
1456
+ if (error && typeof error === "object")
1457
+ error.observation = Object.freeze({
1458
+ operation: "card5-production-host-launch",
1459
+ reason: "host-unavailable",
1460
+ stage: resources.stage.replace(/:failed$/u, ""),
1461
+ chromiumCreated: resources.browser !== null,
1462
+ electronCreated: resources.electronApp !== null,
1463
+ ...(resources.chromiumReadinessObservation
1464
+ ? { chromiumReadiness: resources.chromiumReadinessObservation }
1465
+ : {}),
1466
+ ...(resources.electronReadinessObservation
1467
+ ? { electronReadiness: resources.electronReadinessObservation }
1468
+ : {}),
1469
+ });
1470
+ throw error;
1471
+ } finally {
1472
+ launchSettled = true;
1473
+ }
1474
+ })();
1475
+ return Object.freeze({ ready, close, snapshot: () => receipt() });
1476
+ }
1477
+
1478
+ /**
1479
+ * Launch the two real Web hosts used by Card5 from the existing ProductRig
1480
+ * owner. Electron runs its production main/preload/broker entry and attaches
1481
+ * to the exact canonical daemon record; it never receives a bearer token.
1482
+ */
1483
+ export async function launchCard5ProductionWebHosts(input) {
1484
+ return createCard5ProductionWebHostLease(input).ready;
1485
+ }
1486
+
1487
+ /** Exact browser-side canonical observation; it returns no cell or pane text. */
1488
+ export async function observeCard5WebCanonical(page, keyHex, processIdentity) {
1489
+ if (!HASH.test(keyHex ?? "")) throw new TypeError("Card5 evidence key is malformed");
1490
+ if (typeof processIdentity !== "string" || processIdentity.length > 256) {
1491
+ throw new TypeError("Card5 process identity is malformed");
1492
+ }
1493
+ const expectedIdentity = qualifiedTerminalIdentities.get(page);
1494
+ if (!expectedIdentity) throw new Error("Card5 qualified terminal readiness was not established");
1495
+ const observed = await page.evaluate(
1496
+ async ({
1497
+ exactKey,
1498
+ processIdentity: exactProcessIdentity,
1499
+ expectedIdentity: expected,
1500
+ expectedSurface,
1501
+ daemonInstanceIdPattern,
1502
+ }) => {
1503
+ const exactDaemonInstanceId = (value) =>
1504
+ typeof value === "string" &&
1505
+ value.length === 36 &&
1506
+ new RegExp(`^(?:${daemonInstanceIdPattern})$`, "iu").test(value);
1507
+ const surface = globalThis.__TMUX_IDE_CARD5_QUALIFIED_TERMINAL__?.("observation") ?? null;
1508
+ const surfaceProbeFailure = (axes) => ({
1509
+ card5ObservationFailure: "surface-probe-identity-invalid",
1510
+ surfaceProbeIdentity: Object.freeze({
1511
+ qualifiedSurfaceExact: axes.qualifiedSurfaceExact === true,
1512
+ probeSurfaceExact: axes.probeSurfaceExact === true,
1513
+ connected: axes.connected === true,
1514
+ documentExact: axes.documentExact === true,
1515
+ workspaceExact: axes.workspaceExact === true,
1516
+ paneExact: axes.paneExact === true,
1517
+ phaseExact: axes.phaseExact === true,
1518
+ framePreserved: axes.framePreserved === true,
1519
+ mutationCount: Number.isSafeInteger(axes.mutationCount)
1520
+ ? Math.min(64, axes.mutationCount)
1521
+ : null,
1522
+ mutationOverflow: axes.mutationOverflow === true,
1523
+ physicalBindingStable:
1524
+ axes.physicalBindingStable === null ? null : axes.physicalBindingStable === true,
1525
+ workspaceSnapshotStable:
1526
+ axes.workspaceSnapshotStable === null ? null : axes.workspaceSnapshotStable === true,
1527
+ workspaceHmac: /^[0-9a-f]{64}$/u.test(axes.workspaceHmac ?? "")
1528
+ ? axes.workspaceHmac
1529
+ : null,
1530
+ paneHmac: /^[0-9a-f]{64}$/u.test(axes.paneHmac ?? "") ? axes.paneHmac : null,
1531
+ }),
1532
+ });
1533
+ const initialAxes = () => ({
1534
+ qualifiedSurfaceExact:
1535
+ surface !== null &&
1536
+ surface === expectedSurface &&
1537
+ globalThis.__TMUX_IDE_CARD5_QUALIFIED_TERMINAL__?.("observation") === expectedSurface,
1538
+ probeSurfaceExact: false,
1539
+ connected: surface?.isConnected === true,
1540
+ documentExact:
1541
+ surface?.ownerDocument === globalThis.document &&
1542
+ globalThis.document?.defaultView === globalThis,
1543
+ workspaceExact: false,
1544
+ paneExact: false,
1545
+ phaseExact: surface?.getAttribute?.("data-phase") === "connected",
1546
+ framePreserved: surface?.getAttribute?.("data-preserves-frame") === "true",
1547
+ mutationCount: 0,
1548
+ mutationOverflow: false,
1549
+ physicalBindingStable: null,
1550
+ workspaceSnapshotStable: null,
1551
+ workspaceHmac: null,
1552
+ paneHmac: null,
1553
+ });
1554
+ const firstAxes = initialAxes();
1555
+ let lastAxes = firstAxes;
1556
+ if (
1557
+ !firstAxes.qualifiedSurfaceExact ||
1558
+ !firstAxes.connected ||
1559
+ !firstAxes.documentExact ||
1560
+ !firstAxes.phaseExact ||
1561
+ !firstAxes.framePreserved
1562
+ )
1563
+ return surfaceProbeFailure(firstAxes);
1564
+ const workspaceName = surface.getAttribute("data-workspace-name");
1565
+ const paneId = surface.getAttribute("data-semantic-pane-id");
1566
+ let mutationCount = 0;
1567
+ let mutationOverflow = false;
1568
+ const relevantElement = (node) => {
1569
+ if (!(node instanceof globalThis.Element)) return false;
1570
+ if (node === surface || node.contains?.(surface)) return true;
1571
+ if (
1572
+ node.matches?.(
1573
+ `.terminal-surface[data-semantic-pane-id=${globalThis.CSS.escape(paneId)}]`,
1574
+ )
1575
+ )
1576
+ return true;
1577
+ return (
1578
+ node.querySelector?.(
1579
+ `.terminal-surface[data-semantic-pane-id=${globalThis.CSS.escape(paneId)}]`,
1580
+ ) !== null
1581
+ );
1582
+ };
1583
+ const recordMutations = (records) => {
1584
+ for (const record of records) {
1585
+ const relevant =
1586
+ record.type === "attributes"
1587
+ ? relevantElement(record.target)
1588
+ : [...record.addedNodes, ...record.removedNodes].some(relevantElement);
1589
+ if (!relevant) continue;
1590
+ if (mutationCount === 64) mutationOverflow = true;
1591
+ else mutationCount += 1;
1592
+ }
1593
+ };
1594
+ const observer = new globalThis.MutationObserver(recordMutations);
1595
+ observer.observe(globalThis.document.documentElement, {
1596
+ subtree: true,
1597
+ childList: true,
1598
+ attributes: true,
1599
+ attributeOldValue: true,
1600
+ attributeFilter: [
1601
+ "data-workspace-name",
1602
+ "data-semantic-pane-id",
1603
+ "data-phase",
1604
+ "data-preserves-frame",
1605
+ ],
1606
+ });
1607
+ const drainMutations = () => recordMutations(observer.takeRecords());
1608
+ let expectedPhysicalBindingCaptured = false;
1609
+ let expectedPhysicalBinding = null;
1610
+ let physicalBindingUnstable = false;
1611
+ let expectedWorkspaceSnapshotKey = null;
1612
+ let workspaceSnapshotUnstable = false;
1613
+ const physicalBindingStable = () => {
1614
+ if (!expectedPhysicalBindingCaptured) return true;
1615
+ if (physicalBindingUnstable) return false;
1616
+ try {
1617
+ const current =
1618
+ globalThis.__TMUX_IDE_CARD5_ENVELOPE_EVIDENCE__?.()?.currentPhysicalBinding;
1619
+ const exact =
1620
+ expectedPhysicalBinding === null
1621
+ ? (current ?? null) === null
1622
+ : current?.physicalEpoch === expectedPhysicalBinding.physicalEpoch &&
1623
+ current?.generation === expectedPhysicalBinding.generation &&
1624
+ current?.requestId === expectedPhysicalBinding.requestId &&
1625
+ current?.runtimeSession === expectedPhysicalBinding.runtimeSession &&
1626
+ current?.workspaceName === expectedPhysicalBinding.workspaceName &&
1627
+ current?.clientId === expectedPhysicalBinding.clientId &&
1628
+ current?.stage === expectedPhysicalBinding.stage &&
1629
+ JSON.stringify(current?.semanticPaneIds) ===
1630
+ JSON.stringify(expectedPhysicalBinding.semanticPaneIds);
1631
+ if (!exact) physicalBindingUnstable = true;
1632
+ return exact;
1633
+ } catch {
1634
+ physicalBindingUnstable = true;
1635
+ return false;
1636
+ }
1637
+ };
1638
+ const workspaceSnapshotStable = () => {
1639
+ if (expectedWorkspaceSnapshotKey === null) return true;
1640
+ if (workspaceSnapshotUnstable) return false;
1641
+ try {
1642
+ const current = globalThis.__TMUX_IDE_CARD5_WORKSPACE_EVIDENCE__?.()?.snapshot;
1643
+ const exact =
1644
+ JSON.stringify({
1645
+ generation: current?.generation,
1646
+ phase: current?.phase,
1647
+ targetDaemonGeneration: current?.target?.daemon?.instanceId,
1648
+ authorityGeneration: current?.authority?.generation,
1649
+ authoritySession: current?.authority?.session,
1650
+ authorityClients: current?.authority?.clients,
1651
+ }) === expectedWorkspaceSnapshotKey;
1652
+ if (!exact) workspaceSnapshotUnstable = true;
1653
+ return exact;
1654
+ } catch {
1655
+ workspaceSnapshotUnstable = true;
1656
+ return false;
1657
+ }
1658
+ };
1659
+ const stillExact = () => (
1660
+ drainMutations(),
1661
+ mutationCount === 0 &&
1662
+ mutationOverflow === false &&
1663
+ surface === expectedSurface &&
1664
+ surface.isConnected === true &&
1665
+ surface.ownerDocument === globalThis.document &&
1666
+ globalThis.document?.defaultView === globalThis &&
1667
+ globalThis.__TMUX_IDE_CARD5_QUALIFIED_TERMINAL__?.("observation") === expectedSurface &&
1668
+ surface.getAttribute("data-workspace-name") === workspaceName &&
1669
+ surface.getAttribute("data-semantic-pane-id") === paneId &&
1670
+ surface.getAttribute("data-phase") === "connected" &&
1671
+ surface.getAttribute("data-preserves-frame") === "true" &&
1672
+ physicalBindingStable() &&
1673
+ workspaceSnapshotStable()
1674
+ );
1675
+ const assessedAxes = (overrides = {}) => ({
1676
+ ...lastAxes,
1677
+ qualifiedSurfaceExact:
1678
+ surface === expectedSurface &&
1679
+ globalThis.__TMUX_IDE_CARD5_QUALIFIED_TERMINAL__?.("observation") === expectedSurface,
1680
+ connected: surface?.isConnected === true,
1681
+ documentExact:
1682
+ surface?.ownerDocument === globalThis.document &&
1683
+ globalThis.document?.defaultView === globalThis,
1684
+ workspaceExact: surface?.getAttribute?.("data-workspace-name") === workspaceName,
1685
+ paneExact: surface?.getAttribute?.("data-semantic-pane-id") === paneId,
1686
+ phaseExact: surface?.getAttribute?.("data-phase") === "connected",
1687
+ framePreserved: surface?.getAttribute?.("data-preserves-frame") === "true",
1688
+ mutationCount,
1689
+ mutationOverflow,
1690
+ physicalBindingStable: expectedPhysicalBindingCaptured ? physicalBindingStable() : null,
1691
+ workspaceSnapshotStable:
1692
+ expectedWorkspaceSnapshotKey === null ? null : workspaceSnapshotStable(),
1693
+ ...overrides,
1694
+ });
1695
+ try {
1696
+ const bytes = Uint8Array.from(
1697
+ exactKey.match(/../gu).map((pair) => Number.parseInt(pair, 16)),
1698
+ );
1699
+ const key = await globalThis.crypto.subtle.importKey(
1700
+ "raw",
1701
+ bytes,
1702
+ { name: "HMAC", hash: "SHA-256" },
1703
+ false,
1704
+ ["sign"],
1705
+ );
1706
+ if (!stillExact()) return surfaceProbeFailure(assessedAxes());
1707
+ const hmac = async (domain, value) => {
1708
+ const maxLength = domain === "pane-set" ? 16_384 : 512;
1709
+ if (typeof value !== "string" || value.length === 0 || value.length > maxLength)
1710
+ return null;
1711
+ const signed = await globalThis.crypto.subtle.sign(
1712
+ "HMAC",
1713
+ key,
1714
+ new TextEncoder().encode(`${domain}\0${value}`),
1715
+ );
1716
+ const digest = [...new Uint8Array(signed)]
1717
+ .map((byte) => byte.toString(16).padStart(2, "0"))
1718
+ .join("");
1719
+ return stillExact() ? digest : null;
1720
+ };
1721
+ const paneSetValue = (paneIds) => {
1722
+ const sorted = Array.isArray(paneIds) ? [...paneIds].sort() : [];
1723
+ return `${sorted.length}\0${sorted.map((paneId) => `${paneId.length}\0${paneId}`).join("")}`;
1724
+ };
1725
+ const workspaceHmac = await hmac("workspace", workspaceName);
1726
+ lastAxes = assessedAxes({ workspaceHmac });
1727
+ if (!stillExact()) return surfaceProbeFailure(assessedAxes({ workspaceHmac }));
1728
+ if (workspaceHmac !== expected.workspaceHmac) return null;
1729
+ const paneHmac = await hmac("pane", paneId);
1730
+ lastAxes = assessedAxes({ workspaceHmac, paneHmac });
1731
+ if (!stillExact()) return surfaceProbeFailure(assessedAxes({ workspaceHmac, paneHmac }));
1732
+ if (paneHmac !== expected.paneHmac) return null;
1733
+ const probe = globalThis.__TMUX_IDE_PROBE_TERMINAL_RENDITION__;
1734
+ if (!paneId || typeof probe !== "function") return null;
1735
+ const result = await probe(paneId, exactKey);
1736
+ const resultAxes = assessedAxes({
1737
+ probeSurfaceExact: result?.surface === surface && result?.surface === expectedSurface,
1738
+ workspaceHmac,
1739
+ paneHmac,
1740
+ });
1741
+ lastAxes = resultAxes;
1742
+ if (!result) return surfaceProbeFailure(resultAxes);
1743
+ const resultStillExact = stillExact();
1744
+ if (!resultStillExact || !resultAxes.probeSurfaceExact)
1745
+ return surfaceProbeFailure(
1746
+ assessedAxes({
1747
+ probeSurfaceExact: resultAxes.probeSurfaceExact,
1748
+ workspaceHmac,
1749
+ paneHmac,
1750
+ }),
1751
+ );
1752
+ const queueText = [...globalThis.document.querySelectorAll(".gui-performance-hud dl")]
1753
+ .find((row) => row.querySelector("dt")?.textContent?.trim() === "Queue")
1754
+ ?.querySelector("dd")
1755
+ ?.textContent?.trim();
1756
+ const queue = /^(\d+)\s*\/\s*(\d+)$/u.exec(queueText ?? "");
1757
+ const evidence =
1758
+ typeof globalThis.__TMUX_IDE_CARD5_ENVELOPE_EVIDENCE__ === "function"
1759
+ ? globalThis.__TMUX_IDE_CARD5_ENVELOPE_EVIDENCE__()
1760
+ : null;
1761
+ const workspaceEvidence =
1762
+ typeof globalThis.__TMUX_IDE_CARD5_WORKSPACE_EVIDENCE__ === "function"
1763
+ ? globalThis.__TMUX_IDE_CARD5_WORKSPACE_EVIDENCE__()
1764
+ : null;
1765
+ const workspaceSnapshot = workspaceEvidence?.snapshot ?? null;
1766
+ const physicalBinding = evidence?.currentPhysicalBinding ?? null;
1767
+ expectedPhysicalBinding =
1768
+ physicalBinding === null
1769
+ ? null
1770
+ : Object.freeze({
1771
+ physicalEpoch: physicalBinding.physicalEpoch,
1772
+ generation: physicalBinding.generation,
1773
+ requestId: physicalBinding.requestId,
1774
+ runtimeSession: physicalBinding.runtimeSession,
1775
+ workspaceName: physicalBinding.workspaceName,
1776
+ clientId: physicalBinding.clientId,
1777
+ stage: physicalBinding.stage,
1778
+ semanticPaneIds: Array.isArray(physicalBinding.semanticPaneIds)
1779
+ ? Object.freeze([...physicalBinding.semanticPaneIds])
1780
+ : physicalBinding.semanticPaneIds,
1781
+ });
1782
+ expectedPhysicalBindingCaptured = true;
1783
+ expectedWorkspaceSnapshotKey = JSON.stringify({
1784
+ generation: workspaceSnapshot?.generation,
1785
+ phase: workspaceSnapshot?.phase,
1786
+ targetDaemonGeneration: workspaceSnapshot?.target?.daemon?.instanceId,
1787
+ authorityGeneration: workspaceSnapshot?.authority?.generation,
1788
+ authoritySession: workspaceSnapshot?.authority?.session,
1789
+ authorityClients: workspaceSnapshot?.authority?.clients,
1790
+ });
1791
+ if (!stillExact())
1792
+ return surfaceProbeFailure(
1793
+ assessedAxes({
1794
+ physicalBindingStable: physicalBindingStable(),
1795
+ workspaceSnapshotStable: workspaceSnapshotStable(),
1796
+ }),
1797
+ );
1798
+ const authorityGeneration = workspaceSnapshot?.authority?.generation;
1799
+ const targetDaemonGeneration = workspaceSnapshot?.target?.daemon?.instanceId;
1800
+ const daemonGeneration =
1801
+ exactDaemonInstanceId(authorityGeneration) &&
1802
+ authorityGeneration === targetDaemonGeneration
1803
+ ? authorityGeneration
1804
+ : null;
1805
+ const physicalBindingAxes = Object.freeze({
1806
+ present: physicalBinding !== null,
1807
+ epochSafe:
1808
+ Number.isSafeInteger(physicalBinding?.physicalEpoch) &&
1809
+ physicalBinding.physicalEpoch > 0,
1810
+ generationExact:
1811
+ daemonGeneration !== null &&
1812
+ physicalBinding?.generation === daemonGeneration &&
1813
+ result.canonical.generation === daemonGeneration,
1814
+ runtimeSessionExact:
1815
+ physicalBinding?.runtimeSession === workspaceSnapshot?.authority?.session,
1816
+ workspaceExact: physicalBinding?.workspaceName === workspaceName,
1817
+ paneExact:
1818
+ Array.isArray(physicalBinding?.semanticPaneIds) &&
1819
+ physicalBinding.semanticPaneIds.includes(paneId),
1820
+ stageExact: physicalBinding?.stage === "first-seed",
1821
+ clientExact:
1822
+ Array.isArray(workspaceSnapshot?.authority?.clients) &&
1823
+ workspaceSnapshot.authority.clients.filter(
1824
+ (client) =>
1825
+ client?.clientId === physicalBinding?.clientId && client?.surface === "web",
1826
+ ).length === 1,
1827
+ });
1828
+ const physicalBindingExact = Object.values(physicalBindingAxes).every(Boolean);
1829
+ const rawLifecycleRequests = Array.isArray(evidence?.activeLifecycleRequests)
1830
+ ? evidence.activeLifecycleRequests.filter(
1831
+ (request) =>
1832
+ daemonGeneration !== null &&
1833
+ request?.generation === daemonGeneration &&
1834
+ request.workspaceName === workspaceName &&
1835
+ Array.isArray(request.semanticPaneIds) &&
1836
+ request.semanticPaneIds.includes(paneId),
1837
+ )
1838
+ : [];
1839
+ const epochLifecycleRequests = Array.isArray(evidence?.activeLifecycleRequests)
1840
+ ? evidence.activeLifecycleRequests.filter(
1841
+ (request) =>
1842
+ physicalBindingExact &&
1843
+ request?.physicalEpoch === physicalBinding.physicalEpoch &&
1844
+ daemonGeneration !== null &&
1845
+ request?.generation === daemonGeneration &&
1846
+ request.workspaceName === workspaceName &&
1847
+ Array.isArray(request.semanticPaneIds) &&
1848
+ request.semanticPaneIds.includes(paneId),
1849
+ )
1850
+ : [];
1851
+ const activeLifecycleRequests = epochLifecycleRequests.filter(
1852
+ (request) => request?.requestId === physicalBinding.requestId,
1853
+ );
1854
+ const activeLifecycleRequestOverflow =
1855
+ evidence?.activeLifecycleRequestGlobalOverflow === true ||
1856
+ (Array.isArray(evidence?.activeLifecycleRequestOverflowGenerations) &&
1857
+ daemonGeneration !== null &&
1858
+ evidence.activeLifecycleRequestOverflowGenerations.includes(daemonGeneration)) ||
1859
+ epochLifecycleRequests.length > 8;
1860
+ const currentLifecycleRequestStatus = activeLifecycleRequestOverflow
1861
+ ? "overflow"
1862
+ : activeLifecycleRequests.length === 0
1863
+ ? "missing"
1864
+ : activeLifecycleRequests.length === 1 && epochLifecycleRequests.length === 1
1865
+ ? "exact"
1866
+ : "ambiguous";
1867
+ const currentLifecycleRequestHmac =
1868
+ currentLifecycleRequestStatus === "exact"
1869
+ ? await hmac("request", activeLifecycleRequests[0].requestId)
1870
+ : null;
1871
+ if (!stillExact()) return surfaceProbeFailure(assessedAxes());
1872
+ const epochLifecycleDescriptors =
1873
+ currentLifecycleRequestStatus === "exact" && Array.isArray(evidence?.descriptorEvents)
1874
+ ? evidence.descriptorEvents.filter(
1875
+ (descriptor) =>
1876
+ descriptor?.physicalEpoch === physicalBinding.physicalEpoch &&
1877
+ daemonGeneration !== null &&
1878
+ descriptor?.generation === daemonGeneration,
1879
+ )
1880
+ : [];
1881
+ const currentLifecycleDescriptors = epochLifecycleDescriptors.filter(
1882
+ (descriptor) =>
1883
+ descriptor?.requestId === activeLifecycleRequests[0]?.requestId &&
1884
+ descriptor?.requestId === physicalBinding.requestId,
1885
+ );
1886
+ const currentLifecycleDescriptorContractCount =
1887
+ epochLifecycleDescriptors.length === 0
1888
+ ? 0
1889
+ : epochLifecycleDescriptors.length === 1 && currentLifecycleDescriptors.length === 1
1890
+ ? 1
1891
+ : Math.min(Math.max(epochLifecycleDescriptors.length, 2), 8);
1892
+ const currentLifecycleSocketHmac =
1893
+ epochLifecycleDescriptors.length === 1 && currentLifecycleDescriptors.length === 1
1894
+ ? await hmac(
1895
+ "socket",
1896
+ `${currentLifecycleDescriptors[0].socketUrl}\0${activeLifecycleRequests[0].requestId}`,
1897
+ )
1898
+ : null;
1899
+ const activeLifecycleTail = Array.isArray(evidence?.activeLifecycleRequests)
1900
+ ? evidence.activeLifecycleRequests.slice(-2)
1901
+ : [];
1902
+ if (!stillExact()) return surfaceProbeFailure(assessedAxes());
1903
+ if (
1904
+ surface.getAttribute("data-workspace-name") !== workspaceName ||
1905
+ surface.getAttribute("data-semantic-pane-id") !== paneId
1906
+ ) {
1907
+ return null;
1908
+ }
1909
+ const authorityActivityEvidence =
1910
+ typeof globalThis.__TMUX_IDE_CARD5_AUTHORITY_ACTIVITY_EVIDENCE__ === "function"
1911
+ ? globalThis.__TMUX_IDE_CARD5_AUTHORITY_ACTIVITY_EVIDENCE__()
1912
+ : null;
1913
+ const geometryOkEvents = Array.isArray(authorityActivityEvidence?.events)
1914
+ ? authorityActivityEvidence.events.filter(
1915
+ (event) => event?.kind === "geometry" && event?.outcome === "ok",
1916
+ )
1917
+ : [];
1918
+ const geometrySettlements = Array.isArray(evidence?.geometryReceipts)
1919
+ ? await Promise.all(
1920
+ evidence.geometryReceipts.slice(-16).map(async (receipt, index) => ({
1921
+ ordinal: Number.isSafeInteger(receipt?.ordinal) ? receipt.ordinal : null,
1922
+ operationOrdinal: Number.isSafeInteger(geometryOkEvents[index]?.operationOrdinal)
1923
+ ? geometryOkEvents[index].operationOrdinal
1924
+ : null,
1925
+ requestHmac: await hmac("geometry-request", receipt?.requestId),
1926
+ clientHmac: await hmac("geometry-client", receipt?.authorityClientId),
1927
+ dimensionsHmac: await hmac(
1928
+ "geometry-dimensions",
1929
+ `${receipt?.cols}x${receipt?.rows}`,
1930
+ ),
1931
+ })),
1932
+ )
1933
+ : [];
1934
+ const authorityActivityProjection = authorityActivityEvidence
1935
+ ? {
1936
+ count: authorityActivityEvidence.count,
1937
+ overflow: authorityActivityEvidence.overflow,
1938
+ events: await Promise.all(
1939
+ authorityActivityEvidence.events.slice(-64).map(async (event) => ({
1940
+ ordinal: event.ordinal,
1941
+ surface: event.surface,
1942
+ kind: event.kind,
1943
+ outcome: event.outcome,
1944
+ operationOrdinal: event.operationOrdinal,
1945
+ dimensionsHmac:
1946
+ event.kind === "geometry"
1947
+ ? await hmac("geometry-dimensions", `${event.cols}x${event.rows}`)
1948
+ : null,
1949
+ })),
1950
+ ),
1951
+ geometrySettlements,
1952
+ }
1953
+ : null;
1954
+ const lifecycleTail = Array.isArray(evidence?.lifecycleEvents)
1955
+ ? evidence.lifecycleEvents
1956
+ .filter((event) => event?.physicalEpoch === physicalBinding?.physicalEpoch)
1957
+ .slice(-2)
1958
+ : [];
1959
+ const observation = {
1960
+ workspaceName,
1961
+ semanticPaneId: paneId,
1962
+ incarnation: result.canonical.incarnation,
1963
+ processIdentity: exactProcessIdentity,
1964
+ clockId: "browser-performance-now",
1965
+ atMicros: Math.round(globalThis.performance.now() * 1_000),
1966
+ generation: result.canonical.generation,
1967
+ revision: result.canonical.revision,
1968
+ cols: result.canonical.cols,
1969
+ rows: result.canonical.rows,
1970
+ deliveryFence: evidence?.acceptedCount ?? null,
1971
+ deliveryAckFence: evidence?.ackSentCount ?? null,
1972
+ canonicalStateHash: result.canonical.stateHash,
1973
+ contentHmac: result.rendition.renditionHmac,
1974
+ connected: true,
1975
+ surfaceProbeIdentity: Object.freeze({
1976
+ qualifiedSurfaceExact: true,
1977
+ probeSurfaceExact: true,
1978
+ connected: true,
1979
+ documentExact: true,
1980
+ workspaceExact: true,
1981
+ paneExact: true,
1982
+ phaseExact: true,
1983
+ framePreserved: true,
1984
+ mutationCount: 0,
1985
+ mutationOverflow: false,
1986
+ physicalBindingStable: true,
1987
+ workspaceSnapshotStable: true,
1988
+ workspaceHmac,
1989
+ paneHmac,
1990
+ }),
1991
+ presence: globalThis.document.visibilityState === "visible" ? "foreground" : "background",
1992
+ passive: surface.getAttribute("data-size-passive") === "true",
1993
+ geometryOwner: surface.getAttribute("data-geometry-ownership") === "owner",
1994
+ queueCurrent: queue ? Number(queue[1]) : null,
1995
+ queuePeak: queue ? Number(queue[2]) : null,
1996
+ envelopes: evidence?.events ?? [],
1997
+ runtimeReplacement: evidence
1998
+ ? {
1999
+ replacementCount: evidence.replacementCount,
2000
+ replacementBoundary: evidence.replacementBoundary,
2001
+ predecessorAcceptedAfterReplacement: evidence.predecessorAcceptedAfterReplacement,
2002
+ socketEvents: evidence.socketEvents,
2003
+ socketEventCount: evidence.socketEventCount,
2004
+ ackEvents: evidence.ackEvents,
2005
+ ackSentCount: evidence.ackSentCount,
2006
+ inputReceipts: evidence.inputReceipts,
2007
+ inputReceiptCount: evidence.inputReceiptCount,
2008
+ geometryReceipts: evidence.geometryReceipts,
2009
+ geometryReceiptCount: evidence.geometryReceiptCount,
2010
+ descriptorEvents: evidence.descriptorEvents,
2011
+ descriptorEventCount: evidence.descriptorEventCount,
2012
+ currentLifecycleRequest: Object.freeze({
2013
+ status: currentLifecycleRequestStatus,
2014
+ requestHmac: currentLifecycleRequestHmac,
2015
+ socketHmac: currentLifecycleSocketHmac,
2016
+ activeCount: Math.min(activeLifecycleRequests.length, 8),
2017
+ overflow: activeLifecycleRequestOverflow,
2018
+ descriptorCount: currentLifecycleDescriptorContractCount,
2019
+ rawActiveCount: Math.min(rawLifecycleRequests.length, 8),
2020
+ rawDescriptorCount: Math.min(
2021
+ Array.isArray(evidence.descriptorEvents) ? evidence.descriptorEvents.length : 0,
2022
+ 8,
2023
+ ),
2024
+ physicalBindingExact,
2025
+ physicalBindingAxes: Object.freeze({
2026
+ ...physicalBindingAxes,
2027
+ epochActiveCount: Math.min(epochLifecycleRequests.length, 8),
2028
+ bindingRequestExact:
2029
+ activeLifecycleRequests.length === 1 &&
2030
+ activeLifecycleRequests[0].requestId === physicalBinding?.requestId,
2031
+ descriptorExact:
2032
+ currentLifecycleDescriptorContractCount === 1 &&
2033
+ currentLifecycleSocketHmac !== null,
2034
+ }),
2035
+ physicalEpochHmac: physicalBindingExact
2036
+ ? await hmac("physical-epoch", String(physicalBinding.physicalEpoch))
2037
+ : null,
2038
+ bindingRequestHmac:
2039
+ physicalBindingExact && typeof physicalBinding.requestId === "string"
2040
+ ? await hmac("request", physicalBinding.requestId)
2041
+ : null,
2042
+ bindingClientHmac:
2043
+ physicalBindingExact && typeof physicalBinding.clientId === "string"
2044
+ ? await hmac("authority-client", physicalBinding.clientId)
2045
+ : null,
2046
+ deliveryClientHmac:
2047
+ physicalBindingExact && typeof physicalBinding.clientId === "string"
2048
+ ? await hmac("client", physicalBinding.clientId)
2049
+ : null,
2050
+ activeTail: Object.freeze(
2051
+ await Promise.all(
2052
+ activeLifecycleTail.map(async (request) => ({
2053
+ ordinal: Number.isSafeInteger(request?.firstSeedOrdinal)
2054
+ ? request.firstSeedOrdinal
2055
+ : null,
2056
+ epochHmac: await hmac("physical-epoch", String(request?.physicalEpoch)),
2057
+ generationHmac: await hmac("generation", request?.generation),
2058
+ requestHmac: await hmac("request", request?.requestId),
2059
+ workspaceHmac: await hmac("workspace", request?.workspaceName),
2060
+ paneSetHmac: await hmac("pane-set", paneSetValue(request?.semanticPaneIds)),
2061
+ })),
2062
+ ),
2063
+ ),
2064
+ lifecycleTail: Object.freeze(
2065
+ await Promise.all(
2066
+ lifecycleTail.map(async (event) => ({
2067
+ stage: event.stage,
2068
+ code: event.code,
2069
+ epochHmac: await hmac("physical-epoch", String(event.physicalEpoch)),
2070
+ ordinal: Number.isSafeInteger(event.ordinal) ? event.ordinal : null,
2071
+ })),
2072
+ ),
2073
+ ),
2074
+ firstSeedOrdinal:
2075
+ currentLifecycleRequestStatus === "exact" &&
2076
+ Number.isSafeInteger(activeLifecycleRequests[0].firstSeedOrdinal)
2077
+ ? activeLifecycleRequests[0].firstSeedOrdinal
2078
+ : null,
2079
+ }),
2080
+ }
2081
+ : null,
2082
+ workspaceEvidence: workspaceSnapshot
2083
+ ? {
2084
+ generation: workspaceSnapshot.generation,
2085
+ phase: workspaceSnapshot.phase,
2086
+ target: workspaceSnapshot.target,
2087
+ authority: workspaceSnapshot.authority,
2088
+ operations: workspaceSnapshot.operations,
2089
+ authorityRecords: workspaceEvidence.authorityRecords,
2090
+ authorityRecordCount: workspaceEvidence.authorityRecordCount,
2091
+ authorityActivity: authorityActivityProjection,
2092
+ }
2093
+ : null,
2094
+ };
2095
+ if (!stillExact())
2096
+ return surfaceProbeFailure(
2097
+ assessedAxes({
2098
+ physicalBindingStable: physicalBindingStable(),
2099
+ workspaceSnapshotStable: workspaceSnapshotStable(),
2100
+ }),
2101
+ );
2102
+ return observation;
2103
+ } finally {
2104
+ observer.disconnect();
2105
+ }
2106
+ },
2107
+ {
2108
+ exactKey: keyHex,
2109
+ processIdentity,
2110
+ expectedIdentity: {
2111
+ workspaceHmac: expectedIdentity.workspaceHmac,
2112
+ paneHmac: expectedIdentity.paneHmac,
2113
+ },
2114
+ expectedSurface: expectedIdentity.surfaceHandle,
2115
+ daemonInstanceIdPattern: DAEMON_INSTANCE_ID_PATTERN,
2116
+ },
2117
+ );
2118
+ if (observed?.card5ObservationFailure === "surface-probe-identity-invalid") {
2119
+ const error = new Error("Card5 canonical surface probe identity changed");
2120
+ error.observation = Object.freeze({
2121
+ operation: "card5-web-canonical-observation",
2122
+ reason: "surface-probe-identity-invalid",
2123
+ surfaceProbeIdentity: observed.surfaceProbeIdentity,
2124
+ });
2125
+ throw error;
2126
+ }
2127
+ return observed;
2128
+ }
2129
+
2130
+ /**
2131
+ * Identity-fenced authority/receipt observation for handoff polling. Unlike the
2132
+ * canonical observer this never requests a rendition, so authority progress is
2133
+ * not coupled to a potentially slow terminal capture.
2134
+ */
2135
+ export async function observeCard5WebAuthorityReceipt(page, keyHex, processIdentity) {
2136
+ if (!HASH.test(keyHex ?? "")) throw new TypeError("Card5 evidence key is malformed");
2137
+ if (typeof processIdentity !== "string" || processIdentity.length > 256) {
2138
+ throw new TypeError("Card5 process identity is malformed");
2139
+ }
2140
+ const expectedIdentity = qualifiedTerminalIdentities.get(page);
2141
+ if (!expectedIdentity) throw new Error("Card5 qualified terminal readiness was not established");
2142
+ return page.evaluate(
2143
+ async ({
2144
+ exactKey,
2145
+ processIdentity: exactProcessIdentity,
2146
+ expectedIdentity: expected,
2147
+ expectedSurface,
2148
+ daemonInstanceIdPattern,
2149
+ }) => {
2150
+ const exactDaemonInstanceId = (value) =>
2151
+ typeof value === "string" &&
2152
+ value.length === 36 &&
2153
+ new RegExp(`^(?:${daemonInstanceIdPattern})$`, "iu").test(value);
2154
+ const surface = globalThis.__TMUX_IDE_CARD5_QUALIFIED_TERMINAL__?.("observation") ?? null;
2155
+ if (!surface || surface !== expectedSurface) return null;
2156
+ const bytes = Uint8Array.from(
2157
+ exactKey.match(/../gu).map((pair) => Number.parseInt(pair, 16)),
2158
+ );
2159
+ const key = await globalThis.crypto.subtle.importKey(
2160
+ "raw",
2161
+ bytes,
2162
+ { name: "HMAC", hash: "SHA-256" },
2163
+ false,
2164
+ ["sign"],
2165
+ );
2166
+ const hmac = async (domain, value) => {
2167
+ const maxLength = domain === "pane-set" ? 16_384 : 512;
2168
+ if (typeof value !== "string" || value.length === 0 || value.length > maxLength)
2169
+ return null;
2170
+ const signed = await globalThis.crypto.subtle.sign(
2171
+ "HMAC",
2172
+ key,
2173
+ new TextEncoder().encode(`${domain}\0${value}`),
2174
+ );
2175
+ return [...new Uint8Array(signed)]
2176
+ .map((byte) => byte.toString(16).padStart(2, "0"))
2177
+ .join("");
2178
+ };
2179
+ const paneSetValue = (paneIds) => {
2180
+ const sorted = Array.isArray(paneIds) ? [...paneIds].sort() : [];
2181
+ return `${sorted.length}\0${sorted.map((paneId) => `${paneId.length}\0${paneId}`).join("")}`;
2182
+ };
2183
+ const workspaceName = surface.getAttribute("data-workspace-name");
2184
+ const paneId = surface.getAttribute("data-semantic-pane-id");
2185
+ const stillExact = () =>
2186
+ globalThis.__TMUX_IDE_CARD5_QUALIFIED_TERMINAL__?.("observation") === expectedSurface &&
2187
+ surface.getAttribute("data-workspace-name") === workspaceName &&
2188
+ surface.getAttribute("data-semantic-pane-id") === paneId;
2189
+ if (
2190
+ (await hmac("workspace", workspaceName)) !== expected.workspaceHmac ||
2191
+ (await hmac("pane", paneId)) !== expected.paneHmac ||
2192
+ !stillExact()
2193
+ ) {
2194
+ return null;
2195
+ }
2196
+ const envelope =
2197
+ typeof globalThis.__TMUX_IDE_CARD5_ENVELOPE_EVIDENCE__ === "function"
2198
+ ? globalThis.__TMUX_IDE_CARD5_ENVELOPE_EVIDENCE__()
2199
+ : null;
2200
+ const workspace =
2201
+ typeof globalThis.__TMUX_IDE_CARD5_WORKSPACE_EVIDENCE__ === "function"
2202
+ ? globalThis.__TMUX_IDE_CARD5_WORKSPACE_EVIDENCE__()
2203
+ : null;
2204
+ const snapshot = workspace?.snapshot ?? null;
2205
+ if (!envelope || !snapshot || !stillExact()) return null;
2206
+ const physicalBinding = envelope.currentPhysicalBinding ?? null;
2207
+ const authorityGeneration = snapshot.authority?.generation;
2208
+ const targetDaemonGeneration = snapshot.target?.daemon?.instanceId;
2209
+ const daemonGeneration =
2210
+ exactDaemonInstanceId(authorityGeneration) && authorityGeneration === targetDaemonGeneration
2211
+ ? authorityGeneration
2212
+ : null;
2213
+ const physicalBindingAxes = Object.freeze({
2214
+ present: physicalBinding !== null,
2215
+ epochSafe:
2216
+ Number.isSafeInteger(physicalBinding?.physicalEpoch) && physicalBinding.physicalEpoch > 0,
2217
+ generationExact:
2218
+ daemonGeneration !== null && physicalBinding?.generation === daemonGeneration,
2219
+ runtimeSessionExact: physicalBinding?.runtimeSession === snapshot.authority?.session,
2220
+ workspaceExact: physicalBinding?.workspaceName === workspaceName,
2221
+ paneExact:
2222
+ Array.isArray(physicalBinding?.semanticPaneIds) &&
2223
+ physicalBinding.semanticPaneIds.includes(paneId),
2224
+ stageExact: physicalBinding?.stage === "first-seed",
2225
+ clientExact:
2226
+ Array.isArray(snapshot.authority?.clients) &&
2227
+ snapshot.authority.clients.filter(
2228
+ (client) => client?.clientId === physicalBinding?.clientId && client?.surface === "web",
2229
+ ).length === 1,
2230
+ });
2231
+ const physicalBindingExact = Object.values(physicalBindingAxes).every(Boolean);
2232
+ const rawActive = Array.isArray(envelope.activeLifecycleRequests)
2233
+ ? envelope.activeLifecycleRequests.filter(
2234
+ (request) =>
2235
+ daemonGeneration !== null &&
2236
+ request?.generation === daemonGeneration &&
2237
+ request.workspaceName === workspaceName &&
2238
+ Array.isArray(request.semanticPaneIds) &&
2239
+ request.semanticPaneIds.includes(paneId),
2240
+ )
2241
+ : [];
2242
+ const epochActive = Array.isArray(envelope.activeLifecycleRequests)
2243
+ ? envelope.activeLifecycleRequests.filter(
2244
+ (request) =>
2245
+ physicalBindingExact &&
2246
+ request?.physicalEpoch === physicalBinding.physicalEpoch &&
2247
+ daemonGeneration !== null &&
2248
+ request?.generation === daemonGeneration &&
2249
+ request.workspaceName === workspaceName &&
2250
+ Array.isArray(request.semanticPaneIds) &&
2251
+ request.semanticPaneIds.includes(paneId),
2252
+ )
2253
+ : [];
2254
+ const active = epochActive.filter(
2255
+ (request) => request?.requestId === physicalBinding.requestId,
2256
+ );
2257
+ const overflow =
2258
+ envelope.activeLifecycleRequestGlobalOverflow === true ||
2259
+ (Array.isArray(envelope.activeLifecycleRequestOverflowGenerations) &&
2260
+ daemonGeneration !== null &&
2261
+ envelope.activeLifecycleRequestOverflowGenerations.includes(daemonGeneration)) ||
2262
+ epochActive.length > 8;
2263
+ const requestStatus = overflow
2264
+ ? "overflow"
2265
+ : active.length === 0
2266
+ ? "missing"
2267
+ : active.length === 1 && epochActive.length === 1
2268
+ ? "exact"
2269
+ : "ambiguous";
2270
+ const requestHmac =
2271
+ requestStatus === "exact" ? await hmac("request", active[0].requestId) : null;
2272
+ const epochDescriptors =
2273
+ requestStatus === "exact" && Array.isArray(envelope.descriptorEvents)
2274
+ ? envelope.descriptorEvents.filter(
2275
+ (descriptor) =>
2276
+ descriptor?.physicalEpoch === physicalBinding.physicalEpoch &&
2277
+ daemonGeneration !== null &&
2278
+ descriptor?.generation === daemonGeneration,
2279
+ )
2280
+ : [];
2281
+ const descriptors = epochDescriptors.filter(
2282
+ (descriptor) =>
2283
+ descriptor?.requestId === active[0]?.requestId &&
2284
+ descriptor?.requestId === physicalBinding.requestId,
2285
+ );
2286
+ const descriptorContractCount =
2287
+ epochDescriptors.length === 0
2288
+ ? 0
2289
+ : epochDescriptors.length === 1 && descriptors.length === 1
2290
+ ? 1
2291
+ : Math.min(Math.max(epochDescriptors.length, 2), 8);
2292
+ if (!stillExact()) return null;
2293
+ const lifecycleTail = Array.isArray(envelope.lifecycleEvents)
2294
+ ? envelope.lifecycleEvents
2295
+ .filter((event) => event?.physicalEpoch === physicalBinding?.physicalEpoch)
2296
+ .slice(-2)
2297
+ : [];
2298
+ const activeLifecycleTail = Array.isArray(envelope.activeLifecycleRequests)
2299
+ ? envelope.activeLifecycleRequests.slice(-2)
2300
+ : [];
2301
+ return {
2302
+ workspaceName,
2303
+ semanticPaneId: paneId,
2304
+ processIdentity: exactProcessIdentity,
2305
+ generation: daemonGeneration,
2306
+ runtimeReplacement: {
2307
+ inputReceipts: envelope.inputReceipts,
2308
+ inputReceiptCount: envelope.inputReceiptCount,
2309
+ currentLifecycleRequest: {
2310
+ status: requestStatus,
2311
+ requestHmac,
2312
+ paneSetHmac:
2313
+ requestStatus === "exact" && active.length === 1
2314
+ ? await hmac("pane-set", paneSetValue(active[0].semanticPaneIds))
2315
+ : null,
2316
+ activeCount: Math.min(active.length, 8),
2317
+ descriptorCount: descriptorContractCount,
2318
+ overflow,
2319
+ rawActiveCount: Math.min(rawActive.length, 8),
2320
+ rawDescriptorCount: Math.min(
2321
+ Array.isArray(envelope.descriptorEvents) ? envelope.descriptorEvents.length : 0,
2322
+ 8,
2323
+ ),
2324
+ physicalBindingExact,
2325
+ physicalBindingAxes: Object.freeze({
2326
+ ...physicalBindingAxes,
2327
+ epochActiveCount: Math.min(epochActive.length, 8),
2328
+ bindingRequestExact:
2329
+ active.length === 1 && active[0].requestId === physicalBinding?.requestId,
2330
+ descriptorExact: descriptorContractCount === 1,
2331
+ }),
2332
+ physicalEpochHmac: physicalBindingExact
2333
+ ? await hmac("physical-epoch", String(physicalBinding.physicalEpoch))
2334
+ : null,
2335
+ bindingRequestHmac:
2336
+ physicalBindingExact && typeof physicalBinding.requestId === "string"
2337
+ ? await hmac("request", physicalBinding.requestId)
2338
+ : null,
2339
+ bindingClientHmac:
2340
+ physicalBindingExact && typeof physicalBinding.clientId === "string"
2341
+ ? await hmac("authority-client", physicalBinding.clientId)
2342
+ : null,
2343
+ activeTail: await Promise.all(
2344
+ activeLifecycleTail.map(async (request) => ({
2345
+ ordinal: Number.isSafeInteger(request?.firstSeedOrdinal)
2346
+ ? request.firstSeedOrdinal
2347
+ : null,
2348
+ epochHmac: await hmac("physical-epoch", String(request?.physicalEpoch)),
2349
+ generationHmac: await hmac("generation", request?.generation),
2350
+ requestHmac: await hmac("request", request?.requestId),
2351
+ workspaceHmac: await hmac("workspace", request?.workspaceName),
2352
+ paneSetHmac: await hmac("pane-set", paneSetValue(request?.semanticPaneIds)),
2353
+ })),
2354
+ ),
2355
+ lifecycleTail: await Promise.all(
2356
+ lifecycleTail.map(async (event) => ({
2357
+ stage: event.stage,
2358
+ code: event.code,
2359
+ epochHmac: await hmac("physical-epoch", String(event.physicalEpoch)),
2360
+ ordinal: Number.isSafeInteger(event.ordinal) ? event.ordinal : null,
2361
+ })),
2362
+ ),
2363
+ },
2364
+ },
2365
+ workspaceEvidence: {
2366
+ generation: snapshot.generation,
2367
+ phase: snapshot.phase,
2368
+ target: snapshot.target,
2369
+ authority: snapshot.authority,
2370
+ authorityRecords: workspace.authorityRecords,
2371
+ authorityRecordCount: workspace.authorityRecordCount,
2372
+ },
2373
+ };
2374
+ },
2375
+ {
2376
+ exactKey: keyHex,
2377
+ processIdentity,
2378
+ expectedIdentity: {
2379
+ workspaceHmac: expectedIdentity.workspaceHmac,
2380
+ paneHmac: expectedIdentity.paneHmac,
2381
+ },
2382
+ expectedSurface: expectedIdentity.surfaceHandle,
2383
+ daemonInstanceIdPattern: DAEMON_INSTANCE_ID_PATTERN,
2384
+ },
2385
+ );
2386
+ }
2387
+
2388
+ /** Trusted pointer activation for the one already-qualified Card5 terminal. */
2389
+ export async function activateCard5ExactTerminalSurface({
2390
+ mode,
2391
+ page,
2392
+ keyHex,
2393
+ processIdentity,
2394
+ expectedPane,
2395
+ expectedPaneHmac,
2396
+ inputText,
2397
+ inputSha256,
2398
+ inputHostRole,
2399
+ inputOrdinal,
2400
+ deadline = performance.now() + 3_000,
2401
+ observeAuthorityReceipt = observeCard5WebAuthorityReceipt,
2402
+ }) {
2403
+ const activationStartedAt = performance.now();
2404
+ let activationPhase = "contract";
2405
+ let activationTargetKind = null;
2406
+ let activationTargetAxes = null;
2407
+ let activationLifecycleAxes = null;
2408
+ let activationInputGuardAxes = null;
2409
+ let activationInputGuardReason = null;
2410
+ let activationInputReceiptAxes = null;
2411
+ let activationInputReceiptStartAxes = null;
2412
+ let activationPointerDispatchAxes = null;
2413
+ let activationPointerDispatchReason = null;
2414
+ const boundedInputContextHmac = (domain, value) =>
2415
+ typeof keyHex === "string" && /^[0-9a-f]{64}$/u.test(keyHex) && value !== undefined
2416
+ ? createHmac("sha256", Buffer.from(keyHex, "hex"))
2417
+ .update(`${domain}\0${String(value)}`)
2418
+ .digest("hex")
2419
+ : null;
2420
+ const fail = (reason, cause) => {
2421
+ const failedAt = performance.now();
2422
+ const error = new Error("Card5 exact Web terminal focus activation failed", { cause });
2423
+ error.observation = Object.freeze({
2424
+ operation: "card5-web-terminal-focus",
2425
+ reason,
2426
+ expectedPaneHmac: HASH.test(expectedPaneHmac ?? "") ? expectedPaneHmac : null,
2427
+ phase: activationPhase,
2428
+ elapsedMs:
2429
+ Number.isFinite(failedAt) && Number.isFinite(activationStartedAt)
2430
+ ? Math.min(10_000, Math.max(0, Math.round(failedAt - activationStartedAt)))
2431
+ : null,
2432
+ remainingMs:
2433
+ Number.isFinite(failedAt) && Number.isFinite(deadline)
2434
+ ? Math.min(10_000, Math.max(0, Math.round(deadline - failedAt)))
2435
+ : null,
2436
+ targetKind: activationTargetKind,
2437
+ targetAxes: activationTargetAxes,
2438
+ lifecycleAxes: activationLifecycleAxes,
2439
+ inputGuardAxes: activationInputGuardAxes,
2440
+ inputGuardReason: activationInputGuardReason,
2441
+ inputReceiptAxes: activationInputReceiptAxes,
2442
+ inputReceiptStartAxes: activationInputReceiptStartAxes,
2443
+ pointerDispatchAxes: activationPointerDispatchAxes,
2444
+ pointerDispatchReason: activationPointerDispatchReason,
2445
+ inputHostRoleHmac: insertsInput
2446
+ ? boundedInputContextHmac("input-host-role", inputHostRole)
2447
+ : null,
2448
+ inputOrdinalHmac: insertsInput
2449
+ ? boundedInputContextHmac("input-ordinal", inputOrdinal)
2450
+ : null,
2451
+ });
2452
+ return error;
2453
+ };
2454
+ const insertsInput = mode === "input";
2455
+ if (
2456
+ !["focus", "input"].includes(mode) ||
2457
+ (insertsInput &&
2458
+ (typeof inputText !== "string" ||
2459
+ inputText.length === 0 ||
2460
+ inputText.length > 4_096 ||
2461
+ !HASH.test(inputSha256 ?? "") ||
2462
+ !["chromium", "electron"].includes(inputHostRole) ||
2463
+ !Number.isSafeInteger(inputOrdinal) ||
2464
+ inputOrdinal < 1 ||
2465
+ inputOrdinal > 2)) ||
2466
+ !Number.isFinite(deadline)
2467
+ ) {
2468
+ throw fail("input-contract-invalid");
2469
+ }
2470
+ const withinDeadline = async (operation, reason, phase = reason, disposeLateResult = null) => {
2471
+ activationPhase = phase;
2472
+ const startedAt = performance.now();
2473
+ if (!Number.isFinite(startedAt) || startedAt >= deadline) throw fail("activation-deadline");
2474
+ const remaining = deadline - startedAt;
2475
+ let timer;
2476
+ const pending = Promise.resolve().then(operation);
2477
+ let raceFinished = false;
2478
+ let resultAccepted = false;
2479
+ if (disposeLateResult !== null) {
2480
+ pending
2481
+ .then((result) => {
2482
+ if (raceFinished && !resultAccepted) return disposeLateResult(result);
2483
+ return undefined;
2484
+ })
2485
+ .catch(() => {});
2486
+ }
2487
+ pending.catch(() => {});
2488
+ try {
2489
+ const result = await Promise.race([
2490
+ pending,
2491
+ new Promise((_, reject) => {
2492
+ timer = setTimeout(() => reject(fail(reason)), remaining);
2493
+ }),
2494
+ ]);
2495
+ raceFinished = true;
2496
+ const settledAt = performance.now();
2497
+ if (!Number.isFinite(settledAt) || settledAt >= deadline) {
2498
+ await disposeLateResult?.(result);
2499
+ throw fail(reason);
2500
+ }
2501
+ resultAccepted = true;
2502
+ return result;
2503
+ } catch (error) {
2504
+ raceFinished = true;
2505
+ throw error;
2506
+ } finally {
2507
+ clearTimeout(timer);
2508
+ }
2509
+ };
2510
+ const observe = () =>
2511
+ withinDeadline(
2512
+ () => observeAuthorityReceipt(page, keyHex, processIdentity),
2513
+ "authority-observation-timeout",
2514
+ );
2515
+ await withinDeadline(() => page.bringToFront(), "page-activation-timeout", "bring-to-front");
2516
+ let before = await observe();
2517
+ if (before?.semanticPaneId !== expectedPane) throw fail("surface-identity-invalid");
2518
+ const exactDaemonGeneration = (observed) => {
2519
+ const generation = observed?.generation;
2520
+ return exactDaemonInstanceId(generation) &&
2521
+ observed?.workspaceEvidence?.authority?.generation === generation &&
2522
+ observed?.workspaceEvidence?.target?.daemon?.instanceId === generation
2523
+ ? generation
2524
+ : null;
2525
+ };
2526
+ if (exactDaemonGeneration(before) === null) throw fail("activation-lifecycle-invalid");
2527
+ const lifecycleIdentity = (observed) => {
2528
+ const lifecycle = observed?.runtimeReplacement?.currentLifecycleRequest;
2529
+ if (
2530
+ lifecycle?.status === "missing" &&
2531
+ lifecycle.requestHmac === null &&
2532
+ lifecycle.activeCount === 0 &&
2533
+ lifecycle.overflow === false &&
2534
+ lifecycle.descriptorCount === 0
2535
+ ) {
2536
+ return Object.freeze({
2537
+ status: "missing",
2538
+ requestHmac: null,
2539
+ activeCount: 0,
2540
+ descriptorCount: 0,
2541
+ overflow: false,
2542
+ });
2543
+ }
2544
+ if (
2545
+ lifecycle?.status === "exact" &&
2546
+ HASH.test(lifecycle.requestHmac ?? "") &&
2547
+ HASH.test(lifecycle.paneSetHmac ?? "") &&
2548
+ lifecycle.physicalBindingExact === true &&
2549
+ HASH.test(lifecycle.physicalEpochHmac ?? "") &&
2550
+ lifecycle.activeCount === 1 &&
2551
+ lifecycle.overflow === false &&
2552
+ lifecycle.descriptorCount === 1
2553
+ ) {
2554
+ return Object.freeze({
2555
+ status: "exact",
2556
+ requestHmac: lifecycle.requestHmac,
2557
+ paneSetHmac: lifecycle.paneSetHmac,
2558
+ activeCount: 1,
2559
+ descriptorCount: 1,
2560
+ overflow: false,
2561
+ });
2562
+ }
2563
+ return null;
2564
+ };
2565
+ const samePhysicalBinding = (observed) =>
2566
+ observed?.semanticPaneId === before.semanticPaneId &&
2567
+ observed?.workspaceName === before.workspaceName &&
2568
+ Number.isSafeInteger(before?.workspaceEvidence?.generation) &&
2569
+ before.workspaceEvidence.generation >= 0 &&
2570
+ Number.isSafeInteger(observed?.workspaceEvidence?.generation) &&
2571
+ observed.workspaceEvidence.generation === before.workspaceEvidence.generation &&
2572
+ exactDaemonGeneration(observed) === exactDaemonGeneration(before) &&
2573
+ observed?.generation === before.generation &&
2574
+ observed?.processIdentity === before.processIdentity &&
2575
+ JSON.stringify(observed?.workspaceEvidence?.target) ===
2576
+ JSON.stringify(before.workspaceEvidence?.target);
2577
+ let beforeLifecycle;
2578
+ let stableBefore;
2579
+ let receiptBoundary;
2580
+ let activationRequestHmac;
2581
+ let activationPaneSetHmac;
2582
+ if (insertsInput) {
2583
+ let previousCandidate = null;
2584
+ let previousObserved = null;
2585
+ let highestReceiptCount = -1;
2586
+ let observedRequestHmac = null;
2587
+ let observedPaneSetHmac = null;
2588
+ let current = before;
2589
+ while (performance.now() < deadline) {
2590
+ if (!samePhysicalBinding(current)) throw fail("input-activation-binding-changed");
2591
+ const lifecycle = current?.runtimeReplacement?.currentLifecycleRequest;
2592
+ const identity = lifecycleIdentity(current);
2593
+ const count = current?.runtimeReplacement?.inputReceiptCount;
2594
+ activationLifecycleAxes = Object.freeze({
2595
+ status:
2596
+ typeof lifecycle?.status === "string" && lifecycle.status.length <= 16
2597
+ ? lifecycle.status
2598
+ : "invalid",
2599
+ activeCount: Number.isSafeInteger(lifecycle?.activeCount)
2600
+ ? Math.min(8, Math.max(0, lifecycle.activeCount))
2601
+ : null,
2602
+ descriptorCount: Number.isSafeInteger(lifecycle?.descriptorCount)
2603
+ ? Math.min(8, Math.max(0, lifecycle.descriptorCount))
2604
+ : null,
2605
+ overflow: lifecycle?.overflow === true,
2606
+ rawActiveCount: Number.isSafeInteger(lifecycle?.rawActiveCount)
2607
+ ? Math.min(8, Math.max(0, lifecycle.rawActiveCount))
2608
+ : null,
2609
+ rawDescriptorCount: Number.isSafeInteger(lifecycle?.rawDescriptorCount)
2610
+ ? Math.min(8, Math.max(0, lifecycle.rawDescriptorCount))
2611
+ : null,
2612
+ physicalBindingExact: lifecycle?.physicalBindingExact === true,
2613
+ physicalBindingAxes: Object.freeze({
2614
+ present: lifecycle?.physicalBindingAxes?.present === true,
2615
+ epochSafe: lifecycle?.physicalBindingAxes?.epochSafe === true,
2616
+ generationExact: lifecycle?.physicalBindingAxes?.generationExact === true,
2617
+ runtimeSessionExact: lifecycle?.physicalBindingAxes?.runtimeSessionExact === true,
2618
+ workspaceExact: lifecycle?.physicalBindingAxes?.workspaceExact === true,
2619
+ paneExact: lifecycle?.physicalBindingAxes?.paneExact === true,
2620
+ stageExact: lifecycle?.physicalBindingAxes?.stageExact === true,
2621
+ clientExact: lifecycle?.physicalBindingAxes?.clientExact === true,
2622
+ epochActiveCount: Number.isSafeInteger(lifecycle?.physicalBindingAxes?.epochActiveCount)
2623
+ ? Math.min(8, Math.max(0, lifecycle.physicalBindingAxes.epochActiveCount))
2624
+ : null,
2625
+ bindingRequestExact: lifecycle?.physicalBindingAxes?.bindingRequestExact === true,
2626
+ descriptorExact: lifecycle?.physicalBindingAxes?.descriptorExact === true,
2627
+ }),
2628
+ physicalEpochHmacValid: HASH.test(lifecycle?.physicalEpochHmac ?? ""),
2629
+ bindingRequestHmacValid: HASH.test(lifecycle?.bindingRequestHmac ?? ""),
2630
+ bindingClientHmacValid: HASH.test(lifecycle?.bindingClientHmac ?? ""),
2631
+ activeTail: Object.freeze(
2632
+ Array.isArray(lifecycle?.activeTail)
2633
+ ? lifecycle.activeTail.slice(-2).map((request) =>
2634
+ Object.freeze({
2635
+ ordinal: Number.isSafeInteger(request?.ordinal) ? request.ordinal : null,
2636
+ epochHmacValid: HASH.test(request?.epochHmac ?? ""),
2637
+ generationHmacValid: HASH.test(request?.generationHmac ?? ""),
2638
+ requestHmacValid: HASH.test(request?.requestHmac ?? ""),
2639
+ workspaceHmacValid: HASH.test(request?.workspaceHmac ?? ""),
2640
+ paneSetHmacValid: HASH.test(request?.paneSetHmac ?? ""),
2641
+ }),
2642
+ )
2643
+ : [],
2644
+ ),
2645
+ lifecycleTail: Object.freeze(
2646
+ Array.isArray(lifecycle?.lifecycleTail)
2647
+ ? lifecycle.lifecycleTail.slice(-2).map((event) =>
2648
+ Object.freeze({
2649
+ stage:
2650
+ typeof event?.stage === "string" && event.stage.length <= 24
2651
+ ? event.stage
2652
+ : "invalid",
2653
+ code:
2654
+ typeof event?.code === "string" && event.code.length <= 64
2655
+ ? event.code
2656
+ : "invalid",
2657
+ epochHmacValid: HASH.test(event?.epochHmac ?? ""),
2658
+ ordinal: Number.isSafeInteger(event?.ordinal) ? event.ordinal : null,
2659
+ }),
2660
+ )
2661
+ : [],
2662
+ ),
2663
+ countValid: Number.isSafeInteger(count) && count >= 0,
2664
+ requestHmacValid: HASH.test(lifecycle?.requestHmac ?? ""),
2665
+ });
2666
+ if (!Number.isSafeInteger(count) || count < 0) throw fail("input-receipt-boundary-invalid");
2667
+ if (count < highestReceiptCount) throw fail("input-receipt-boundary-regressed");
2668
+ highestReceiptCount = count;
2669
+ if (lifecycle?.status === "overflow") throw fail("activation-lifecycle-overflow");
2670
+ if (lifecycle?.status === "ambiguous") throw fail("activation-lifecycle-ambiguous");
2671
+ if (identity === null) throw fail("activation-lifecycle-invalid");
2672
+ if (identity?.status === "exact") {
2673
+ if (observedRequestHmac !== null && observedRequestHmac !== identity.requestHmac)
2674
+ throw fail("input-activation-request-changed");
2675
+ if (observedPaneSetHmac !== null && observedPaneSetHmac !== identity.paneSetHmac)
2676
+ throw fail("input-activation-pane-set-changed");
2677
+ observedRequestHmac = identity.requestHmac;
2678
+ observedPaneSetHmac = identity.paneSetHmac;
2679
+ const candidate = JSON.stringify({
2680
+ requestHmac: identity.requestHmac,
2681
+ paneSetHmac: identity.paneSetHmac,
2682
+ count,
2683
+ });
2684
+ if (candidate === previousCandidate) {
2685
+ before = previousObserved;
2686
+ stableBefore = current;
2687
+ beforeLifecycle = identity;
2688
+ activationRequestHmac = identity.requestHmac;
2689
+ activationPaneSetHmac = identity.paneSetHmac;
2690
+ receiptBoundary = count;
2691
+ break;
2692
+ }
2693
+ previousCandidate = candidate;
2694
+ previousObserved = current;
2695
+ } else {
2696
+ previousCandidate = null;
2697
+ previousObserved = null;
2698
+ }
2699
+ await withinDeadline(
2700
+ () => new Promise((resolveWait) => setTimeout(resolveWait, 5)),
2701
+ "input-activation-request-timeout",
2702
+ "input-lifecycle-readiness",
2703
+ );
2704
+ current = await observe();
2705
+ }
2706
+ if (stableBefore === undefined) throw fail("input-activation-request-timeout");
2707
+ } else {
2708
+ beforeLifecycle = lifecycleIdentity(before);
2709
+ if (beforeLifecycle === null) {
2710
+ const status = before?.runtimeReplacement?.currentLifecycleRequest?.status;
2711
+ throw fail(
2712
+ status === "overflow"
2713
+ ? "activation-lifecycle-overflow"
2714
+ : status === "ambiguous"
2715
+ ? "activation-lifecycle-ambiguous"
2716
+ : "activation-lifecycle-invalid",
2717
+ );
2718
+ }
2719
+ activationRequestHmac = beforeLifecycle.requestHmac;
2720
+ activationPaneSetHmac = beforeLifecycle.paneSetHmac;
2721
+ receiptBoundary = before?.runtimeReplacement?.inputReceiptCount;
2722
+ stableBefore = await observe();
2723
+ if (
2724
+ !samePhysicalBinding(stableBefore) ||
2725
+ JSON.stringify(lifecycleIdentity(stableBefore)) !== JSON.stringify(beforeLifecycle)
2726
+ ) {
2727
+ throw fail("activation-binding-unstable");
2728
+ }
2729
+ }
2730
+ const sameBinding = (observed) =>
2731
+ samePhysicalBinding(observed) &&
2732
+ JSON.stringify(lifecycleIdentity(observed)) === JSON.stringify(beforeLifecycle);
2733
+ const samePreInputBinding = (observed) =>
2734
+ sameBinding(observed) && observed?.runtimeReplacement?.inputReceiptCount === receiptBoundary;
2735
+ const surfaces = page.locator(".terminal-surface[data-phase='connected']");
2736
+ const retainedHandles = new Set();
2737
+ let deferRetainedHandleDisposal = false;
2738
+ let deferredRetainedHandleTrigger = null;
2739
+ const disposeHandles = (handles) =>
2740
+ Promise.allSettled(
2741
+ (Array.isArray(handles) ? handles : []).map((handle) =>
2742
+ Promise.resolve().then(() => handle?.dispose?.()),
2743
+ ),
2744
+ );
2745
+ const disposeHandle = (handle) => Promise.resolve().then(() => handle?.dispose?.());
2746
+ const surfaceHandles = await withinDeadline(
2747
+ () => surfaces.elementHandles(),
2748
+ "surface-observation-timeout",
2749
+ "surface-handle-snapshot",
2750
+ disposeHandles,
2751
+ );
2752
+ surfaceHandles.forEach((handle) => retainedHandles.add(handle));
2753
+ try {
2754
+ const exactSurfaceHandles = [];
2755
+ for (const handle of surfaceHandles) {
2756
+ const exact = await withinDeadline(
2757
+ () =>
2758
+ handle.evaluate(
2759
+ (surface, exactPane) =>
2760
+ surface instanceof globalThis.HTMLElement &&
2761
+ surface.isConnected &&
2762
+ surface.getAttribute("data-phase") === "connected" &&
2763
+ surface.getAttribute("data-semantic-pane-id") === exactPane,
2764
+ expectedPane,
2765
+ ),
2766
+ "surface-observation-timeout",
2767
+ "surface-handle-qualification",
2768
+ );
2769
+ if (exact) exactSurfaceHandles.push(handle);
2770
+ }
2771
+ if (exactSurfaceHandles.length !== 1) throw fail("surface-handle-cardinality-invalid");
2772
+ const exactSurfaceHandle = exactSurfaceHandles[0];
2773
+ const areaJsHandle = await withinDeadline(
2774
+ () =>
2775
+ exactSurfaceHandle.evaluateHandle((surface) =>
2776
+ surface instanceof globalThis.HTMLElement ? surface.closest(".tiled-pane-area") : null,
2777
+ ),
2778
+ "surface-observation-timeout",
2779
+ "pointer-area-resolution",
2780
+ disposeHandle,
2781
+ );
2782
+ retainedHandles.add(areaJsHandle);
2783
+ const areaHandle = areaJsHandle.asElement();
2784
+ if (areaHandle === null) throw fail("pointer-target-cardinality-invalid");
2785
+ retainedHandles.add(areaHandle);
2786
+ const pointerTargetJsHandle = await withinDeadline(
2787
+ () =>
2788
+ exactSurfaceHandle.evaluateHandle(
2789
+ (surface, { area, exactPane }) => {
2790
+ if (!(surface instanceof globalThis.HTMLElement)) return null;
2791
+ if (
2792
+ !(area instanceof globalThis.HTMLElement) ||
2793
+ area.isConnected !== true ||
2794
+ surface.closest(".tiled-pane-area") !== area
2795
+ )
2796
+ return null;
2797
+ const paneCount = Number(area.getAttribute("data-pane-count"));
2798
+ const exactSurfaces = [
2799
+ ...globalThis.document.querySelectorAll(".terminal-surface[data-phase='connected']"),
2800
+ ].filter((candidate) => candidate.getAttribute("data-semantic-pane-id") === exactPane);
2801
+ if (exactSurfaces.length !== 1 || exactSurfaces[0] !== surface) return null;
2802
+ const composedBodies = [
2803
+ ...area.querySelectorAll(
2804
+ ":scope > .tiled-pane-area__overlay > .pane-tile[data-composed='true'] > .pane-tile__body",
2805
+ ),
2806
+ ];
2807
+ if (area.getAttribute("data-pane-compositor") === "true") {
2808
+ const composedPanes = composedBodies.map((body) =>
2809
+ body.parentElement?.getAttribute("data-pane"),
2810
+ );
2811
+ if (
2812
+ !Number.isSafeInteger(paneCount) ||
2813
+ paneCount <= 1 ||
2814
+ composedBodies.length !== paneCount ||
2815
+ composedPanes.some((pane) => typeof pane !== "string") ||
2816
+ new Set(composedPanes).size !== paneCount
2817
+ )
2818
+ return null;
2819
+ const matchingBodies = composedBodies.filter(
2820
+ (body) => body.parentElement?.getAttribute("data-pane") === exactPane,
2821
+ );
2822
+ return matchingBodies.length === 1 ? matchingBodies[0] : null;
2823
+ }
2824
+ return area.getAttribute("data-pane-compositor") === "false" &&
2825
+ paneCount === 1 &&
2826
+ composedBodies.length === 0
2827
+ ? surface
2828
+ : null;
2829
+ },
2830
+ { area: areaHandle, exactPane: expectedPane },
2831
+ ),
2832
+ "surface-observation-timeout",
2833
+ "pointer-target-resolution",
2834
+ disposeHandle,
2835
+ );
2836
+ retainedHandles.add(pointerTargetJsHandle);
2837
+ const pointerTargetHandle = pointerTargetJsHandle.asElement();
2838
+ if (pointerTargetHandle === null) throw fail("pointer-target-cardinality-invalid");
2839
+ retainedHandles.add(pointerTargetHandle);
2840
+ const observePointerTarget = () =>
2841
+ withinDeadline(
2842
+ () =>
2843
+ pointerTargetHandle.evaluate(
2844
+ (target, { surface, area, exactPane }) => {
2845
+ if (
2846
+ !(target instanceof globalThis.HTMLElement) ||
2847
+ !(surface instanceof globalThis.HTMLElement) ||
2848
+ !(area instanceof globalThis.HTMLElement) ||
2849
+ area.isConnected !== true
2850
+ )
2851
+ return null;
2852
+ if (
2853
+ surface.closest(".tiled-pane-area") !== area ||
2854
+ target.closest(".tiled-pane-area") !== area
2855
+ )
2856
+ return null;
2857
+ const paneCount = Number(area.getAttribute("data-pane-count"));
2858
+ const exactSurfaces = [
2859
+ ...globalThis.document.querySelectorAll(
2860
+ ".terminal-surface[data-phase='connected']",
2861
+ ),
2862
+ ].filter(
2863
+ (candidate) => candidate.getAttribute("data-semantic-pane-id") === exactPane,
2864
+ );
2865
+ const composedBodies = [
2866
+ ...area.querySelectorAll(
2867
+ ":scope > .tiled-pane-area__overlay > .pane-tile[data-composed='true'] > .pane-tile__body",
2868
+ ),
2869
+ ];
2870
+ const compositor = area.getAttribute("data-pane-compositor") === "true";
2871
+ const kind = compositor ? "compositor-pane-body" : "single-pane-surface";
2872
+ const matchingBodies = composedBodies.filter(
2873
+ (body) => body.parentElement?.getAttribute("data-pane") === exactPane,
2874
+ );
2875
+ const composedPanes = composedBodies.map((body) =>
2876
+ body.parentElement?.getAttribute("data-pane"),
2877
+ );
2878
+ const identityExact = compositor
2879
+ ? paneCount > 1 &&
2880
+ composedBodies.length === paneCount &&
2881
+ composedPanes.every((pane) => typeof pane === "string") &&
2882
+ new Set(composedPanes).size === paneCount &&
2883
+ matchingBodies.length === 1 &&
2884
+ matchingBodies[0] === target
2885
+ : area.getAttribute("data-pane-compositor") === "false" &&
2886
+ paneCount === 1 &&
2887
+ composedBodies.length === 0 &&
2888
+ target === surface;
2889
+ if (exactSurfaces.length !== 1 || exactSurfaces[0] !== surface || !identityExact)
2890
+ return null;
2891
+ const rect = target.getBoundingClientRect();
2892
+ const style = globalThis.getComputedStyle(target);
2893
+ const hit = globalThis.document.elementFromPoint(
2894
+ rect.left + rect.width / 2,
2895
+ rect.top + rect.height / 2,
2896
+ );
2897
+ const axes = Object.freeze({
2898
+ connected: target.isConnected === true && surface.isConnected === true,
2899
+ visible:
2900
+ style.display !== "none" &&
2901
+ style.visibility !== "hidden" &&
2902
+ Number(style.opacity) > 0,
2903
+ nonempty:
2904
+ Number.isFinite(rect.width) &&
2905
+ Number.isFinite(rect.height) &&
2906
+ rect.width > 0 &&
2907
+ rect.height > 0,
2908
+ hitTarget:
2909
+ hit === target || (hit instanceof globalThis.Node && target.contains(hit)),
2910
+ });
2911
+ return {
2912
+ kind,
2913
+ paneCount,
2914
+ axes,
2915
+ rect: [rect.left, rect.top, rect.width, rect.height].map((value) =>
2916
+ Math.round(value * 1000),
2917
+ ),
2918
+ };
2919
+ },
2920
+ { surface: exactSurfaceHandle, area: areaHandle, exactPane: expectedPane },
2921
+ ),
2922
+ "surface-observation-timeout",
2923
+ "pointer-target-observation",
2924
+ );
2925
+ const selectedTarget = await observePointerTarget();
2926
+ if (selectedTarget === null) throw fail("pointer-target-cardinality-invalid");
2927
+ activationTargetKind = selectedTarget.kind;
2928
+ activationTargetAxes = Object.freeze(selectedTarget.axes);
2929
+ if (Object.values(selectedTarget.axes).some((value) => value !== true))
2930
+ throw fail("pointer-target-actionability-invalid");
2931
+ let dispatchGuardHandle = null;
2932
+ try {
2933
+ if (!(insertsInput ? samePreInputBinding(await observe()) : sameBinding(await observe())))
2934
+ throw fail("activation-binding-unstable");
2935
+ dispatchGuardHandle = await withinDeadline(
2936
+ () =>
2937
+ pointerTargetHandle.evaluateHandle(
2938
+ (target, { surface, area, exactPane, keyHex: pointerKeyHex }) => {
2939
+ if (
2940
+ !(target instanceof globalThis.HTMLElement) ||
2941
+ !(surface instanceof globalThis.HTMLElement) ||
2942
+ !(area instanceof globalThis.HTMLElement)
2943
+ )
2944
+ return null;
2945
+ const outcome = {
2946
+ dispatched: false,
2947
+ trusted: false,
2948
+ buttonExact: false,
2949
+ pathExact: false,
2950
+ allowed: false,
2951
+ mutationCount: 0,
2952
+ mutationOverflow: false,
2953
+ eventCount: 0,
2954
+ eventOverflow: false,
2955
+ rejected: false,
2956
+ mutationCategories: {
2957
+ identityNode: 0,
2958
+ areaDescendant: 0,
2959
+ terminalAttribute: 0,
2960
+ paneAttribute: 0,
2961
+ childList: 0,
2962
+ inspectionOverflow: 0,
2963
+ },
2964
+ mutationTail: [],
2965
+ current: {
2966
+ areaConnected: false,
2967
+ surfaceConnected: false,
2968
+ targetConnected: false,
2969
+ surfaceAreaExact: false,
2970
+ targetAreaExact: false,
2971
+ surfaceCardinalityExact: false,
2972
+ compositorExact: false,
2973
+ topologyExact: false,
2974
+ },
2975
+ };
2976
+ let active = true;
2977
+ let mutationInspectionCount = 0;
2978
+ let relevantCategory = null;
2979
+ const touchesIdentity = (record) => {
2980
+ relevantCategory = null;
2981
+ mutationInspectionCount += 1;
2982
+ if (mutationInspectionCount > 256) {
2983
+ outcome.mutationOverflow = true;
2984
+ relevantCategory = "inspectionOverflow";
2985
+ return true;
2986
+ }
2987
+ const node = record.target;
2988
+ if (node === area || node === surface || node === target) {
2989
+ relevantCategory = "identityNode";
2990
+ return true;
2991
+ }
2992
+ if (node instanceof globalThis.Node && area.contains(node)) {
2993
+ relevantCategory = "areaDescendant";
2994
+ return true;
2995
+ }
2996
+ if (
2997
+ record.type === "attributes" &&
2998
+ node instanceof globalThis.HTMLElement &&
2999
+ node.matches(".terminal-surface") &&
3000
+ ((record.attributeName === "data-semantic-pane-id" &&
3001
+ (record.oldValue === exactPane ||
3002
+ node.getAttribute("data-semantic-pane-id") === exactPane)) ||
3003
+ (record.attributeName === "data-phase" &&
3004
+ (record.oldValue === "connected" ||
3005
+ node.getAttribute("data-phase") === "connected")))
3006
+ ) {
3007
+ relevantCategory = "terminalAttribute";
3008
+ return true;
3009
+ }
3010
+ if (
3011
+ record.type === "attributes" &&
3012
+ node instanceof globalThis.HTMLElement &&
3013
+ node.matches(".pane-tile[data-composed='true']") &&
3014
+ record.attributeName === "data-pane" &&
3015
+ (record.oldValue === exactPane || node.getAttribute("data-pane") === exactPane)
3016
+ ) {
3017
+ relevantCategory = "paneAttribute";
3018
+ return true;
3019
+ }
3020
+ const changed = [...record.addedNodes, ...record.removedNodes];
3021
+ for (const entry of changed) {
3022
+ if (entry === area || entry === surface || entry === target) {
3023
+ relevantCategory = "childList";
3024
+ return true;
3025
+ }
3026
+ if (!(entry instanceof globalThis.HTMLElement)) continue;
3027
+ if (
3028
+ area.contains(entry) ||
3029
+ entry.contains(area) ||
3030
+ entry.contains(surface) ||
3031
+ entry.contains(target)
3032
+ ) {
3033
+ relevantCategory = "childList";
3034
+ return true;
3035
+ }
3036
+ const descendants = [entry];
3037
+ let inspected = 0;
3038
+ while (descendants.length > 0) {
3039
+ const descendant = descendants.pop();
3040
+ inspected += 1;
3041
+ if (inspected > 64) {
3042
+ outcome.mutationOverflow = true;
3043
+ relevantCategory = "inspectionOverflow";
3044
+ return true;
3045
+ }
3046
+ if (
3047
+ descendant.matches(".terminal-surface") &&
3048
+ descendant.getAttribute("data-semantic-pane-id") === exactPane
3049
+ ) {
3050
+ relevantCategory = "childList";
3051
+ return true;
3052
+ }
3053
+ for (const child of descendant.children) {
3054
+ if (descendants.length + inspected >= 64) {
3055
+ outcome.mutationOverflow = true;
3056
+ relevantCategory = "inspectionOverflow";
3057
+ return true;
3058
+ }
3059
+ descendants.push(child);
3060
+ }
3061
+ }
3062
+ }
3063
+ return false;
3064
+ };
3065
+ const retainMutations = (records) => {
3066
+ for (const record of records) {
3067
+ if (outcome.mutationOverflow) break;
3068
+ if (!touchesIdentity(record)) continue;
3069
+ if (outcome.mutationCount >= 64) outcome.mutationOverflow = true;
3070
+ else {
3071
+ outcome.mutationCount += 1;
3072
+ const category = relevantCategory ?? "inspectionOverflow";
3073
+ outcome.mutationCategories[category] = Math.min(
3074
+ 64,
3075
+ outcome.mutationCategories[category] + 1,
3076
+ );
3077
+ outcome.mutationTail.push({
3078
+ type: record.type,
3079
+ attribute: record.type === "attributes" ? record.attributeName : null,
3080
+ relevance: `${category}\0${record.type}\0${record.attributeName ?? ""}`,
3081
+ });
3082
+ if (outcome.mutationTail.length > 2) outcome.mutationTail.shift();
3083
+ }
3084
+ }
3085
+ };
3086
+ const observer = new globalThis.MutationObserver((records) =>
3087
+ retainMutations(records),
3088
+ );
3089
+ observer.observe(globalThis.document.documentElement, {
3090
+ subtree: true,
3091
+ childList: true,
3092
+ attributes: true,
3093
+ attributeOldValue: true,
3094
+ attributeFilter: [
3095
+ "data-composed",
3096
+ "data-pane",
3097
+ "data-pane-compositor",
3098
+ "data-pane-count",
3099
+ "data-phase",
3100
+ "data-semantic-pane-id",
3101
+ ],
3102
+ });
3103
+ const stop = () => {
3104
+ if (!active) return;
3105
+ active = false;
3106
+ globalThis.document.removeEventListener("pointerdown", onPointerDown, true);
3107
+ for (const type of ["pointerup", "pointercancel", "click", "mousedown", "mouseup"])
3108
+ globalThis.document.removeEventListener(type, onPoisonedGesture, true);
3109
+ observer.disconnect();
3110
+ };
3111
+ const retainEvent = () => {
3112
+ if (outcome.eventCount >= 8) outcome.eventOverflow = true;
3113
+ else outcome.eventCount += 1;
3114
+ };
3115
+ const onPoisonedGesture = (event) => {
3116
+ if (!active || outcome.rejected !== true) return;
3117
+ retainEvent();
3118
+ event.preventDefault();
3119
+ event.stopImmediatePropagation();
3120
+ };
3121
+ const onPointerDown = (event) => {
3122
+ if (!active) return;
3123
+ retainEvent();
3124
+ outcome.dispatched = true;
3125
+ outcome.trusted = event.isTrusted === true;
3126
+ outcome.buttonExact = event.button === 0;
3127
+ retainMutations(observer.takeRecords());
3128
+ const exactSurfaces = [
3129
+ ...globalThis.document.querySelectorAll(
3130
+ ".terminal-surface[data-phase='connected']",
3131
+ ),
3132
+ ].filter(
3133
+ (candidate) => candidate.getAttribute("data-semantic-pane-id") === exactPane,
3134
+ );
3135
+ const composedBodies = [
3136
+ ...area.querySelectorAll(
3137
+ ":scope > .tiled-pane-area__overlay > .pane-tile[data-composed='true'] > .pane-tile__body",
3138
+ ),
3139
+ ];
3140
+ const paneCount = Number(area.getAttribute("data-pane-count"));
3141
+ const compositor = area.getAttribute("data-pane-compositor") === "true";
3142
+ const composedPanes = composedBodies.map((body) =>
3143
+ body.parentElement?.getAttribute("data-pane"),
3144
+ );
3145
+ const matchingBodies = composedBodies.filter(
3146
+ (body) => body.parentElement?.getAttribute("data-pane") === exactPane,
3147
+ );
3148
+ const topologyExact = compositor
3149
+ ? paneCount > 1 &&
3150
+ composedBodies.length === paneCount &&
3151
+ composedPanes.every((pane) => typeof pane === "string") &&
3152
+ new Set(composedPanes).size === paneCount &&
3153
+ matchingBodies.length === 1 &&
3154
+ matchingBodies[0] === target
3155
+ : area.getAttribute("data-pane-compositor") === "false" &&
3156
+ paneCount === 1 &&
3157
+ composedBodies.length === 0 &&
3158
+ target === surface;
3159
+ const path = event.composedPath();
3160
+ outcome.pathExact = path.includes(target);
3161
+ outcome.current = {
3162
+ areaConnected: area.isConnected === true,
3163
+ surfaceConnected: surface.isConnected === true,
3164
+ targetConnected: target.isConnected === true,
3165
+ surfaceAreaExact: surface.closest(".tiled-pane-area") === area,
3166
+ targetAreaExact: target.closest(".tiled-pane-area") === area,
3167
+ surfaceCardinalityExact:
3168
+ exactSurfaces.length === 1 && exactSurfaces[0] === surface,
3169
+ compositorExact: compositor ? target !== surface : target === surface,
3170
+ topologyExact,
3171
+ };
3172
+ const allowed =
3173
+ event.button === 0 &&
3174
+ outcome.trusted &&
3175
+ outcome.rejected === false &&
3176
+ outcome.eventOverflow === false &&
3177
+ outcome.mutationCount === 0 &&
3178
+ outcome.mutationOverflow === false &&
3179
+ area.isConnected === true &&
3180
+ surface.isConnected === true &&
3181
+ target.isConnected === true &&
3182
+ surface.closest(".tiled-pane-area") === area &&
3183
+ target.closest(".tiled-pane-area") === area &&
3184
+ exactSurfaces.length === 1 &&
3185
+ exactSurfaces[0] === surface &&
3186
+ topologyExact &&
3187
+ outcome.pathExact;
3188
+ if (allowed) {
3189
+ outcome.allowed = true;
3190
+ stop();
3191
+ } else {
3192
+ outcome.rejected = true;
3193
+ event.preventDefault();
3194
+ event.stopImmediatePropagation();
3195
+ }
3196
+ };
3197
+ globalThis.document.addEventListener("pointerdown", onPointerDown, true);
3198
+ for (const type of ["pointerup", "pointercancel", "click", "mousedown", "mouseup"])
3199
+ globalThis.document.addEventListener(type, onPoisonedGesture, true);
3200
+ return {
3201
+ async finish() {
3202
+ retainMutations(observer.takeRecords());
3203
+ stop();
3204
+ const key = await globalThis.crypto.subtle.importKey(
3205
+ "raw",
3206
+ Uint8Array.from(pointerKeyHex.match(/.{2}/gu), (byte) =>
3207
+ Number.parseInt(byte, 16),
3208
+ ),
3209
+ { name: "HMAC", hash: "SHA-256" },
3210
+ false,
3211
+ ["sign"],
3212
+ );
3213
+ const mutationTail = await Promise.all(
3214
+ outcome.mutationTail.map(async ({ type, attribute, relevance }) => ({
3215
+ type,
3216
+ attribute,
3217
+ relevanceHmac: [
3218
+ ...new Uint8Array(
3219
+ await globalThis.crypto.subtle.sign(
3220
+ "HMAC",
3221
+ key,
3222
+ new TextEncoder().encode(`card5-pointer-mutation\0${relevance}`),
3223
+ ),
3224
+ ),
3225
+ ]
3226
+ .map((byte) => byte.toString(16).padStart(2, "0"))
3227
+ .join(""),
3228
+ })),
3229
+ );
3230
+ return Object.freeze({ ...outcome, mutationTail });
3231
+ },
3232
+ };
3233
+ },
3234
+ {
3235
+ surface: exactSurfaceHandle,
3236
+ area: areaHandle,
3237
+ exactPane: expectedPane,
3238
+ keyHex,
3239
+ },
3240
+ ),
3241
+ "surface-observation-timeout",
3242
+ "trusted-pointer-dispatch-guard",
3243
+ disposeHandle,
3244
+ );
3245
+ retainedHandles.add(dispatchGuardHandle);
3246
+ const immediateTarget = await observePointerTarget();
3247
+ if (JSON.stringify(immediateTarget) !== JSON.stringify(selectedTarget))
3248
+ throw fail("pointer-target-changed");
3249
+ const clickRemaining = deadline - performance.now();
3250
+ if (!Number.isFinite(clickRemaining) || clickRemaining <= 25) {
3251
+ activationPhase = "trusted-pointer";
3252
+ throw fail("trusted-pointer-deadline");
3253
+ }
3254
+ await withinDeadline(
3255
+ () =>
3256
+ pointerTargetHandle.click({
3257
+ timeout: Math.max(1, Math.floor(clickRemaining - 25)),
3258
+ }),
3259
+ "trusted-pointer-deadline",
3260
+ "trusted-pointer",
3261
+ );
3262
+ const dispatchOutcome = await withinDeadline(
3263
+ () => dispatchGuardHandle.evaluate((guard) => guard?.finish?.() ?? null),
3264
+ "trusted-pointer-deadline",
3265
+ "trusted-pointer-dispatch-fence",
3266
+ );
3267
+ dispatchGuardHandle = null;
3268
+ activationPointerDispatchAxes = boundedCard5PointerDispatchAxes(dispatchOutcome);
3269
+ activationPointerDispatchReason = card5PointerDispatchFailureReason(
3270
+ activationPointerDispatchAxes,
3271
+ );
3272
+ if (
3273
+ dispatchOutcome?.dispatched !== true ||
3274
+ dispatchOutcome.trusted !== true ||
3275
+ dispatchOutcome.allowed !== true ||
3276
+ dispatchOutcome.mutationCount !== 0 ||
3277
+ dispatchOutcome.mutationOverflow !== false ||
3278
+ dispatchOutcome.eventOverflow !== false ||
3279
+ dispatchOutcome.rejected !== false
3280
+ )
3281
+ throw fail("trusted-pointer-topology-rejected");
3282
+ } catch (cause) {
3283
+ if (cause?.observation?.operation === "card5-web-terminal-focus") throw cause;
3284
+ if (cause?.name === "TimeoutError")
3285
+ throw fail("trusted-pointer-actionability-timeout", cause);
3286
+ throw fail("trusted-pointer-rejected", cause);
3287
+ } finally {
3288
+ if (dispatchGuardHandle !== null) {
3289
+ await Promise.resolve()
3290
+ .then(() => dispatchGuardHandle.evaluate((guard) => guard?.finish?.() ?? null))
3291
+ .catch(() => {});
3292
+ }
3293
+ }
3294
+ const exactXtermFocused = () =>
3295
+ withinDeadline(
3296
+ () =>
3297
+ exactSurfaceHandle.evaluate((surface, exactPane) => {
3298
+ if (!(surface instanceof globalThis.HTMLElement)) return false;
3299
+ const active = globalThis.document.activeElement;
3300
+ return (
3301
+ surface.isConnected &&
3302
+ surface.getAttribute("data-phase") === "connected" &&
3303
+ surface.getAttribute("data-semantic-pane-id") === exactPane &&
3304
+ active instanceof globalThis.HTMLTextAreaElement &&
3305
+ active.classList.contains("xterm-helper-textarea") &&
3306
+ surface.contains(active)
3307
+ );
3308
+ }, expectedPane),
3309
+ "focus-observation-timeout",
3310
+ );
3311
+ const focused = await exactXtermFocused();
3312
+ if (!focused) throw fail("xterm-focus-invalid");
3313
+ const pointerTargetUnchanged = async () => {
3314
+ const observed = await observePointerTarget();
3315
+ return JSON.stringify(observed) === JSON.stringify(selectedTarget);
3316
+ };
3317
+ if (!(await pointerTargetUnchanged())) throw fail("pointer-target-changed");
3318
+ const afterClick = await observe();
3319
+ if (!(insertsInput ? samePreInputBinding(afterClick) : sameBinding(afterClick)))
3320
+ throw fail("surface-binding-changed");
3321
+ if (!(await pointerTargetUnchanged())) throw fail("pointer-target-changed");
3322
+ if (!(await exactXtermFocused())) throw fail("xterm-focus-changed");
3323
+ if (!insertsInput) {
3324
+ const completedAt = performance.now();
3325
+ if (!Number.isFinite(completedAt) || completedAt >= deadline)
3326
+ throw fail("activation-deadline");
3327
+ return Object.freeze({
3328
+ before: Object.freeze({
3329
+ workspaceName: before.workspaceName,
3330
+ semanticPaneId: before.semanticPaneId,
3331
+ generation: before.generation,
3332
+ target: before.workspaceEvidence.target,
3333
+ }),
3334
+ after: Object.freeze({
3335
+ workspaceName: afterClick.workspaceName,
3336
+ semanticPaneId: afterClick.semanticPaneId,
3337
+ generation: afterClick.generation,
3338
+ target: afterClick.workspaceEvidence.target,
3339
+ }),
3340
+ receiptBoundary: null,
3341
+ requestHmac: activationRequestHmac,
3342
+ authorityClientId: null,
3343
+ receiptOrdinal: null,
3344
+ });
3345
+ }
3346
+ if (!(await exactXtermFocused())) throw fail("pre-input-focus-changed");
3347
+ const preInsert = await observe();
3348
+ if (!samePreInputBinding(preInsert)) throw fail("pre-input-receipt-boundary-changed");
3349
+ if (!(await pointerTargetUnchanged())) throw fail("pre-input-target-changed");
3350
+ const inputTextareaHandle = await withinDeadline(
3351
+ () =>
3352
+ exactSurfaceHandle.evaluateHandle((surface, exactPane) => {
3353
+ const active = globalThis.document.activeElement;
3354
+ return surface.isConnected &&
3355
+ surface.getAttribute("data-phase") === "connected" &&
3356
+ surface.getAttribute("data-semantic-pane-id") === exactPane &&
3357
+ active instanceof globalThis.HTMLTextAreaElement &&
3358
+ active.classList.contains("xterm-helper-textarea") &&
3359
+ surface.contains(active)
3360
+ ? active
3361
+ : null;
3362
+ }, expectedPane),
3363
+ "pre-input-focus-changed",
3364
+ "input-textarea-latch",
3365
+ disposeHandle,
3366
+ );
3367
+ retainedHandles.add(inputTextareaHandle);
3368
+ if (inputTextareaHandle.asElement() === null) throw fail("pre-input-focus-changed");
3369
+ const inputReceiptWaiterHandle = await withinDeadline(
3370
+ () =>
3371
+ inputTextareaHandle.evaluateHandle(
3372
+ async (
3373
+ textarea,
3374
+ {
3375
+ surface,
3376
+ exactPane,
3377
+ expectedWorkspace,
3378
+ expectedGeneration,
3379
+ expectedSession,
3380
+ expectedClientGeneration,
3381
+ expectedTarget,
3382
+ expectedRequestHmac,
3383
+ expectedPaneSetHmac,
3384
+ expectedInputSha,
3385
+ baselineCount,
3386
+ keyHex,
3387
+ paneIdPattern,
3388
+ paneIdReserved,
3389
+ paneIdDiscoveredPrefix,
3390
+ reserveMs,
3391
+ },
3392
+ ) => {
3393
+ const invalid = { status: "input-receipt-invalid", settled: true };
3394
+ if (
3395
+ !(textarea instanceof globalThis.HTMLTextAreaElement) ||
3396
+ !(surface instanceof globalThis.HTMLElement) ||
3397
+ !Number.isSafeInteger(baselineCount) ||
3398
+ baselineCount < 0 ||
3399
+ !Number.isFinite(reserveMs) ||
3400
+ reserveMs < 4_000
3401
+ )
3402
+ return { browserArmSample: globalThis.performance.now(), invalid };
3403
+ const bytes = Uint8Array.from(keyHex.match(/../gu) ?? [], (byte) =>
3404
+ Number.parseInt(byte, 16),
3405
+ );
3406
+ const cryptoKey = await globalThis.crypto.subtle.importKey(
3407
+ "raw",
3408
+ bytes,
3409
+ { name: "HMAC", hash: "SHA-256" },
3410
+ false,
3411
+ ["sign"],
3412
+ );
3413
+ const hmac = async (domain, value) =>
3414
+ [
3415
+ ...new Uint8Array(
3416
+ await globalThis.crypto.subtle.sign(
3417
+ "HMAC",
3418
+ cryptoKey,
3419
+ new TextEncoder().encode(`${domain}\0${value}`),
3420
+ ),
3421
+ ),
3422
+ ]
3423
+ .map((byte) => byte.toString(16).padStart(2, "0"))
3424
+ .join("");
3425
+ const envelope = globalThis.__TMUX_IDE_CARD5_ENVELOPE_EVIDENCE__?.();
3426
+ const snapshot = globalThis.__TMUX_IDE_CARD5_WORKSPACE_EVIDENCE__?.()?.snapshot;
3427
+ const binding = envelope?.currentPhysicalBinding;
3428
+ const workspaceName = surface.getAttribute("data-workspace-name");
3429
+ // The immediately preceding lightweight observation authenticated the
3430
+ // exact request HMAC and binding-request equality. Capture its raw
3431
+ // request only to join the later browser-local receipt without doing
3432
+ // another broad/HMAC-tail projection here.
3433
+ const requestExact =
3434
+ typeof expectedRequestHmac === "string" &&
3435
+ expectedRequestHmac.length === 64 &&
3436
+ typeof binding?.requestId === "string" &&
3437
+ binding.requestId.length > 0 &&
3438
+ binding.requestId.length <= 512 &&
3439
+ (await hmac("request", binding.requestId)) === expectedRequestHmac;
3440
+ const clientExact =
3441
+ typeof binding?.clientId === "string" &&
3442
+ Array.isArray(snapshot?.authority?.clients) &&
3443
+ snapshot.authority.clients.filter(
3444
+ (client) => client?.clientId === binding.clientId && client?.surface === "web",
3445
+ ).length === 1;
3446
+ const captured = {
3447
+ physicalEpoch: binding?.physicalEpoch,
3448
+ generation: binding?.generation,
3449
+ runtimeSession: binding?.runtimeSession,
3450
+ workspaceName: binding?.workspaceName,
3451
+ semanticPaneIds: Array.isArray(binding?.semanticPaneIds)
3452
+ ? [...binding.semanticPaneIds]
3453
+ : null,
3454
+ stage: binding?.stage,
3455
+ clientId: binding?.clientId,
3456
+ requestId: binding?.requestId,
3457
+ };
3458
+ const bindingPaneIds = binding?.semanticPaneIds;
3459
+ const paneIdRegex = new RegExp(`^(?:${paneIdPattern})$`, "u");
3460
+ const exactPaneId = (paneId) =>
3461
+ typeof paneId === "string" &&
3462
+ paneIdRegex.test(paneId) &&
3463
+ !paneIdReserved.includes(paneId) &&
3464
+ !paneId.startsWith(paneIdDiscoveredPrefix);
3465
+ const paneSetValue = (paneIds) =>
3466
+ `${paneIds.length}\0${paneIds
3467
+ .map((paneId) => `${paneId.length}\0${paneId}`)
3468
+ .join("")}`;
3469
+ const bindingPaneSetExact =
3470
+ Array.isArray(bindingPaneIds) &&
3471
+ bindingPaneIds.length > 0 &&
3472
+ bindingPaneIds.length <= 64 &&
3473
+ bindingPaneIds.every(exactPaneId) &&
3474
+ new Set(bindingPaneIds).size === bindingPaneIds.length &&
3475
+ JSON.stringify(bindingPaneIds) === JSON.stringify([...bindingPaneIds].sort()) &&
3476
+ bindingPaneIds.filter((paneId) => paneId === exactPane).length === 1;
3477
+ const bindingPaneSetHmacExact =
3478
+ bindingPaneSetExact &&
3479
+ typeof expectedPaneSetHmac === "string" &&
3480
+ expectedPaneSetHmac.length === 64 &&
3481
+ (await hmac("pane-set", paneSetValue([...bindingPaneIds].sort()))) ===
3482
+ expectedPaneSetHmac;
3483
+ const initial = {
3484
+ surfaceExact:
3485
+ surface.isConnected === true &&
3486
+ surface.getAttribute("data-phase") === "connected" &&
3487
+ surface.getAttribute("data-semantic-pane-id") === exactPane &&
3488
+ workspaceName === expectedWorkspace,
3489
+ textareaExact: surface.contains(textarea),
3490
+ focusExact: globalThis.document.activeElement === textarea,
3491
+ bindingEpochExact:
3492
+ Number.isSafeInteger(binding?.physicalEpoch) && binding.physicalEpoch > 0,
3493
+ bindingGenerationExact: binding?.generation === expectedGeneration,
3494
+ bindingSessionExact: binding?.runtimeSession === expectedSession,
3495
+ bindingWorkspaceExact: binding?.workspaceName === expectedWorkspace,
3496
+ bindingPaneExact: bindingPaneSetExact,
3497
+ bindingPaneSetHmacExact,
3498
+ bindingStageExact: binding?.stage === "first-seed",
3499
+ bindingClientExact: clientExact,
3500
+ bindingRequestExact: requestExact,
3501
+ authorityGenerationExact: snapshot?.authority?.generation === expectedGeneration,
3502
+ authoritySessionExact: snapshot?.authority?.session === expectedSession,
3503
+ clientGenerationExact: snapshot?.generation === expectedClientGeneration,
3504
+ targetExact: JSON.stringify(snapshot?.target) === expectedTarget,
3505
+ baselineCountSafe: Number.isSafeInteger(baselineCount) && baselineCount >= 0,
3506
+ currentCountSafe:
3507
+ Number.isSafeInteger(envelope?.inputReceiptCount) &&
3508
+ envelope.inputReceiptCount >= 0,
3509
+ currentCountExact: envelope?.inputReceiptCount === baselineCount,
3510
+ operationBoundarySafe:
3511
+ Number.isSafeInteger(envelope?.inputOperationCount) &&
3512
+ envelope.inputOperationCount >= 0,
3513
+ };
3514
+ const inputOperationBoundary = Number.isSafeInteger(envelope?.inputOperationCount)
3515
+ ? envelope.inputOperationCount
3516
+ : null;
3517
+ const initialExact =
3518
+ initial.surfaceExact &&
3519
+ initial.textareaExact &&
3520
+ initial.focusExact &&
3521
+ initial.bindingEpochExact &&
3522
+ initial.bindingGenerationExact &&
3523
+ initial.bindingSessionExact &&
3524
+ initial.bindingWorkspaceExact &&
3525
+ initial.bindingPaneExact &&
3526
+ initial.bindingPaneSetHmacExact &&
3527
+ initial.bindingStageExact &&
3528
+ initial.bindingClientExact &&
3529
+ initial.bindingRequestExact &&
3530
+ initial.authorityGenerationExact &&
3531
+ initial.authoritySessionExact &&
3532
+ initial.clientGenerationExact &&
3533
+ initial.targetExact &&
3534
+ initial.baselineCountSafe &&
3535
+ initial.currentCountSafe &&
3536
+ initial.currentCountExact &&
3537
+ initial.operationBoundarySafe;
3538
+ const state = {
3539
+ status: initialExact ? "pending" : "input-receipt-invalid",
3540
+ baselineCount,
3541
+ currentCount: Number.isSafeInteger(envelope?.inputReceiptCount)
3542
+ ? envelope.inputReceiptCount
3543
+ : null,
3544
+ candidateCount: 0,
3545
+ countRegressed: false,
3546
+ countAdvanced: false,
3547
+ surfaceExact: initialExact,
3548
+ textareaExact: initialExact,
3549
+ focusExact: initialExact,
3550
+ bindingExact: initialExact,
3551
+ generationExact: initialExact,
3552
+ sessionExact: initialExact,
3553
+ workspaceExact: initialExact,
3554
+ paneExact: initialExact,
3555
+ clientExact,
3556
+ requestExact,
3557
+ epochExact: initialExact,
3558
+ clientGenerationExact: initialExact,
3559
+ targetExact: initialExact,
3560
+ mutationCount: 0,
3561
+ mutationOverflow: false,
3562
+ authorityState: "null",
3563
+ timerCleared: false,
3564
+ settled: !initialExact,
3565
+ authorityClientId: null,
3566
+ receiptOrdinal: null,
3567
+ operationCount: 0,
3568
+ operationOverflow: false,
3569
+ operationTail: [],
3570
+ };
3571
+ let fixedDeadline = null;
3572
+ let dispatchAt = null;
3573
+ let authorityRequestAt = null;
3574
+ let inputSentAt = null;
3575
+ let timer = null;
3576
+ const recordMutations = (records) => {
3577
+ for (const record of records) {
3578
+ const changed = [...(record.addedNodes ?? []), ...(record.removedNodes ?? [])];
3579
+ const relevant =
3580
+ record.target === surface ||
3581
+ record.target === textarea ||
3582
+ changed.some(
3583
+ (node) =>
3584
+ node === surface ||
3585
+ node === textarea ||
3586
+ (node instanceof globalThis.Node &&
3587
+ (node.contains?.(surface) || node.contains?.(textarea))),
3588
+ );
3589
+ if (!relevant) continue;
3590
+ if (state.mutationCount < 32) state.mutationCount += 1;
3591
+ else state.mutationOverflow = true;
3592
+ }
3593
+ };
3594
+ const observer = new globalThis.MutationObserver(recordMutations);
3595
+ observer.observe(globalThis.document.documentElement, {
3596
+ attributes: true,
3597
+ childList: true,
3598
+ subtree: true,
3599
+ });
3600
+ let resolveOutcome;
3601
+ const outcomePromise = new Promise((resolve) => {
3602
+ resolveOutcome = resolve;
3603
+ });
3604
+ const finish = (status = state.status) => {
3605
+ if (!state.settled) state.settled = true;
3606
+ state.status = status;
3607
+ if (timer !== null) globalThis.clearInterval(timer);
3608
+ timer = null;
3609
+ recordMutations(observer.takeRecords());
3610
+ observer.disconnect();
3611
+ state.timerCleared = true;
3612
+ resolveOutcome?.({ ...state });
3613
+ resolveOutcome = null;
3614
+ return { ...state };
3615
+ };
3616
+ if (!initialExact) finish("input-receipt-invalid");
3617
+ const poll = () => {
3618
+ if (state.settled || dispatchAt === null) return;
3619
+ const now = globalThis.performance.now();
3620
+ if (
3621
+ !Number.isFinite(now) ||
3622
+ !Number.isFinite(fixedDeadline) ||
3623
+ now >= fixedDeadline
3624
+ ) {
3625
+ finish(
3626
+ authorityRequestAt === null
3627
+ ? "input-authority-unobserved-timeout"
3628
+ : "input-receipt-timeout",
3629
+ );
3630
+ return;
3631
+ }
3632
+ const nextEnvelope = globalThis.__TMUX_IDE_CARD5_ENVELOPE_EVIDENCE__?.();
3633
+ const nextSnapshot = globalThis.__TMUX_IDE_CARD5_WORKSPACE_EVIDENCE__?.()?.snapshot;
3634
+ const nextBinding = nextEnvelope?.currentPhysicalBinding;
3635
+ recordMutations(observer.takeRecords());
3636
+ const sameBinding = JSON.stringify(nextBinding) === JSON.stringify(binding);
3637
+ state.surfaceExact =
3638
+ surface.isConnected === true &&
3639
+ surface.getAttribute("data-phase") === "connected" &&
3640
+ surface.getAttribute("data-workspace-name") === expectedWorkspace &&
3641
+ surface.getAttribute("data-semantic-pane-id") === exactPane;
3642
+ state.textareaExact = textarea.isConnected === true && surface.contains(textarea);
3643
+ state.focusExact = globalThis.document.activeElement === textarea;
3644
+ state.bindingExact = sameBinding;
3645
+ state.generationExact =
3646
+ nextBinding?.generation === captured.generation &&
3647
+ nextSnapshot?.authority?.generation === expectedGeneration;
3648
+ state.sessionExact =
3649
+ nextBinding?.runtimeSession === captured.runtimeSession &&
3650
+ nextSnapshot?.authority?.session === expectedSession;
3651
+ state.workspaceExact = nextBinding?.workspaceName === captured.workspaceName;
3652
+ state.paneExact =
3653
+ JSON.stringify(nextBinding?.semanticPaneIds) ===
3654
+ JSON.stringify(captured.semanticPaneIds);
3655
+ state.clientExact = nextBinding?.clientId === captured.clientId;
3656
+ state.requestExact = nextBinding?.requestId === captured.requestId;
3657
+ state.epochExact = nextBinding?.physicalEpoch === captured.physicalEpoch;
3658
+ state.clientGenerationExact = nextSnapshot?.generation === expectedClientGeneration;
3659
+ state.targetExact = JSON.stringify(nextSnapshot?.target) === expectedTarget;
3660
+ if (
3661
+ !state.surfaceExact ||
3662
+ !state.textareaExact ||
3663
+ !state.focusExact ||
3664
+ !state.bindingExact ||
3665
+ !state.generationExact ||
3666
+ !state.sessionExact ||
3667
+ !state.workspaceExact ||
3668
+ !state.paneExact ||
3669
+ !state.clientExact ||
3670
+ !state.requestExact ||
3671
+ !state.epochExact ||
3672
+ !state.clientGenerationExact ||
3673
+ !state.targetExact ||
3674
+ state.mutationCount !== 0 ||
3675
+ state.mutationOverflow
3676
+ ) {
3677
+ finish("input-receipt-invalid");
3678
+ return;
3679
+ }
3680
+ const nextInputOperationCount = nextEnvelope?.inputOperationCount;
3681
+ const inputOperationDelta =
3682
+ Number.isSafeInteger(inputOperationBoundary) &&
3683
+ Number.isSafeInteger(nextInputOperationCount)
3684
+ ? nextInputOperationCount - inputOperationBoundary
3685
+ : null;
3686
+ const rawOperationEvents =
3687
+ Number.isSafeInteger(inputOperationBoundary) &&
3688
+ Array.isArray(nextEnvelope?.inputOperations)
3689
+ ? nextEnvelope.inputOperations.filter(
3690
+ (event) =>
3691
+ Number.isSafeInteger(event?.ordinal) &&
3692
+ event.ordinal >= inputOperationBoundary,
3693
+ )
3694
+ : [];
3695
+ const operationEvents = rawOperationEvents.filter(
3696
+ (event) =>
3697
+ event?.physicalEpoch === captured.physicalEpoch &&
3698
+ event?.generation === captured.generation &&
3699
+ event?.lifecycleRequestId === captured.requestId &&
3700
+ (event?.pane === null || event?.pane === exactPane) &&
3701
+ (event?.clientId === null || event?.clientId === captured.clientId),
3702
+ );
3703
+ const allowedOutcomes = {
3704
+ "xterm-enqueue": new Set(["ok"]),
3705
+ "surface-write": new Set(["attempt", "ok", "failed"]),
3706
+ "authority-request": new Set(["attempt", "sent", "send-failed"]),
3707
+ "authority-result": new Set([
3708
+ "granted",
3709
+ "rejected",
3710
+ "authority-timeout",
3711
+ "closed",
3712
+ "unavailable",
3713
+ ]),
3714
+ "input-send": new Set(["attempt", "sent", "send-failed"]),
3715
+ "input-ack": new Set(["ok", "ack-timeout"]),
3716
+ "receipt-published": new Set(["ok"]),
3717
+ };
3718
+ const eventIndex = (stage, outcome) =>
3719
+ operationEvents.findIndex(
3720
+ (event) => event.stage === stage && event.outcome === outcome,
3721
+ );
3722
+ const eventCount = (stage, outcome = null) =>
3723
+ operationEvents.filter(
3724
+ (event) =>
3725
+ event.stage === stage && (outcome === null || event.outcome === outcome),
3726
+ ).length;
3727
+ const authorityEvents = operationEvents.filter(
3728
+ (event) =>
3729
+ event.stage === "authority-request" || event.stage === "authority-result",
3730
+ );
3731
+ const authorityIds = new Set(
3732
+ authorityEvents.map((event) => event.authorityRequestId),
3733
+ );
3734
+ const inputEvents = operationEvents.filter((event) =>
3735
+ ["input-send", "input-ack", "receipt-published"].includes(event.stage),
3736
+ );
3737
+ const inputSequences = new Set(inputEvents.map((event) => event.seq));
3738
+ const surfaceAttempt = eventIndex("surface-write", "attempt");
3739
+ const authorityAttempt = eventIndex("authority-request", "attempt");
3740
+ const authoritySent = eventIndex("authority-request", "sent");
3741
+ const authoritySendFailed = eventIndex("authority-request", "send-failed");
3742
+ const authorityGranted = eventIndex("authority-result", "granted");
3743
+ const authorityTerminal = operationEvents.findIndex(
3744
+ (event) =>
3745
+ event.stage === "authority-result" &&
3746
+ ["rejected", "authority-timeout", "closed", "unavailable"].includes(
3747
+ event.outcome,
3748
+ ),
3749
+ );
3750
+ const inputAttempt = eventIndex("input-send", "attempt");
3751
+ const inputSent = eventIndex("input-send", "sent");
3752
+ const inputSendFailed = eventIndex("input-send", "send-failed");
3753
+ const inputAck = eventIndex("input-ack", "ok");
3754
+ const inputAckTimeout = eventIndex("input-ack", "ack-timeout");
3755
+ const receiptPublished = eventIndex("receipt-published", "ok");
3756
+ const operationTokens = operationEvents.map(
3757
+ (event) => `${event.stage}/${event.outcome}`,
3758
+ );
3759
+ const base = ["xterm-enqueue/ok", "surface-write/attempt"];
3760
+ const authorityGrantedPath = [
3761
+ ...base,
3762
+ "authority-request/attempt",
3763
+ "authority-request/sent",
3764
+ "authority-result/granted",
3765
+ ];
3766
+ const inputSuccessTail = [
3767
+ "input-send/attempt",
3768
+ "input-send/sent",
3769
+ "input-ack/ok",
3770
+ "receipt-published/ok",
3771
+ "surface-write/ok",
3772
+ ];
3773
+ const inputBranches = (prefix) => [
3774
+ [...prefix, ...inputSuccessTail],
3775
+ [...prefix, "input-send/attempt", "input-send/send-failed"],
3776
+ [...prefix, "input-send/attempt", "input-send/send-failed", "surface-write/failed"],
3777
+ [...prefix, "input-send/attempt", "input-send/sent", "input-ack/ack-timeout"],
3778
+ [
3779
+ ...prefix,
3780
+ "input-send/attempt",
3781
+ "input-send/sent",
3782
+ "input-ack/ack-timeout",
3783
+ "surface-write/failed",
3784
+ ],
3785
+ [
3786
+ ...prefix,
3787
+ "input-send/attempt",
3788
+ "input-send/sent",
3789
+ "input-ack/ok",
3790
+ "surface-write/failed",
3791
+ ],
3792
+ [...prefix, "input-send/attempt", "input-send/sent", "surface-write/failed"],
3793
+ ];
3794
+ const operationBranches = [
3795
+ [...base, "surface-write/failed"],
3796
+ ...inputBranches(base),
3797
+ ...inputBranches(authorityGrantedPath),
3798
+ ...["rejected", "authority-timeout", "closed", "unavailable"].flatMap((outcome) => {
3799
+ const terminal = [
3800
+ ...base,
3801
+ "authority-request/attempt",
3802
+ "authority-request/sent",
3803
+ `authority-result/${outcome}`,
3804
+ ];
3805
+ return [terminal, [...terminal, "surface-write/failed"]];
3806
+ }),
3807
+ [
3808
+ ...base,
3809
+ "authority-request/attempt",
3810
+ "authority-result/closed",
3811
+ "authority-request/send-failed",
3812
+ ],
3813
+ [
3814
+ ...base,
3815
+ "authority-request/attempt",
3816
+ "authority-result/closed",
3817
+ "authority-request/send-failed",
3818
+ "surface-write/failed",
3819
+ ],
3820
+ ];
3821
+ const operationFsmExact =
3822
+ operationTokens.length === 0 ||
3823
+ operationBranches.some(
3824
+ (branch) =>
3825
+ operationTokens.length <= branch.length &&
3826
+ operationTokens.every((token, index) => branch[index] === token),
3827
+ );
3828
+ const operationShapeExact =
3829
+ Number.isSafeInteger(inputOperationDelta) &&
3830
+ inputOperationDelta >= 0 &&
3831
+ inputOperationDelta <= 64 &&
3832
+ inputOperationDelta === rawOperationEvents.length &&
3833
+ rawOperationEvents.every(
3834
+ (event, index) => event.ordinal === inputOperationBoundary + index,
3835
+ ) &&
3836
+ operationEvents.length === rawOperationEvents.length &&
3837
+ operationEvents.every(
3838
+ (event) =>
3839
+ Object.hasOwn(allowedOutcomes, event.stage) &&
3840
+ allowedOutcomes[event.stage].has(event.outcome),
3841
+ ) &&
3842
+ operationEvents.every((event) => eventCount(event.stage, event.outcome) === 1) &&
3843
+ operationFsmExact &&
3844
+ authorityIds.size <= 1 &&
3845
+ !authorityIds.has(null) &&
3846
+ inputSequences.size <= 1 &&
3847
+ !inputSequences.has(null) &&
3848
+ (authorityEvents.length === 0 || authorityAttempt >= 2) &&
3849
+ (authoritySent < 0 ||
3850
+ (authorityAttempt >= 0 && authoritySent > authorityAttempt)) &&
3851
+ (authoritySendFailed < 0 ||
3852
+ (authorityAttempt >= 0 && authoritySendFailed > authorityAttempt)) &&
3853
+ (authorityGranted < 0 ||
3854
+ (authoritySent >= 0 && authorityGranted > authoritySent)) &&
3855
+ (authorityTerminal < 0 ||
3856
+ (authoritySent >= 0 && authorityTerminal > authoritySent) ||
3857
+ (authoritySendFailed >= 0 && authorityTerminal < authoritySendFailed)) &&
3858
+ (inputAttempt < 0 ||
3859
+ ((authorityEvents.length === 0 ||
3860
+ (authorityGranted >= 0 && inputAttempt > authorityGranted)) &&
3861
+ inputAttempt > surfaceAttempt)) &&
3862
+ (inputSent < 0 || (inputAttempt >= 0 && inputSent > inputAttempt)) &&
3863
+ (inputSendFailed < 0 || (inputAttempt >= 0 && inputSendFailed > inputAttempt)) &&
3864
+ (inputAck < 0 || (inputSent >= 0 && inputAck > inputSent)) &&
3865
+ (inputAckTimeout < 0 || (inputSent >= 0 && inputAckTimeout > inputSent)) &&
3866
+ (receiptPublished < 0 || (inputAck >= 0 && receiptPublished > inputAck));
3867
+ state.operationCount = Math.min(operationEvents.length, 64);
3868
+ state.operationOverflow = !operationShapeExact;
3869
+ const boundedOperationIdentity = (value) =>
3870
+ typeof value === "string" && value.length <= 512 ? value : null;
3871
+ state.operationTail = operationEvents.slice(-2).map((event) => ({
3872
+ ordinal: Number.isSafeInteger(event.ordinal) ? event.ordinal : null,
3873
+ stage: event.stage,
3874
+ outcome: event.outcome,
3875
+ generation: boundedOperationIdentity(event.generation),
3876
+ lifecycleRequestId: boundedOperationIdentity(event.lifecycleRequestId),
3877
+ authorityRequestId: boundedOperationIdentity(event.authorityRequestId),
3878
+ clientId: boundedOperationIdentity(event.clientId),
3879
+ pane: boundedOperationIdentity(event.pane),
3880
+ seq: Number.isSafeInteger(event.seq) && event.seq >= 0 ? event.seq : null,
3881
+ }));
3882
+ if (state.operationOverflow) {
3883
+ finish("input-receipt-invalid");
3884
+ return;
3885
+ }
3886
+ if (
3887
+ operationEvents.some(
3888
+ (event) => event.stage === "surface-write" && event.outcome === "failed",
3889
+ )
3890
+ ) {
3891
+ finish("input-receipt-invalid");
3892
+ return;
3893
+ }
3894
+ const latestAuthorityResult = operationEvents
3895
+ .filter((event) => event.stage === "authority-result")
3896
+ .at(-1);
3897
+ if (latestAuthorityResult?.outcome === "rejected") {
3898
+ finish("input-authority-rejected");
3899
+ return;
3900
+ }
3901
+ if (latestAuthorityResult?.outcome === "authority-timeout") {
3902
+ finish("input-authority-timeout");
3903
+ return;
3904
+ }
3905
+ if (["closed", "unavailable"].includes(latestAuthorityResult?.outcome)) {
3906
+ finish("input-authority-unavailable");
3907
+ return;
3908
+ }
3909
+ if (
3910
+ operationEvents.some(
3911
+ (event) => event.stage === "authority-request" && event.outcome === "send-failed",
3912
+ )
3913
+ ) {
3914
+ finish("input-authority-unavailable");
3915
+ return;
3916
+ }
3917
+ if (
3918
+ authorityRequestAt === null &&
3919
+ operationEvents.some(
3920
+ (event) => event.stage === "authority-request" && event.outcome === "sent",
3921
+ )
3922
+ )
3923
+ authorityRequestAt = now;
3924
+ if (
3925
+ inputSentAt === null &&
3926
+ operationEvents.some(
3927
+ (event) => event.stage === "input-send" && event.outcome === "sent",
3928
+ )
3929
+ )
3930
+ inputSentAt = now;
3931
+ if (
3932
+ operationEvents.some(
3933
+ (event) => event.stage === "input-ack" && event.outcome === "ack-timeout",
3934
+ )
3935
+ ) {
3936
+ finish("input-ack-timeout");
3937
+ return;
3938
+ }
3939
+ const owner = nextSnapshot?.authority?.owners?.input;
3940
+ state.authorityState =
3941
+ owner === null
3942
+ ? "null"
3943
+ : owner === captured.clientId
3944
+ ? "expected"
3945
+ : typeof owner === "string"
3946
+ ? "foreign"
3947
+ : "invalid";
3948
+ if (state.authorityState === "foreign" || state.authorityState === "invalid") {
3949
+ finish("input-authority-foreign");
3950
+ return;
3951
+ }
3952
+ if (
3953
+ authorityRequestAt !== null &&
3954
+ state.authorityState !== "expected" &&
3955
+ now - authorityRequestAt >= 2_000
3956
+ ) {
3957
+ finish("input-authority-timeout");
3958
+ return;
3959
+ }
3960
+ const count = nextEnvelope?.inputReceiptCount;
3961
+ state.currentCount = Number.isSafeInteger(count) && count >= 0 ? count : null;
3962
+ state.countRegressed = Number.isSafeInteger(count) && count < baselineCount;
3963
+ state.countAdvanced = Number.isSafeInteger(count) && count > baselineCount + 1;
3964
+ if (state.currentCount === null || state.countRegressed || state.countAdvanced) {
3965
+ finish("input-receipt-invalid");
3966
+ return;
3967
+ }
3968
+ const boundaryReceipts = Array.isArray(nextEnvelope?.inputReceipts)
3969
+ ? nextEnvelope.inputReceipts.filter((receipt) => receipt?.ordinal === baselineCount)
3970
+ : [];
3971
+ const candidates = boundaryReceipts.filter(
3972
+ (receipt) =>
3973
+ receipt?.generation === expectedGeneration &&
3974
+ receipt?.pane === exactPane &&
3975
+ receipt?.inputSha256 === expectedInputSha &&
3976
+ receipt?.authorityClientId === captured.clientId &&
3977
+ receipt?.requestId === captured.requestId,
3978
+ );
3979
+ state.candidateCount = Math.min(candidates.length, 8);
3980
+ if (
3981
+ boundaryReceipts.length > 1 ||
3982
+ candidates.length > 1 ||
3983
+ (count === baselineCount + 1 &&
3984
+ (boundaryReceipts.length !== 1 || candidates.length !== 1))
3985
+ ) {
3986
+ finish("input-receipt-invalid");
3987
+ return;
3988
+ }
3989
+ if (count === baselineCount + 1 && candidates.length === 1) {
3990
+ state.authorityClientId = captured.clientId;
3991
+ state.receiptOrdinal = baselineCount;
3992
+ state.clientGeneration = nextSnapshot.generation;
3993
+ state.target = nextSnapshot.target;
3994
+ finish("accepted");
3995
+ return;
3996
+ }
3997
+ if (inputSentAt !== null && now - inputSentAt >= 2_000) finish("input-ack-timeout");
3998
+ };
3999
+ return {
4000
+ browserArmSample: globalThis.performance.now(),
4001
+ armDeadline(deadline) {
4002
+ if (fixedDeadline !== null || !Number.isFinite(deadline)) return false;
4003
+ fixedDeadline = deadline;
4004
+ return true;
4005
+ },
4006
+ deadlineInstalled(deadline) {
4007
+ return fixedDeadline === deadline && globalThis.performance.now() < deadline;
4008
+ },
4009
+ startDispatch() {
4010
+ const now = globalThis.performance.now();
4011
+ const fixedDeadlineInstalled = fixedDeadline !== null;
4012
+ const fixedDeadlineFinite = Number.isFinite(fixedDeadline);
4013
+ const browserRemainingMs = fixedDeadlineFinite ? fixedDeadline - now : null;
4014
+ const dispatchFresh = dispatchAt === null;
4015
+ const result = (status) => ({
4016
+ status,
4017
+ settledStatus: state.status,
4018
+ fixedDeadlineInstalled,
4019
+ fixedDeadlineFinite,
4020
+ browserRemainingMs,
4021
+ reserveMs,
4022
+ dispatchFresh,
4023
+ initial: { ...initial },
4024
+ receipt: { ...state },
4025
+ });
4026
+ if (!initialExact) return result("initial-invalid");
4027
+ if (!dispatchFresh) return result("already-started");
4028
+ if (!fixedDeadlineFinite || !Number.isFinite(now))
4029
+ return result("deadline-invalid");
4030
+ if (browserRemainingMs < reserveMs) return result("reserve-insufficient");
4031
+ dispatchAt = now;
4032
+ timer = globalThis.setInterval(poll, 5);
4033
+ poll();
4034
+ return result("started");
4035
+ },
4036
+ awaitOutcome() {
4037
+ return outcomePromise;
4038
+ },
4039
+ finish() {
4040
+ return finish(state.settled ? state.status : "input-receipt-timeout");
4041
+ },
4042
+ };
4043
+ },
4044
+ {
4045
+ surface: exactSurfaceHandle,
4046
+ exactPane: expectedPane,
4047
+ expectedWorkspace: before.workspaceName,
4048
+ expectedGeneration: before.generation,
4049
+ expectedSession: before.workspaceEvidence.authority.session,
4050
+ expectedClientGeneration: before.workspaceEvidence.generation,
4051
+ expectedTarget: JSON.stringify(before.workspaceEvidence.target),
4052
+ expectedRequestHmac: activationRequestHmac,
4053
+ expectedPaneSetHmac: activationPaneSetHmac,
4054
+ expectedInputSha: inputSha256,
4055
+ baselineCount: receiptBoundary,
4056
+ keyHex,
4057
+ paneIdPattern: TERMINAL_ATTACHMENT_PANE_ID_PATTERN,
4058
+ paneIdReserved: TERMINAL_ATTACHMENT_PANE_ID_RESERVED,
4059
+ paneIdDiscoveredPrefix: TERMINAL_ATTACHMENT_PANE_ID_DISCOVERED_PREFIX,
4060
+ reserveMs: CARD5_INPUT_PRODUCT_PATH_RESERVE_MS + CARD5_INPUT_PREFLIGHT_MARGIN_MS,
4061
+ },
4062
+ ),
4063
+ "input-receipt-invalid",
4064
+ "input-receipt-waiter-arm",
4065
+ disposeHandle,
4066
+ );
4067
+ const inputGuardHandle = await withinDeadline(
4068
+ () =>
4069
+ inputTextareaHandle.evaluateHandle(
4070
+ (textarea, { surface, exactPane, exactInput }) => {
4071
+ if (
4072
+ !(textarea instanceof globalThis.HTMLTextAreaElement) ||
4073
+ !(surface instanceof globalThis.HTMLElement)
4074
+ )
4075
+ return null;
4076
+ const outcome = {
4077
+ beforeInputCount: 0,
4078
+ inputCount: 0,
4079
+ eventCount: 0,
4080
+ eventOverflow: false,
4081
+ mutationCount: 0,
4082
+ mutationOverflow: false,
4083
+ trusted: true,
4084
+ exactTarget: true,
4085
+ exactData: true,
4086
+ exactInputType: true,
4087
+ cancelableBeforeInput: true,
4088
+ restorationExact: true,
4089
+ rejected: false,
4090
+ };
4091
+ const browserArmSample = globalThis.performance.now();
4092
+ let dispatchDeadline = null;
4093
+ const valueSnapshots = new WeakMap();
4094
+ const retainValue = (target, allowReadOnlyProtection = false) => {
4095
+ if (target && typeof target.value === "string" && !valueSnapshots.has(target)) {
4096
+ if (target.value.length <= 16_384) {
4097
+ valueSnapshots.set(target, {
4098
+ kind: "value",
4099
+ value: target.value,
4100
+ selectionStart: Number.isSafeInteger(target.selectionStart)
4101
+ ? target.selectionStart
4102
+ : null,
4103
+ selectionEnd: Number.isSafeInteger(target.selectionEnd)
4104
+ ? target.selectionEnd
4105
+ : null,
4106
+ });
4107
+ return true;
4108
+ }
4109
+ if (allowReadOnlyProtection && typeof target.readOnly === "boolean") {
4110
+ const readOnly = target.readOnly;
4111
+ try {
4112
+ target.readOnly = true;
4113
+ if (target.readOnly !== true) return false;
4114
+ valueSnapshots.set(target, { kind: "read-only", readOnly });
4115
+ return true;
4116
+ } catch {
4117
+ return false;
4118
+ }
4119
+ }
4120
+ }
4121
+ return valueSnapshots.has(target);
4122
+ };
4123
+ const restoreValue = (target) => {
4124
+ const snapshot = valueSnapshots.get(target);
4125
+ if (!snapshot) return false;
4126
+ try {
4127
+ if (snapshot.kind === "read-only") {
4128
+ target.readOnly = snapshot.readOnly;
4129
+ return target.readOnly === snapshot.readOnly;
4130
+ }
4131
+ if (typeof target?.value !== "string") return false;
4132
+ target.value = snapshot.value;
4133
+ let selectionExact = true;
4134
+ if (
4135
+ snapshot.selectionStart !== null &&
4136
+ snapshot.selectionEnd !== null &&
4137
+ typeof target.setSelectionRange === "function"
4138
+ ) {
4139
+ try {
4140
+ target.setSelectionRange(snapshot.selectionStart, snapshot.selectionEnd);
4141
+ } catch {
4142
+ selectionExact = false;
4143
+ }
4144
+ }
4145
+ return target.value === snapshot.value && selectionExact;
4146
+ } catch {
4147
+ return false;
4148
+ }
4149
+ };
4150
+ if (!retainValue(textarea)) return null;
4151
+ let active = true;
4152
+ const relevantNode = (node) =>
4153
+ node instanceof globalThis.Element &&
4154
+ (node === surface ||
4155
+ node === textarea ||
4156
+ node.contains(surface) ||
4157
+ node.contains(textarea) ||
4158
+ (node.matches(".terminal-surface[data-phase='connected']") &&
4159
+ node.getAttribute("data-semantic-pane-id") === exactPane) ||
4160
+ (typeof node.querySelectorAll === "function" &&
4161
+ [...node.querySelectorAll(".terminal-surface[data-phase='connected']")].some(
4162
+ (candidate) => candidate.getAttribute("data-semantic-pane-id") === exactPane,
4163
+ )));
4164
+ const recordMutations = (records) => {
4165
+ for (const record of records) {
4166
+ if (outcome.mutationOverflow) break;
4167
+ const changed = [
4168
+ record.target,
4169
+ ...(record.addedNodes ?? []),
4170
+ ...(record.removedNodes ?? []),
4171
+ ];
4172
+ if (
4173
+ (record.type === "attributes" && relevantNode(record.target)) ||
4174
+ (record.type === "childList" && changed.some(relevantNode))
4175
+ ) {
4176
+ outcome.mutationCount += 1;
4177
+ if (outcome.mutationCount > 32) outcome.mutationOverflow = true;
4178
+ }
4179
+ }
4180
+ };
4181
+ const observer = new globalThis.MutationObserver(recordMutations);
4182
+ observer.observe(globalThis.document.documentElement, {
4183
+ attributes: true,
4184
+ attributeOldValue: true,
4185
+ childList: true,
4186
+ subtree: true,
4187
+ });
4188
+ const currentExact = () =>
4189
+ surface.isConnected &&
4190
+ textarea.isConnected !== false &&
4191
+ surface.getAttribute("data-phase") === "connected" &&
4192
+ surface.getAttribute("data-semantic-pane-id") === exactPane &&
4193
+ surface.contains(textarea) &&
4194
+ globalThis.document.activeElement === textarea &&
4195
+ [
4196
+ ...globalThis.document.querySelectorAll(
4197
+ ".terminal-surface[data-phase='connected']",
4198
+ ),
4199
+ ].filter((candidate) => candidate.getAttribute("data-semantic-pane-id") === exactPane)
4200
+ .length === 1;
4201
+ const block = (event) => {
4202
+ outcome.rejected = true;
4203
+ try {
4204
+ if (event.type === "input")
4205
+ outcome.restorationExact =
4206
+ restoreValue(event.composedPath()[0]) && outcome.restorationExact;
4207
+ } finally {
4208
+ event.preventDefault();
4209
+ event.stopImmediatePropagation();
4210
+ }
4211
+ };
4212
+ const inspect = (event, kind) => {
4213
+ recordMutations(observer.takeRecords());
4214
+ outcome.eventCount += 1;
4215
+ if (outcome.eventCount > 4) outcome.eventOverflow = true;
4216
+ const trusted = event.isTrusted === true;
4217
+ const exactTarget = event.composedPath()[0] === textarea && event.target === textarea;
4218
+ const exactData = event.data === exactInput;
4219
+ const exactInputType = event.inputType === "insertText";
4220
+ const cancelableBeforeInput = kind !== "beforeinput" || event.cancelable === true;
4221
+ const withinDispatchDeadline =
4222
+ Number.isFinite(dispatchDeadline) &&
4223
+ globalThis.performance.now() < dispatchDeadline;
4224
+ outcome.trusted = outcome.trusted && trusted;
4225
+ outcome.exactTarget = outcome.exactTarget && exactTarget;
4226
+ outcome.exactData = outcome.exactData && exactData;
4227
+ outcome.exactInputType = outcome.exactInputType && exactInputType;
4228
+ outcome.cancelableBeforeInput =
4229
+ outcome.cancelableBeforeInput && cancelableBeforeInput;
4230
+ if (
4231
+ outcome.rejected ||
4232
+ outcome.eventOverflow ||
4233
+ outcome.mutationCount !== 0 ||
4234
+ outcome.mutationOverflow ||
4235
+ !trusted ||
4236
+ !exactTarget ||
4237
+ !exactData ||
4238
+ !exactInputType ||
4239
+ !cancelableBeforeInput ||
4240
+ !withinDispatchDeadline ||
4241
+ !currentExact() ||
4242
+ (kind === "beforeinput" && outcome.beforeInputCount !== 0) ||
4243
+ (kind === "input" && (outcome.beforeInputCount !== 1 || outcome.inputCount !== 0))
4244
+ ) {
4245
+ block(event);
4246
+ return;
4247
+ }
4248
+ if (kind === "beforeinput") outcome.beforeInputCount += 1;
4249
+ else outcome.inputCount += 1;
4250
+ };
4251
+ const onBeforeInput = (event) => inspect(event, "beforeinput");
4252
+ const onInput = (event) => inspect(event, "input");
4253
+ const onFocusChurn = (event) => {
4254
+ if (event.type === "focusin")
4255
+ outcome.restorationExact =
4256
+ retainValue(event.composedPath()[0], true) && outcome.restorationExact;
4257
+ outcome.rejected = true;
4258
+ };
4259
+ globalThis.document.addEventListener("beforeinput", onBeforeInput, true);
4260
+ globalThis.document.addEventListener("input", onInput, true);
4261
+ globalThis.document.addEventListener("focusin", onFocusChurn, true);
4262
+ globalThis.document.addEventListener("focusout", onFocusChurn, true);
4263
+ const stop = () => {
4264
+ if (!active) return;
4265
+ active = false;
4266
+ observer.disconnect();
4267
+ globalThis.document.removeEventListener("beforeinput", onBeforeInput, true);
4268
+ globalThis.document.removeEventListener("input", onInput, true);
4269
+ globalThis.document.removeEventListener("focusin", onFocusChurn, true);
4270
+ globalThis.document.removeEventListener("focusout", onFocusChurn, true);
4271
+ };
4272
+ return {
4273
+ browserArmSample,
4274
+ armDeadline(fixedBrowserDeadline) {
4275
+ if (
4276
+ dispatchDeadline !== null ||
4277
+ !Number.isFinite(fixedBrowserDeadline) ||
4278
+ fixedBrowserDeadline <= browserArmSample
4279
+ )
4280
+ return false;
4281
+ dispatchDeadline = fixedBrowserDeadline;
4282
+ return true;
4283
+ },
4284
+ deadlineInstalled(fixedBrowserDeadline) {
4285
+ return (
4286
+ dispatchDeadline === fixedBrowserDeadline &&
4287
+ globalThis.performance.now() < dispatchDeadline
4288
+ );
4289
+ },
4290
+ finish() {
4291
+ recordMutations(observer.takeRecords());
4292
+ const exact = currentExact();
4293
+ if (outcome.beforeInputCount !== 1 || outcome.inputCount !== 1 || outcome.rejected)
4294
+ for (const target of [textarea, globalThis.document.activeElement])
4295
+ outcome.restorationExact = restoreValue(target) && outcome.restorationExact;
4296
+ stop();
4297
+ return { ...outcome, exact };
4298
+ },
4299
+ };
4300
+ },
4301
+ {
4302
+ surface: exactSurfaceHandle,
4303
+ exactPane: expectedPane,
4304
+ exactInput: inputText,
4305
+ },
4306
+ ),
4307
+ "input-guard-unavailable",
4308
+ "input-guard-arm",
4309
+ disposeHandle,
4310
+ );
4311
+ let inputGuardFinished = false;
4312
+ let inputOperationPending = false;
4313
+ let inputReceiptWaiterFinished = false;
4314
+ const finishInputGuard = async () => {
4315
+ if (inputGuardFinished) return null;
4316
+ const outcome = await inputGuardHandle.evaluate((guard) => guard?.finish?.() ?? null);
4317
+ inputGuardFinished = true;
4318
+ await Promise.resolve(inputGuardHandle.dispose()).catch(() => {});
4319
+ return outcome;
4320
+ };
4321
+ const finishInputReceiptWaiter = async () => {
4322
+ if (inputReceiptWaiterFinished) return null;
4323
+ const outcome = await inputReceiptWaiterHandle.evaluate(
4324
+ (waiter) => waiter?.finish?.() ?? null,
4325
+ );
4326
+ inputReceiptWaiterFinished = true;
4327
+ const disposal = Promise.resolve(inputReceiptWaiterHandle.dispose()).catch(() => {});
4328
+ let disposalTimer;
4329
+ await Promise.race([
4330
+ disposal,
4331
+ new Promise((resolveWait) => {
4332
+ disposalTimer = setTimeout(resolveWait, 100);
4333
+ }),
4334
+ ]);
4335
+ clearTimeout(disposalTimer);
4336
+ return outcome;
4337
+ };
4338
+ const boundedFinishInputReceiptWaiter = async () => {
4339
+ if (inputReceiptWaiterFinished) return;
4340
+ const pending = Promise.resolve().then(finishInputReceiptWaiter);
4341
+ pending.catch(() => {});
4342
+ deferredRetainedHandleTrigger = pending;
4343
+ const wait = async (promise, timeoutMs) => {
4344
+ let timer;
4345
+ try {
4346
+ return await Promise.race([
4347
+ Promise.resolve(promise).then(
4348
+ () => true,
4349
+ () => true,
4350
+ ),
4351
+ new Promise((resolveWait) => {
4352
+ timer = setTimeout(() => resolveWait(false), timeoutMs);
4353
+ }),
4354
+ ]);
4355
+ } finally {
4356
+ clearTimeout(timer);
4357
+ }
4358
+ };
4359
+ if (await wait(pending, 250)) return;
4360
+ const closePending = Promise.resolve().then(() =>
4361
+ page.close({ runBeforeUnload: false, reason: "Card5 input receipt waiter deadline" }),
4362
+ );
4363
+ closePending.catch(() => {});
4364
+ const pendingSettled = pending.then(
4365
+ () => undefined,
4366
+ () => undefined,
4367
+ );
4368
+ const closeSucceeded = closePending.then(
4369
+ () => undefined,
4370
+ () => new Promise(() => {}),
4371
+ );
4372
+ deferredRetainedHandleTrigger = Promise.race([pendingSettled, closeSucceeded]);
4373
+ if (await wait(closePending, 250)) await wait(pending, 250);
4374
+ };
4375
+ try {
4376
+ const browserArmSample = await withinDeadline(
4377
+ () =>
4378
+ inputGuardHandle.evaluate((guard) =>
4379
+ typeof guard?.finish === "function" && Number.isFinite(guard.browserArmSample)
4380
+ ? guard.browserArmSample
4381
+ : null,
4382
+ ),
4383
+ "input-guard-unavailable",
4384
+ "input-guard-arm",
4385
+ );
4386
+ const armSampleReceivedAt = performance.now();
4387
+ const armRemaining = deadline - armSampleReceivedAt;
4388
+ if (
4389
+ !Number.isFinite(browserArmSample) ||
4390
+ !Number.isFinite(armSampleReceivedAt) ||
4391
+ !Number.isFinite(armRemaining) ||
4392
+ armRemaining <= 0
4393
+ )
4394
+ throw fail("input-guard-unavailable");
4395
+ const fixedBrowserDeadline = browserArmSample + armRemaining;
4396
+ const inputGuardArmed = await withinDeadline(
4397
+ () =>
4398
+ inputGuardHandle.evaluate(
4399
+ (guard, expectedDeadline) => guard?.armDeadline?.(expectedDeadline) === true,
4400
+ fixedBrowserDeadline,
4401
+ ),
4402
+ "input-guard-unavailable",
4403
+ "input-guard-arm",
4404
+ );
4405
+ if (!inputGuardArmed) throw fail("input-guard-unavailable");
4406
+ const inputGuardDeadlineVerified = await withinDeadline(
4407
+ () =>
4408
+ inputGuardHandle.evaluate(
4409
+ (guard, expectedDeadline) => guard?.deadlineInstalled?.(expectedDeadline) === true,
4410
+ fixedBrowserDeadline,
4411
+ ),
4412
+ "input-guard-unavailable",
4413
+ "input-guard-arm",
4414
+ );
4415
+ if (!inputGuardDeadlineVerified) throw fail("input-guard-unavailable");
4416
+ const inputReceiptWaiterArmed = await withinDeadline(
4417
+ () =>
4418
+ inputReceiptWaiterHandle.evaluate(
4419
+ (waiter, expectedDeadline) => waiter?.armDeadline?.(expectedDeadline) === true,
4420
+ fixedBrowserDeadline,
4421
+ ),
4422
+ "input-receipt-invalid",
4423
+ "input-receipt-waiter-arm",
4424
+ );
4425
+ const inputReceiptWaiterDeadlineVerified = await withinDeadline(
4426
+ () =>
4427
+ inputReceiptWaiterHandle.evaluate(
4428
+ (waiter, expectedDeadline) => waiter?.deadlineInstalled?.(expectedDeadline) === true,
4429
+ fixedBrowserDeadline,
4430
+ ),
4431
+ "input-receipt-invalid",
4432
+ "input-receipt-waiter-arm",
4433
+ );
4434
+ if (!inputReceiptWaiterArmed || !inputReceiptWaiterDeadlineVerified)
4435
+ throw fail("input-receipt-invalid");
4436
+ if (!(await exactXtermFocused())) throw fail("pre-input-focus-changed");
4437
+ const inputReceiptWaiterStart = await withinDeadline(
4438
+ () => inputReceiptWaiterHandle.evaluate((waiter) => waiter?.startDispatch?.() ?? null),
4439
+ "input-product-path-reserve-insufficient",
4440
+ "input-receipt-waiter-dispatch",
4441
+ );
4442
+ activationInputReceiptStartAxes = boundedCard5InputReceiptStartAxes(inputReceiptWaiterStart);
4443
+ activationInputReceiptAxes = boundedCard5InputReceiptAxes(
4444
+ inputReceiptWaiterStart?.receipt,
4445
+ keyHex,
4446
+ );
4447
+ if (activationInputReceiptStartAxes.status === "initial-invalid")
4448
+ throw fail("input-receipt-invalid");
4449
+ if (activationInputReceiptStartAxes.status === "reserve-insufficient")
4450
+ throw fail("input-product-path-reserve-insufficient");
4451
+ if (activationInputReceiptStartAxes.status !== "started") throw fail("input-receipt-invalid");
4452
+ activationPhase = "input-insertion-timeout";
4453
+ const insertionStartedAt = performance.now();
4454
+ if (!Number.isFinite(insertionStartedAt) || insertionStartedAt >= deadline)
4455
+ throw fail("input-insertion-timeout");
4456
+ let insertionSettled = false;
4457
+ const insertionPending = Promise.resolve()
4458
+ .then(() => page.keyboard.insertText(inputText))
4459
+ .finally(() => {
4460
+ insertionSettled = true;
4461
+ });
4462
+ insertionPending.catch(() => {});
4463
+ let insertionTimer;
4464
+ let insertionTimedOut = false;
4465
+ try {
4466
+ await Promise.race([
4467
+ insertionPending,
4468
+ new Promise((_, reject) => {
4469
+ insertionTimer = setTimeout(() => {
4470
+ insertionTimedOut = true;
4471
+ reject(fail("input-insertion-timeout"));
4472
+ }, deadline - insertionStartedAt);
4473
+ }),
4474
+ ]);
4475
+ const insertionSettledAt = performance.now();
4476
+ if (!Number.isFinite(insertionSettledAt) || insertionSettledAt >= deadline) {
4477
+ insertionTimedOut = true;
4478
+ throw fail("input-insertion-timeout");
4479
+ }
4480
+ } catch (cause) {
4481
+ if (!insertionTimedOut && cause?.observation?.reason !== "input-insertion-timeout")
4482
+ throw cause;
4483
+ const cleanupWait = async (promise, timeoutMs) => {
4484
+ let timer;
4485
+ try {
4486
+ return await Promise.race([
4487
+ Promise.resolve(promise).then(
4488
+ () => "fulfilled",
4489
+ () => "rejected",
4490
+ ),
4491
+ new Promise((resolveWait) => {
4492
+ timer = setTimeout(() => resolveWait("timeout"), timeoutMs);
4493
+ }),
4494
+ ]);
4495
+ } finally {
4496
+ clearTimeout(timer);
4497
+ }
4498
+ };
4499
+ if (!insertionSettled) await cleanupWait(insertionPending, 250);
4500
+ let pageCloseSucceeded = false;
4501
+ let closePending = null;
4502
+ if (!insertionSettled) {
4503
+ closePending = Promise.resolve().then(() =>
4504
+ page.close({ runBeforeUnload: false, reason: "Card5 input insertion deadline" }),
4505
+ );
4506
+ closePending.catch(() => {});
4507
+ pageCloseSucceeded = (await cleanupWait(closePending, 250)) === "fulfilled";
4508
+ if (pageCloseSucceeded) await cleanupWait(insertionPending, 250);
4509
+ }
4510
+ if (!insertionSettled && !pageCloseSucceeded) {
4511
+ inputOperationPending = true;
4512
+ const closeSucceeded = closePending
4513
+ ? closePending.then(
4514
+ () => undefined,
4515
+ () => new Promise(() => {}),
4516
+ )
4517
+ : new Promise(() => {});
4518
+ Promise.race([insertionPending.catch(() => {}), closeSucceeded]).finally(() =>
4519
+ Promise.allSettled([finishInputGuard(), finishInputReceiptWaiter()]),
4520
+ );
4521
+ }
4522
+ throw cause;
4523
+ } finally {
4524
+ clearTimeout(insertionTimer);
4525
+ }
4526
+ const inputGuardOutcome = await withinDeadline(
4527
+ finishInputGuard,
4528
+ "input-guard-unavailable",
4529
+ "input-guard-finish",
4530
+ );
4531
+ inputGuardFinished = true;
4532
+ const inputGuardFinishedAt = performance.now();
4533
+ activationInputGuardAxes = boundedCard5InputGuardAxes(inputGuardOutcome, {
4534
+ deadlineValid: Number.isFinite(inputGuardFinishedAt) && inputGuardFinishedAt < deadline,
4535
+ settled: insertionSettled,
4536
+ });
4537
+ activationInputGuardReason = card5InputGuardFailureReason(activationInputGuardAxes);
4538
+ if (
4539
+ inputGuardOutcome?.inputCount !== 1 ||
4540
+ inputGuardOutcome?.beforeInputCount !== 1 ||
4541
+ inputGuardOutcome.eventCount !==
4542
+ inputGuardOutcome.inputCount + inputGuardOutcome.beforeInputCount ||
4543
+ inputGuardOutcome.eventOverflow !== false ||
4544
+ inputGuardOutcome.mutationCount !== 0 ||
4545
+ inputGuardOutcome.mutationOverflow !== false ||
4546
+ inputGuardOutcome.trusted !== true ||
4547
+ inputGuardOutcome.exactTarget !== true ||
4548
+ inputGuardOutcome.exactData !== true ||
4549
+ inputGuardOutcome.exactInputType !== true ||
4550
+ inputGuardOutcome.cancelableBeforeInput !== true ||
4551
+ inputGuardOutcome.restorationExact !== true ||
4552
+ inputGuardOutcome.rejected !== false ||
4553
+ inputGuardOutcome.exact !== true
4554
+ )
4555
+ throw fail("input-dispatch-rejected");
4556
+ let inputReceiptOutcome;
4557
+ try {
4558
+ inputReceiptOutcome = await withinDeadline(
4559
+ () => inputReceiptWaiterHandle.evaluate((waiter) => waiter?.awaitOutcome?.() ?? null),
4560
+ "input-receipt-timeout",
4561
+ "input-receipt-wait",
4562
+ );
4563
+ } catch (cause) {
4564
+ if (cause?.observation?.reason === "input-receipt-timeout") {
4565
+ deferRetainedHandleDisposal = true;
4566
+ await boundedFinishInputReceiptWaiter().catch(() => {});
4567
+ }
4568
+ throw cause;
4569
+ }
4570
+ inputReceiptWaiterFinished = true;
4571
+ const waiterDisposal = Promise.resolve(inputReceiptWaiterHandle.dispose()).catch(() => {});
4572
+ let waiterDisposalTimer;
4573
+ await Promise.race([
4574
+ waiterDisposal,
4575
+ new Promise((resolveWait) => {
4576
+ waiterDisposalTimer = setTimeout(resolveWait, 100);
4577
+ }),
4578
+ ]);
4579
+ clearTimeout(waiterDisposalTimer);
4580
+ activationInputReceiptAxes = boundedCard5InputReceiptAxes(inputReceiptOutcome, keyHex);
4581
+ if (inputReceiptOutcome?.status !== "accepted") {
4582
+ const reason = [
4583
+ "input-authority-foreign",
4584
+ "input-authority-unobserved-timeout",
4585
+ "input-authority-rejected",
4586
+ "input-authority-timeout",
4587
+ "input-authority-unavailable",
4588
+ "input-ack-timeout",
4589
+ "input-receipt-timeout",
4590
+ "input-receipt-invalid",
4591
+ ].includes(inputReceiptOutcome?.status)
4592
+ ? inputReceiptOutcome.status
4593
+ : "input-receipt-invalid";
4594
+ throw fail(reason);
4595
+ }
4596
+ if (!(await pointerTargetUnchanged())) throw fail("post-input-target-changed");
4597
+ if (!(await exactXtermFocused())) throw fail("post-input-focus-changed");
4598
+ const completedAt = performance.now();
4599
+ if (!Number.isFinite(completedAt) || completedAt >= deadline)
4600
+ throw fail("activation-deadline");
4601
+ return Object.freeze({
4602
+ before: Object.freeze({
4603
+ workspaceName: before.workspaceName,
4604
+ semanticPaneId: before.semanticPaneId,
4605
+ generation: before.generation,
4606
+ target: before.workspaceEvidence.target,
4607
+ }),
4608
+ after: Object.freeze({
4609
+ workspaceName: before.workspaceName,
4610
+ semanticPaneId: before.semanticPaneId,
4611
+ generation: before.generation,
4612
+ target: inputReceiptOutcome.target,
4613
+ }),
4614
+ receiptBoundary,
4615
+ requestHmac: activationRequestHmac,
4616
+ authorityClientId: inputReceiptOutcome.authorityClientId,
4617
+ receiptOrdinal: inputReceiptOutcome.receiptOrdinal,
4618
+ });
4619
+ } finally {
4620
+ if (!inputGuardFinished && !inputOperationPending) {
4621
+ await Promise.resolve()
4622
+ .then(finishInputGuard)
4623
+ .catch(() => {});
4624
+ }
4625
+ if (!inputReceiptWaiterFinished && !inputOperationPending && !deferRetainedHandleDisposal) {
4626
+ await boundedFinishInputReceiptWaiter().catch(() => {});
4627
+ }
4628
+ }
4629
+ } finally {
4630
+ if (!deferRetainedHandleDisposal) {
4631
+ await Promise.allSettled(
4632
+ [...retainedHandles].map((handle) => Promise.resolve().then(() => handle.dispose())),
4633
+ );
4634
+ } else {
4635
+ // The exact owned page close releases all of these CDP handles. If the
4636
+ // renderer/transport never confirms closure, retaining local JSHandle
4637
+ // wrappers is safer than blocking the controller or sending any broader
4638
+ // cleanup signal. Late disposal is deliberately best-effort and detached.
4639
+ deferredRetainedHandleTrigger
4640
+ ?.then(() =>
4641
+ Promise.allSettled(
4642
+ [...retainedHandles].map((handle) => Promise.resolve().then(() => handle.dispose())),
4643
+ ),
4644
+ )
4645
+ .catch(() => {});
4646
+ }
4647
+ }
4648
+ }
4649
+
4650
+ /** Release only authority currently owned by this exact detailed-mode Web binding. */
4651
+ export async function releaseCard5WebOwnedAuthorities(page, expected) {
4652
+ return page.evaluate(
4653
+ async ({ expected, keyHex }) => {
4654
+ const control = globalThis.__TMUX_IDE_CARD5_AUTHORITY_CONTROL__;
4655
+ const workspace = globalThis.__TMUX_IDE_CARD5_WORKSPACE_EVIDENCE__?.();
4656
+ const envelope = globalThis.__TMUX_IDE_CARD5_ENVELOPE_EVIDENCE__?.();
4657
+ const snapshot = workspace?.snapshot;
4658
+ const authority = snapshot?.authority;
4659
+ const active = Array.isArray(envelope?.activeLifecycleRequests)
4660
+ ? envelope.activeLifecycleRequests.filter(
4661
+ (request) =>
4662
+ request?.generation === expected.generation &&
4663
+ request?.workspaceName === expected.workspaceName &&
4664
+ request?.semanticPaneIds?.includes(expected.semanticPaneId),
4665
+ )
4666
+ : [];
4667
+ const descriptors =
4668
+ active.length === 1 && Array.isArray(envelope?.descriptorEvents)
4669
+ ? envelope.descriptorEvents.filter(
4670
+ (descriptor) =>
4671
+ descriptor?.generation === expected.generation &&
4672
+ descriptor?.requestId === active[0].requestId,
4673
+ )
4674
+ : [];
4675
+ if (
4676
+ !control ||
4677
+ snapshot?.phase !== "live" ||
4678
+ snapshot?.target?.workspaceName !== expected.workspaceName ||
4679
+ snapshot?.target?.daemon?.instanceId !== expected.generation ||
4680
+ authority?.generation !== expected.generation ||
4681
+ authority?.session !== expected.runtimeSession ||
4682
+ active.length !== 1 ||
4683
+ descriptors.length !== 1
4684
+ ) {
4685
+ return Object.freeze({
4686
+ status: "binding-invalid",
4687
+ pageHmac: expected.pageHmac,
4688
+ localClientHmac: null,
4689
+ preOwnerTupleHmac: null,
4690
+ preRevisionHmac: null,
4691
+ receipts: Object.freeze([]),
4692
+ });
4693
+ }
4694
+ const key = await globalThis.crypto.subtle.importKey(
4695
+ "raw",
4696
+ Uint8Array.from(keyHex.match(/../gu) ?? [], (value) => Number.parseInt(value, 16)),
4697
+ { name: "HMAC", hash: "SHA-256" },
4698
+ false,
4699
+ ["sign"],
4700
+ );
4701
+ const hmac = async (domain, value) => {
4702
+ const bytes = new TextEncoder().encode(`${domain}\0${value}`);
4703
+ const signed = await globalThis.crypto.subtle.sign("HMAC", key, bytes);
4704
+ return [...new Uint8Array(signed)]
4705
+ .map((value) => value.toString(16).padStart(2, "0"))
4706
+ .join("");
4707
+ };
4708
+ const preOwnerTupleHmac = await hmac(
4709
+ "release-pre-owner-tuple",
4710
+ JSON.stringify({
4711
+ input: authority.owners?.input ?? null,
4712
+ focus: authority.owners?.focus ?? null,
4713
+ geometry: authority.owners?.geometry ?? null,
4714
+ }),
4715
+ );
4716
+ const preRevisionHmac = await hmac("release-pre-revision", String(authority.revision));
4717
+ const receipts = [];
4718
+ for (const authorityKind of ["input", "focus", "geometry"]) {
4719
+ const clientId = authority.owners?.[authorityKind];
4720
+ const owner = authority.clients?.find((client) => client.clientId === clientId);
4721
+ if (clientId === null || owner?.surface !== "web") continue;
4722
+ const receipt = await control.release({
4723
+ version: 1,
4724
+ workspaceName: expected.workspaceName,
4725
+ generation: expected.generation,
4726
+ runtimeSession: expected.runtimeSession,
4727
+ semanticPaneId: expected.semanticPaneId,
4728
+ requestId: active[0].requestId,
4729
+ clientId,
4730
+ authority: authorityKind,
4731
+ });
4732
+ if (receipt === null) continue;
4733
+ receipts.push(
4734
+ Object.freeze({
4735
+ authority: receipt.authority,
4736
+ status: receipt.status,
4737
+ operationOrdinal: receipt.operationOrdinal,
4738
+ beforeRevision: receipt.beforeRevision,
4739
+ afterRevision: receipt.afterRevision,
4740
+ workspaceHmac: await hmac("release-workspace", receipt.workspaceName),
4741
+ generationHmac: await hmac("release-generation", receipt.generation),
4742
+ runtimeSessionHmac: await hmac("release-runtime-session", receipt.runtimeSession),
4743
+ paneHmac: await hmac("release-pane", receipt.semanticPaneId),
4744
+ requestHmac: await hmac("request", receipt.requestId),
4745
+ clientHmac: await hmac("authority-client", receipt.clientId),
4746
+ }),
4747
+ );
4748
+ }
4749
+ return Object.freeze({
4750
+ status: "exact",
4751
+ pageHmac: expected.pageHmac,
4752
+ // The WorkspaceClient contract exposes connection-local ownership but
4753
+ // intentionally does not expose the raw local client identity.
4754
+ localClientHmac: null,
4755
+ preOwnerTupleHmac,
4756
+ preRevisionHmac,
4757
+ receipts: Object.freeze(receipts),
4758
+ });
4759
+ },
4760
+ { expected, keyHex: expected.evidenceKey },
4761
+ );
4762
+ }
4763
+
4764
+ export async function issueCard5PredecessorDescriptor(page, expected) {
4765
+ if (
4766
+ typeof expected?.workspaceName !== "string" ||
4767
+ typeof expected?.generation !== "string" ||
4768
+ typeof expected?.semanticPaneId !== "string"
4769
+ ) {
4770
+ throw new TypeError("Card5 predecessor identity is malformed");
4771
+ }
4772
+ return page.evaluate(async (exact) => {
4773
+ const host = globalThis.tmuxIdeHost;
4774
+ const shell = await host.daemon.fetchApplicationShell({ workspaceName: exact.workspaceName });
4775
+ if (shell.status !== "ok") return null;
4776
+ const resource = shell.envelope.resource?.terminalInventory?.resources?.find(
4777
+ (entry) =>
4778
+ entry.attachability?.status === "available" &&
4779
+ entry.attachability?.semanticPaneId === exact.semanticPaneId,
4780
+ );
4781
+ const pane = resource?.attachability?.semanticPaneId;
4782
+ if (!pane) return null;
4783
+ const issued = await host.daemon.issuePaneStream({
4784
+ protocolVersion: 1,
4785
+ workspaceName: exact.workspaceName,
4786
+ panes: [pane],
4787
+ viewerMode: "read-only",
4788
+ });
4789
+ if (
4790
+ issued.status !== "issued" ||
4791
+ issued.descriptor.daemonInstanceId !== exact.generation ||
4792
+ issued.descriptor.panes.length !== 1 ||
4793
+ issued.descriptor.panes[0] !== exact.semanticPaneId
4794
+ ) {
4795
+ return null;
4796
+ }
4797
+ return issued.descriptor;
4798
+ }, expected);
4799
+ }
4800
+
4801
+ export async function rejectCard5PredecessorDescriptor(page, descriptor) {
4802
+ if (!descriptor) return Object.freeze({ rejected: false, reason: "descriptor-missing" });
4803
+ return page.evaluate(async (stale) => {
4804
+ const { browserWebSocketHandshakeUrl } =
4805
+ await import("/src/runtime/browser-websocket-session.ts");
4806
+ return new Promise((resolve) => {
4807
+ const socket = new globalThis.WebSocket(
4808
+ browserWebSocketHandshakeUrl(stale.webSocketUrl),
4809
+ stale.subprotocol,
4810
+ );
4811
+ let settled = false;
4812
+ const finish = (value) => {
4813
+ if (settled) return;
4814
+ settled = true;
4815
+ clearTimeout(timer);
4816
+ try {
4817
+ socket.close();
4818
+ } catch {
4819
+ // Already terminal.
4820
+ }
4821
+ resolve(value);
4822
+ };
4823
+ const timer = setTimeout(() => finish({ rejected: false, reason: "timeout" }), 2_000);
4824
+ socket.addEventListener("open", () => {
4825
+ socket.send(
4826
+ JSON.stringify({
4827
+ type: "redeem",
4828
+ protocolVersion: 1,
4829
+ ticket: stale.redemptionTicket,
4830
+ requestId: stale.requestId,
4831
+ daemonInstanceId: stale.daemonInstanceId,
4832
+ panes: stale.panes,
4833
+ effectiveViewerMode: stale.effectiveViewerMode,
4834
+ }),
4835
+ );
4836
+ });
4837
+ socket.addEventListener("message", (event) => {
4838
+ let frame;
4839
+ try {
4840
+ frame = JSON.parse(String(event.data));
4841
+ } catch {
4842
+ finish({ rejected: true, reason: "malformed" });
4843
+ return;
4844
+ }
4845
+ if (
4846
+ frame?.type === "error" &&
4847
+ ["redemption-rejected", "ticket-expired"].includes(frame.code)
4848
+ ) {
4849
+ finish({ rejected: true, typed: true, reason: frame.code });
4850
+ } else if (frame?.type === "error") {
4851
+ finish({ rejected: false, typed: false, reason: "unexpected-error-code" });
4852
+ } else if (frame?.type === "redeemed" || frame?.type === "seed-batch") {
4853
+ finish({ rejected: false, reason: "stale-authority-accepted" });
4854
+ }
4855
+ });
4856
+ socket.addEventListener("close", () =>
4857
+ finish({ rejected: false, typed: false, reason: "closed-without-error-frame" }),
4858
+ );
4859
+ socket.addEventListener("error", () =>
4860
+ finish({ rejected: false, typed: false, reason: "socket-error" }),
4861
+ );
4862
+ });
4863
+ }, descriptor);
4864
+ }