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,3897 @@
1
+ import assert from "node:assert/strict";
2
+ import { createHmac } from "node:crypto";
3
+ import test from "node:test";
4
+
5
+ import {
6
+ advanceCard5AuthorityReleaseStability,
7
+ advanceCard5PostInputAuthorityPreconditionHistory,
8
+ advanceCard5CanonicalStability,
9
+ advanceCard5FocusedConvergenceStability,
10
+ advanceCard5WebPhysicalLifecycleStability,
11
+ advanceCard5RetainedFocusStability,
12
+ assessCard5WebAuthorityRelease,
13
+ assessCard5WebPhysicalLifecycle,
14
+ assessCard5NullAuthorityPair,
15
+ assessCard5TuiFocusAuthority,
16
+ assessCard5TuiFocusedPane,
17
+ assessCard5TuiRetainedFocus,
18
+ assessCard5PostHandoffAuthority,
19
+ assessCard5TuiFocusTransition,
20
+ assessCard5TuiHandoffInput,
21
+ assessCard5ReplacementEnvelopeEvidence,
22
+ boundedCard5PostInputAuthorityPreconditionObservation,
23
+ boundedCard5TuiFocusFailureObservation,
24
+ boundedCard5TuiBlurTransitionObservation,
25
+ boundedCard5HostFailureObservation,
26
+ card5AuthorityActivityWithinCap,
27
+ createCard5DiagnosticEvidenceBinding,
28
+ createCard5TuiFrameFenceTracker,
29
+ exactSharedCard5WebPane,
30
+ hasExactCard5TuiFocusAuthority,
31
+ isExactCard5TuiHostInputReceipt,
32
+ matchesExpectedCard5WebPane,
33
+ mergeCard5SemanticAuthorityEvidence,
34
+ observeCard5WithinDeadline,
35
+ selectCard5PostInputAuthorityJoin,
36
+ selectExactCard5PaneGeometry,
37
+ selectExactCard5TmuxPaneBinding,
38
+ sameExactCard5TmuxPaneBinding,
39
+ card5TmuxCapturePaneArgv,
40
+ runExactCard5TmuxPaneCapture,
41
+ sealCard5NullAuthority,
42
+ sealCard5CorrelationEvidence,
43
+ sealCard5TuiFocusAuthority,
44
+ selectCard5TuiHostFocusBinding,
45
+ sealCard5ProductionClientObservation,
46
+ sameCard5WebPhysicalLifecycleEvidence,
47
+ } from "./product-cross-client-host-evidence.mjs";
48
+
49
+ test("Card5 Web physical lifecycle proof requires one exact current epoch and descriptor", () => {
50
+ const hash = (byte) => byte.repeat(64);
51
+ const exact = {
52
+ semanticPaneId: "pane-a",
53
+ generation: "generation-a",
54
+ runtimeReplacement: {
55
+ currentLifecycleRequest: {
56
+ status: "exact",
57
+ requestHmac: hash("a"),
58
+ physicalBindingExact: true,
59
+ physicalEpochHmac: hash("b"),
60
+ bindingRequestHmac: hash("a"),
61
+ bindingClientHmac: hash("c"),
62
+ activeCount: 1,
63
+ descriptorCount: 1,
64
+ overflow: false,
65
+ rawActiveCount: 1,
66
+ rawDescriptorCount: 1,
67
+ firstSeedOrdinal: 4,
68
+ physicalBindingAxes: {
69
+ present: true,
70
+ epochSafe: true,
71
+ generationExact: true,
72
+ runtimeSessionExact: true,
73
+ workspaceExact: true,
74
+ paneExact: true,
75
+ stageExact: true,
76
+ clientExact: true,
77
+ epochActiveCount: 1,
78
+ bindingRequestExact: true,
79
+ descriptorExact: true,
80
+ },
81
+ },
82
+ },
83
+ };
84
+ assert.equal(assessCard5WebPhysicalLifecycle(exact, "pane-a", "generation-a").valid, true);
85
+ const changes = [
86
+ (value) => (value.runtimeReplacement.currentLifecycleRequest.status = "missing"),
87
+ (value) => (value.runtimeReplacement.currentLifecycleRequest.activeCount = 0),
88
+ (value) => (value.runtimeReplacement.currentLifecycleRequest.descriptorCount = 0),
89
+ (value) => (value.runtimeReplacement.currentLifecycleRequest.descriptorCount = 2),
90
+ (value) => (value.runtimeReplacement.currentLifecycleRequest.overflow = true),
91
+ (value) => (value.runtimeReplacement.currentLifecycleRequest.bindingRequestHmac = hash("d")),
92
+ (value) =>
93
+ (value.runtimeReplacement.currentLifecycleRequest.physicalBindingAxes.clientExact = false),
94
+ (value) =>
95
+ (value.runtimeReplacement.currentLifecycleRequest.physicalBindingAxes.epochActiveCount = 2),
96
+ (value) => (value.semanticPaneId = "pane-b"),
97
+ (value) => (value.generation = "generation-b"),
98
+ ];
99
+ for (const change of changes) {
100
+ const value = structuredClone(exact);
101
+ change(value);
102
+ assert.equal(assessCard5WebPhysicalLifecycle(value, "pane-a", "generation-a").valid, false);
103
+ }
104
+ const key = "1".repeat(64);
105
+ const canonicalDigest = "2".repeat(64);
106
+ const evidence = assessCard5WebPhysicalLifecycle(exact, "pane-a", "generation-a").evidence;
107
+ const electronEvidence = Object.freeze({
108
+ ...evidence,
109
+ requestHmac: "4".repeat(64),
110
+ clientHmac: "5".repeat(64),
111
+ });
112
+ const pair = Object.freeze({ chromium: evidence, electron: electronEvidence });
113
+ const first = advanceCard5WebPhysicalLifecycleStability(null, canonicalDigest, pair, key);
114
+ assert.equal(first.stable, false);
115
+ assert.match(first.digest, /^[0-9a-f]{64}$/u);
116
+ assert.equal(
117
+ advanceCard5WebPhysicalLifecycleStability(first.digest, canonicalDigest, pair, key).stable,
118
+ true,
119
+ );
120
+ assert.equal(
121
+ advanceCard5WebPhysicalLifecycleStability(
122
+ first.digest,
123
+ canonicalDigest,
124
+ { chromium: evidence, electron: null },
125
+ key,
126
+ ).digest,
127
+ null,
128
+ "one Web host without an exact lifecycle can never form a stable sample",
129
+ );
130
+ const rebound = {
131
+ chromium: { ...evidence, physicalEpochHmac: "3".repeat(64) },
132
+ electron: electronEvidence,
133
+ };
134
+ assert.equal(
135
+ advanceCard5WebPhysicalLifecycleStability(first.digest, canonicalDigest, rebound, key).stable,
136
+ false,
137
+ "between-sample physical epoch churn must reset convergence",
138
+ );
139
+ assert.equal(sameCard5WebPhysicalLifecycleEvidence(pair, structuredClone(pair)), true);
140
+ assert.equal(
141
+ sameCard5WebPhysicalLifecycleEvidence(pair, rebound),
142
+ false,
143
+ "a convergence-to-preflight rebind must reject",
144
+ );
145
+ for (const aliased of [
146
+ { chromium: evidence, electron: { ...electronEvidence, requestHmac: evidence.requestHmac } },
147
+ { chromium: evidence, electron: { ...electronEvidence, clientHmac: evidence.clientHmac } },
148
+ {
149
+ chromium: evidence,
150
+ electron: {
151
+ ...electronEvidence,
152
+ requestHmac: evidence.requestHmac,
153
+ clientHmac: evidence.clientHmac,
154
+ },
155
+ },
156
+ ]) {
157
+ assert.equal(
158
+ advanceCard5WebPhysicalLifecycleStability(null, canonicalDigest, aliased, key).digest,
159
+ null,
160
+ "two Web views cannot alias one physical request or client",
161
+ );
162
+ }
163
+ const swapped = Object.freeze({ chromium: electronEvidence, electron: evidence });
164
+ assert.equal(
165
+ advanceCard5WebPhysicalLifecycleStability(first.digest, canonicalDigest, swapped, key).stable,
166
+ false,
167
+ "a positional host swap resets two-sample stability",
168
+ );
169
+ assert.equal(
170
+ sameCard5WebPhysicalLifecycleEvidence(pair, swapped),
171
+ false,
172
+ "a positional host swap fails the convergence-to-preflight join",
173
+ );
174
+ });
175
+
176
+ test("Card5 post-input precondition history preserves success across terminal timeouts", () => {
177
+ const informative = Object.freeze({ reason: "receipt-missing", axes: Object.freeze({}) });
178
+ const terminal = Object.freeze({ reason: "web-observation-timeout", axes: Object.freeze({}) });
179
+ const first = advanceCard5PostInputAuthorityPreconditionHistory(null, informative, [
180
+ { status: "ok" },
181
+ { status: "ok" },
182
+ ]);
183
+ const final = advanceCard5PostInputAuthorityPreconditionHistory(first, terminal, [
184
+ { status: "deadline" },
185
+ { status: "deadline" },
186
+ ]);
187
+ assert.equal(final.firstInformative, informative);
188
+ assert.equal(final.lastSuccessful, informative);
189
+ assert.equal(final.terminal, terminal);
190
+ const mixedTimeout = advanceCard5PostInputAuthorityPreconditionHistory(null, terminal, [
191
+ { status: "ok" },
192
+ { status: "deadline" },
193
+ ]);
194
+ const recovered = advanceCard5PostInputAuthorityPreconditionHistory(mixedTimeout, informative, [
195
+ { status: "ok" },
196
+ { status: "ok" },
197
+ ]);
198
+ assert.equal(recovered.firstInformative, informative);
199
+ assert.equal(recovered.lastSuccessful, informative);
200
+ });
201
+
202
+ const KEY = "1".repeat(64);
203
+ const HASH = "a".repeat(16);
204
+ const CONTENT = "b".repeat(64);
205
+ const HMAC = "c".repeat(64);
206
+
207
+ function card5PostInputPreconditionFixture() {
208
+ const generation = "11111111-1111-4111-8111-111111111111";
209
+ const session = "22222222-2222-4222-8222-222222222222";
210
+ const clients = [
211
+ {
212
+ clientId: "tui-a",
213
+ surface: "opentui",
214
+ state: "background",
215
+ connectedRevision: 1,
216
+ activityRevision: 1,
217
+ },
218
+ {
219
+ clientId: "web-a",
220
+ surface: "web",
221
+ state: "foreground",
222
+ connectedRevision: 2,
223
+ activityRevision: 2,
224
+ },
225
+ {
226
+ clientId: "web-b",
227
+ surface: "web",
228
+ state: "background",
229
+ connectedRevision: 3,
230
+ activityRevision: 1,
231
+ },
232
+ ];
233
+ const authority = {
234
+ generation,
235
+ session,
236
+ revision: 11,
237
+ owners: { input: "web-a", focus: "web-a", geometry: "web-a" },
238
+ nativeGeometryYieldUntilMs: 0,
239
+ clients,
240
+ };
241
+ const record = {
242
+ ordinal: 2,
243
+ generation,
244
+ session,
245
+ revision: 11,
246
+ nativeGeometryYieldUntilMs: 0,
247
+ inputOwner: "web-a",
248
+ focusOwner: "web-a",
249
+ geometryOwner: "web-a",
250
+ clients,
251
+ };
252
+ const receipt = {
253
+ generation,
254
+ pane: "pane-a",
255
+ seq: 1,
256
+ inputSha256: "a".repeat(64),
257
+ requestId: "request-a",
258
+ authorityClientId: "web-a",
259
+ ordinal: 0,
260
+ };
261
+ const web = (page) => ({
262
+ semanticPaneId: "pane-a",
263
+ generation,
264
+ page,
265
+ workspaceEvidence: { authority: structuredClone(authority) },
266
+ });
267
+ return {
268
+ webResults: [
269
+ { status: "ok", value: web("chromium") },
270
+ { status: "ok", value: web("electron") },
271
+ ],
272
+ receiptPage: "chromium",
273
+ receiptBoundary: 0,
274
+ rawReceipts: [receipt],
275
+ receiptCandidates: [receipt],
276
+ expectedInputSha256: "a".repeat(64),
277
+ expectedRequestHmac: createHmac("sha256", Buffer.from(KEY, "hex"))
278
+ .update("request\0request-a")
279
+ .digest("hex"),
280
+ requireReceipt: true,
281
+ expectedPane: "pane-a",
282
+ expectedGeneration: generation,
283
+ expectedBaselineAuthority: {
284
+ generation,
285
+ session,
286
+ revision: 10,
287
+ owners: { input: null, focus: null, geometry: null },
288
+ nativeGeometryYieldUntilMs: 0,
289
+ clients: clients.map((client) =>
290
+ client.clientId === "web-a"
291
+ ? { ...client, state: "background", activityRevision: 1 }
292
+ : { ...client },
293
+ ),
294
+ },
295
+ expectedClientId: "web-a",
296
+ expectedSurface: "web",
297
+ expectedGrantRecord: record,
298
+ authorityRecords: [record],
299
+ authorityBoundary: 1,
300
+ boundaryOverflow: false,
301
+ evidenceKey: KEY,
302
+ };
303
+ }
304
+
305
+ test("Card5 post-input producer preconditions expose every strict latch leaf without raw identity", () => {
306
+ const exact = card5PostInputPreconditionFixture();
307
+ const accepted = boundedCard5PostInputAuthorityPreconditionObservation(exact);
308
+ assert.equal(accepted.reason, null);
309
+ assert.equal(Object.values(accepted.axes).some(Boolean), false);
310
+ assert.equal(JSON.stringify(accepted).includes('"web-a"'), false);
311
+ assert.equal(JSON.stringify(accepted).includes('"request-a"'), false);
312
+
313
+ const absentTerminal = structuredClone(exact);
314
+ absentTerminal.expectedGrantRecord = null;
315
+ absentTerminal.authorityRecords = [];
316
+ assert.equal(
317
+ boundedCard5PostInputAuthorityPreconditionObservation(absentTerminal).reason,
318
+ "terminal-record-missing",
319
+ );
320
+ const unlatchableTerminal = structuredClone(exact);
321
+ unlatchableTerminal.expectedGrantRecord = null;
322
+ assert.equal(
323
+ boundedCard5PostInputAuthorityPreconditionObservation(unlatchableTerminal).reason,
324
+ "selector-contract-invalid",
325
+ );
326
+
327
+ const cases = [
328
+ ["receipt-missing", (value) => ((value.rawReceipts = []), (value.receiptCandidates = []))],
329
+ [
330
+ "receipt-ambiguous",
331
+ (value) => {
332
+ value.rawReceipts.push({ ...value.rawReceipts[0], ordinal: 1 });
333
+ value.receiptCandidates = [...value.rawReceipts];
334
+ },
335
+ ],
336
+ ["receipt-invalid", (value) => (value.rawReceipts[0].seq = -1)],
337
+ [
338
+ "receipt-target-mismatch",
339
+ (value) => {
340
+ value.rawReceipts[0].authorityClientId = "web-b";
341
+ value.receiptCandidates = [value.rawReceipts[0]];
342
+ },
343
+ ],
344
+ ["web-observation-invalid", (value) => (value.webResults[0].status = "source-unavailable")],
345
+ ["web-observation-timeout", (value) => (value.webResults[0].status = "deadline")],
346
+ [
347
+ "web-current-mismatch",
348
+ (value) => (value.webResults[1].value.workspaceEvidence.authority.revision += 1),
349
+ ],
350
+ [
351
+ "target-web-absent",
352
+ (value) => {
353
+ for (const result of value.webResults) {
354
+ const client = result.value.workspaceEvidence.authority.clients[1];
355
+ client.clientId = "web-z";
356
+ }
357
+ },
358
+ ],
359
+ [
360
+ "target-web-wrong-surface",
361
+ (value) => {
362
+ for (const result of value.webResults)
363
+ result.value.workspaceEvidence.authority.clients[1].surface = "opentui";
364
+ },
365
+ ],
366
+ [
367
+ "input-owner-mismatch",
368
+ (value) => {
369
+ for (const result of value.webResults)
370
+ result.value.workspaceEvidence.authority.owners.input = null;
371
+ },
372
+ ],
373
+ [
374
+ "focus-owner-mismatch",
375
+ (value) => {
376
+ for (const result of value.webResults)
377
+ result.value.workspaceEvidence.authority.owners.focus = null;
378
+ },
379
+ ],
380
+ [
381
+ "geometry-owner-mismatch",
382
+ (value) => {
383
+ for (const result of value.webResults)
384
+ result.value.workspaceEvidence.authority.owners.geometry = null;
385
+ },
386
+ ],
387
+ [
388
+ "current-revision-mismatch",
389
+ (value) => {
390
+ for (const result of value.webResults)
391
+ result.value.workspaceEvidence.authority.revision = 12;
392
+ },
393
+ ],
394
+ [
395
+ "current-generation-mismatch",
396
+ (value) => {
397
+ for (const result of value.webResults)
398
+ result.value.workspaceEvidence.authority.generation =
399
+ "33333333-3333-4333-8333-333333333333";
400
+ },
401
+ ],
402
+ [
403
+ "current-session-mismatch",
404
+ (value) => {
405
+ for (const result of value.webResults)
406
+ result.value.workspaceEvidence.authority.session = "33333333-3333-4333-8333-333333333333";
407
+ },
408
+ ],
409
+ [
410
+ "current-native-yield-mismatch",
411
+ (value) => {
412
+ for (const result of value.webResults)
413
+ result.value.workspaceEvidence.authority.nativeGeometryYieldUntilMs = 1;
414
+ },
415
+ ],
416
+ [
417
+ "current-topology-mismatch",
418
+ (value) => {
419
+ for (const result of value.webResults)
420
+ result.value.workspaceEvidence.authority.clients[1].activityRevision = 3;
421
+ },
422
+ ],
423
+ ["terminal-record-missing", (value) => (value.authorityRecords = [])],
424
+ [
425
+ "terminal-record-mismatch",
426
+ (value) => (value.expectedGrantRecord = { ...value.expectedGrantRecord, ordinal: 3 }),
427
+ ],
428
+ ["selector-contract-invalid", (value) => (value.evidenceKey = "invalid")],
429
+ ["boundary-overflow", (value) => (value.boundaryOverflow = true)],
430
+ ];
431
+ for (const [reason, mutate] of cases) {
432
+ const input = structuredClone(exact);
433
+ mutate(input);
434
+ let observed;
435
+ assert.doesNotThrow(() => {
436
+ observed = boundedCard5PostInputAuthorityPreconditionObservation(input);
437
+ });
438
+ assert.equal(observed.reason, reason);
439
+ assert.equal(JSON.stringify(observed).includes('"web-a"'), false, reason);
440
+ assert.equal(JSON.stringify(observed).includes('"request-a"'), false, reason);
441
+ }
442
+
443
+ const exactMismatchCases = [
444
+ [
445
+ "receiptInputMismatch",
446
+ (value) => {
447
+ value.rawReceipts[0].inputSha256 = "b".repeat(64);
448
+ value.receiptCandidates = [];
449
+ },
450
+ ],
451
+ [
452
+ "receiptRequestMismatch",
453
+ (value) => {
454
+ value.rawReceipts[0].requestId = "request-b";
455
+ value.receiptCandidates = [];
456
+ },
457
+ ],
458
+ ["receiptCandidateMismatch", (value) => (value.receiptCandidates = [])],
459
+ [
460
+ "webObservationInvalid",
461
+ (value) => delete value.webResults[0].value.workspaceEvidence.authority.clients,
462
+ ],
463
+ ];
464
+ for (const [axis, mutate] of exactMismatchCases) {
465
+ const input = structuredClone(exact);
466
+ mutate(input);
467
+ const observed = boundedCard5PostInputAuthorityPreconditionObservation(input);
468
+ assert.equal(
469
+ observed.reason,
470
+ axis === "webObservationInvalid" ? "web-observation-invalid" : "receipt-invalid",
471
+ axis,
472
+ );
473
+ assert.equal(observed.axes[axis], true);
474
+ }
475
+
476
+ const reordered = structuredClone(exact);
477
+ reordered.webResults[1].value.workspaceEvidence.authority.clients.reverse();
478
+ const reorderedObservation = boundedCard5PostInputAuthorityPreconditionObservation(reordered);
479
+ assert.equal(reorderedObservation.reason, "web-current-mismatch");
480
+ assert.equal(reorderedObservation.axes.webCurrentMismatch, true);
481
+ });
482
+
483
+ test("Card5 post-input precondition evidence caps receipts and records", () => {
484
+ const input = card5PostInputPreconditionFixture();
485
+ input.rawReceipts = Array.from({ length: 9 }, (_, ordinal) => ({
486
+ ...input.rawReceipts[0],
487
+ ordinal,
488
+ requestId: `request-${ordinal}`,
489
+ }));
490
+ input.receiptCandidates = [...input.rawReceipts];
491
+ input.authorityRecords = Array.from({ length: 17 }, (_, index) => ({
492
+ ...structuredClone(input.expectedGrantRecord),
493
+ ordinal: index + 1,
494
+ revision: index + 10,
495
+ }));
496
+ const observed = boundedCard5PostInputAuthorityPreconditionObservation(input);
497
+ assert.equal(observed.receipt.count, 8);
498
+ assert.equal(observed.receipt.overflow, true);
499
+ assert.equal(observed.records.count, 16);
500
+ assert.equal(observed.records.overflow, true);
501
+ assert.equal(observed.records.last.length, 2);
502
+ });
503
+
504
+ test("Card5 post-input join accepts a same-client new epoch and exact Web target", () => {
505
+ const generation = "11111111-1111-4111-8111-111111111111";
506
+ const session = "22222222-2222-4222-8222-222222222222";
507
+ const clients = [
508
+ {
509
+ clientId: "tui-a",
510
+ surface: "opentui",
511
+ state: "background",
512
+ connectedRevision: 1,
513
+ activityRevision: 1,
514
+ },
515
+ {
516
+ clientId: "web-a",
517
+ surface: "web",
518
+ state: "background",
519
+ connectedRevision: 2,
520
+ activityRevision: 1,
521
+ },
522
+ {
523
+ clientId: "web-b",
524
+ surface: "web",
525
+ state: "background",
526
+ connectedRevision: 3,
527
+ activityRevision: 1,
528
+ },
529
+ ];
530
+ const nullAuthority = {
531
+ generation,
532
+ session,
533
+ revision: 10,
534
+ owners: { input: null, focus: null, geometry: null },
535
+ nativeGeometryYieldUntilMs: 0,
536
+ clients,
537
+ };
538
+ const nullEvidence = sealCard5NullAuthority(nullAuthority, generation, KEY);
539
+ const grantClients = clients.map((client) =>
540
+ client.clientId === "tui-a"
541
+ ? { ...client, state: "foreground", activityRevision: 2 }
542
+ : { ...client },
543
+ );
544
+ const records = [
545
+ {
546
+ ordinal: 7,
547
+ generation,
548
+ session,
549
+ revision: 10,
550
+ nativeGeometryYieldUntilMs: 0,
551
+ inputOwner: null,
552
+ focusOwner: null,
553
+ geometryOwner: null,
554
+ clients,
555
+ },
556
+ {
557
+ ordinal: 8,
558
+ generation,
559
+ session,
560
+ revision: 11,
561
+ nativeGeometryYieldUntilMs: 0,
562
+ inputOwner: "tui-a",
563
+ focusOwner: "tui-a",
564
+ geometryOwner: "tui-a",
565
+ clients: grantClients,
566
+ },
567
+ ];
568
+ const tui = selectCard5PostInputAuthorityJoin({
569
+ records,
570
+ nullRevision: 10,
571
+ expectedNullAuthority: nullAuthority,
572
+ expectedNullEvidence: nullEvidence,
573
+ expectedClientId: "tui-a",
574
+ expectedSurface: "opentui",
575
+ expectedGrantRevision: 11,
576
+ expectedGrantRecord: records[1],
577
+ receiptCandidates: [],
578
+ requireReceipt: false,
579
+ boundary: 6,
580
+ evidenceKey: KEY,
581
+ });
582
+ assert.equal(tui.passed, true);
583
+ assert.equal(tui.grant, records[1]);
584
+ for (const order of [
585
+ ["inputOwner", "focusOwner", "geometryOwner"],
586
+ ["geometryOwner", "inputOwner", "focusOwner"],
587
+ ["focusOwner", "geometryOwner", "inputOwner"],
588
+ ]) {
589
+ const staged = [structuredClone(records[0])];
590
+ const owners = { inputOwner: null, focusOwner: null, geometryOwner: null };
591
+ for (const [index, owner] of order.entries()) {
592
+ owners[owner] = "tui-a";
593
+ staged.push({
594
+ ...structuredClone(records[1]),
595
+ ...owners,
596
+ ordinal: 8 + index,
597
+ revision: 11 + index,
598
+ });
599
+ }
600
+ const stagedResult = selectCard5PostInputAuthorityJoin({
601
+ records: staged,
602
+ nullRevision: 10,
603
+ expectedNullAuthority: nullAuthority,
604
+ expectedNullEvidence: nullEvidence,
605
+ expectedClientId: "tui-a",
606
+ expectedSurface: "opentui",
607
+ expectedGrantRevision: 13,
608
+ expectedGrantRecord: staged.at(-1),
609
+ receiptCandidates: [],
610
+ requireReceipt: false,
611
+ boundary: 6,
612
+ evidenceKey: KEY,
613
+ });
614
+ assert.equal(stagedResult.passed, true);
615
+ assert.equal(stagedResult.observation.stagingCount, 4);
616
+ assert.equal(stagedResult.observation.stagingExact, true);
617
+ }
618
+ const presenceOnly = {
619
+ ...structuredClone(records[1]),
620
+ ordinal: 8,
621
+ revision: 11,
622
+ inputOwner: null,
623
+ focusOwner: null,
624
+ geometryOwner: null,
625
+ };
626
+ const presenceAndReplay = [
627
+ structuredClone(records[0]),
628
+ presenceOnly,
629
+ { ...structuredClone(presenceOnly), ordinal: 9 },
630
+ { ...structuredClone(records[1]), ordinal: 10, revision: 12 },
631
+ ];
632
+ const presenceResult = selectCard5PostInputAuthorityJoin({
633
+ records: presenceAndReplay,
634
+ nullRevision: 10,
635
+ expectedNullAuthority: nullAuthority,
636
+ expectedNullEvidence: nullEvidence,
637
+ expectedClientId: "tui-a",
638
+ expectedSurface: "opentui",
639
+ expectedGrantRevision: 12,
640
+ expectedGrantRecord: presenceAndReplay.at(-1),
641
+ receiptCandidates: [],
642
+ requireReceipt: false,
643
+ boundary: 6,
644
+ evidenceKey: KEY,
645
+ });
646
+ assert.equal(presenceResult.passed, true);
647
+ assert.equal(presenceResult.observation.stagingExact, true);
648
+ const replayedNullRecords = [
649
+ records[0],
650
+ { ...structuredClone(records[0]), ordinal: 8 },
651
+ { ...structuredClone(records[1]), ordinal: 9 },
652
+ ];
653
+ const replayedNull = selectCard5PostInputAuthorityJoin({
654
+ records: replayedNullRecords,
655
+ nullRevision: 10,
656
+ expectedNullAuthority: nullAuthority,
657
+ expectedNullEvidence: nullEvidence,
658
+ expectedClientId: "tui-a",
659
+ expectedSurface: "opentui",
660
+ expectedGrantRevision: 11,
661
+ expectedGrantRecord: replayedNullRecords[2],
662
+ receiptCandidates: [],
663
+ requireReceipt: false,
664
+ boundary: 6,
665
+ evidenceKey: KEY,
666
+ });
667
+ assert.equal(replayedNull.passed, true);
668
+ assert.equal(replayedNull.observation.nullReplayCount, 1);
669
+ assert.match(replayedNull.observation.nullReplayOrdinalHmac, /^[a-f0-9]{64}$/u);
670
+ for (const mutate of [
671
+ (record) => (record.generation = "33333333-3333-4333-8333-333333333333"),
672
+ (record) => (record.session = "33333333-3333-4333-8333-333333333333"),
673
+ (record) => (record.nativeGeometryYieldUntilMs = 1),
674
+ (record) => (record.focusOwner = null),
675
+ (record) => (record.clients[0].activityRevision += 1),
676
+ ]) {
677
+ const changedRecords = structuredClone(records);
678
+ mutate(changedRecords[1]);
679
+ assert.equal(
680
+ selectCard5PostInputAuthorityJoin({
681
+ records: changedRecords,
682
+ nullRevision: 10,
683
+ expectedNullAuthority: nullAuthority,
684
+ expectedNullEvidence: nullEvidence,
685
+ expectedClientId: "tui-a",
686
+ expectedSurface: "opentui",
687
+ expectedGrantRevision: 11,
688
+ expectedGrantRecord: records[1],
689
+ receiptCandidates: [],
690
+ requireReceipt: false,
691
+ boundary: 6,
692
+ evidenceKey: KEY,
693
+ }).passed,
694
+ false,
695
+ );
696
+ }
697
+ const webRecords = [
698
+ records[0],
699
+ {
700
+ ...records[1],
701
+ inputOwner: "web-a",
702
+ focusOwner: "web-a",
703
+ geometryOwner: "web-a",
704
+ clients: grantClients.map((client) =>
705
+ client.clientId === "tui-a"
706
+ ? { ...client, state: "background", activityRevision: 1 }
707
+ : client.clientId === "web-a"
708
+ ? { ...client, state: "foreground", activityRevision: 2 }
709
+ : client,
710
+ ),
711
+ },
712
+ ];
713
+ const receipt = { authorityClientId: "web-a", requestId: "request-a" };
714
+ const web = selectCard5PostInputAuthorityJoin({
715
+ records: webRecords,
716
+ nullRevision: 10,
717
+ expectedNullAuthority: nullAuthority,
718
+ expectedNullEvidence: nullEvidence,
719
+ expectedClientId: "web-a",
720
+ expectedSurface: "web",
721
+ expectedGrantRevision: 11,
722
+ expectedGrantRecord: webRecords[1],
723
+ receiptCandidates: [receipt],
724
+ requireReceipt: true,
725
+ boundary: 6,
726
+ evidenceKey: KEY,
727
+ });
728
+ assert.equal(web.passed, true);
729
+ assert.equal(web.receipt, receipt);
730
+ for (const order of [
731
+ ["inputOwner", "focusOwner", "geometryOwner"],
732
+ ["inputOwner", "geometryOwner", "focusOwner"],
733
+ ["focusOwner", "inputOwner", "geometryOwner"],
734
+ ["focusOwner", "geometryOwner", "inputOwner"],
735
+ ["geometryOwner", "inputOwner", "focusOwner"],
736
+ ["geometryOwner", "focusOwner", "inputOwner"],
737
+ ]) {
738
+ const staged = [structuredClone(webRecords[0])];
739
+ const owners = { inputOwner: null, focusOwner: null, geometryOwner: null };
740
+ for (const [index, owner] of order.entries()) {
741
+ owners[owner] = "web-a";
742
+ staged.push({
743
+ ...structuredClone(webRecords[1]),
744
+ ...owners,
745
+ ordinal: 8 + index,
746
+ revision: 11 + index,
747
+ });
748
+ }
749
+ assert.equal(
750
+ selectCard5PostInputAuthorityJoin({
751
+ records: staged,
752
+ nullRevision: 10,
753
+ expectedNullAuthority: nullAuthority,
754
+ expectedNullEvidence: nullEvidence,
755
+ expectedClientId: "web-a",
756
+ expectedSurface: "web",
757
+ expectedGrantRevision: 13,
758
+ expectedGrantRecord: staged.at(-1),
759
+ receiptCandidates: [receipt],
760
+ requireReceipt: true,
761
+ boundary: 6,
762
+ evidenceKey: KEY,
763
+ }).passed,
764
+ true,
765
+ );
766
+ }
767
+ assert.equal(
768
+ selectCard5PostInputAuthorityJoin({
769
+ records: webRecords,
770
+ nullRevision: 10,
771
+ expectedNullAuthority: nullAuthority,
772
+ expectedNullEvidence: nullEvidence,
773
+ expectedClientId: "web-a",
774
+ expectedSurface: "web",
775
+ expectedGrantRevision: 11,
776
+ expectedGrantRecord: webRecords[1],
777
+ receiptCandidates: [receipt, { authorityClientId: "web-b", requestId: "request-b" }],
778
+ requireReceipt: true,
779
+ boundary: 6,
780
+ evidenceKey: KEY,
781
+ }).passed,
782
+ false,
783
+ );
784
+ });
785
+
786
+ test("Card5 post-input join rejects stale, cross, duplicate, and missing grants without throwing", () => {
787
+ const generation = "11111111-1111-4111-8111-111111111111";
788
+ const session = "22222222-2222-4222-8222-222222222222";
789
+ const clients = [
790
+ {
791
+ clientId: "tui-a",
792
+ surface: "opentui",
793
+ state: "foreground",
794
+ connectedRevision: 1,
795
+ activityRevision: 2,
796
+ },
797
+ {
798
+ clientId: "web-a",
799
+ surface: "web",
800
+ state: "background",
801
+ connectedRevision: 2,
802
+ activityRevision: 1,
803
+ },
804
+ {
805
+ clientId: "web-b",
806
+ surface: "web",
807
+ state: "background",
808
+ connectedRevision: 3,
809
+ activityRevision: 1,
810
+ },
811
+ ];
812
+ const nullAuthority = {
813
+ generation,
814
+ session,
815
+ revision: 10,
816
+ owners: { input: null, focus: null, geometry: null },
817
+ nativeGeometryYieldUntilMs: 0,
818
+ clients,
819
+ };
820
+ const exact = {
821
+ records: [
822
+ {
823
+ ordinal: 1,
824
+ generation,
825
+ session,
826
+ revision: 10,
827
+ nativeGeometryYieldUntilMs: 0,
828
+ inputOwner: null,
829
+ focusOwner: null,
830
+ geometryOwner: null,
831
+ clients,
832
+ },
833
+ {
834
+ ordinal: 2,
835
+ generation,
836
+ session,
837
+ revision: 11,
838
+ nativeGeometryYieldUntilMs: 0,
839
+ inputOwner: "tui-a",
840
+ focusOwner: "tui-a",
841
+ geometryOwner: "tui-a",
842
+ clients,
843
+ },
844
+ ],
845
+ nullRevision: 10,
846
+ expectedNullAuthority: nullAuthority,
847
+ expectedNullEvidence: sealCard5NullAuthority(nullAuthority, generation, KEY),
848
+ expectedClientId: "tui-a",
849
+ expectedSurface: "opentui",
850
+ expectedGrantRevision: 11,
851
+ expectedGrantRecord: null,
852
+ receiptCandidates: [],
853
+ requireReceipt: false,
854
+ boundary: 0,
855
+ evidenceKey: KEY,
856
+ };
857
+ const adversaries = [
858
+ (value) => (value.expectedGrantRevision = 12),
859
+ (value) => (value.expectedClientId = "other-client"),
860
+ (value) => value.records.pop(),
861
+ (value) => (value.nullRevision = 9),
862
+ (value) => (value.boundaryOverflow = true),
863
+ (value) => (value.records[0].session = "33333333-3333-4333-8333-333333333333"),
864
+ (value) => (value.records[0].nativeGeometryYieldUntilMs = 1),
865
+ (value) => (value.records[0].clients[0].activityRevision += 1),
866
+ (value) => {
867
+ value.records.splice(1, 0, {
868
+ ...structuredClone(value.records[1]),
869
+ ordinal: 2,
870
+ revision: 10,
871
+ inputOwner: "web-a",
872
+ focusOwner: "web-a",
873
+ geometryOwner: "web-a",
874
+ });
875
+ value.records[2].ordinal = 3;
876
+ },
877
+ (value) => {
878
+ value.records.splice(1, 0, {
879
+ ...structuredClone(value.records[0]),
880
+ ordinal: 2,
881
+ clients: value.records[0].clients.map((client, index) =>
882
+ index === 0 ? { ...client, activityRevision: client.activityRevision + 1 } : client,
883
+ ),
884
+ });
885
+ value.records[2].ordinal = 3;
886
+ },
887
+ (value) => (value.records[1].ordinal = 3),
888
+ (value) => {
889
+ value.records[1].ordinal = 3;
890
+ value.records[1].revision = 12;
891
+ value.expectedGrantRevision = 12;
892
+ value.records.splice(1, 0, {
893
+ ...structuredClone(value.records[1]),
894
+ ordinal: 2,
895
+ revision: 11,
896
+ inputOwner: "other-client",
897
+ focusOwner: null,
898
+ geometryOwner: null,
899
+ });
900
+ },
901
+ (value) => {
902
+ value.records[1].ordinal = 4;
903
+ value.records[1].revision = 13;
904
+ value.expectedGrantRevision = 13;
905
+ const partial = {
906
+ ...structuredClone(value.records[1]),
907
+ ordinal: 2,
908
+ revision: 11,
909
+ focusOwner: null,
910
+ geometryOwner: null,
911
+ };
912
+ value.records.splice(1, 0, partial, {
913
+ ...structuredClone(partial),
914
+ ordinal: 3,
915
+ revision: 12,
916
+ inputOwner: null,
917
+ focusOwner: "tui-a",
918
+ });
919
+ },
920
+ (value) => {
921
+ value.records[1].ordinal = 3;
922
+ value.records[1].revision = 12;
923
+ value.expectedGrantRevision = 12;
924
+ value.records.splice(1, 0, {
925
+ ...structuredClone(value.records[1]),
926
+ ordinal: 2,
927
+ revision: 11,
928
+ focusOwner: null,
929
+ geometryOwner: null,
930
+ clients: value.records[1].clients.map((client, index) =>
931
+ index === 1 ? { ...client, activityRevision: client.activityRevision + 1 } : client,
932
+ ),
933
+ });
934
+ },
935
+ (value) => {
936
+ const terminal = value.records[1];
937
+ terminal.ordinal = 18;
938
+ terminal.revision = 27;
939
+ value.expectedGrantRevision = 27;
940
+ value.records.splice(
941
+ 1,
942
+ 0,
943
+ ...Array.from({ length: 16 }, (_, index) => ({
944
+ ...structuredClone(terminal),
945
+ ordinal: index + 2,
946
+ revision: index + 11,
947
+ focusOwner: null,
948
+ geometryOwner: null,
949
+ })),
950
+ );
951
+ },
952
+ (value) =>
953
+ value.records.splice(
954
+ 0,
955
+ 1,
956
+ ...Array.from({ length: 9 }, (_, index) => ({
957
+ ...structuredClone(value.records[0]),
958
+ ordinal: index + 1,
959
+ })),
960
+ ),
961
+ ];
962
+ for (const mutate of adversaries) {
963
+ const input = structuredClone(exact);
964
+ mutate(input);
965
+ let result;
966
+ assert.doesNotThrow(() => {
967
+ result = selectCard5PostInputAuthorityJoin(input);
968
+ });
969
+ assert.equal(result.passed, false);
970
+ assert.match(JSON.stringify(result.observation), /^[\x20-\x7e]+$/u);
971
+ assert.equal(JSON.stringify(result).includes("tui-a"), false);
972
+ }
973
+ });
974
+
975
+ test("Card5 diagnostic binding keeps the selector separate from the private HMAC key", () => {
976
+ const selected = Object.freeze({ value: "selected" });
977
+ const binding = createCard5DiagnosticEvidenceBinding({
978
+ journeyEvidence: { crossClientHandoff: selected, daemonRestart: { value: "other" } },
979
+ journeyEvidenceKey: "crossClientHandoff",
980
+ privateEvidenceKey: KEY,
981
+ });
982
+ assert.equal(binding.evidence, selected);
983
+ assert.deepEqual(
984
+ binding.correlate((evidence, privateKey) => ({ evidence, privateKey })),
985
+ { evidence: selected, privateKey: KEY },
986
+ );
987
+ assert.equal(
988
+ binding.assess((_evidence, privateKey) => privateKey),
989
+ KEY,
990
+ );
991
+ assert.equal(JSON.stringify(binding).includes(KEY), false);
992
+ assert.throws(() =>
993
+ createCard5DiagnosticEvidenceBinding({
994
+ journeyEvidence: { crossClientHandoff: selected },
995
+ journeyEvidenceKey: "crossClientHandoff",
996
+ privateEvidenceKey: "crossClientHandoff",
997
+ }),
998
+ );
999
+ assert.throws(() =>
1000
+ createCard5DiagnosticEvidenceBinding({
1001
+ journeyEvidence: { crossClientHandoff: selected },
1002
+ journeyEvidenceKey: "crossClientHandoff",
1003
+ privateEvidenceKey: null,
1004
+ }),
1005
+ );
1006
+ });
1007
+
1008
+ function card5FocusReceipt(state, status = "changed") {
1009
+ return {
1010
+ version: 1,
1011
+ status,
1012
+ action: state,
1013
+ nonceHmac: HMAC,
1014
+ diagnosticEpoch: status === "changed" ? (state === "blur" ? 7 : 8) : null,
1015
+ state: state === "blur" ? "background" : "foreground",
1016
+ bindingHmac: HMAC,
1017
+ receiptHmac: HMAC,
1018
+ };
1019
+ }
1020
+
1021
+ function card5FocusTransitionRecords() {
1022
+ const identity = {
1023
+ processId: "opentui:42",
1024
+ clockId: "opentui-performance-now",
1025
+ daemonInstanceId: "daemon-generation-a",
1026
+ runtimeSession: "runtime-session-a",
1027
+ workspaceName: "workspace-a",
1028
+ rendererEpoch: 3,
1029
+ clientGeneration: 7,
1030
+ };
1031
+ const record = (phase, diagnosticEpoch, monotonicMicros, extra = {}) => ({
1032
+ phase,
1033
+ diagnosticEpoch,
1034
+ monotonicMicros,
1035
+ ...identity,
1036
+ ...extra,
1037
+ });
1038
+ return [
1039
+ record("terminal-host-renderer-blur-event", 7, 100, { state: "background" }),
1040
+ record("terminal-host-blur-presence", 7, 101),
1041
+ record("terminal-host-blur-authority-settled", 7, 102, {
1042
+ status: "fulfilled",
1043
+ bindingCurrent: true,
1044
+ receipts: ["input", "focus", "geometry"].map((authority) => ({
1045
+ authority,
1046
+ status: "fulfilled",
1047
+ generation: "daemon-generation-a",
1048
+ owners: { input: null, focus: null, geometry: null },
1049
+ revision: 13,
1050
+ session: "runtime-session-a",
1051
+ })),
1052
+ settledIdentity: {
1053
+ authorityRevision: 13,
1054
+ authorityOwners: { input: null, focus: null, geometry: null },
1055
+ },
1056
+ }),
1057
+ record("terminal-host-focus-fence", 7, 103, {
1058
+ settledPhase: "blur-authority-settled",
1059
+ writerHealth: { failed: false, droppedRecords: 0, pendingCriticalRecords: 0 },
1060
+ }),
1061
+ record("terminal-host-renderer-focus-event", 8, 104, { state: "foreground" }),
1062
+ record("terminal-host-focus-claim-attempt", 8, 105, { claimOrdinal: 4 }),
1063
+ record("terminal-host-focus-presence", 8, 106),
1064
+ record("terminal-host-focus-activity", 8, 107),
1065
+ record("terminal-host-focus-authority-reconcile", 8, 108),
1066
+ record("terminal-host-focus-authority-settled", 8, 109, {
1067
+ status: "fulfilled",
1068
+ bindingCurrent: true,
1069
+ receipts: ["input", "focus", "geometry"].map((authority, index) => ({
1070
+ authority,
1071
+ status: "fulfilled",
1072
+ granted: true,
1073
+ generation: "daemon-generation-a",
1074
+ clientId: "opentui:42",
1075
+ revision: 14 + index,
1076
+ session: "runtime-session-a",
1077
+ })),
1078
+ settledIdentity: { authorityRevision: 16 },
1079
+ }),
1080
+ record("terminal-host-focus-fence", 8, 110, {
1081
+ settledPhase: "focus-authority-settled",
1082
+ writerHealth: { failed: false, droppedRecords: 0, pendingCriticalRecords: 0 },
1083
+ }),
1084
+ ];
1085
+ }
1086
+
1087
+ test("qualifies one explicit Card5 blur-focus epoch and rejects passive loss or duplicate claims", () => {
1088
+ const input = {
1089
+ records: card5FocusTransitionRecords(),
1090
+ receipts: {
1091
+ blur: card5FocusReceipt("blur"),
1092
+ focus: card5FocusReceipt("focus"),
1093
+ duplicateFocus: card5FocusReceipt("focus", "no-op"),
1094
+ },
1095
+ expectedCanonical: {
1096
+ processId: "opentui:42",
1097
+ clockId: "opentui-performance-now",
1098
+ generation: "daemon-generation-a",
1099
+ },
1100
+ expectedBindingHmac: HMAC,
1101
+ expectedWorkspaceName: "workspace-a",
1102
+ expectedRendererEpoch: 3,
1103
+ expectedClientGeneration: 7,
1104
+ expectedRuntimeSession: "runtime-session-a",
1105
+ expectedAuthorityOwners: { input: "opentui:42", focus: "opentui:42", geometry: "opentui:42" },
1106
+ expectedTuiClientId: "opentui:42",
1107
+ minimumBlurAuthorityRevision: 12,
1108
+ minimumFocusAuthorityRevision: 13,
1109
+ baselineClaimOrdinal: 3,
1110
+ evidenceKey: KEY,
1111
+ };
1112
+ const passed = assessCard5TuiFocusTransition(input);
1113
+ assert.equal(passed.passed, true);
1114
+ assert.equal(passed.evidence.claimCount, 1);
1115
+ assert.equal(passed.evidence.duplicateClaimCount, 0);
1116
+ assert.equal(passed.evidence.duplicateFocusReceiptHmac, HMAC);
1117
+ const focusBeforeDuplicate = assessCard5TuiFocusTransition({
1118
+ ...input,
1119
+ receipts: { blur: input.receipts.blur, focus: input.receipts.focus },
1120
+ stage: "focus",
1121
+ });
1122
+ assert.equal(focusBeforeDuplicate.passed, true);
1123
+ assert.equal(focusBeforeDuplicate.evidence.focusReceiptHmac, HMAC);
1124
+ assert.equal(focusBeforeDuplicate.evidence.duplicateFocusReceiptHmac, null);
1125
+ const alreadyBackground = assessCard5TuiFocusTransition({
1126
+ ...input,
1127
+ priorBlurRecords: input.records.slice(0, 4),
1128
+ records: input.records.slice(4),
1129
+ receipts: { ...input.receipts, blur: card5FocusReceipt("blur", "no-op") },
1130
+ });
1131
+ assert.equal(alreadyBackground.passed, true);
1132
+ assert.equal(
1133
+ assessCard5TuiFocusTransition({
1134
+ ...input,
1135
+ priorBlurRecords: [],
1136
+ records: input.records.slice(4),
1137
+ receipts: { ...input.receipts, blur: card5FocusReceipt("blur", "no-op") },
1138
+ }).passed,
1139
+ false,
1140
+ );
1141
+ const mixedOwners = { input: "opentui:42", focus: "web-a", geometry: null };
1142
+ const mixedAfterBlur = { input: null, focus: "web-a", geometry: null };
1143
+ const mixedRecords = input.records.map((record) =>
1144
+ record.phase === "terminal-host-blur-authority-settled"
1145
+ ? {
1146
+ ...record,
1147
+ receipts: record.receipts.map((receipt) => ({
1148
+ ...receipt,
1149
+ owners: mixedAfterBlur,
1150
+ })),
1151
+ settledIdentity: {
1152
+ ...record.settledIdentity,
1153
+ authorityOwners: mixedAfterBlur,
1154
+ },
1155
+ }
1156
+ : record,
1157
+ );
1158
+ assert.equal(
1159
+ assessCard5TuiFocusTransition({
1160
+ ...input,
1161
+ records: mixedRecords.slice(0, 4),
1162
+ receipts: { blur: input.receipts.blur },
1163
+ expectedAuthorityOwners: mixedOwners,
1164
+ stage: "blur",
1165
+ }).passed,
1166
+ true,
1167
+ );
1168
+ assert.equal(
1169
+ assessCard5TuiFocusTransition({
1170
+ ...input,
1171
+ records: input.records.slice(0, 4),
1172
+ receipts: { blur: input.receipts.blur, focus: input.receipts.focus },
1173
+ stage: "focus",
1174
+ }).reason,
1175
+ "focus-claim-cardinality",
1176
+ );
1177
+ assert.equal(
1178
+ assessCard5TuiFocusTransition({
1179
+ ...input,
1180
+ records: [...input.records, { ...input.records[5], monotonicMicros: 111, claimOrdinal: 5 }],
1181
+ }).reason,
1182
+ "focus-claim-cardinality",
1183
+ );
1184
+ const receiptAdversaries = [
1185
+ { stage: "blur", receipts: {} },
1186
+ { stage: "blur", receipts: { blur: input.receipts.blur, extra: input.receipts.focus } },
1187
+ { stage: "focus", receipts: { blur: input.receipts.blur } },
1188
+ {
1189
+ stage: "focus",
1190
+ receipts: {
1191
+ blur: input.receipts.blur,
1192
+ focus: { ...input.receipts.focus, receiptHmac: null },
1193
+ },
1194
+ },
1195
+ { stage: "focus", receipts: input.receipts },
1196
+ {
1197
+ stage: "complete",
1198
+ receipts: { blur: input.receipts.blur, focus: input.receipts.focus },
1199
+ },
1200
+ {
1201
+ stage: "complete",
1202
+ receipts: {
1203
+ ...input.receipts,
1204
+ duplicateFocus: card5FocusReceipt("focus", "changed"),
1205
+ },
1206
+ },
1207
+ { stage: "complete", receipts: { ...input.receipts, extra: input.receipts.focus } },
1208
+ ];
1209
+ for (const changed of receiptAdversaries) {
1210
+ const assessed = assessCard5TuiFocusTransition({ ...input, ...changed });
1211
+ assert.equal(assessed.passed, false);
1212
+ assert.match(assessed.reason, /^focus-(?:blur|focus)-receipt-invalid$/u);
1213
+ }
1214
+ });
1215
+
1216
+ test("Card5 host-focus binding joins separate lifecycle and source-shaped canonical streams", () => {
1217
+ const authority = {
1218
+ generation: "daemon-generation-a",
1219
+ session: "runtime-session-a",
1220
+ revision: 17,
1221
+ owners: { input: "opentui:42", focus: "opentui:42", geometry: "opentui:42" },
1222
+ nativeGeometryYieldUntilMs: 0,
1223
+ clients: [
1224
+ {
1225
+ clientId: "web:a",
1226
+ surface: "web",
1227
+ state: "background",
1228
+ connectedRevision: 1,
1229
+ activityRevision: 1,
1230
+ },
1231
+ {
1232
+ clientId: "web:b",
1233
+ surface: "web",
1234
+ state: "background",
1235
+ connectedRevision: 2,
1236
+ activityRevision: 2,
1237
+ },
1238
+ {
1239
+ clientId: "opentui:42",
1240
+ surface: "opentui",
1241
+ state: "foreground",
1242
+ connectedRevision: 3,
1243
+ activityRevision: 17,
1244
+ },
1245
+ ],
1246
+ };
1247
+ const reconcile = {
1248
+ phase: "terminal-host-focus-authority-reconcile",
1249
+ diagnosticEpoch: null,
1250
+ status: "applied",
1251
+ processId: "opentui:42",
1252
+ clockId: "opentui-performance-now",
1253
+ daemonInstanceId: authority.generation,
1254
+ authorityGeneration: authority.generation,
1255
+ runtimeSession: authority.session,
1256
+ workspaceName: "workspace-a",
1257
+ clientPhase: "live",
1258
+ rendererEpoch: 3,
1259
+ clientGeneration: 7,
1260
+ authorityRevision: authority.revision,
1261
+ authorityOwners: authority.owners,
1262
+ opentuiPresence: {
1263
+ clientId: "opentui:42",
1264
+ state: "foreground",
1265
+ connectedRevision: 3,
1266
+ activityRevision: 17,
1267
+ },
1268
+ receipts: ["input", "focus", "geometry"].map((authorityKind) => ({
1269
+ authority: authorityKind,
1270
+ status: "fulfilled",
1271
+ granted: true,
1272
+ exact: true,
1273
+ })),
1274
+ };
1275
+ const bindingReady = {
1276
+ phase: "terminal-host-focus-control-binding-ready",
1277
+ elapsedMs: 10,
1278
+ at: "2026-08-24T20:00:00.000Z",
1279
+ bindingEpoch: 1,
1280
+ processId: "opentui:42",
1281
+ clockId: "opentui-performance-now",
1282
+ daemonInstanceId: authority.generation,
1283
+ authorityGeneration: authority.generation,
1284
+ runtimeSession: authority.session,
1285
+ workspaceName: "workspace-a",
1286
+ clientId: "opentui:42",
1287
+ clientPhase: "live",
1288
+ rendererEpoch: 3,
1289
+ clientGeneration: 7,
1290
+ monotonicMicros: 100,
1291
+ };
1292
+ const gateReady = {
1293
+ phase: "terminal-host-focus-control-gate-ready",
1294
+ elapsedMs: 9,
1295
+ at: "2026-08-24T20:00:00.000Z",
1296
+ processId: "opentui:42",
1297
+ clockId: "opentui-performance-now",
1298
+ capability: true,
1299
+ detail: true,
1300
+ path: true,
1301
+ root: true,
1302
+ key: true,
1303
+ trace: true,
1304
+ enabled: true,
1305
+ monotonicMicros: 90,
1306
+ };
1307
+ const input = {
1308
+ referenceRecords: [
1309
+ {
1310
+ type: "performance.terminal-frame-fence",
1311
+ semanticPaneId: "pane-a",
1312
+ processId: "opentui:42",
1313
+ clockId: "opentui-performance-now",
1314
+ generation: "daemon-generation-a",
1315
+ incarnation: "daemon-generation-a:0",
1316
+ revision: 5,
1317
+ stateHash: "a".repeat(16),
1318
+ rendererEpoch: 3,
1319
+ },
1320
+ ],
1321
+ lifecycleRecords: [gateReady, bindingReady, reconcile],
1322
+ expectedCanonical: {
1323
+ processId: "opentui:42",
1324
+ clockId: "opentui-performance-now",
1325
+ semanticPaneId: "pane-a",
1326
+ generation: "daemon-generation-a",
1327
+ incarnation: "daemon-generation-a:0",
1328
+ revision: 5,
1329
+ canonicalStateHash: "a".repeat(16),
1330
+ },
1331
+ expectedAuthority: authority,
1332
+ expectedWorkspaceName: "workspace-a",
1333
+ expectedTuiClientId: "opentui:42",
1334
+ evidenceKey: KEY,
1335
+ };
1336
+ const exact = selectCard5TuiHostFocusBinding(input);
1337
+ assert.equal(exact.passed, true);
1338
+ assert.equal(exact.source, "binding-ready");
1339
+ assert.deepEqual(exact.binding, { rendererEpoch: 3, clientGeneration: 7, bindingEpoch: 1 });
1340
+ assert.equal(selectCard5TuiHostFocusBinding({ ...input, lifecycleRecords: [] }).passed, false);
1341
+ assert.equal(selectCard5TuiHostFocusBinding({ ...input, referenceRecords: [] }).passed, false);
1342
+ const advancedAuthority = structuredClone(authority);
1343
+ advancedAuthority.revision = 23;
1344
+ advancedAuthority.clients.find(({ clientId }) => clientId === "opentui:42").activityRevision = 23;
1345
+ assert.equal(
1346
+ selectCard5TuiHostFocusBinding({ ...input, expectedAuthority: advancedAuthority }).passed,
1347
+ true,
1348
+ );
1349
+ const futureReconcile = structuredClone(reconcile);
1350
+ futureReconcile.authorityRevision = 24;
1351
+ futureReconcile.opentuiPresence.activityRevision = 24;
1352
+ const future = selectCard5TuiHostFocusBinding({
1353
+ ...input,
1354
+ lifecycleRecords: [gateReady, bindingReady, futureReconcile],
1355
+ expectedAuthority: advancedAuthority,
1356
+ });
1357
+ assert.equal(future.passed, true);
1358
+ assert.equal(future.observation.revisionRelationMismatch, true);
1359
+ for (const mutate of [
1360
+ (record) => (record.rendererEpoch = -1),
1361
+ (record) => (record.runtimeSession = "runtime-session-b"),
1362
+ (record) => (record.clientId = "opentui:foreign"),
1363
+ (record) => (record.bindingEpoch = 0),
1364
+ ]) {
1365
+ const changed = structuredClone(bindingReady);
1366
+ mutate(changed);
1367
+ assert.equal(
1368
+ selectCard5TuiHostFocusBinding({
1369
+ ...input,
1370
+ lifecycleRecords: [gateReady, changed, reconcile],
1371
+ }).passed,
1372
+ false,
1373
+ );
1374
+ }
1375
+ for (const field of ["capability", "detail", "path", "root", "key", "trace", "enabled"]) {
1376
+ const changed = structuredClone(gateReady);
1377
+ changed[field] = false;
1378
+ const selected = selectCard5TuiHostFocusBinding({
1379
+ ...input,
1380
+ lifecycleRecords: [changed, bindingReady, reconcile],
1381
+ });
1382
+ assert.equal(selected.passed, false);
1383
+ assert.equal(selected.reason, "binding-gate-invalid");
1384
+ assert.equal(selected.observation[`gate${field[0].toUpperCase()}${field.slice(1)}`], false);
1385
+ }
1386
+ for (const record of [gateReady, bindingReady]) {
1387
+ const changed = { ...record, extra: true };
1388
+ assert.equal(
1389
+ selectCard5TuiHostFocusBinding({
1390
+ ...input,
1391
+ lifecycleRecords:
1392
+ record === gateReady
1393
+ ? [changed, bindingReady, reconcile]
1394
+ : [gateReady, changed, reconcile],
1395
+ }).passed,
1396
+ false,
1397
+ );
1398
+ }
1399
+ const mixedReconcile = structuredClone(reconcile);
1400
+ mixedReconcile.status = "failed";
1401
+ mixedReconcile.authorityOwners.geometry = "web:b";
1402
+ mixedReconcile.receipts[2].granted = false;
1403
+ mixedReconcile.receipts[2].exact = false;
1404
+ const mixed = selectCard5TuiHostFocusBinding({
1405
+ ...input,
1406
+ lifecycleRecords: [gateReady, bindingReady, mixedReconcile],
1407
+ });
1408
+ assert.equal(mixed.passed, true);
1409
+ assert.equal(mixed.observation.statusMismatch, true);
1410
+ assert.equal(mixed.observation.receiptMismatch, true);
1411
+ assert.equal(mixed.observation.allTuiOwners, false);
1412
+ assert.equal(mixed.observation.authorityOutcome.geometry, "not-granted");
1413
+ assert.equal(
1414
+ selectCard5TuiHostFocusBinding({
1415
+ ...input,
1416
+ lifecycleRecords: [gateReady, bindingReady, structuredClone(bindingReady), reconcile],
1417
+ }).passed,
1418
+ true,
1419
+ );
1420
+
1421
+ const laterAuthority = structuredClone(authority);
1422
+ laterAuthority.revision = 23;
1423
+ laterAuthority.owners = { input: "web:a", focus: "web:a", geometry: "web:b" };
1424
+ const focusSettlement = {
1425
+ ...reconcile,
1426
+ phase: "terminal-host-focus-authority-settled",
1427
+ diagnosticEpoch: 8,
1428
+ status: "fulfilled",
1429
+ bindingCurrent: true,
1430
+ authorityRevision: 16,
1431
+ authorityOwners: { input: null, focus: null, geometry: null },
1432
+ opentuiPresence: { ...reconcile.opentuiPresence, state: "background" },
1433
+ receipts: ["input", "focus", "geometry"].map((authorityKind, index) => ({
1434
+ authority: authorityKind,
1435
+ status: "fulfilled",
1436
+ generation: authority.generation,
1437
+ granted: true,
1438
+ revision: 17 + index,
1439
+ session: authority.session,
1440
+ clientId: "opentui:42",
1441
+ })),
1442
+ settledIdentity: {
1443
+ clientGeneration: 7,
1444
+ clientPhase: "live",
1445
+ authorityGeneration: authority.generation,
1446
+ runtimeSession: authority.session,
1447
+ authorityOwners: authority.owners,
1448
+ authorityRevision: 19,
1449
+ daemonInstanceId: authority.generation,
1450
+ workspaceName: "workspace-a",
1451
+ opentuiPresence: reconcile.opentuiPresence,
1452
+ },
1453
+ };
1454
+ assert.equal(
1455
+ selectCard5TuiHostFocusBinding({
1456
+ ...input,
1457
+ lifecycleRecords: [gateReady, bindingReady, focusSettlement],
1458
+ expectedAuthority: laterAuthority,
1459
+ }).passed,
1460
+ true,
1461
+ );
1462
+ const blurSettlement = {
1463
+ ...focusSettlement,
1464
+ phase: "terminal-host-blur-authority-settled",
1465
+ diagnosticEpoch: 9,
1466
+ authorityRevision: 19,
1467
+ authorityOwners: authority.owners,
1468
+ opentuiPresence: reconcile.opentuiPresence,
1469
+ receipts: ["input", "focus", "geometry"].map((authorityKind, index) => ({
1470
+ authority: authorityKind,
1471
+ status: "fulfilled",
1472
+ generation: authority.generation,
1473
+ owners: { input: null, focus: null, geometry: null },
1474
+ revision: 20 + index,
1475
+ session: authority.session,
1476
+ })),
1477
+ settledIdentity: {
1478
+ ...focusSettlement.settledIdentity,
1479
+ authorityOwners: { input: null, focus: null, geometry: null },
1480
+ authorityRevision: 22,
1481
+ opentuiPresence: { ...reconcile.opentuiPresence, state: "background", activityRevision: 22 },
1482
+ },
1483
+ };
1484
+ assert.equal(
1485
+ selectCard5TuiHostFocusBinding({
1486
+ ...input,
1487
+ lifecycleRecords: [gateReady, bindingReady, blurSettlement],
1488
+ expectedAuthority: laterAuthority,
1489
+ }).passed,
1490
+ true,
1491
+ );
1492
+ for (const mutate of [
1493
+ (record) => (record.rendererEpoch = 4),
1494
+ (record) => (record.runtimeSession = "runtime-session-b"),
1495
+ (record) => (record.clientGeneration = -1),
1496
+ (record) => (record.clientId = "opentui:9"),
1497
+ (record) => (record.daemonInstanceId = "daemon-generation-b"),
1498
+ ]) {
1499
+ const changed = structuredClone(bindingReady);
1500
+ mutate(changed);
1501
+ assert.equal(
1502
+ selectCard5TuiHostFocusBinding({
1503
+ ...input,
1504
+ lifecycleRecords: [changed, focusSettlement],
1505
+ expectedAuthority: laterAuthority,
1506
+ }).passed,
1507
+ false,
1508
+ );
1509
+ }
1510
+ });
1511
+
1512
+ test("fails closed on stale lifecycle, missing fences, and malformed focus receipts", () => {
1513
+ const records = card5FocusTransitionRecords();
1514
+ const input = {
1515
+ records,
1516
+ receipts: {
1517
+ blur: card5FocusReceipt("blur"),
1518
+ focus: card5FocusReceipt("focus"),
1519
+ duplicateFocus: card5FocusReceipt("focus", "no-op"),
1520
+ },
1521
+ expectedCanonical: {
1522
+ processId: "opentui:42",
1523
+ clockId: "opentui-performance-now",
1524
+ generation: "daemon-generation-a",
1525
+ },
1526
+ expectedBindingHmac: HMAC,
1527
+ expectedWorkspaceName: "workspace-a",
1528
+ expectedRendererEpoch: 3,
1529
+ expectedClientGeneration: 7,
1530
+ expectedRuntimeSession: "runtime-session-a",
1531
+ expectedAuthorityOwners: { input: "opentui:42", focus: "opentui:42", geometry: "opentui:42" },
1532
+ expectedTuiClientId: "opentui:42",
1533
+ minimumBlurAuthorityRevision: 13,
1534
+ minimumFocusAuthorityRevision: 13,
1535
+ baselineClaimOrdinal: 3,
1536
+ evidenceKey: KEY,
1537
+ };
1538
+ for (const changed of [
1539
+ { records: records.filter((record) => record.phase !== "terminal-host-focus-fence") },
1540
+ {
1541
+ records: records.map((record, index) =>
1542
+ index === 4 ? { ...record, processId: "opentui:9" } : record,
1543
+ ),
1544
+ },
1545
+ { receipts: { ...input.receipts, blur: { ...input.receipts.blur, bytesInjected: 2 } } },
1546
+ {
1547
+ receipts: {
1548
+ ...input.receipts,
1549
+ duplicateFocus: { ...input.receipts.duplicateFocus, requestedState: "blur" },
1550
+ },
1551
+ },
1552
+ {
1553
+ records: records.map((record) =>
1554
+ record.phase === "terminal-host-blur-authority-settled"
1555
+ ? {
1556
+ ...record,
1557
+ receipts: record.receipts.map((receipt, index) =>
1558
+ index === 0 ? { ...receipt, session: "runtime-session-b" } : receipt,
1559
+ ),
1560
+ }
1561
+ : record,
1562
+ ),
1563
+ },
1564
+ {
1565
+ records: records.map((record) =>
1566
+ record.phase === "terminal-host-focus-authority-settled"
1567
+ ? {
1568
+ ...record,
1569
+ receipts: record.receipts.map((receipt, index) =>
1570
+ index === 0 ? { ...receipt, session: "runtime-session-b" } : receipt,
1571
+ ),
1572
+ }
1573
+ : record,
1574
+ ),
1575
+ },
1576
+ {
1577
+ records: records.map((record) =>
1578
+ record.phase === "terminal-host-focus-authority-settled"
1579
+ ? {
1580
+ ...record,
1581
+ receipts: record.receipts.map((receipt, index) =>
1582
+ index === 0 ? { ...receipt, revision: 13 } : receipt,
1583
+ ),
1584
+ }
1585
+ : record,
1586
+ ),
1587
+ },
1588
+ { expectedRuntimeSession: "runtime-session-b" },
1589
+ ]) {
1590
+ assert.equal(assessCard5TuiFocusTransition({ ...input, ...changed }).passed, false);
1591
+ }
1592
+ });
1593
+
1594
+ test("waits for a delayed blur fence and requires two identical qualified release samples", () => {
1595
+ const records = card5FocusTransitionRecords().slice(0, 4);
1596
+ const input = {
1597
+ receipts: { blur: card5FocusReceipt("blur") },
1598
+ expectedCanonical: {
1599
+ processId: "opentui:42",
1600
+ clockId: "opentui-performance-now",
1601
+ generation: "daemon-generation-a",
1602
+ },
1603
+ expectedBindingHmac: HMAC,
1604
+ expectedWorkspaceName: "workspace-a",
1605
+ expectedRendererEpoch: 3,
1606
+ expectedClientGeneration: 7,
1607
+ expectedRuntimeSession: "runtime-session-a",
1608
+ expectedAuthorityOwners: {
1609
+ input: "opentui:42",
1610
+ focus: "opentui:42",
1611
+ geometry: "opentui:42",
1612
+ },
1613
+ expectedTuiClientId: "opentui:42",
1614
+ minimumBlurAuthorityRevision: 12,
1615
+ minimumFocusAuthorityRevision: 12,
1616
+ baselineClaimOrdinal: 3,
1617
+ evidenceKey: KEY,
1618
+ stage: "blur",
1619
+ };
1620
+ const beforeFence = assessCard5TuiFocusTransition({ ...input, records: records.slice(0, 3) });
1621
+ assert.equal(beforeFence.passed, false);
1622
+ const failedObservation = boundedCard5TuiBlurTransitionObservation({
1623
+ assessment: beforeFence,
1624
+ records: records.slice(0, 3),
1625
+ receipt: input.receipts.blur,
1626
+ evidenceKey: KEY,
1627
+ });
1628
+ assert.equal(failedObservation.reason, "focus-blur-lifecycle-invalid");
1629
+ assert.equal(failedObservation.fenceCount, 0);
1630
+ let stability = advanceCard5AuthorityReleaseStability(undefined, "candidate", false);
1631
+ assert.deepEqual(stability, { candidate: null, samples: 0, passed: false });
1632
+
1633
+ const afterFence = assessCard5TuiFocusTransition({ ...input, records });
1634
+ assert.equal(afterFence.passed, true);
1635
+ const observation = boundedCard5TuiBlurTransitionObservation({
1636
+ assessment: afterFence,
1637
+ records,
1638
+ receipt: input.receipts.blur,
1639
+ evidenceKey: KEY,
1640
+ });
1641
+ assert.deepEqual(Object.keys(observation).sort(), [
1642
+ "blurEventCount",
1643
+ "controlBindingHmac",
1644
+ "controlEpoch",
1645
+ "controlStatus",
1646
+ "diagnosticEpoch",
1647
+ "fenceCount",
1648
+ "passed",
1649
+ "reason",
1650
+ "receiptCount",
1651
+ "receiptOverflow",
1652
+ "receiptRevisions",
1653
+ "receiptStatuses",
1654
+ "recordCount",
1655
+ "recordOverflow",
1656
+ "settledOwnersHmac",
1657
+ "settledRevision",
1658
+ "settlementCount",
1659
+ "tailPosition",
1660
+ "writerHealthy",
1661
+ ]);
1662
+ assert.equal(observation.reason, "exact");
1663
+ assert.equal(observation.writerHealthy, true);
1664
+ assert.match(observation.settledOwnersHmac, /^[0-9a-f]{64}$/);
1665
+ assert.equal(JSON.stringify(observation).includes("opentui:42"), false);
1666
+ const candidate = JSON.stringify({ blur: observation, authority: "exact-null" });
1667
+ stability = advanceCard5AuthorityReleaseStability(stability, candidate, true);
1668
+ assert.deepEqual(stability, { candidate, samples: 1, passed: false });
1669
+ stability = advanceCard5AuthorityReleaseStability(stability, candidate, true);
1670
+ assert.deepEqual(stability, { candidate, samples: 2, passed: true });
1671
+ assert.equal(
1672
+ advanceCard5AuthorityReleaseStability(stability, `${candidate}-growth`, true).passed,
1673
+ false,
1674
+ );
1675
+ assert.equal(
1676
+ advanceCard5AuthorityReleaseStability(stability, "x".repeat(16_385), true).samples,
1677
+ 0,
1678
+ );
1679
+ });
1680
+
1681
+ test("blur release rejects duplicate, cross-session, stale, foreign-owner, and unhealthy evidence", () => {
1682
+ const records = card5FocusTransitionRecords().slice(0, 4);
1683
+ const input = {
1684
+ records,
1685
+ receipts: { blur: card5FocusReceipt("blur") },
1686
+ expectedCanonical: {
1687
+ processId: "opentui:42",
1688
+ clockId: "opentui-performance-now",
1689
+ generation: "daemon-generation-a",
1690
+ },
1691
+ expectedBindingHmac: HMAC,
1692
+ expectedWorkspaceName: "workspace-a",
1693
+ expectedRendererEpoch: 3,
1694
+ expectedClientGeneration: 7,
1695
+ expectedRuntimeSession: "runtime-session-a",
1696
+ expectedAuthorityOwners: {
1697
+ input: "opentui:42",
1698
+ focus: "opentui:42",
1699
+ geometry: "opentui:42",
1700
+ },
1701
+ expectedTuiClientId: "opentui:42",
1702
+ minimumBlurAuthorityRevision: 13,
1703
+ minimumFocusAuthorityRevision: 13,
1704
+ baselineClaimOrdinal: 3,
1705
+ evidenceKey: KEY,
1706
+ stage: "blur",
1707
+ };
1708
+ const mutateSettlement = (mutate) =>
1709
+ records.map((record) =>
1710
+ record.phase === "terminal-host-blur-authority-settled" ? mutate(record) : record,
1711
+ );
1712
+ const invalid = [
1713
+ [...records, { ...records[2], monotonicMicros: 104 }],
1714
+ mutateSettlement((record) => ({
1715
+ ...record,
1716
+ receipts: record.receipts.map((receipt, index) =>
1717
+ index === 0 ? { ...receipt, session: "runtime-session-b" } : receipt,
1718
+ ),
1719
+ })),
1720
+ mutateSettlement((record) => ({
1721
+ ...record,
1722
+ receipts: record.receipts.map((receipt, index) =>
1723
+ index === 0 ? { ...receipt, revision: 12 } : receipt,
1724
+ ),
1725
+ })),
1726
+ mutateSettlement((record) => ({
1727
+ ...record,
1728
+ settledIdentity: {
1729
+ ...record.settledIdentity,
1730
+ authorityOwners: { input: "web-a", focus: null, geometry: null },
1731
+ },
1732
+ })),
1733
+ records.map((record) =>
1734
+ record.phase === "terminal-host-focus-fence"
1735
+ ? { ...record, writerHealth: { ...record.writerHealth, failed: true } }
1736
+ : record,
1737
+ ),
1738
+ ];
1739
+ for (const changedRecords of invalid) {
1740
+ assert.equal(
1741
+ assessCard5TuiFocusTransition({ ...input, records: changedRecords }).passed,
1742
+ false,
1743
+ );
1744
+ }
1745
+ });
1746
+
1747
+ function focusAuthorityFixture(generation = "daemon-generation-a") {
1748
+ return {
1749
+ generation,
1750
+ session: "runtime-session-a",
1751
+ revision: 11,
1752
+ owners: { input: "client-a", focus: "client-a", geometry: "client-a" },
1753
+ nativeGeometryYieldUntilMs: 0,
1754
+ clients: [
1755
+ {
1756
+ clientId: "client-a",
1757
+ surface: "opentui",
1758
+ state: "foreground",
1759
+ connectedRevision: 1,
1760
+ activityRevision: 10,
1761
+ },
1762
+ {
1763
+ clientId: "client-b",
1764
+ surface: "web",
1765
+ state: "background",
1766
+ connectedRevision: 2,
1767
+ activityRevision: 9,
1768
+ },
1769
+ {
1770
+ clientId: "client-c",
1771
+ surface: "web",
1772
+ state: "background",
1773
+ connectedRevision: 3,
1774
+ activityRevision: 8,
1775
+ },
1776
+ ],
1777
+ };
1778
+ }
1779
+
1780
+ test("seals exact Card5 null authority topology and rejects cross-view splices", () => {
1781
+ const authority = {
1782
+ ...focusAuthorityFixture(),
1783
+ revision: 13,
1784
+ owners: { input: null, focus: null, geometry: null },
1785
+ };
1786
+ const sealed = sealCard5NullAuthority(authority, authority.generation, KEY);
1787
+ assert.ok(sealed);
1788
+ assert.equal(sealed.authorityRevision, 13);
1789
+ assert.equal(
1790
+ sealCard5NullAuthority({ ...authority }, authority.generation, KEY)?.authorityHmac,
1791
+ sealed.authorityHmac,
1792
+ );
1793
+ for (const changed of [
1794
+ { ...authority, session: "runtime-session-b" },
1795
+ { ...authority, revision: 14 },
1796
+ { ...authority, owners: { ...authority.owners, focus: "client-a" } },
1797
+ {
1798
+ ...authority,
1799
+ clients: authority.clients.map((client, index) =>
1800
+ index === 0 ? { ...client, state: "background" } : client,
1801
+ ),
1802
+ },
1803
+ {
1804
+ ...authority,
1805
+ clients: authority.clients.map((client, index) =>
1806
+ index === 1 ? { ...client, activityRevision: client.activityRevision + 1 } : client,
1807
+ ),
1808
+ },
1809
+ ]) {
1810
+ const candidate = sealCard5NullAuthority(changed, changed.generation, KEY);
1811
+ if (candidate === null) continue;
1812
+ assert.equal(
1813
+ candidate.authorityHmac !== sealed.authorityHmac ||
1814
+ candidate.authorityTopologyHmac !== sealed.authorityTopologyHmac ||
1815
+ candidate.authorityMutationHmac !== sealed.authorityMutationHmac,
1816
+ true,
1817
+ );
1818
+ }
1819
+ assert.equal(
1820
+ sealCard5NullAuthority({ ...authority, extra: true }, authority.generation, KEY),
1821
+ null,
1822
+ );
1823
+ });
1824
+
1825
+ test("Card5 null authority pair localizes each view and exact cross-view mismatch", () => {
1826
+ const authority = {
1827
+ ...focusAuthorityFixture(),
1828
+ revision: 13,
1829
+ owners: { input: null, focus: null, geometry: null },
1830
+ };
1831
+ const input = {
1832
+ authorities: [authority, structuredClone(authority)],
1833
+ generations: [authority.generation, authority.generation],
1834
+ minimumRevision: 12,
1835
+ evidenceKey: KEY,
1836
+ };
1837
+ assert.equal(assessCard5NullAuthorityPair(input).passed, true);
1838
+ const cases = [
1839
+ [{ ...authority, owners: { ...authority.owners, input: "client-a" } }, "owner-nonnull"],
1840
+ [{ ...authority, revision: 12 }, "cross-revision"],
1841
+ [{ ...authority, revision: 14 }, "cross-revision"],
1842
+ [{ ...authority, session: "runtime-session-b" }, "cross-authority"],
1843
+ [
1844
+ {
1845
+ ...authority,
1846
+ clients: authority.clients.map((client, index) =>
1847
+ index === 0 ? { ...client, state: "background" } : client,
1848
+ ),
1849
+ },
1850
+ "cross-authority",
1851
+ ],
1852
+ [
1853
+ {
1854
+ ...authority,
1855
+ clients: authority.clients.map((client, index) =>
1856
+ index === 0 ? { ...client, activityRevision: client.activityRevision + 1 } : client,
1857
+ ),
1858
+ },
1859
+ "cross-mutation",
1860
+ ],
1861
+ ];
1862
+ for (const [changed, reason] of cases) {
1863
+ const result = assessCard5NullAuthorityPair({
1864
+ ...input,
1865
+ authorities: [authority, changed],
1866
+ });
1867
+ assert.equal(result.passed, false);
1868
+ assert.equal(result.reason, reason);
1869
+ assert.equal(JSON.stringify(result.observation).includes("client-a"), false);
1870
+ assert.equal(result.observation.views.length, 2);
1871
+ }
1872
+ assert.equal(
1873
+ assessCard5NullAuthorityPair({
1874
+ ...input,
1875
+ authorities: [
1876
+ { ...authority, revision: 12 },
1877
+ { ...authority, revision: 12 },
1878
+ ],
1879
+ }).reason,
1880
+ "revision-not-advanced",
1881
+ );
1882
+ assert.equal(
1883
+ assessCard5NullAuthorityPair({
1884
+ ...input,
1885
+ releaseRevisions: [13, 13, 13],
1886
+ }).passed,
1887
+ true,
1888
+ );
1889
+ assert.equal(
1890
+ assessCard5NullAuthorityPair({
1891
+ ...input,
1892
+ releaseRevisions: [14],
1893
+ }).reason,
1894
+ "release-revision-not-settled",
1895
+ );
1896
+ assert.equal(
1897
+ assessCard5NullAuthorityPair({
1898
+ ...input,
1899
+ releaseRevisions: [Number.NaN],
1900
+ }).reason,
1901
+ "contract-invalid",
1902
+ );
1903
+ });
1904
+
1905
+ function tuiHandoffFixture(overrides = {}) {
1906
+ const payload = "CARD5_HANDOFF_0_deadbeef\n";
1907
+ const traceId = "trace-a";
1908
+ const canonical = {
1909
+ generation: "daemon-generation-a",
1910
+ incarnation: "daemon-generation-a:0",
1911
+ revision: 1,
1912
+ canonicalStateHash: HASH,
1913
+ processId: "opentui:123",
1914
+ clockId: "opentui-performance-now",
1915
+ cols: 80,
1916
+ rows: 24,
1917
+ };
1918
+ const next = { revision: 2, stateHash: "c".repeat(16), cols: 80, rows: 24 };
1919
+ const writerHealth = {
1920
+ droppedRecords: 0,
1921
+ oversizedRecords: 0,
1922
+ failed: false,
1923
+ pendingCriticalRecords: 0,
1924
+ };
1925
+ const common = {
1926
+ traceId,
1927
+ processId: "opentui:123",
1928
+ clockId: "opentui-performance-now",
1929
+ clockKind: "performance-now",
1930
+ };
1931
+ const records = [
1932
+ {
1933
+ version: 1,
1934
+ type: "performance.input-origin",
1935
+ ...common,
1936
+ origin: "bracketed-paste",
1937
+ parserConsumption: "paste-event",
1938
+ atMicros: 1_000,
1939
+ semanticPaneId: "pane-a",
1940
+ generation: canonical.generation,
1941
+ incarnation: canonical.incarnation,
1942
+ revision: canonical.revision,
1943
+ stateHash: canonical.canonicalStateHash,
1944
+ payloadByteCount: Buffer.byteLength(payload),
1945
+ payloadFingerprint: createHmac("sha256", KEY)
1946
+ .update(traceId)
1947
+ .update("\0")
1948
+ .update(payload)
1949
+ .digest("hex"),
1950
+ },
1951
+ {
1952
+ version: 1,
1953
+ type: "performance.terminal-framebuffer-projection",
1954
+ ...common,
1955
+ atMicros: 1_025,
1956
+ semanticPaneId: "pane-a",
1957
+ generation: canonical.generation,
1958
+ incarnation: canonical.incarnation,
1959
+ ...next,
1960
+ },
1961
+ {
1962
+ version: 1,
1963
+ type: "performance.stage",
1964
+ stage: "input",
1965
+ ...common,
1966
+ scenario: "terminal-input-to-paint",
1967
+ startedAtMicros: 1_000,
1968
+ endedAtMicros: 1_010,
1969
+ authority: { generation: canonical.generation, incarnation: canonical.incarnation },
1970
+ },
1971
+ {
1972
+ version: 1,
1973
+ type: "performance.stage",
1974
+ stage: "paint",
1975
+ ...common,
1976
+ scenario: "terminal-input-to-paint",
1977
+ startedAtMicros: 1_020,
1978
+ endedAtMicros: 1_030,
1979
+ paintStateIdentity: "latest-canonical-state-blitted",
1980
+ semanticPaneId: "pane-a",
1981
+ generation: canonical.generation,
1982
+ incarnation: canonical.incarnation,
1983
+ revision: next.revision,
1984
+ stateHash: next.stateHash,
1985
+ },
1986
+ {
1987
+ version: 1,
1988
+ type: "performance.input-fence",
1989
+ ...common,
1990
+ atMicros: 1_031,
1991
+ semanticPaneId: "pane-a",
1992
+ generation: canonical.generation,
1993
+ incarnation: canonical.incarnation,
1994
+ revision: next.revision,
1995
+ stateHash: next.stateHash,
1996
+ writerHealth,
1997
+ },
1998
+ {
1999
+ version: 1,
2000
+ type: "performance.terminal-frame-fence",
2001
+ semanticPaneId: "pane-a",
2002
+ generation: canonical.generation,
2003
+ incarnation: canonical.incarnation,
2004
+ ...next,
2005
+ acceptedRevision: next.revision,
2006
+ identityDrops: 0,
2007
+ processId: common.processId,
2008
+ clockId: common.clockId,
2009
+ clockKind: common.clockKind,
2010
+ atMicros: 1_050,
2011
+ writerHealth,
2012
+ },
2013
+ ];
2014
+ return {
2015
+ records,
2016
+ hostReceipt: {
2017
+ version: 1,
2018
+ kind: "paste",
2019
+ target: "%7",
2020
+ paneId: "%7",
2021
+ sessionId: "$3",
2022
+ geometry: { cols: 160, rows: 44 },
2023
+ delivery: "exact-bytes-to-immutable-host-pane-pty",
2024
+ bytesInjected: Buffer.byteLength(`\x1b[200~${payload}\x1b[201~`),
2025
+ phases: 1,
2026
+ transportCalls: 1,
2027
+ physicalTransportCalls: 1,
2028
+ },
2029
+ payload,
2030
+ expectedPane: "pane-a",
2031
+ expectedCanonical: canonical,
2032
+ inputFingerprintKey: KEY,
2033
+ evidenceKey: KEY,
2034
+ ...overrides,
2035
+ };
2036
+ }
2037
+
2038
+ function tuiFocusedPaneFixture() {
2039
+ const input = tuiHandoffFixture();
2040
+ const canonical = input.expectedCanonical;
2041
+ const common = {
2042
+ processId: canonical.processId,
2043
+ clockId: canonical.clockId,
2044
+ clockKind: "performance-now",
2045
+ semanticPaneId: input.expectedPane,
2046
+ generation: canonical.generation,
2047
+ incarnation: canonical.incarnation,
2048
+ revision: canonical.revision,
2049
+ stateHash: canonical.canonicalStateHash,
2050
+ cols: canonical.cols,
2051
+ rows: canonical.rows,
2052
+ };
2053
+ return {
2054
+ records: [
2055
+ {
2056
+ version: 1,
2057
+ type: "performance.terminal-cursor-presentation",
2058
+ ...common,
2059
+ atMicros: 900,
2060
+ viewportCols: 70,
2061
+ viewportRows: 20,
2062
+ presentationCount: 3,
2063
+ },
2064
+ {
2065
+ version: 1,
2066
+ type: "performance.terminal-frame-fence",
2067
+ ...common,
2068
+ atMicros: 950,
2069
+ viewportCols: 70,
2070
+ viewportRows: 20,
2071
+ acceptedRevision: canonical.revision,
2072
+ identityDrops: 0,
2073
+ writerHealth: {
2074
+ droppedRecords: 0,
2075
+ oversizedRecords: 0,
2076
+ failed: false,
2077
+ pendingCriticalRecords: 0,
2078
+ },
2079
+ },
2080
+ ],
2081
+ expectedPane: input.expectedPane,
2082
+ expectedCanonical: canonical,
2083
+ evidenceKey: KEY,
2084
+ };
2085
+ }
2086
+
2087
+ function observation(client, host, overrides = {}) {
2088
+ return sealCard5ProductionClientObservation(
2089
+ {
2090
+ client,
2091
+ host,
2092
+ generation: "daemon-generation-a",
2093
+ connected: true,
2094
+ canonicalStateHash: HASH,
2095
+ ...(client === "opentui" ? {} : { contentHmac: CONTENT }),
2096
+ workspaceName: "workspace-a",
2097
+ semanticPaneId: "pane-a",
2098
+ incarnation: "incarnation-a",
2099
+ processIdentity: `${host}:process-a`,
2100
+ clockId: "performance-now",
2101
+ atMicros: 10_000,
2102
+ revision: 7,
2103
+ cols: 120,
2104
+ rows: 40,
2105
+ deliveryFence: 9,
2106
+ presence: client === "web-b" ? "background" : "foreground",
2107
+ passive: client !== "opentui",
2108
+ geometryOwner: client === "opentui",
2109
+ queueCurrent: 0,
2110
+ queuePeak: 4,
2111
+ queueCap: 32,
2112
+ connectElapsedMs: 100,
2113
+ ownerToken: "must-not-project",
2114
+ descriptor: "must-not-project",
2115
+ paneContent: "must-not-project",
2116
+ ...overrides,
2117
+ },
2118
+ KEY,
2119
+ );
2120
+ }
2121
+
2122
+ test("production host evidence is exact, bounded, and capability/content free", () => {
2123
+ const sealed = observation("web-a", "chromium");
2124
+ assert.deepEqual(Object.keys(sealed).sort(), [
2125
+ "atMicros",
2126
+ "canonicalStateHash",
2127
+ "client",
2128
+ "clockHmac",
2129
+ "cols",
2130
+ "connectElapsedMs",
2131
+ "connected",
2132
+ "correlationHmac",
2133
+ "deliveryFence",
2134
+ "generation",
2135
+ "geometryOwner",
2136
+ "host",
2137
+ "incarnationHmac",
2138
+ "paneHmac",
2139
+ "passive",
2140
+ "presence",
2141
+ "processHmac",
2142
+ "queueCap",
2143
+ "queueCurrent",
2144
+ "queuePeak",
2145
+ "renditionHmac",
2146
+ "revision",
2147
+ "rows",
2148
+ "workspaceHmac",
2149
+ ]);
2150
+ const serialized = JSON.stringify(sealed);
2151
+ assert.equal(serialized.includes("must-not-project"), false);
2152
+ assert.equal(sealed.correlationHmac.length, 64);
2153
+ });
2154
+
2155
+ test("Card5 correlation joins the same bounded observed records and scans privacy", () => {
2156
+ const kinds = [
2157
+ "host-open",
2158
+ "canonical-before",
2159
+ "authority-handoff",
2160
+ "slow-isolation",
2161
+ "generation-replacement",
2162
+ "canonical-after",
2163
+ "native-observer",
2164
+ ];
2165
+ const hmac = (domain, value) =>
2166
+ createHmac("sha256", Buffer.from(KEY, "hex")).update(`${domain}\0${value}`).digest("hex");
2167
+ const records = kinds.map((kind, ordinal) => {
2168
+ const sourceBindings = ["opentui", "web-a", "web-b"].map((client, clientOrdinal) => {
2169
+ const paneHmac = "a".repeat(64);
2170
+ const processHmac = String(clientOrdinal + 1).repeat(64);
2171
+ const clockHmac = String(clientOrdinal + 4).repeat(64);
2172
+ return {
2173
+ client,
2174
+ paneHmac,
2175
+ processHmac,
2176
+ clockHmac,
2177
+ bindingHmac: hmac("source-binding", [client, paneHmac, processHmac, clockHmac].join("\0")),
2178
+ };
2179
+ });
2180
+ const valueHmac = hmac("value", kind);
2181
+ return {
2182
+ kind,
2183
+ ordinal,
2184
+ valueHmac,
2185
+ sourceBindings,
2186
+ recordHmac: hmac(
2187
+ "record",
2188
+ [kind, ordinal, valueHmac, ...sourceBindings.map(({ bindingHmac }) => bindingHmac)].join(
2189
+ "\0",
2190
+ ),
2191
+ ),
2192
+ };
2193
+ });
2194
+ const sealed = sealCard5CorrelationEvidence(records, KEY);
2195
+ assert.equal(sealed.correlation.complete, true);
2196
+ assert.equal(sealed.correlation.recordCount, 7);
2197
+ assert.equal(sealed.privacy.rawCapabilityCount, 0);
2198
+ assert.equal(
2199
+ sealCard5CorrelationEvidence([...records, records[0]], KEY).correlation.complete,
2200
+ false,
2201
+ );
2202
+ assert.equal(
2203
+ sealCard5CorrelationEvidence(
2204
+ records.map((record, index) =>
2205
+ index === 2
2206
+ ? {
2207
+ ...record,
2208
+ sourceBindings: record.sourceBindings.map((binding, bindingIndex) =>
2209
+ bindingIndex === 1 ? { ...binding, processHmac: "9".repeat(64) } : binding,
2210
+ ),
2211
+ }
2212
+ : record,
2213
+ ),
2214
+ KEY,
2215
+ ).correlation.complete,
2216
+ false,
2217
+ );
2218
+ assert.equal(
2219
+ sealCard5CorrelationEvidence(
2220
+ records.map((record, index) => (index === 0 ? { ...record, ownerToken: "raw" } : record)),
2221
+ KEY,
2222
+ ).privacy.rawOwnerTokenCount,
2223
+ 1,
2224
+ );
2225
+ });
2226
+
2227
+ test("canonical convergence requires two identical exact three-host samples", () => {
2228
+ const sample = [
2229
+ observation("opentui", "opentui"),
2230
+ observation("web-a", "chromium"),
2231
+ observation("web-b", "electron"),
2232
+ ];
2233
+ const first = advanceCard5CanonicalStability(null, sample);
2234
+ assert.equal(first.stable, false);
2235
+ assert.equal(first.reason, "stability-pending");
2236
+ assert.equal(advanceCard5CanonicalStability(first.digest, sample).stable, true);
2237
+ assert.equal(
2238
+ advanceCard5CanonicalStability(first.digest, sample.slice(0, 2)).reason,
2239
+ "client-cardinality",
2240
+ );
2241
+ assert.equal(
2242
+ advanceCard5CanonicalStability(first.digest, [sample[0], sample[1], sample[1]]).reason,
2243
+ "client-identity",
2244
+ );
2245
+ const divergence = advanceCard5CanonicalStability(first.digest, [
2246
+ sample[0],
2247
+ sample[1],
2248
+ { ...sample[2], canonicalStateHash: "c".repeat(16) },
2249
+ ]);
2250
+ assert.equal(divergence.reason, "canonical-divergence");
2251
+ assert.deepEqual(divergence.axes, {
2252
+ generation: true,
2253
+ canonicalHash: false,
2254
+ revision: true,
2255
+ dimensions: true,
2256
+ workspace: true,
2257
+ pane: true,
2258
+ incarnation: true,
2259
+ webRendition: true,
2260
+ fieldsComplete: true,
2261
+ });
2262
+ assert.equal(divergence.candidate.clients.length, 3);
2263
+ assert.equal(JSON.stringify(divergence.candidate).includes("workspace-a"), false);
2264
+ });
2265
+
2266
+ test("focused convergence requires two identical Web, cursor, frame, viewport, and authority tuples", () => {
2267
+ const focused = tuiFocusedPaneFixture();
2268
+ focused.expectedAuthority = focusAuthorityFixture(focused.expectedCanonical.generation);
2269
+ const focus = assessCard5TuiFocusedPane(focused).evidence;
2270
+ const common = {
2271
+ generation: focused.expectedCanonical.generation,
2272
+ canonicalStateHash: focused.expectedCanonical.canonicalStateHash,
2273
+ semanticPaneId: focused.expectedPane,
2274
+ incarnation: focused.expectedCanonical.incarnation,
2275
+ revision: focused.expectedCanonical.revision,
2276
+ cols: focused.expectedCanonical.cols,
2277
+ rows: focused.expectedCanonical.rows,
2278
+ };
2279
+ const clients = [
2280
+ observation("opentui", "opentui", {
2281
+ ...common,
2282
+ processIdentity: focused.expectedCanonical.processId,
2283
+ clockId: focused.expectedCanonical.clockId,
2284
+ }),
2285
+ observation("web-a", "chromium", common),
2286
+ observation("web-b", "electron", common),
2287
+ ];
2288
+ const first = advanceCard5FocusedConvergenceStability(null, clients, focus, KEY);
2289
+ assert.equal(first.stable, false);
2290
+ assert.match(first.digest, /^[0-9a-f]{64}$/u);
2291
+ assert.equal(
2292
+ advanceCard5FocusedConvergenceStability(first.digest, clients, focus, KEY).stable,
2293
+ true,
2294
+ );
2295
+ const changedViewport = { ...focus, viewportCols: focus.viewportCols + 1 };
2296
+ const changed = advanceCard5FocusedConvergenceStability(
2297
+ first.digest,
2298
+ clients,
2299
+ changedViewport,
2300
+ KEY,
2301
+ );
2302
+ assert.equal(changed.stable, false);
2303
+ assert.notEqual(changed.digest, first.digest);
2304
+ const revisionChangedInput = tuiFocusedPaneFixture();
2305
+ revisionChangedInput.expectedAuthority = {
2306
+ ...focusAuthorityFixture(revisionChangedInput.expectedCanonical.generation),
2307
+ revision: 12,
2308
+ };
2309
+ const revisionChanged = assessCard5TuiFocusedPane(revisionChangedInput).evidence;
2310
+ assert.equal(
2311
+ advanceCard5FocusedConvergenceStability(first.digest, clients, revisionChanged, KEY).digest,
2312
+ first.digest,
2313
+ );
2314
+ const topologyChangedInput = tuiFocusedPaneFixture();
2315
+ const topologyAuthority = focusAuthorityFixture(
2316
+ topologyChangedInput.expectedCanonical.generation,
2317
+ );
2318
+ topologyChangedInput.expectedAuthority = {
2319
+ ...topologyAuthority,
2320
+ clients: topologyAuthority.clients.map((client, index) =>
2321
+ index === 1 ? { ...client, activityRevision: client.activityRevision + 1 } : client,
2322
+ ),
2323
+ };
2324
+ const topologyChanged = assessCard5TuiFocusedPane(topologyChangedInput).evidence;
2325
+ assert.equal(topologyChanged.authorityTopologyHmac, focus.authorityTopologyHmac);
2326
+ assert.notEqual(topologyChanged.authorityMutationHmac, focus.authorityMutationHmac);
2327
+ assert.equal(
2328
+ advanceCard5FocusedConvergenceStability(first.digest, clients, topologyChanged, KEY).digest,
2329
+ first.digest,
2330
+ );
2331
+ assert.equal(
2332
+ advanceCard5FocusedConvergenceStability(
2333
+ null,
2334
+ clients,
2335
+ {
2336
+ ...focus,
2337
+ paneHmac: "f".repeat(64),
2338
+ },
2339
+ KEY,
2340
+ ).digest,
2341
+ null,
2342
+ );
2343
+ });
2344
+
2345
+ test("Card5 TUI convergence selects the latest exact frame fence per pane", () => {
2346
+ const tracker = createCard5TuiFrameFenceTracker();
2347
+ const fence = (revision, semanticPaneId = "pane-a") => ({
2348
+ type: "performance.terminal-frame-fence",
2349
+ generation: "generation-a",
2350
+ revision,
2351
+ acceptedRevision: revision,
2352
+ stateHash: revision === 5 ? "b".repeat(16) : "a".repeat(16),
2353
+ semanticPaneId,
2354
+ incarnation: "generation-a:0",
2355
+ cols: 120,
2356
+ rows: 40,
2357
+ atMicros: 1_000 + revision,
2358
+ processId: "opentui:123",
2359
+ clockId: "opentui-performance-now",
2360
+ });
2361
+
2362
+ assert.equal(tracker.ingest(fence(2)), true);
2363
+ assert.equal(tracker.ingest(fence(3)), true);
2364
+ assert.equal(tracker.ingest(fence(4)), true);
2365
+ assert.equal(tracker.ingest(fence(5)), true);
2366
+ assert.equal(tracker.latest("pane-a")?.revision, 5);
2367
+ assert.equal(tracker.latest("pane-b"), null);
2368
+
2369
+ const tuiFence = tracker.latest("pane-a");
2370
+ const samples = [
2371
+ observation("opentui", "opentui", {
2372
+ generation: tuiFence.generation,
2373
+ canonicalStateHash: tuiFence.canonicalStateHash,
2374
+ semanticPaneId: tuiFence.semanticPaneId,
2375
+ incarnation: tuiFence.incarnation,
2376
+ processIdentity: tuiFence.processId,
2377
+ clockId: tuiFence.clockId,
2378
+ atMicros: tuiFence.atMicros,
2379
+ revision: tuiFence.revision,
2380
+ cols: tuiFence.cols,
2381
+ rows: tuiFence.rows,
2382
+ deliveryFence: tuiFence.deliveryFence,
2383
+ }),
2384
+ observation("web-a", "chromium", {
2385
+ generation: "generation-a",
2386
+ canonicalStateHash: "b".repeat(16),
2387
+ semanticPaneId: "pane-a",
2388
+ incarnation: "generation-a:0",
2389
+ revision: 5,
2390
+ }),
2391
+ observation("web-b", "electron", {
2392
+ generation: "generation-a",
2393
+ canonicalStateHash: "b".repeat(16),
2394
+ semanticPaneId: "pane-a",
2395
+ incarnation: "generation-a:0",
2396
+ revision: 5,
2397
+ }),
2398
+ ];
2399
+ const first = advanceCard5CanonicalStability(null, samples);
2400
+ assert.equal(first.reason, "stability-pending");
2401
+ assert.equal(advanceCard5CanonicalStability(first.digest, samples).stable, true);
2402
+ });
2403
+
2404
+ test("Card5 TUI convergence rejects malformed and nonmonotonic frame fences", () => {
2405
+ const valid = {
2406
+ type: "performance.terminal-frame-fence",
2407
+ generation: "generation-a",
2408
+ revision: 5,
2409
+ acceptedRevision: 5,
2410
+ stateHash: "a".repeat(16),
2411
+ semanticPaneId: "pane-a",
2412
+ incarnation: "generation-a:0",
2413
+ cols: 120,
2414
+ rows: 40,
2415
+ atMicros: 1_005,
2416
+ processId: "opentui:123",
2417
+ clockId: "opentui-performance-now",
2418
+ };
2419
+ const malformed = createCard5TuiFrameFenceTracker();
2420
+ assert.equal(malformed.ingest({ ...valid, acceptedRevision: 4 }), false);
2421
+ assert.equal(malformed.latest("pane-a"), null);
2422
+
2423
+ const nonmonotonic = createCard5TuiFrameFenceTracker();
2424
+ assert.equal(nonmonotonic.ingest(valid), true);
2425
+ assert.equal(nonmonotonic.ingest({ ...valid, revision: 4, acceptedRevision: 4 }), false);
2426
+ assert.equal(nonmonotonic.latest("pane-a"), null);
2427
+ });
2428
+
2429
+ test("Card5 TUI pane selection requires the exact shared qualified Web pane", () => {
2430
+ assert.equal(
2431
+ exactSharedCard5WebPane([{ semanticPaneId: "pane-b" }, { semanticPaneId: "pane-b" }]),
2432
+ "pane-b",
2433
+ );
2434
+ assert.equal(
2435
+ exactSharedCard5WebPane([{ semanticPaneId: "pane-a" }, { semanticPaneId: "pane-b" }]),
2436
+ null,
2437
+ );
2438
+ assert.equal(exactSharedCard5WebPane([{ semanticPaneId: "pane-a" }, {}]), null);
2439
+ assert.equal(exactSharedCard5WebPane(undefined), null);
2440
+ const stable = [{ semanticPaneId: "pane-a" }, { semanticPaneId: "pane-a" }];
2441
+ assert.equal(matchesExpectedCard5WebPane(stable, "pane-a"), true);
2442
+ for (const switched of [
2443
+ [{ semanticPaneId: "pane-b" }, { semanticPaneId: "pane-b" }],
2444
+ [{ semanticPaneId: "pane-a" }, { semanticPaneId: "pane-b" }],
2445
+ [{ semanticPaneId: "pane-a" }, {}],
2446
+ ]) {
2447
+ assert.equal(matchesExpectedCard5WebPane(switched, "pane-a"), false);
2448
+ }
2449
+ assert.equal(matchesExpectedCard5WebPane(stable, undefined), false);
2450
+ });
2451
+
2452
+ test("Card5 native pane selection is identity-bound and row-order independent", () => {
2453
+ const paneA = { paneId: "%1", semanticPaneId: "pane-a" };
2454
+ const paneB = { paneId: "%2", semanticPaneId: "pane-b" };
2455
+ assert.equal(selectExactCard5PaneGeometry([paneB, paneA], "pane-a"), paneA);
2456
+ assert.equal(selectExactCard5PaneGeometry([paneA, paneB], "pane-b"), paneB);
2457
+ assert.equal(selectExactCard5PaneGeometry([paneA], "pane-b"), null);
2458
+ assert.equal(selectExactCard5PaneGeometry([paneA, { ...paneA }], "pane-a"), null);
2459
+ assert.equal(selectExactCard5PaneGeometry([paneA], undefined), null);
2460
+ });
2461
+
2462
+ test("Card5 tmux capture binds hostile semantic identity to one exact raw pane", () => {
2463
+ const pane = {
2464
+ paneId: "%17",
2465
+ semanticPaneId: "pane.promoted.hostile:1.2",
2466
+ sessionName: "card5-session",
2467
+ sessionId: "$3",
2468
+ paneCreated: 123,
2469
+ windowActive: true,
2470
+ left: 0,
2471
+ top: 0,
2472
+ width: 120,
2473
+ height: 40,
2474
+ };
2475
+ const sibling = { ...pane, paneId: "%18", semanticPaneId: "pane-other", left: 121 };
2476
+ const binding = selectExactCard5TmuxPaneBinding(
2477
+ [sibling, pane],
2478
+ pane.semanticPaneId,
2479
+ pane.sessionName,
2480
+ );
2481
+ assert.equal(binding.paneId, "%17");
2482
+ assert.deepEqual(card5TmuxCapturePaneArgv(binding), ["capture-pane", "-p", "-J", "-t", "%17"]);
2483
+ assert.equal(
2484
+ JSON.stringify(card5TmuxCapturePaneArgv(binding)).includes(pane.semanticPaneId),
2485
+ false,
2486
+ );
2487
+ assert.equal(
2488
+ sameExactCard5TmuxPaneBinding(
2489
+ binding,
2490
+ selectExactCard5TmuxPaneBinding([pane, sibling], pane.semanticPaneId, pane.sessionName),
2491
+ ),
2492
+ true,
2493
+ );
2494
+ });
2495
+
2496
+ test("Card5 tmux capture rejects missing, duplicate, replaced, or cross-session bindings", () => {
2497
+ const pane = {
2498
+ paneId: "%17",
2499
+ semanticPaneId: "pane-a",
2500
+ sessionName: "card5-session",
2501
+ sessionId: "$3",
2502
+ paneCreated: 123,
2503
+ windowActive: true,
2504
+ left: 0,
2505
+ top: 0,
2506
+ width: 120,
2507
+ height: 40,
2508
+ };
2509
+ const binding = selectExactCard5TmuxPaneBinding([pane], "pane-a", "card5-session");
2510
+ assert.equal(selectExactCard5TmuxPaneBinding([], "pane-a", "card5-session"), null);
2511
+ assert.equal(
2512
+ selectExactCard5TmuxPaneBinding([pane, { ...pane }], "pane-a", "card5-session"),
2513
+ null,
2514
+ );
2515
+ assert.equal(selectExactCard5TmuxPaneBinding([pane], "pane-a", "other-session"), null);
2516
+ for (const changed of [
2517
+ { ...pane, paneId: "%19" },
2518
+ { ...pane, paneCreated: 124 },
2519
+ { ...pane, sessionId: "$4" },
2520
+ { ...pane, left: 1 },
2521
+ ]) {
2522
+ assert.equal(
2523
+ sameExactCard5TmuxPaneBinding(
2524
+ binding,
2525
+ selectExactCard5TmuxPaneBinding([changed], "pane-a", "card5-session"),
2526
+ ),
2527
+ false,
2528
+ );
2529
+ }
2530
+ assert.equal(card5TmuxCapturePaneArgv({ paneId: "pane.promoted.hostile" }), null);
2531
+ });
2532
+
2533
+ test("Card5 tmux capture revalidates the exact binding before and after its raw argv", () => {
2534
+ const pane = {
2535
+ paneId: "%17",
2536
+ semanticPaneId: "pane.promoted.hostile",
2537
+ sessionName: "card5-session",
2538
+ sessionId: "$3",
2539
+ paneCreated: 123,
2540
+ windowActive: true,
2541
+ left: 0,
2542
+ top: 0,
2543
+ width: 120,
2544
+ height: 40,
2545
+ };
2546
+ const binding = selectExactCard5TmuxPaneBinding([pane], pane.semanticPaneId, pane.sessionName);
2547
+ let observations = 0;
2548
+ let capturedArgv = null;
2549
+ const result = runExactCard5TmuxPaneCapture({
2550
+ latchedBinding: binding,
2551
+ observeBinding: () => {
2552
+ observations += 1;
2553
+ return selectExactCard5TmuxPaneBinding([pane], pane.semanticPaneId, pane.sessionName);
2554
+ },
2555
+ capture: (argv) => {
2556
+ capturedArgv = argv;
2557
+ return "marker";
2558
+ },
2559
+ });
2560
+ assert.deepEqual(result, { status: "ok", value: "marker" });
2561
+ assert.equal(observations, 2);
2562
+ assert.deepEqual(capturedArgv, ["capture-pane", "-p", "-J", "-t", "%17"]);
2563
+
2564
+ let turn = 0;
2565
+ let calls = 0;
2566
+ const drift = runExactCard5TmuxPaneCapture({
2567
+ latchedBinding: binding,
2568
+ observeBinding: () => {
2569
+ turn += 1;
2570
+ const current = turn === 1 ? pane : { ...pane, paneId: "%19", paneCreated: 124 };
2571
+ return selectExactCard5TmuxPaneBinding([current], pane.semanticPaneId, pane.sessionName);
2572
+ },
2573
+ capture: () => {
2574
+ calls += 1;
2575
+ return "marker";
2576
+ },
2577
+ });
2578
+ assert.deepEqual(drift, { status: "topology-changed", value: null });
2579
+ assert.equal(calls, 1);
2580
+
2581
+ calls = 0;
2582
+ const preDrift = runExactCard5TmuxPaneCapture({
2583
+ latchedBinding: binding,
2584
+ observeBinding: () => null,
2585
+ capture: () => {
2586
+ calls += 1;
2587
+ },
2588
+ });
2589
+ assert.deepEqual(preDrift, { status: "topology-changed", value: null });
2590
+ assert.equal(calls, 0);
2591
+ });
2592
+
2593
+ test("Card5 TUI focus qualifies the exact current cursor presentation and later frame", () => {
2594
+ const input = tuiFocusedPaneFixture();
2595
+ const result = assessCard5TuiFocusedPane(input);
2596
+ assert.equal(result.passed, true);
2597
+ assert.equal(JSON.stringify(result.evidence).includes(input.expectedPane), false);
2598
+ assert.equal(result.evidence.revision, input.expectedCanonical.revision);
2599
+ assert.equal(result.evidence.cols, 80);
2600
+ assert.equal(result.evidence.viewportCols, 70);
2601
+ });
2602
+
2603
+ function tuiRetainedFocusFixture() {
2604
+ const initial = tuiFocusedPaneFixture();
2605
+ const acceptedFocusEvidence = assessCard5TuiFocusedPane(initial).evidence;
2606
+ const common = {
2607
+ processId: initial.expectedCanonical.processId,
2608
+ clockId: initial.expectedCanonical.clockId,
2609
+ clockKind: "performance-now",
2610
+ semanticPaneId: initial.expectedPane,
2611
+ generation: initial.expectedCanonical.generation,
2612
+ incarnation: initial.expectedCanonical.incarnation,
2613
+ revision: initial.expectedCanonical.revision,
2614
+ stateHash: initial.expectedCanonical.canonicalStateHash,
2615
+ cols: initial.expectedCanonical.cols,
2616
+ rows: initial.expectedCanonical.rows,
2617
+ viewportCols: acceptedFocusEvidence.viewportCols,
2618
+ viewportRows: acceptedFocusEvidence.viewportRows,
2619
+ sourceEpoch: 4,
2620
+ rendererEpoch: 3,
2621
+ };
2622
+ return {
2623
+ records: [
2624
+ {
2625
+ version: 1,
2626
+ type: "performance.terminal-cursor-presentation",
2627
+ ...common,
2628
+ atMicros: 1_000,
2629
+ presentationCount: 4,
2630
+ },
2631
+ {
2632
+ version: 1,
2633
+ type: "performance.terminal-focus-fence",
2634
+ ...common,
2635
+ atMicros: 1_050,
2636
+ diagnosticEpoch: 2,
2637
+ rendererEpoch: 3,
2638
+ focused: true,
2639
+ writerHealth: {
2640
+ droppedRecords: 0,
2641
+ oversizedRecords: 0,
2642
+ failed: false,
2643
+ pendingCriticalRecords: 0,
2644
+ },
2645
+ },
2646
+ ],
2647
+ expectedPane: initial.expectedPane,
2648
+ expectedCanonical: initial.expectedCanonical,
2649
+ acceptedFocusEvidence,
2650
+ expectedDiagnosticEpoch: 2,
2651
+ expectedRendererEpoch: 3,
2652
+ evidenceKey: KEY,
2653
+ };
2654
+ }
2655
+
2656
+ test("Card5 retained focus accepts a production focus-only redraw without a canonical frame", () => {
2657
+ const input = tuiRetainedFocusFixture();
2658
+ const result = assessCard5TuiRetainedFocus(input);
2659
+ assert.equal(result.passed, true);
2660
+ assert.equal(
2661
+ input.records.some(({ type }) => type === "performance.terminal-frame-fence"),
2662
+ false,
2663
+ );
2664
+ assert.equal(result.evidence.focusStateHmac, input.acceptedFocusEvidence.focusStateHmac);
2665
+ assert.match(result.evidence.focusFenceHmac, /^[0-9a-f]{64}$/u);
2666
+ assert.equal(result.evidence.rendererEpoch, input.expectedRendererEpoch);
2667
+ assert.match(result.evidence.rendererEpochHmac, /^[0-9a-f]{64}$/u);
2668
+ const delayed = tuiRetainedFocusFixture();
2669
+ delayed.records.splice(1, 1);
2670
+ const missing = assessCard5TuiRetainedFocus(delayed);
2671
+ let stability = advanceCard5RetainedFocusStability(
2672
+ null,
2673
+ JSON.stringify(missing.candidate),
2674
+ false,
2675
+ );
2676
+ assert.equal(stability.passed, false);
2677
+ delayed.records.push(structuredClone(input.records[1]));
2678
+ const settled = assessCard5TuiRetainedFocus(delayed);
2679
+ const candidate = JSON.stringify({ focus: settled.candidate, referenceOffset: 2 });
2680
+ stability = advanceCard5RetainedFocusStability(stability, candidate, settled.passed);
2681
+ assert.equal(stability.passed, false);
2682
+ stability = advanceCard5RetainedFocusStability(stability, candidate, settled.passed);
2683
+ assert.equal(stability.passed, true);
2684
+ assert.equal(
2685
+ advanceCard5RetainedFocusStability(stability, `${candidate}-growth`, true).passed,
2686
+ false,
2687
+ );
2688
+ });
2689
+
2690
+ test("Card5 retained focus rejects missing, foreign, unhealthy, later, or changed evidence", () => {
2691
+ const mutations = [
2692
+ (value) => value.records.splice(1, 1),
2693
+ (value) => (value.records[1].diagnosticEpoch = 3),
2694
+ (value) => (value.records[0].rendererEpoch = 2),
2695
+ (value) => delete value.records[0].rendererEpoch,
2696
+ (value) => (value.records[0].rendererEpoch = Number.MAX_SAFE_INTEGER + 1),
2697
+ (value) => (value.records[1].rendererEpoch = 4),
2698
+ (value) => (value.records[1].sourceEpoch = 5),
2699
+ (value) => (value.records[1].processId = "opentui:456"),
2700
+ (value) => (value.records[1].writerHealth.failed = true),
2701
+ (value) => value.records.push({ ...structuredClone(value.records[1]), atMicros: 1_075 }),
2702
+ (value) =>
2703
+ value.records.push({
2704
+ ...structuredClone(value.records[0]),
2705
+ atMicros: 1_100,
2706
+ semanticPaneId: "pane-b",
2707
+ presentationCount: 5,
2708
+ }),
2709
+ (value) =>
2710
+ value.records.push({
2711
+ version: 1,
2712
+ type: "performance.terminal-canonical-update",
2713
+ semanticPaneId: value.expectedPane,
2714
+ revision: 2,
2715
+ stateHash: "d".repeat(16),
2716
+ }),
2717
+ (value) =>
2718
+ value.records.push({
2719
+ version: 1,
2720
+ ...structuredClone(value.records[1]),
2721
+ type: "performance.terminal-frame-fence",
2722
+ revision: 2,
2723
+ acceptedRevision: 2,
2724
+ stateHash: "d".repeat(16),
2725
+ atMicros: 1_100,
2726
+ }),
2727
+ ];
2728
+ for (const mutate of mutations) {
2729
+ const input = tuiRetainedFocusFixture();
2730
+ mutate(input);
2731
+ assert.equal(assessCard5TuiRetainedFocus(input).passed, false);
2732
+ }
2733
+ });
2734
+
2735
+ test("Card5 TUI focus rejects missing, ambiguous, stale, cross-identity, and unhealthy facts", () => {
2736
+ const mutations = [
2737
+ (value) => value.records.splice(0, 1),
2738
+ (value) => value.records.push({ ...value.records[0] }),
2739
+ (value) =>
2740
+ value.records.push({
2741
+ ...value.records[0],
2742
+ atMicros: value.records[0].atMicros + 1,
2743
+ semanticPaneId: "pane-b",
2744
+ }),
2745
+ (value) => (value.records[0].semanticPaneId = "pane-b"),
2746
+ (value) => (value.records[0].generation = "daemon-generation-b"),
2747
+ (value) => (value.records[0].incarnation = "daemon-generation-a:1"),
2748
+ (value) => (value.records[0].revision = 0),
2749
+ (value) => (value.records[0].stateHash = "d".repeat(16)),
2750
+ (value) => (value.records[0].cols = 79),
2751
+ (value) => (value.records[0].rows = 23),
2752
+ (value) => (value.records[0].processId = "opentui:456"),
2753
+ (value) => (value.records[0].clockId = "foreign-clock"),
2754
+ (value) => (value.records[0].viewportCols = 79),
2755
+ (value) => value.records.splice(1, 1),
2756
+ (value) => (value.records[1].acceptedRevision = 0),
2757
+ (value) => (value.records[1].identityDrops = 1),
2758
+ (value) => (value.records[1].writerHealth.droppedRecords = 1),
2759
+ (value) => (value.records[1].atMicros = 899),
2760
+ ];
2761
+ for (const mutate of mutations) {
2762
+ const input = tuiFocusedPaneFixture();
2763
+ mutate(input);
2764
+ assert.equal(assessCard5TuiFocusedPane(input).passed, false);
2765
+ }
2766
+ });
2767
+
2768
+ test("Card5 retained focus ignores background frames but rejects later focus or canonical change", () => {
2769
+ const background = tuiFocusedPaneFixture();
2770
+ background.records.push({
2771
+ ...structuredClone(background.records[1]),
2772
+ semanticPaneId: "pane-b",
2773
+ atMicros: 960,
2774
+ });
2775
+ assert.equal(assessCard5TuiFocusedPane(background).passed, true);
2776
+
2777
+ const repaint = tuiFocusedPaneFixture();
2778
+ repaint.records.push({ ...structuredClone(repaint.records[1]), atMicros: 960 });
2779
+ assert.equal(assessCard5TuiFocusedPane(repaint).passed, true);
2780
+ assert.equal(
2781
+ assessCard5TuiFocusedPane(repaint).evidence.focusStateHmac,
2782
+ assessCard5TuiFocusedPane(tuiFocusedPaneFixture()).evidence.focusStateHmac,
2783
+ );
2784
+
2785
+ const laterCursor = tuiFocusedPaneFixture();
2786
+ laterCursor.records.push({
2787
+ ...structuredClone(laterCursor.records[0]),
2788
+ semanticPaneId: "pane-b",
2789
+ atMicros: 960,
2790
+ });
2791
+ assert.equal(assessCard5TuiFocusedPane(laterCursor).passed, false);
2792
+
2793
+ const changedCanonical = tuiFocusedPaneFixture();
2794
+ changedCanonical.records.push({
2795
+ ...structuredClone(changedCanonical.records[1]),
2796
+ revision: 2,
2797
+ acceptedRevision: 2,
2798
+ stateHash: "d".repeat(16),
2799
+ atMicros: 960,
2800
+ });
2801
+ assert.equal(assessCard5TuiFocusedPane(changedCanonical).passed, false);
2802
+ });
2803
+
2804
+ test("Card5 TUI focus reports fixed bounded axes and keeps canonical and viewport dimensions separate", () => {
2805
+ const input = tuiFocusedPaneFixture();
2806
+ input.expectedAuthority = focusAuthorityFixture(input.expectedCanonical.generation);
2807
+ const exact = assessCard5TuiFocusedPane(input);
2808
+ assert.equal(exact.passed, true);
2809
+ assert.deepEqual(Object.values(exact.axes), Array(13).fill(false));
2810
+ assert.equal(exact.evidence.cols, 80);
2811
+ assert.equal(exact.evidence.rows, 24);
2812
+ assert.equal(exact.evidence.viewportCols, 70);
2813
+ assert.equal(exact.evidence.viewportRows, 20);
2814
+ assert.match(exact.evidence.authorityHmac, /^[0-9a-f]{64}$/u);
2815
+ assert.equal(exact.evidence.authorityRevision, 11);
2816
+ assert.match(exact.evidence.authorityTopologyHmac, /^[0-9a-f]{64}$/u);
2817
+
2818
+ input.records[0].semanticPaneId = "pane-b";
2819
+ const wrongPane = assessCard5TuiFocusedPane(input);
2820
+ assert.equal(wrongPane.passed, false);
2821
+ assert.equal(wrongPane.axes.pane, true);
2822
+ assert.deepEqual(Object.keys(wrongPane.axes), [
2823
+ "pane",
2824
+ "generation",
2825
+ "incarnation",
2826
+ "revision",
2827
+ "canonicalHash",
2828
+ "process",
2829
+ "clock",
2830
+ "canonicalDimensions",
2831
+ "viewportDimensions",
2832
+ "presentationCount",
2833
+ "followingFrame",
2834
+ "frameHealth",
2835
+ "authority",
2836
+ ]);
2837
+ assert.equal(JSON.stringify(wrongPane.candidate).includes("pane-b"), false);
2838
+ assert.match(wrongPane.candidate.paneHmac, /^[0-9a-f]{64}$/u);
2839
+ });
2840
+
2841
+ test("Card5 TUI focus authority requires one exact OpenTUI input and focus owner", () => {
2842
+ const generation = "daemon-generation-a";
2843
+ const authority = focusAuthorityFixture(generation);
2844
+ assert.equal(hasExactCard5TuiFocusAuthority(authority, generation), true);
2845
+ for (const invalid of [
2846
+ { ...authority, generation: "daemon-generation-b" },
2847
+ { ...authority, owners: { ...authority.owners, input: null } },
2848
+ { ...authority, owners: { ...authority.owners, focus: "client-b" } },
2849
+ { ...authority, clients: [] },
2850
+ { ...authority, clients: [...authority.clients, { ...authority.clients[0] }] },
2851
+ { ...authority, clients: [{ clientId: "client-a", surface: "web" }] },
2852
+ ]) {
2853
+ assert.equal(hasExactCard5TuiFocusAuthority(invalid, generation), false);
2854
+ }
2855
+ });
2856
+
2857
+ test("Card5 semantic authority changes on owners, clients, presence, connection, or native yield", () => {
2858
+ const generation = "daemon-generation-a";
2859
+ const authority = focusAuthorityFixture(generation);
2860
+ const exact = sealCard5TuiFocusAuthority(authority, generation, KEY);
2861
+ const mutations = [
2862
+ { ...authority, owners: { ...authority.owners, geometry: "client-b" } },
2863
+ {
2864
+ ...authority,
2865
+ clients: authority.clients.map((client, index) =>
2866
+ index === 1 ? { ...client, state: "foreground" } : client,
2867
+ ),
2868
+ },
2869
+ {
2870
+ ...authority,
2871
+ clients: authority.clients.map((client, index) =>
2872
+ index === 1 ? { ...client, connectedRevision: client.connectedRevision + 1 } : client,
2873
+ ),
2874
+ },
2875
+ { ...authority, nativeGeometryYieldUntilMs: 20 },
2876
+ ];
2877
+ for (const changed of mutations) {
2878
+ const sealed = sealCard5TuiFocusAuthority(changed, generation, KEY);
2879
+ assert.notEqual(sealed.authorityHmac, exact.authorityHmac);
2880
+ assert.notEqual(sealed.authorityTopologyHmac, exact.authorityTopologyHmac);
2881
+ }
2882
+ });
2883
+
2884
+ test("Card5 semantic authority merge admits async ambient revisions and rejects causal regression", () => {
2885
+ const input = tuiFocusedPaneFixture();
2886
+ input.expectedAuthority = focusAuthorityFixture(input.expectedCanonical.generation);
2887
+ const left = assessCard5TuiFocusedPane(input).evidence;
2888
+ input.expectedAuthority = {
2889
+ ...input.expectedAuthority,
2890
+ revision: left.authorityRevision + 2,
2891
+ clients: input.expectedAuthority.clients.map((client, index) =>
2892
+ index === 2 ? { ...client, activityRevision: client.activityRevision + 2 } : client,
2893
+ ),
2894
+ };
2895
+ const right = assessCard5TuiFocusedPane(input).evidence;
2896
+ const merged = mergeCard5SemanticAuthorityEvidence(left, right, left.authorityRevision);
2897
+ assert.equal(merged.status, "exact");
2898
+ assert.equal(merged.evidence.authorityRevision, right.authorityRevision);
2899
+ assert.equal(merged.evidence.authorityHmac, left.authorityHmac);
2900
+ assert.equal(
2901
+ mergeCard5SemanticAuthorityEvidence(left, right, right.authorityRevision + 1).status,
2902
+ "revision-regressed",
2903
+ );
2904
+ assert.equal(
2905
+ mergeCard5SemanticAuthorityEvidence(
2906
+ left,
2907
+ { ...right, authorityTopologyHmac: "f".repeat(64) },
2908
+ left.authorityRevision,
2909
+ ).status,
2910
+ "semantic-mismatch",
2911
+ );
2912
+ });
2913
+
2914
+ test("Card5 TUI handoff separates the outer host pane from the exact semantic trace", () => {
2915
+ const input = tuiHandoffFixture();
2916
+ assert.equal(isExactCard5TuiHostInputReceipt(input.hostReceipt, input.payload), true);
2917
+ const result = assessCard5TuiHandoffInput(input);
2918
+ assert.equal(result.passed, true);
2919
+ assert.equal(input.hostReceipt.paneId === input.expectedPane, false);
2920
+ assert.equal(JSON.stringify(result.evidence).includes("%7"), false);
2921
+ assert.equal(JSON.stringify(result.evidence).includes("pane-a"), false);
2922
+ assert.match(result.evidence.hostPaneHmac, /^[0-9a-f]{64}$/u);
2923
+ assert.match(result.evidence.paneHmac, /^[0-9a-f]{64}$/u);
2924
+ });
2925
+
2926
+ test("Card5 TUI handoff rejects wrong, duplicated, missing, and spliced semantic traces", () => {
2927
+ const mutations = [
2928
+ (value) => (value.records[0].semanticPaneId = "pane-b"),
2929
+ (value) => (value.records[4].semanticPaneId = "pane-b"),
2930
+ (value) => (value.records[3].semanticPaneId = "pane-b"),
2931
+ (value) => value.records.push({ ...value.records[0] }),
2932
+ (value) => value.records.splice(4, 1),
2933
+ (value) => (value.records[3].traceId = "trace-b"),
2934
+ (value) => (value.records[0].generation = "daemon-generation-b"),
2935
+ (value) => (value.records[3].incarnation = "daemon-generation-a:1"),
2936
+ (value) => (value.records[0].payloadFingerprint = "f".repeat(64)),
2937
+ (value) => (value.records[5].acceptedRevision = 1),
2938
+ (value) => (value.records[5].identityDrops = 1),
2939
+ (value) => (value.records[4].processId = "opentui:456"),
2940
+ (value) => {
2941
+ value.expectedCanonical.processId = "opentui:456";
2942
+ },
2943
+ (value) => (value.records[3].clockId = "foreign-clock"),
2944
+ (value) => (value.records[2].endedAtMicros = 999),
2945
+ (value) => (value.records[3].startedAtMicros = 1_005),
2946
+ (value) => value.records.splice(2, 2, value.records[3], value.records[2]),
2947
+ (value) => value.records.splice(1, 2, value.records[2], value.records[1]),
2948
+ (value) => (value.records[4].writerHealth.oversizedRecords = 1),
2949
+ (value) => (value.hostReceipt.physicalTransportCalls = 2),
2950
+ ];
2951
+ for (const mutate of mutations) {
2952
+ const input = tuiHandoffFixture();
2953
+ mutate(input);
2954
+ assert.equal(assessCard5TuiHandoffInput(input).passed, false);
2955
+ }
2956
+ });
2957
+
2958
+ test("Card5 browser observation is deadline bounded and consumes late settlement", async () => {
2959
+ let expire;
2960
+ let settle;
2961
+ const pending = new Promise((resolve) => {
2962
+ settle = resolve;
2963
+ });
2964
+ const resultPromise = observeCard5WithinDeadline(() => pending, {
2965
+ deadline: 5_000,
2966
+ now: () => 0,
2967
+ scheduleDeadline: (callback) => {
2968
+ expire = callback;
2969
+ return 1;
2970
+ },
2971
+ cancelDeadline: () => undefined,
2972
+ });
2973
+ await Promise.resolve();
2974
+ expire();
2975
+ assert.deepEqual(await resultPromise, { status: "deadline", value: null });
2976
+ settle("late-private-page-result");
2977
+ await Promise.resolve();
2978
+ });
2979
+
2980
+ test("Card5 browser observation rejects a result that settles after its deadline", async () => {
2981
+ const clock = [0, 5_001];
2982
+ assert.deepEqual(
2983
+ await observeCard5WithinDeadline(async () => ["late"], {
2984
+ deadline: 5_000,
2985
+ now: () => clock.shift(),
2986
+ scheduleDeadline: () => 1,
2987
+ cancelDeadline: () => undefined,
2988
+ }),
2989
+ { status: "deadline", value: null },
2990
+ );
2991
+ });
2992
+
2993
+ test("Card5 browser observation consumes a late rejection and rejects a regressing clock", async () => {
2994
+ let expire;
2995
+ let rejectLate;
2996
+ const pending = new Promise((_, reject) => {
2997
+ rejectLate = reject;
2998
+ });
2999
+ const resultPromise = observeCard5WithinDeadline(() => pending, {
3000
+ deadline: 5_000,
3001
+ now: () => 0,
3002
+ scheduleDeadline: (callback) => {
3003
+ expire = callback;
3004
+ return 1;
3005
+ },
3006
+ cancelDeadline: () => undefined,
3007
+ });
3008
+ await Promise.resolve();
3009
+ expire();
3010
+ assert.deepEqual(await resultPromise, { status: "deadline", value: null });
3011
+ rejectLate(new Error("late private renderer failure"));
3012
+ await Promise.resolve();
3013
+
3014
+ const clock = [10, 9];
3015
+ assert.deepEqual(
3016
+ await observeCard5WithinDeadline(async () => ["value"], {
3017
+ deadline: 5_000,
3018
+ now: () => clock.shift(),
3019
+ scheduleDeadline: () => 1,
3020
+ cancelDeadline: () => undefined,
3021
+ }),
3022
+ { status: "clock-invalid", value: null },
3023
+ );
3024
+ });
3025
+
3026
+ test("host failure evidence is enum-only and saturated", () => {
3027
+ assert.deepEqual(
3028
+ boundedCard5HostFailureObservation({
3029
+ reason: "queue-overflow",
3030
+ host: "electron",
3031
+ attempts: 99_999,
3032
+ elapsedMs: 99_999,
3033
+ observedClients: 99,
3034
+ stableSamples: 99,
3035
+ queuePeak: 99_999,
3036
+ secret: "not-projected",
3037
+ }),
3038
+ {
3039
+ operation: "card5-production-host-observation",
3040
+ reason: "queue-overflow",
3041
+ host: "electron",
3042
+ attempts: 4_096,
3043
+ elapsedMs: 60_000,
3044
+ observedClients: 3,
3045
+ stableSamples: 2,
3046
+ queuePeak: 65_535,
3047
+ divergenceAxes: null,
3048
+ focusDivergenceAxes: null,
3049
+ focusCandidates: [],
3050
+ authorityViews: [],
3051
+ candidateSummaries: [],
3052
+ },
3053
+ );
3054
+ });
3055
+
3056
+ test("host failure evidence distinguishes semantic authority from ambient mutation clocks", () => {
3057
+ const input = tuiFocusedPaneFixture();
3058
+ input.expectedAuthority = focusAuthorityFixture(input.expectedCanonical.generation);
3059
+ const first = assessCard5TuiFocusedPane(input).evidence;
3060
+ input.expectedAuthority = {
3061
+ ...input.expectedAuthority,
3062
+ revision: input.expectedAuthority.revision + 1,
3063
+ clients: input.expectedAuthority.clients.map((client, index) =>
3064
+ index === 1 ? { ...client, activityRevision: client.activityRevision + 1 } : client,
3065
+ ),
3066
+ };
3067
+ const second = assessCard5TuiFocusedPane(input).evidence;
3068
+ const observed = boundedCard5HostFailureObservation({
3069
+ reason: "stability-timeout",
3070
+ authorityViews: [
3071
+ {
3072
+ a: first,
3073
+ b: second,
3074
+ semanticEqual: true,
3075
+ revisionMonotonic: true,
3076
+ activityA: {
3077
+ count: 66,
3078
+ overflow: true,
3079
+ events: [
3080
+ { ordinal: 64, surface: "web", kind: "focus", outcome: "ok" },
3081
+ {
3082
+ ordinal: 65,
3083
+ surface: "web",
3084
+ kind: "geometry",
3085
+ outcome: "attempt",
3086
+ dimensionsHmac: "c".repeat(64),
3087
+ },
3088
+ {
3089
+ ordinal: 66,
3090
+ surface: "web",
3091
+ kind: "geometry",
3092
+ outcome: "ok",
3093
+ dimensionsHmac: "c".repeat(64),
3094
+ raw: "private",
3095
+ },
3096
+ ],
3097
+ geometrySettlements: [
3098
+ {
3099
+ ordinal: 1,
3100
+ requestHmac: "a".repeat(64),
3101
+ clientHmac: "b".repeat(64),
3102
+ dimensionsHmac: "c".repeat(64),
3103
+ },
3104
+ ],
3105
+ },
3106
+ },
3107
+ ],
3108
+ });
3109
+ assert.equal(observed.authorityViews.length, 1);
3110
+ assert.equal(observed.authorityViews[0].semanticEqual, true);
3111
+ assert.equal(
3112
+ observed.authorityViews[0].a.semanticHmac,
3113
+ observed.authorityViews[0].b.semanticHmac,
3114
+ );
3115
+ assert.notEqual(
3116
+ observed.authorityViews[0].a.mutationHmac,
3117
+ observed.authorityViews[0].b.mutationHmac,
3118
+ );
3119
+ assert.deepEqual(Object.keys(observed.authorityViews[0].a), [
3120
+ "valid",
3121
+ "reason",
3122
+ "axes",
3123
+ "counts",
3124
+ "ownerHmac",
3125
+ "clientsHmac",
3126
+ "recordTransitions",
3127
+ "revision",
3128
+ "semanticHmac",
3129
+ "topologyHmac",
3130
+ "mutationHmac",
3131
+ "mode",
3132
+ "relation",
3133
+ "grantRevision",
3134
+ "releaseRevision",
3135
+ "relationHmac",
3136
+ "sequenceHmac",
3137
+ "duplicateCount",
3138
+ ]);
3139
+ assert.deepEqual(observed.authorityViews[0].activityA.byKind, {
3140
+ focus: 1,
3141
+ geometry: 2,
3142
+ input: 0,
3143
+ });
3144
+ assert.equal(observed.authorityViews[0].activityA.events.length, 3);
3145
+ assert.equal(observed.authorityViews[0].activityA.geometrySettlements.length, 1);
3146
+ assert.equal(JSON.stringify(observed.authorityViews).includes("private"), false);
3147
+ });
3148
+
3149
+ test("Card5 authority seal rejection is exact, bounded, and identity opaque", () => {
3150
+ const exact = assessCard5TuiFocusAuthority(focusAuthorityFixture(), "daemon-generation-a", KEY, [
3151
+ {
3152
+ ordinal: 1,
3153
+ revision: 10,
3154
+ inputOwner: "private-tui",
3155
+ focusOwner: "private-tui",
3156
+ geometryOwner: "private-web",
3157
+ clients: focusAuthorityFixture().clients,
3158
+ },
3159
+ ]);
3160
+ assert.equal(exact.valid, true);
3161
+ assert.equal(exact.reason, null);
3162
+ assert.equal(exact.recordTransitions.length, 1);
3163
+ assert.equal(JSON.stringify(exact).includes("private-"), false);
3164
+ const adversaries = [
3165
+ ["generation-mismatch", (value) => (value.generation = "other-generation")],
3166
+ ["session-invalid", (value) => (value.session = "")],
3167
+ ["revision-invalid", (value) => (value.revision = -1)],
3168
+ ["native-yield-invalid", (value) => (value.nativeGeometryYieldUntilMs = -1)],
3169
+ ["client-count-invalid", (value) => value.clients.pop()],
3170
+ ["client-schema-invalid", (value) => (value.clients[0].state = "unknown")],
3171
+ ["surface-cardinality-invalid", (value) => (value.clients[1].surface = "sdk")],
3172
+ ["duplicate-client", (value) => (value.clients[1].clientId = value.clients[0].clientId)],
3173
+ ["input-owner-invalid", (value) => (value.owners.input = value.clients[1].clientId)],
3174
+ ["focus-owner-invalid", (value) => (value.owners.focus = value.clients[1].clientId)],
3175
+ ];
3176
+ for (const [reason, mutate] of adversaries) {
3177
+ const authority = structuredClone(focusAuthorityFixture());
3178
+ mutate(authority);
3179
+ const assessed = assessCard5TuiFocusAuthority(authority, "daemon-generation-a", KEY);
3180
+ assert.equal(assessed.valid, false);
3181
+ assert.equal(assessed.reason, reason);
3182
+ assert.equal(
3183
+ assessed.axes[
3184
+ reason === "duplicate-client"
3185
+ ? "duplicateClients"
3186
+ : Object.keys(assessed.axes).find((key) => assessed.axes[key])
3187
+ ],
3188
+ true,
3189
+ );
3190
+ }
3191
+ });
3192
+
3193
+ test("Card5 post-handoff authority accepts retained owner or causal later null", () => {
3194
+ const retained = focusAuthorityFixture();
3195
+ retained.revision = 12;
3196
+ const retainedRecord = {
3197
+ ordinal: 1,
3198
+ generation: "daemon-generation-a",
3199
+ session: retained.session,
3200
+ revision: 11,
3201
+ nativeGeometryYieldUntilMs: retained.nativeGeometryYieldUntilMs,
3202
+ inputOwner: "client-a",
3203
+ focusOwner: "client-a",
3204
+ geometryOwner: "client-a",
3205
+ clients: structuredClone(retained.clients),
3206
+ };
3207
+ const retainedCurrentRecord = {
3208
+ ...structuredClone(retainedRecord),
3209
+ ordinal: 2,
3210
+ revision: 12,
3211
+ };
3212
+ const retainedResult = assessCard5PostHandoffAuthority({
3213
+ authority: retained,
3214
+ authorityRecords: [retainedRecord, retainedCurrentRecord],
3215
+ generation: "daemon-generation-a",
3216
+ expectedClientId: "client-a",
3217
+ expectedSurface: "opentui",
3218
+ grantRevision: 11,
3219
+ inputProofHmac: HMAC,
3220
+ evidenceKey: KEY,
3221
+ });
3222
+ assert.equal(retainedResult.valid, true);
3223
+ assert.equal(retainedResult.relation, "retained-owner");
3224
+
3225
+ const released = structuredClone(retained);
3226
+ released.revision = 13;
3227
+ released.owners = { input: null, focus: null, geometry: null };
3228
+ released.clients.find(({ clientId }) => clientId === "client-a").state = "background";
3229
+ const releaseRecord = {
3230
+ ordinal: 3,
3231
+ generation: "daemon-generation-a",
3232
+ session: released.session,
3233
+ revision: 13,
3234
+ nativeGeometryYieldUntilMs: released.nativeGeometryYieldUntilMs,
3235
+ inputOwner: null,
3236
+ focusOwner: null,
3237
+ geometryOwner: null,
3238
+ clients: structuredClone(released.clients),
3239
+ };
3240
+ const releasedResult = assessCard5PostHandoffAuthority({
3241
+ authority: released,
3242
+ authorityRecords: [retainedRecord, retainedCurrentRecord, releaseRecord],
3243
+ generation: "daemon-generation-a",
3244
+ expectedClientId: "client-a",
3245
+ expectedSurface: "opentui",
3246
+ grantRevision: 11,
3247
+ inputProofHmac: HMAC,
3248
+ evidenceKey: KEY,
3249
+ });
3250
+ assert.equal(releasedResult.valid, true);
3251
+ assert.equal(releasedResult.relation, "released-null");
3252
+ assert.equal(releasedResult.evidence.releaseRevision, 13);
3253
+ });
3254
+
3255
+ test("Card5 post-handoff authority rejects unexplained null, rollback, and cross-client owners", () => {
3256
+ const authority = focusAuthorityFixture();
3257
+ authority.revision = 11;
3258
+ const grant = {
3259
+ ordinal: 1,
3260
+ generation: "daemon-generation-a",
3261
+ session: authority.session,
3262
+ revision: 11,
3263
+ nativeGeometryYieldUntilMs: authority.nativeGeometryYieldUntilMs,
3264
+ inputOwner: "client-a",
3265
+ focusOwner: "client-a",
3266
+ geometryOwner: "client-a",
3267
+ clients: structuredClone(authority.clients),
3268
+ };
3269
+ const input = {
3270
+ authority,
3271
+ authorityRecords: [grant],
3272
+ generation: "daemon-generation-a",
3273
+ expectedClientId: "client-a",
3274
+ expectedSurface: "opentui",
3275
+ grantRevision: 11,
3276
+ inputProofHmac: HMAC,
3277
+ evidenceKey: KEY,
3278
+ };
3279
+ const unexplained = structuredClone(input);
3280
+ unexplained.authority.owners = { input: null, focus: null, geometry: null };
3281
+ assert.equal(assessCard5PostHandoffAuthority(unexplained).valid, false);
3282
+ const rollback = structuredClone(input);
3283
+ rollback.authority.revision = 10;
3284
+ assert.equal(assessCard5PostHandoffAuthority(rollback).valid, false);
3285
+ const crossOwner = structuredClone(input);
3286
+ crossOwner.authority.owners.input = "client-b";
3287
+ assert.equal(assessCard5PostHandoffAuthority(crossOwner).valid, false);
3288
+ const crossGrant = structuredClone(input);
3289
+ crossGrant.authorityRecords[0].inputOwner = "client-b";
3290
+ assert.equal(assessCard5PostHandoffAuthority(crossGrant).valid, false);
3291
+ const topologyChange = structuredClone(input);
3292
+ topologyChange.authorityRecords[0].clients[1].connectedRevision += 1;
3293
+ assert.equal(assessCard5PostHandoffAuthority(topologyChange).valid, false);
3294
+ const arbitraryOwner = structuredClone(input);
3295
+ arbitraryOwner.authority.owners.geometry = "client-b";
3296
+ assert.equal(assessCard5PostHandoffAuthority(arbitraryOwner).valid, false);
3297
+ });
3298
+
3299
+ test("Card5 post-handoff authority rejects every invalid post-grant state transition", () => {
3300
+ const make = () => {
3301
+ const authority = focusAuthorityFixture();
3302
+ authority.revision = 13;
3303
+ const record = (ordinal, revision, owners, state = "foreground") => {
3304
+ const clients = structuredClone(authority.clients);
3305
+ clients.find(({ clientId }) => clientId === "client-a").state = state;
3306
+ return {
3307
+ ordinal,
3308
+ generation: authority.generation,
3309
+ session: authority.session,
3310
+ revision,
3311
+ nativeGeometryYieldUntilMs: authority.nativeGeometryYieldUntilMs,
3312
+ inputOwner: owners.input,
3313
+ focusOwner: owners.focus,
3314
+ geometryOwner: owners.geometry,
3315
+ clients,
3316
+ };
3317
+ };
3318
+ const owned = { input: "client-a", focus: "client-a", geometry: "client-a" };
3319
+ const records = [record(1, 11, owned), record(2, 12, owned), record(3, 13, owned)];
3320
+ return {
3321
+ authority,
3322
+ authorityRecords: records,
3323
+ generation: authority.generation,
3324
+ expectedClientId: "client-a",
3325
+ expectedSurface: "opentui",
3326
+ grantRevision: 11,
3327
+ inputProofHmac: HMAC,
3328
+ evidenceKey: KEY,
3329
+ };
3330
+ };
3331
+ const rejected = (mutate) => {
3332
+ const input = make();
3333
+ mutate(input);
3334
+ assert.equal(assessCard5PostHandoffAuthority(input).valid, false);
3335
+ };
3336
+ rejected(({ authorityRecords }) => {
3337
+ authorityRecords[1].inputOwner = "client-b";
3338
+ });
3339
+ rejected(({ authority, authorityRecords }) => {
3340
+ authorityRecords[1].inputOwner = "client-b";
3341
+ authorityRecords[2].inputOwner = null;
3342
+ authorityRecords[2].focusOwner = null;
3343
+ authorityRecords[2].geometryOwner = null;
3344
+ authorityRecords[2].clients.find(({ clientId }) => clientId === "client-a").state =
3345
+ "background";
3346
+ authority.owners = { input: null, focus: null, geometry: null };
3347
+ authority.clients.find(({ clientId }) => clientId === "client-a").state = "background";
3348
+ });
3349
+ rejected(({ authority, authorityRecords }) => {
3350
+ authorityRecords[1].inputOwner = null;
3351
+ authorityRecords[1].focusOwner = null;
3352
+ authorityRecords[1].geometryOwner = null;
3353
+ authorityRecords[1].clients.find(({ clientId }) => clientId === "client-a").state =
3354
+ "background";
3355
+ authorityRecords[2].clients.find(({ clientId }) => clientId === "client-a").state =
3356
+ "foreground";
3357
+ authority.owners = authorityRecords[2].inputOwner
3358
+ ? { input: "client-a", focus: "client-a", geometry: "client-a" }
3359
+ : authority.owners;
3360
+ });
3361
+ rejected(({ authority, authorityRecords }) => {
3362
+ authorityRecords[2].inputOwner = null;
3363
+ authorityRecords[2].focusOwner = null;
3364
+ authorityRecords[2].geometryOwner = null;
3365
+ authority.owners = { input: null, focus: null, geometry: null };
3366
+ });
3367
+ rejected(({ authorityRecords }) => {
3368
+ authorityRecords[2].revision = authorityRecords[1].revision;
3369
+ });
3370
+ rejected(({ authorityRecords }) => {
3371
+ authorityRecords[2].revision = authorityRecords[1].revision - 1;
3372
+ });
3373
+ rejected(({ authorityRecords }) => {
3374
+ authorityRecords[1].clients.find(({ clientId }) => clientId === "client-b").state =
3375
+ "foreground";
3376
+ });
3377
+ rejected(({ authorityRecords }) => {
3378
+ authorityRecords[2].revision = 14;
3379
+ });
3380
+ });
3381
+
3382
+ test("Card5 post-handoff authority accepts an exact Web transfer", () => {
3383
+ const authority = focusAuthorityFixture();
3384
+ const web = authority.clients.find(({ clientId }) => clientId === "client-b");
3385
+ web.state = "foreground";
3386
+ authority.clients.find(({ clientId }) => clientId === "client-a").state = "background";
3387
+ authority.owners = {
3388
+ input: "client-b",
3389
+ focus: "client-b",
3390
+ geometry: "client-b",
3391
+ };
3392
+ authority.revision = 15;
3393
+ const result = assessCard5PostHandoffAuthority({
3394
+ authority,
3395
+ authorityRecords: [
3396
+ {
3397
+ ordinal: 3,
3398
+ generation: "daemon-generation-a",
3399
+ session: authority.session,
3400
+ revision: 15,
3401
+ nativeGeometryYieldUntilMs: authority.nativeGeometryYieldUntilMs,
3402
+ inputOwner: "client-b",
3403
+ focusOwner: "client-b",
3404
+ geometryOwner: "client-b",
3405
+ clients: structuredClone(authority.clients),
3406
+ },
3407
+ ],
3408
+ generation: "daemon-generation-a",
3409
+ expectedClientId: "client-b",
3410
+ expectedSurface: "web",
3411
+ grantRevision: 15,
3412
+ inputProofHmac: HMAC,
3413
+ evidenceKey: KEY,
3414
+ });
3415
+ assert.equal(result.valid, true);
3416
+ assert.equal(result.relation, "retained-owner");
3417
+ });
3418
+
3419
+ test("Card5 post-handoff authority collapses only bounded byte-exact revision replays", () => {
3420
+ const authority = focusAuthorityFixture();
3421
+ authority.revision = 12;
3422
+ const record = (ordinal, revision) => ({
3423
+ ordinal,
3424
+ generation: authority.generation,
3425
+ session: authority.session,
3426
+ revision,
3427
+ nativeGeometryYieldUntilMs: authority.nativeGeometryYieldUntilMs,
3428
+ inputOwner: "client-a",
3429
+ focusOwner: "client-a",
3430
+ geometryOwner: "client-a",
3431
+ clients: structuredClone(authority.clients),
3432
+ });
3433
+ const input = {
3434
+ authority,
3435
+ authorityRecords: [record(1, 11), record(2, 11), record(3, 12), record(4, 12)],
3436
+ generation: authority.generation,
3437
+ expectedClientId: "client-a",
3438
+ expectedSurface: "opentui",
3439
+ grantRevision: 11,
3440
+ inputProofHmac: HMAC,
3441
+ evidenceKey: KEY,
3442
+ };
3443
+ input.authorityRecords[1].clients.reverse();
3444
+ input.authorityRecords[3].clients.reverse();
3445
+ const exact = assessCard5PostHandoffAuthority(input);
3446
+ assert.equal(exact.valid, true);
3447
+ assert.equal(exact.evidence.authorityDuplicateCount, 2);
3448
+ assert.match(exact.evidence.authoritySequenceHmac, /^[0-9a-f]{64}$/u);
3449
+
3450
+ for (const mutate of [
3451
+ (value) => (value.authorityRecords[1].inputOwner = null),
3452
+ (value) =>
3453
+ (value.authorityRecords[1].clients.find(({ clientId }) => clientId === "client-a").state =
3454
+ "background"),
3455
+ (value) => (value.authorityRecords[1].nativeGeometryYieldUntilMs += 1),
3456
+ (value) => (value.authorityRecords[1].generation = "other-generation"),
3457
+ (value) => (value.authorityRecords[1].session = "other-session"),
3458
+ ]) {
3459
+ const conflict = structuredClone(input);
3460
+ mutate(conflict);
3461
+ assert.equal(assessCard5PostHandoffAuthority(conflict).valid, false);
3462
+ }
3463
+ const storm = structuredClone(input);
3464
+ storm.authority.revision = 11;
3465
+ storm.authorityRecords = Array.from({ length: 10 }, (_, index) => record(index + 1, 11));
3466
+ assert.equal(assessCard5PostHandoffAuthority(storm).valid, false);
3467
+ });
3468
+
3469
+ test("Card5 post-handoff authority returns typed failures for malformed raw records", () => {
3470
+ const authority = focusAuthorityFixture();
3471
+ authority.revision = 11;
3472
+ const exactRecord = {
3473
+ ordinal: 1,
3474
+ generation: authority.generation,
3475
+ session: authority.session,
3476
+ revision: 11,
3477
+ nativeGeometryYieldUntilMs: authority.nativeGeometryYieldUntilMs,
3478
+ inputOwner: "client-a",
3479
+ focusOwner: "client-a",
3480
+ geometryOwner: "client-a",
3481
+ clients: structuredClone(authority.clients),
3482
+ };
3483
+ const input = {
3484
+ authority,
3485
+ authorityRecords: [exactRecord],
3486
+ generation: authority.generation,
3487
+ expectedClientId: "client-a",
3488
+ expectedSurface: "opentui",
3489
+ grantRevision: 11,
3490
+ inputProofHmac: HMAC,
3491
+ evidenceKey: KEY,
3492
+ };
3493
+ const adversaries = [
3494
+ (record) => delete record.clients,
3495
+ (record) => (record.clients = null),
3496
+ (record) => (record.clients = {}),
3497
+ (record) => (record.clients[0] = null),
3498
+ (record) => (record.clients[0].clientId = ""),
3499
+ (record) => (record.nativeGeometryYieldUntilMs = Number.MAX_SAFE_INTEGER + 1),
3500
+ (record) => (record.revision = Number.MAX_SAFE_INTEGER + 1),
3501
+ (record) => (record.ordinal = Number.MAX_SAFE_INTEGER + 1),
3502
+ (record) => (record.extra = true),
3503
+ (record) => delete record.session,
3504
+ ];
3505
+ for (const mutate of adversaries) {
3506
+ const malformed = structuredClone(input);
3507
+ mutate(malformed.authorityRecords[0]);
3508
+ let result;
3509
+ assert.doesNotThrow(() => {
3510
+ result = assessCard5PostHandoffAuthority(malformed);
3511
+ });
3512
+ assert.deepEqual(result, {
3513
+ valid: false,
3514
+ reason: "post-handoff-contract-invalid",
3515
+ evidence: null,
3516
+ });
3517
+ }
3518
+ });
3519
+
3520
+ test("Card5 authority activity cap fails closed at cap plus one and malformed evidence", () => {
3521
+ const events = Array.from({ length: 64 }, (_, index) => ({
3522
+ ordinal: index + 1,
3523
+ surface: "web",
3524
+ kind: "focus",
3525
+ outcome: "ok",
3526
+ operationOrdinal: null,
3527
+ dimensionsHmac: null,
3528
+ }));
3529
+ const activity = (source, settlements = []) => ({
3530
+ count: source.length,
3531
+ overflow: false,
3532
+ events: source,
3533
+ geometrySettlements: settlements,
3534
+ });
3535
+ assert.equal(card5AuthorityActivityWithinCap(activity(events)), true);
3536
+ const tuiClaims = events.slice(0, 2).map((event) => ({ ...event, surface: "opentui" }));
3537
+ assert.equal(card5AuthorityActivityWithinCap(activity(tuiClaims)), true);
3538
+ assert.equal(
3539
+ card5AuthorityActivityWithinCap(activity([tuiClaims[0], { ...tuiClaims[1], ordinal: 3 }])),
3540
+ false,
3541
+ "a gapped private OpenTUI claim ordinal must not be renumbered into validity",
3542
+ );
3543
+ assert.equal(
3544
+ card5AuthorityActivityWithinCap({ ...activity(events), count: 65, overflow: true }),
3545
+ false,
3546
+ );
3547
+ assert.equal(card5AuthorityActivityWithinCap({ ...activity(events.slice(1)), count: 64 }), false);
3548
+ assert.equal(
3549
+ card5AuthorityActivityWithinCap({ ...activity(events.slice(0, 1)), extra: true }),
3550
+ false,
3551
+ );
3552
+ for (const mutation of [
3553
+ (candidate) => (candidate[1].ordinal = 1),
3554
+ (candidate) => (candidate[1].surface = "unknown"),
3555
+ (candidate) => (candidate[1].kind = "unknown"),
3556
+ (candidate) => (candidate[1].outcome = "attempt"),
3557
+ (candidate) => (candidate[1].operationOrdinal = 1),
3558
+ (candidate) => (candidate[1].dimensionsHmac = "a".repeat(64)),
3559
+ (candidate) => (candidate[1].extra = true),
3560
+ ]) {
3561
+ const candidate = structuredClone(events.slice(0, 2));
3562
+ mutation(candidate);
3563
+ assert.equal(card5AuthorityActivityWithinCap(activity(candidate)), false);
3564
+ }
3565
+ const dimensionsHmac = "c".repeat(64);
3566
+ const geometry = [
3567
+ {
3568
+ ordinal: 1,
3569
+ surface: "web",
3570
+ kind: "geometry",
3571
+ outcome: "attempt",
3572
+ operationOrdinal: 1,
3573
+ dimensionsHmac,
3574
+ },
3575
+ {
3576
+ ordinal: 2,
3577
+ surface: "web",
3578
+ kind: "geometry",
3579
+ outcome: "ok",
3580
+ operationOrdinal: 1,
3581
+ dimensionsHmac,
3582
+ },
3583
+ ];
3584
+ const settlement = {
3585
+ ordinal: 0,
3586
+ operationOrdinal: 1,
3587
+ requestHmac: "a".repeat(64),
3588
+ clientHmac: "b".repeat(64),
3589
+ dimensionsHmac,
3590
+ };
3591
+ assert.equal(card5AuthorityActivityWithinCap(activity(geometry, [settlement])), true);
3592
+ assert.equal(
3593
+ card5AuthorityActivityWithinCap(
3594
+ activity(
3595
+ [{ ...geometry[0] }, { ...geometry[1], dimensionsHmac: "d".repeat(64) }],
3596
+ [settlement],
3597
+ ),
3598
+ ),
3599
+ false,
3600
+ );
3601
+ assert.equal(
3602
+ card5AuthorityActivityWithinCap(
3603
+ activity(geometry, [{ ...settlement, dimensionsHmac: "d".repeat(64) }]),
3604
+ ),
3605
+ false,
3606
+ );
3607
+ assert.equal(card5AuthorityActivityWithinCap(activity(geometry.slice(0, 1))), true);
3608
+ assert.equal(card5AuthorityActivityWithinCap(activity(geometry)), false);
3609
+ assert.equal(
3610
+ card5AuthorityActivityWithinCap(activity(geometry, [settlement, settlement])),
3611
+ false,
3612
+ );
3613
+ assert.equal(
3614
+ card5AuthorityActivityWithinCap(activity(geometry, [{ ...settlement, ordinal: 1 }])),
3615
+ false,
3616
+ );
3617
+ const twoSameDimensions = [
3618
+ ...geometry,
3619
+ { ...geometry[0], ordinal: 3, operationOrdinal: 2 },
3620
+ { ...geometry[1], ordinal: 4, operationOrdinal: 2 },
3621
+ ];
3622
+ assert.equal(card5AuthorityActivityWithinCap(activity(twoSameDimensions, [settlement])), false);
3623
+ assert.equal(
3624
+ card5AuthorityActivityWithinCap(
3625
+ activity(twoSameDimensions, [
3626
+ settlement,
3627
+ {
3628
+ ...settlement,
3629
+ ordinal: 1,
3630
+ operationOrdinal: 2,
3631
+ requestHmac: "d".repeat(64),
3632
+ },
3633
+ ]),
3634
+ ),
3635
+ true,
3636
+ );
3637
+ assert.equal(
3638
+ boundedCard5HostFailureObservation({ reason: "authority-activity-storm" }).reason,
3639
+ "authority-activity-storm",
3640
+ );
3641
+ });
3642
+
3643
+ test("host failure evidence seals two bounded focus candidates and every divergence axis", () => {
3644
+ const focus = assessCard5TuiFocusedPane(tuiFocusedPaneFixture());
3645
+ const axes = { ...focus.axes, pane: true };
3646
+ const observed = boundedCard5HostFailureObservation({
3647
+ reason: "stability-timeout",
3648
+ focusDivergenceAxes: axes,
3649
+ focusCandidates: [focus.candidate, focus.candidate, { ...focus.candidate, secret: "raw" }],
3650
+ });
3651
+ assert.deepEqual(observed.focusDivergenceAxes, axes);
3652
+ assert.equal(observed.focusCandidates.length, 2);
3653
+ assert.deepEqual(Object.keys(observed.focusCandidates[0]), [
3654
+ "paneHmac",
3655
+ "generationHmac",
3656
+ "incarnationHmac",
3657
+ "processHmac",
3658
+ "clockHmac",
3659
+ "canonicalHashHmac",
3660
+ "revision",
3661
+ "cols",
3662
+ "rows",
3663
+ "viewportCols",
3664
+ "viewportRows",
3665
+ "presentationCount",
3666
+ "presentationHmac",
3667
+ "frameHmac",
3668
+ "authoritySequenceHmac",
3669
+ ]);
3670
+ assert.equal(JSON.stringify(observed).includes("raw"), false);
3671
+ });
3672
+
3673
+ function card5WebReleaseFixture() {
3674
+ const expected = {
3675
+ expectedAuthorities: ["input", "focus"],
3676
+ workspaceHmac: "1".repeat(64),
3677
+ generationHmac: "2".repeat(64),
3678
+ runtimeSessionHmac: "3".repeat(64),
3679
+ paneHmac: "4".repeat(64),
3680
+ requestHmacs: ["5".repeat(64), "6".repeat(64)],
3681
+ clientHmacs: {
3682
+ input: "7".repeat(64),
3683
+ focus: "8".repeat(64),
3684
+ geometry: "9".repeat(64),
3685
+ },
3686
+ };
3687
+ const receipt = (authority, requestHmac, clientHmac, operationOrdinal) => ({
3688
+ authority,
3689
+ status: "released",
3690
+ operationOrdinal,
3691
+ beforeRevision: operationOrdinal + 10,
3692
+ afterRevision: operationOrdinal + 11,
3693
+ workspaceHmac: expected.workspaceHmac,
3694
+ generationHmac: expected.generationHmac,
3695
+ runtimeSessionHmac: expected.runtimeSessionHmac,
3696
+ paneHmac: expected.paneHmac,
3697
+ requestHmac,
3698
+ clientHmac,
3699
+ });
3700
+ const results = [
3701
+ {
3702
+ status: "exact",
3703
+ pageHmac: "a".repeat(64),
3704
+ localClientHmac: "b".repeat(64),
3705
+ preOwnerTupleHmac: "c".repeat(64),
3706
+ preRevisionHmac: "d".repeat(64),
3707
+ receipts: [receipt("input", expected.requestHmacs[0], expected.clientHmacs.input, 1)],
3708
+ },
3709
+ {
3710
+ status: "exact",
3711
+ pageHmac: "e".repeat(64),
3712
+ localClientHmac: null,
3713
+ preOwnerTupleHmac: "f".repeat(64),
3714
+ preRevisionHmac: "0".repeat(64),
3715
+ receipts: [receipt("focus", expected.requestHmacs[1], expected.clientHmacs.focus, 2)],
3716
+ },
3717
+ ];
3718
+ return { expected, results };
3719
+ }
3720
+
3721
+ test("Web release evidence preserves exact bounded page and receipt joins", () => {
3722
+ const { expected, results } = card5WebReleaseFixture();
3723
+ const assessed = assessCard5WebAuthorityRelease({ ...expected, results });
3724
+ assert.equal(assessed.passed, true);
3725
+ assert.equal(assessed.observation.resultCount, 2);
3726
+ assert.equal(assessed.observation.expectedReceiptCount, 2);
3727
+ assert.equal(assessed.observation.actualReceiptCount, 2);
3728
+ assert.equal(assessed.observation.pages.length, 2);
3729
+ assert.equal(assessed.observation.receipts.length, 2);
3730
+ assert.equal(assessed.observation.pages[0].pageHmac, "a".repeat(64));
3731
+ assert.equal(assessed.observation.pages[0].localClientHmac, "b".repeat(64));
3732
+ assert.equal(assessed.observation.pages[1].preOwnerTupleHmac, "f".repeat(64));
3733
+ assert.deepEqual(Object.values(assessed.observation.axes), Array(17).fill(false));
3734
+ assert.equal(JSON.stringify(assessed).includes("raw-client"), false);
3735
+ });
3736
+
3737
+ test("Web release evidence identifies every rejected acceptance conjunct", () => {
3738
+ const adversaries = [
3739
+ ["resultStatus", (value) => (value.results[0].status = "binding-invalid")],
3740
+ ["resultCount", (value) => value.results.pop()],
3741
+ ["receiptCount", (value) => value.results[1].receipts.pop()],
3742
+ ["inputCardinality", (value) => (value.results[1].receipts[0].authority = "input")],
3743
+ ["releasedStatus", (value) => (value.results[0].receipts[0].status = "rejected")],
3744
+ ["operationOrdinal", (value) => (value.results[0].receipts[0].operationOrdinal = 0)],
3745
+ ["revisionOrder", (value) => (value.results[0].receipts[0].afterRevision = 11)],
3746
+ ["workspace", (value) => (value.results[0].receipts[0].workspaceHmac = HMAC)],
3747
+ ["generation", (value) => (value.results[0].receipts[0].generationHmac = HMAC)],
3748
+ ["runtimeSession", (value) => (value.results[0].receipts[0].runtimeSessionHmac = HMAC)],
3749
+ ["pane", (value) => (value.results[0].receipts[0].paneHmac = HMAC)],
3750
+ ["request", (value) => (value.results[0].receipts[0].requestHmac = HMAC)],
3751
+ ["client", (value) => (value.results[0].receipts[0].clientHmac = HMAC)],
3752
+ ["overflow", (value) => value.results.push(structuredClone(value.results[0]))],
3753
+ ];
3754
+ for (const [axis, mutate] of adversaries) {
3755
+ const fixture = card5WebReleaseFixture();
3756
+ mutate(fixture);
3757
+ const assessed = assessCard5WebAuthorityRelease({
3758
+ ...fixture.expected,
3759
+ results: fixture.results,
3760
+ });
3761
+ assert.equal(assessed.passed, false, axis);
3762
+ assert.equal(assessed.observation.axes[axis], true, axis);
3763
+ assert.ok(assessed.observation.pages.length <= 2, axis);
3764
+ assert.ok(assessed.observation.receipts.length <= 3, axis);
3765
+ }
3766
+ });
3767
+
3768
+ test("Web release compound failure remains HMAC-only and keeps the fixed reason", () => {
3769
+ const fixture = card5WebReleaseFixture();
3770
+ fixture.results[0].status = "binding-invalid";
3771
+ fixture.results[0].receipts[0].requestHmac = "raw-private-request";
3772
+ fixture.results.push({ status: "raw-private-status", receipts: Array(4).fill({}) });
3773
+ const assessed = assessCard5WebAuthorityRelease({
3774
+ ...fixture.expected,
3775
+ results: fixture.results,
3776
+ });
3777
+ const observed = boundedCard5TuiFocusFailureObservation({
3778
+ reason: "focus-web-release-invalid",
3779
+ axes: { authority: true },
3780
+ webRelease: assessed.observation,
3781
+ rawClientId: "raw-private-client",
3782
+ });
3783
+ assert.equal(observed.reason, "focus-web-release-invalid");
3784
+ assert.equal(observed.webRelease.axes.resultStatus, true);
3785
+ assert.equal(observed.webRelease.axes.request, true);
3786
+ assert.equal(observed.webRelease.axes.overflow, true);
3787
+ assert.equal(JSON.stringify(observed).includes("raw-private"), false);
3788
+ });
3789
+
3790
+ test("focused-pane failure evidence preserves only the fixed HMAC axis vector", () => {
3791
+ const input = tuiFocusedPaneFixture();
3792
+ input.records[0].semanticPaneId = "pane-private";
3793
+ const failed = assessCard5TuiFocusedPane(input);
3794
+ const observed = boundedCard5TuiFocusFailureObservation({
3795
+ reason: failed.reason,
3796
+ axes: failed.axes,
3797
+ candidate: failed.candidate,
3798
+ rawPane: "pane-private",
3799
+ });
3800
+ assert.equal(observed.operation, "card5-tui-focused-pane");
3801
+ assert.equal(observed.reason, "focus-presentation-mismatch");
3802
+ assert.equal(observed.focusDivergenceAxes.pane, true);
3803
+ assert.equal(observed.focusCandidates.length, 1);
3804
+ assert.equal(JSON.stringify(observed).includes("pane-private"), false);
3805
+ });
3806
+
3807
+ test("replacement evidence requires seed-first G2 and typed retirement with no late G1", () => {
3808
+ const lanes = [
3809
+ {
3810
+ replacementBoundary: {
3811
+ predecessorGeneration: "g1",
3812
+ replacementGeneration: "g2",
3813
+ acceptedOrdinal: 1,
3814
+ socketOrdinal: 2,
3815
+ },
3816
+ predecessorAcceptedAfterReplacement: 0,
3817
+ socketEvents: [
3818
+ { generation: "g1", outcome: "closed", ordinal: 2 },
3819
+ { generation: "g2", outcome: "open", ordinal: 1 },
3820
+ ],
3821
+ events: [
3822
+ { type: "terminal.patch", generation: "g1", acceptedOrdinal: 0 },
3823
+ { type: "terminal.seed", generation: "g2", acceptedOrdinal: 1 },
3824
+ { type: "terminal.patch", generation: "g2", acceptedOrdinal: 2 },
3825
+ ],
3826
+ },
3827
+ {
3828
+ replacementBoundary: {
3829
+ predecessorGeneration: "g1",
3830
+ replacementGeneration: "g2",
3831
+ acceptedOrdinal: 4,
3832
+ socketOrdinal: 7,
3833
+ },
3834
+ predecessorAcceptedAfterReplacement: 0,
3835
+ socketEvents: [
3836
+ { generation: "g2", outcome: "open", ordinal: 7 },
3837
+ { generation: "g1", outcome: "closed", ordinal: 8 },
3838
+ ],
3839
+ events: [{ type: "terminal.seed", generation: "g2", acceptedOrdinal: 4 }],
3840
+ },
3841
+ {
3842
+ replacementBoundary: {
3843
+ predecessorGeneration: "g1",
3844
+ replacementGeneration: "g2",
3845
+ acceptedOrdinal: 8,
3846
+ },
3847
+ predecessorAcceptedAfterReplacement: 0,
3848
+ events: [{ type: "terminal.seed", generation: "g2", acceptedOrdinal: 8 }],
3849
+ },
3850
+ ];
3851
+ assert.deepEqual(
3852
+ assessCard5ReplacementEnvelopeEvidence({
3853
+ predecessorGeneration: "g1",
3854
+ replacementGeneration: "g2",
3855
+ staleRedemptions: [
3856
+ { rejected: true, typed: true, reason: "ticket-expired" },
3857
+ { rejected: true, typed: true, reason: "redemption-rejected" },
3858
+ ],
3859
+ lanes,
3860
+ }),
3861
+ {
3862
+ passed: true,
3863
+ reason: null,
3864
+ staleGenerationError: "generation-replaced",
3865
+ replacementFirstEnvelope: "seed",
3866
+ replacementSeedGeneration: "g2",
3867
+ predecessorEnvelopeAcceptedAfterReplace: false,
3868
+ },
3869
+ );
3870
+ for (const change of [
3871
+ {
3872
+ lanes: [
3873
+ { ...lanes[0], events: [{ type: "terminal.patch", generation: "g2", acceptedOrdinal: 1 }] },
3874
+ lanes[1],
3875
+ lanes[2],
3876
+ ],
3877
+ },
3878
+ {
3879
+ lanes: [{ ...lanes[0], predecessorAcceptedAfterReplacement: 1 }, lanes[1], lanes[2]],
3880
+ },
3881
+ { staleRedemptions: [{ rejected: true, typed: false, reason: "closed" }] },
3882
+ ]) {
3883
+ assert.equal(
3884
+ assessCard5ReplacementEnvelopeEvidence({
3885
+ predecessorGeneration: "g1",
3886
+ replacementGeneration: "g2",
3887
+ staleRedemptions: [
3888
+ { rejected: true, typed: true, reason: "ticket-expired" },
3889
+ { rejected: true, typed: true, reason: "redemption-rejected" },
3890
+ ],
3891
+ lanes,
3892
+ ...change,
3893
+ }).passed,
3894
+ false,
3895
+ );
3896
+ }
3897
+ });