@timurproko/a1 0.2.6 → 0.2.7-dev.1222

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 (419) hide show
  1. package/README.md +41 -3
  2. package/bin/automatic-update.js +7 -0
  3. package/bin/cli.js +4 -0
  4. package/bin/guardian.js +5 -0
  5. package/bin/tab-launch-context.d.ts +27 -0
  6. package/bin/tab-launch-context.js +94 -0
  7. package/bin/ui.js +107 -59
  8. package/dist/app/session-shell/clipboard-diagnostics.js +1 -1
  9. package/dist/app/session-shell/dialog-coordinator.d.ts +42 -0
  10. package/dist/app/session-shell/dialog-coordinator.js +133 -0
  11. package/dist/app/session-shell/dock-chrome.d.ts +34 -0
  12. package/dist/app/session-shell/dock-chrome.js +109 -0
  13. package/dist/app/session-shell/exit-notice.d.ts +1 -1
  14. package/dist/app/session-shell/exit-notice.js +1 -1
  15. package/dist/app/session-shell/extension-surface.d.ts +30 -0
  16. package/dist/app/session-shell/extension-surface.js +105 -0
  17. package/dist/app/session-shell/helper-pool.d.ts +3 -5
  18. package/dist/app/session-shell/helper-pool.js +3 -5
  19. package/dist/app/session-shell/input-surface-switch.d.ts +36 -0
  20. package/dist/app/session-shell/input-surface-switch.js +85 -0
  21. package/dist/app/session-shell/login-interaction.d.ts +27 -0
  22. package/dist/app/session-shell/login-interaction.js +91 -0
  23. package/dist/app/session-shell/prompt-submission.d.ts +48 -0
  24. package/dist/app/session-shell/prompt-submission.js +276 -0
  25. package/dist/app/session-shell/resident-tab-coordinator.d.ts +38 -0
  26. package/dist/app/session-shell/resident-tab-coordinator.js +77 -0
  27. package/dist/app/session-shell/response-copy-helper.js +21 -6
  28. package/dist/app/session-shell/response-copy-protocol.d.ts +1 -1
  29. package/dist/app/session-shell/response-copy-transport.d.ts +16 -6
  30. package/dist/app/session-shell/response-copy-transport.js +69 -17
  31. package/dist/app/session-shell/session-concern.d.ts +22 -0
  32. package/dist/app/session-shell/session-concern.js +29 -0
  33. package/dist/app/session-shell/session-lifecycle.d.ts +29 -0
  34. package/dist/app/session-shell/session-lifecycle.js +49 -0
  35. package/dist/app/session-shell/session-shell-root.d.ts +42 -6
  36. package/dist/app/session-shell/session-shell-root.js +197 -908
  37. package/dist/app/session-shell/session-shell.d.ts +3 -8
  38. package/dist/app/session-shell/session-shell.js +327 -835
  39. package/dist/app/session-shell/session-viewport-controller.d.ts +2 -1
  40. package/dist/app/session-shell/session-viewport-controller.js +41 -38
  41. package/dist/app/session-shell/settings-bindings.d.ts +17 -0
  42. package/dist/app/session-shell/settings-bindings.js +91 -0
  43. package/dist/app/session-shell/shell-editor-factory.d.ts +27 -0
  44. package/dist/app/session-shell/shell-editor-factory.js +105 -0
  45. package/dist/app/session-shell/shell-host.d.ts +6 -0
  46. package/dist/app/session-shell/shell-host.js +34 -7
  47. package/dist/app/session-shell/shell-layout.d.ts +64 -0
  48. package/dist/app/session-shell/shell-layout.js +18 -0
  49. package/dist/app/session-shell/suggestion-surface.d.ts +25 -0
  50. package/dist/app/session-shell/suggestion-surface.js +63 -0
  51. package/dist/app/session-shell/transcript-document.d.ts +78 -0
  52. package/dist/app/session-shell/transcript-document.js +365 -0
  53. package/dist/app/session-shell/viewport-layout.d.ts +31 -0
  54. package/dist/app/session-shell/viewport-layout.js +160 -0
  55. package/dist/app/session-shell/workflow-output.d.ts +33 -0
  56. package/dist/app/session-shell/workflow-output.js +174 -0
  57. package/dist/app/session-shell/workflow-router.d.ts +25 -0
  58. package/dist/app/session-shell/workflow-router.js +39 -0
  59. package/dist/cli/dispatch.d.ts +11 -1
  60. package/dist/cli/dispatch.js +79 -5
  61. package/dist/cli/tabs-request.d.ts +7 -0
  62. package/dist/cli/tabs-request.js +1 -0
  63. package/dist/cli/tabs.d.ts +14 -0
  64. package/dist/cli/tabs.js +151 -0
  65. package/dist/cli/version-stats.js +38 -3
  66. package/dist/composition/owned-settings.d.ts +12 -0
  67. package/dist/composition/owned-settings.js +36 -0
  68. package/dist/composition/owned-ui.d.ts +27 -28
  69. package/dist/composition/owned-ui.js +207 -153
  70. package/dist/composition/reference-selection-options.d.ts +3 -0
  71. package/dist/composition/reference-selection-options.js +16 -0
  72. package/dist/composition/resident-tab-bridge.d.ts +25 -0
  73. package/dist/composition/resident-tab-bridge.js +180 -0
  74. package/dist/composition/session-backend.d.ts +19 -0
  75. package/dist/composition/session-backend.js +1 -0
  76. package/dist/composition/session-runtime-registry.d.ts +20 -0
  77. package/dist/composition/session-runtime-registry.js +85 -0
  78. package/dist/composition/settings-route-host.d.ts +16 -2
  79. package/dist/composition/settings-route-host.js +42 -17
  80. package/dist/composition/settings-search-input.d.ts +9 -0
  81. package/dist/composition/settings-search-input.js +61 -0
  82. package/dist/composition/startup-route.d.ts +32 -0
  83. package/dist/composition/startup-route.js +72 -0
  84. package/dist/composition/utility-tab.d.ts +28 -0
  85. package/dist/composition/utility-tab.js +244 -0
  86. package/dist/contracts/owned-ui/index.d.ts +1 -1
  87. package/dist/contracts/owned-ui/model.d.ts +3 -0
  88. package/dist/contracts/owned-ui/session-backend.d.ts +3 -0
  89. package/dist/contracts/owned-ui/session-workflows.d.ts +11 -4
  90. package/dist/contracts/presentation/index.d.ts +11 -0
  91. package/dist/contracts/presentation/index.js +12 -0
  92. package/dist/features/launch/development-launch.js +6 -0
  93. package/dist/features/launch/index.d.ts +1 -1
  94. package/dist/features/launch/intent.d.ts +3 -1
  95. package/dist/features/launch/intent.js +7 -4
  96. package/dist/features/launch/profile-paths.js +4 -0
  97. package/dist/features/owned-ui/plus-menu-dialog.d.ts +22 -0
  98. package/dist/features/owned-ui/plus-menu-dialog.js +84 -0
  99. package/dist/features/owned-ui/project-trust-dialog.d.ts +1 -1
  100. package/dist/features/owned-ui/project-trust-dialog.js +6 -8
  101. package/dist/features/owned-ui/project-trust-prompt.d.ts +1 -0
  102. package/dist/features/owned-ui/project-trust-prompt.js +7 -3
  103. package/dist/features/owned-ui/reference-document-selection.d.ts +30 -0
  104. package/dist/features/owned-ui/reference-document-selection.js +179 -0
  105. package/dist/features/owned-ui/reference-screen-app.d.ts +6 -1
  106. package/dist/features/owned-ui/reference-screen-app.js +51 -10
  107. package/dist/features/owned-ui/settings-app.d.ts +13 -2
  108. package/dist/features/owned-ui/settings-app.js +136 -97
  109. package/dist/features/owned-ui/settings-search-input.d.ts +29 -0
  110. package/dist/features/owned-ui/settings-search-input.js +1 -0
  111. package/dist/features/prompt-history/index.d.ts +1 -1
  112. package/dist/features/prompt-history/paths.d.ts +2 -1
  113. package/dist/features/prompt-history/paths.js +10 -2
  114. package/dist/features/prompt-history/service.d.ts +5 -0
  115. package/dist/features/prompt-history/service.js +1 -1
  116. package/dist/features/resident-tab/auto-name.d.ts +11 -0
  117. package/dist/features/resident-tab/auto-name.js +44 -0
  118. package/dist/features/resident-tab/index.d.ts +5 -0
  119. package/dist/features/resident-tab/index.js +7 -0
  120. package/dist/features/resident-tab/shortcut-bindings-file.d.ts +8 -0
  121. package/dist/features/resident-tab/shortcut-bindings-file.js +40 -0
  122. package/dist/features/resident-tab/shortcut-declarations.d.ts +13 -0
  123. package/dist/features/resident-tab/shortcut-declarations.js +26 -0
  124. package/dist/features/resident-tab/shortcut-projection.d.ts +29 -0
  125. package/dist/features/resident-tab/shortcut-projection.js +64 -0
  126. package/dist/features/resident-tab/status-deriver.d.ts +10 -0
  127. package/dist/features/resident-tab/status-deriver.js +12 -0
  128. package/dist/foundation/launch-context/index.d.ts +12 -0
  129. package/dist/foundation/launch-context/index.js +26 -0
  130. package/dist/foundation/launch-guardian/exit-watcher.d.ts +14 -0
  131. package/dist/foundation/launch-guardian/exit-watcher.js +94 -0
  132. package/dist/foundation/launch-guardian/main.d.ts +7 -1
  133. package/dist/foundation/launch-guardian/main.js +60 -7
  134. package/dist/foundation/lifecycle/session-repository-context.js +16 -2
  135. package/dist/foundation/process-containment/{native-guardian-containment.d.ts → addon-containment.d.ts} +7 -5
  136. package/dist/foundation/process-containment/addon-containment.js +139 -0
  137. package/dist/foundation/process-containment/addon-process-inspector.d.ts +11 -0
  138. package/dist/foundation/process-containment/addon-process-inspector.js +36 -0
  139. package/dist/foundation/process-containment/addon.d.ts +42 -0
  140. package/dist/foundation/process-containment/addon.js +57 -0
  141. package/dist/foundation/process-containment/artifact.d.ts +1 -1
  142. package/dist/foundation/process-containment/artifact.js +6 -5
  143. package/dist/foundation/process-containment/contracts.d.ts +2 -0
  144. package/dist/foundation/process-containment/index.d.ts +4 -4
  145. package/dist/foundation/process-containment/index.js +3 -3
  146. package/dist/foundation/process-containment/native-process-inspector.d.ts +2 -1
  147. package/dist/foundation/process-containment/native-process-inspector.js +10 -10
  148. package/dist/foundation/release/automatic-update.d.ts +37 -0
  149. package/dist/foundation/release/automatic-update.js +265 -0
  150. package/dist/foundation/release/bootstrap.d.ts +7 -9
  151. package/dist/foundation/release/bootstrap.js +107 -24
  152. package/dist/foundation/release/cohort-state.d.ts +1 -1
  153. package/dist/foundation/release/cohort-state.js +1 -1
  154. package/dist/foundation/release/dependency-certification.js +54 -19
  155. package/dist/foundation/release/early-accent.d.ts +12 -0
  156. package/dist/foundation/release/early-accent.js +59 -0
  157. package/dist/foundation/release/index.d.ts +2 -2
  158. package/dist/foundation/release/index.js +2 -2
  159. package/dist/foundation/release/latest-release.d.ts +24 -2
  160. package/dist/foundation/release/latest-release.js +51 -1
  161. package/dist/foundation/release/progress-palette.generated.d.ts +137 -3
  162. package/dist/foundation/release/progress-palette.generated.js +137 -3
  163. package/dist/foundation/release/release-gc.d.ts +3 -0
  164. package/dist/foundation/release/release-gc.js +59 -8
  165. package/dist/foundation/release/release-store.d.ts +12 -0
  166. package/dist/foundation/release/release-store.js +124 -2
  167. package/dist/foundation/release/update-execution-lease.d.ts +48 -0
  168. package/dist/foundation/release/update-execution-lease.js +161 -0
  169. package/dist/foundation/release/update.d.ts +12 -7
  170. package/dist/foundation/release/update.js +281 -196
  171. package/dist/foundation/resident-tabs/bounded-host-command.d.ts +18 -0
  172. package/dist/foundation/resident-tabs/bounded-host-command.js +39 -0
  173. package/dist/foundation/resident-tabs/bridge-client.d.ts +70 -0
  174. package/dist/foundation/resident-tabs/bridge-client.js +321 -0
  175. package/dist/foundation/resident-tabs/doctor.d.ts +28 -0
  176. package/dist/foundation/resident-tabs/doctor.js +166 -0
  177. package/dist/foundation/resident-tabs/draft-checkpoint.d.ts +27 -0
  178. package/dist/foundation/resident-tabs/draft-checkpoint.js +145 -0
  179. package/dist/foundation/resident-tabs/ensure-terminal-host.d.ts +36 -0
  180. package/dist/foundation/resident-tabs/ensure-terminal-host.js +151 -0
  181. package/dist/foundation/resident-tabs/fault-injection.d.ts +8 -0
  182. package/dist/foundation/resident-tabs/fault-injection.js +26 -0
  183. package/dist/foundation/resident-tabs/fixture-control.d.ts +7 -0
  184. package/dist/foundation/resident-tabs/fixture-control.js +35 -0
  185. package/dist/foundation/resident-tabs/host-entry.d.ts +1 -0
  186. package/dist/foundation/resident-tabs/host-entry.js +17 -0
  187. package/dist/foundation/resident-tabs/index.d.ts +12 -0
  188. package/dist/foundation/resident-tabs/index.js +6 -0
  189. package/dist/foundation/resident-tabs/maintenance.d.ts +39 -0
  190. package/dist/foundation/resident-tabs/maintenance.js +75 -0
  191. package/dist/foundation/resident-tabs/progress-observation-schema.d.ts +34 -0
  192. package/dist/foundation/resident-tabs/progress-observation-schema.js +1 -0
  193. package/dist/foundation/resident-tabs/progress-observation.d.ts +4 -0
  194. package/dist/foundation/resident-tabs/progress-observation.js +150 -0
  195. package/dist/foundation/resident-tabs/prompt-journal.d.ts +63 -0
  196. package/dist/foundation/resident-tabs/prompt-journal.js +213 -0
  197. package/dist/foundation/resident-tabs/protocol.d.ts +12 -0
  198. package/dist/foundation/resident-tabs/protocol.js +195 -0
  199. package/dist/foundation/resident-tabs/recovery.d.ts +26 -0
  200. package/dist/foundation/resident-tabs/recovery.js +205 -0
  201. package/dist/foundation/resident-tabs/release-holds.d.ts +28 -0
  202. package/dist/foundation/resident-tabs/release-holds.js +75 -0
  203. package/dist/foundation/resident-tabs/routes.d.ts +5 -0
  204. package/dist/foundation/resident-tabs/routes.js +5 -0
  205. package/dist/foundation/resident-tabs/routing.d.ts +11 -0
  206. package/dist/foundation/resident-tabs/routing.js +10 -0
  207. package/dist/foundation/resident-tabs/session-sync.d.ts +14 -0
  208. package/dist/foundation/resident-tabs/session-sync.js +37 -0
  209. package/dist/foundation/resident-tabs/settings.d.ts +12 -0
  210. package/dist/foundation/resident-tabs/settings.js +58 -0
  211. package/dist/foundation/resident-tabs/terminal-host-artifact.d.ts +14 -0
  212. package/dist/foundation/resident-tabs/terminal-host-artifact.js +78 -0
  213. package/dist/foundation/resident-tabs/zip-archive.d.ts +9 -0
  214. package/dist/foundation/resident-tabs/zip-archive.js +56 -0
  215. package/dist/foundation/session-writer-lock/index.d.ts +30 -0
  216. package/dist/foundation/session-writer-lock/index.js +203 -0
  217. package/dist/foundation/startup/startup-descriptor.js +2 -2
  218. package/dist/foundation/terminal-cleanup/index.d.ts +1 -1
  219. package/dist/foundation/terminal-cleanup/index.js +1 -1
  220. package/dist/foundation/terminal-cleanup/terminal-reset.d.ts +6 -0
  221. package/dist/foundation/terminal-cleanup/terminal-reset.js +6 -0
  222. package/dist/integrations/pi/components/editor-interaction.d.ts +2 -0
  223. package/dist/integrations/pi/components/modal-frame.d.ts +17 -1
  224. package/dist/integrations/pi/components/modal-frame.js +48 -9
  225. package/dist/integrations/pi/components/models-dialog.js +4 -52
  226. package/dist/integrations/pi/components/owned-editor-ux.d.ts +6 -1
  227. package/dist/integrations/pi/components/owned-editor-ux.js +138 -11
  228. package/dist/integrations/pi/components/resources/builtin-themes.d.ts +4 -4
  229. package/dist/integrations/pi/components/resources/builtin-themes.js +4 -4
  230. package/dist/integrations/pi/components/share-operation-dialog.d.ts +2 -0
  231. package/dist/integrations/pi/components/share-operation-dialog.js +2 -1
  232. package/dist/integrations/pi/components/shell-editor-autocomplete.js +58 -36
  233. package/dist/integrations/pi/components/shell-extension-ui.js +79 -60
  234. package/dist/integrations/pi/components/shell-footer-status.d.ts +1 -1
  235. package/dist/integrations/pi/components/shell-footer-status.js +21 -5
  236. package/dist/integrations/pi/components/shell-hotkey-sections.js +1 -1
  237. package/dist/integrations/pi/components/shell-presenters-info.d.ts +5 -2
  238. package/dist/integrations/pi/components/shell-presenters-info.js +18 -4
  239. package/dist/integrations/pi/components/shell-presenters-transcript.js +4 -1
  240. package/dist/integrations/pi/components/shell-selectors-dialogs.js +5 -1
  241. package/dist/integrations/pi/components/shell-shared-facade.d.ts +12 -1
  242. package/dist/integrations/pi/components/skills-dialog.js +2 -2
  243. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.d.ts +1 -1
  244. package/dist/integrations/pi/components/upstream/adjacent/core/keybindings.js +17 -4
  245. package/dist/integrations/pi/components/upstream/assets/earendil-image.json +2 -2
  246. package/dist/integrations/pi/components/upstream/components/countdown-timer.d.ts +1 -1
  247. package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +1 -1
  248. package/dist/integrations/pi/components/upstream/components/extension-editor.d.ts +1 -1
  249. package/dist/integrations/pi/components/upstream/components/extension-editor.js +1 -1
  250. package/dist/integrations/pi/components/upstream/components/extension-input.js +1 -1
  251. package/dist/integrations/pi/components/upstream/components/extension-selector.js +1 -1
  252. package/dist/integrations/pi/components/upstream/components/mermaid.js +1 -1
  253. package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +8 -6
  254. package/dist/integrations/pi/components/upstream/components/owned-editor.js +16 -9
  255. package/dist/integrations/pi/components/upstream/components/pi-logo.js +1 -1
  256. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +4 -4
  257. package/dist/integrations/pi/components/upstream/components/scoped-models-selector.js +2 -2
  258. package/dist/integrations/pi/components/upstream/components/session-footer.d.ts +2 -1
  259. package/dist/integrations/pi/components/upstream/components/session-footer.js +31 -25
  260. package/dist/integrations/pi/components/upstream/components/session-selector-search.js +1 -1
  261. package/dist/integrations/pi/components/upstream/components/session-selector.js +8 -7
  262. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.d.ts +1 -1
  263. package/dist/integrations/pi/components/upstream/components/skill-invocation-message.js +1 -1
  264. package/dist/integrations/pi/components/upstream/components/status-indicator.d.ts +2 -2
  265. package/dist/integrations/pi/components/upstream/components/status-indicator.js +3 -3
  266. package/dist/integrations/pi/components/upstream/components/themed-text.d.ts +1 -1
  267. package/dist/integrations/pi/components/upstream/components/themed-text.js +1 -1
  268. package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +8 -7
  269. package/dist/integrations/pi/components/upstream/components/thinking-selector.js +10 -9
  270. package/dist/integrations/pi/components/upstream/components/tool-execution.d.ts +2 -6
  271. package/dist/integrations/pi/components/upstream/components/tool-execution.js +103 -101
  272. package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +9 -9
  273. package/dist/integrations/pi/components/upstream/components/tree-selector.js +13 -21
  274. package/dist/integrations/pi/components/upstream/components/trust-selector.js +1 -1
  275. package/dist/integrations/pi/components/upstream/external-editor.js +1 -1
  276. package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +2 -2
  277. package/dist/integrations/pi/components/upstream/history/editor-core.js +7 -5
  278. package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +1 -1
  279. package/dist/integrations/pi/components/upstream/history/kill-ring.js +1 -1
  280. package/dist/integrations/pi/components/upstream/history/printable-key.js +1 -1
  281. package/dist/integrations/pi/components/upstream/history/text-helpers.js +1 -1
  282. package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +1 -1
  283. package/dist/integrations/pi/components/upstream/history/undo-stack.js +1 -1
  284. package/dist/integrations/pi/components/upstream/history/word-navigation.js +1 -1
  285. package/dist/integrations/pi/components/upstream/model-search.d.ts +1 -1
  286. package/dist/integrations/pi/components/upstream/program-status-reporter.d.ts +1 -1
  287. package/dist/integrations/pi/components/upstream/theme/theme-controller.d.ts +1 -1
  288. package/dist/integrations/pi/components/upstream/theme/theme.d.ts +5 -0
  289. package/dist/integrations/pi/components/upstream/theme/theme.js +29 -2
  290. package/dist/integrations/pi/engine/adapter.d.ts +5 -77
  291. package/dist/integrations/pi/engine/adapter.js +95 -394
  292. package/dist/integrations/pi/engine/command-dispatch.d.ts +13 -0
  293. package/dist/integrations/pi/engine/command-dispatch.js +57 -0
  294. package/dist/integrations/pi/engine/host.js +2 -2
  295. package/dist/integrations/pi/engine/offline-settings-port.d.ts +23 -0
  296. package/dist/integrations/pi/engine/offline-settings-port.js +53 -0
  297. package/dist/integrations/pi/engine/pi-settings-metadata.json +14 -2
  298. package/dist/integrations/pi/engine/ports.d.ts +56 -0
  299. package/dist/integrations/pi/engine/ports.js +93 -0
  300. package/dist/integrations/pi/engine/prompt-suggestions.d.ts +1 -0
  301. package/dist/integrations/pi/engine/prompt-suggestions.js +40 -0
  302. package/dist/integrations/pi/engine/resources/changelog.json +4 -4
  303. package/dist/integrations/pi/engine/runtime-integration.js +102 -29
  304. package/dist/integrations/pi/engine/session-runtime.d.ts +0 -6
  305. package/dist/integrations/pi/engine/session-runtime.js +13 -5
  306. package/dist/integrations/pi/engine/session-selection.d.ts +3 -0
  307. package/dist/integrations/pi/engine/session-selection.js +45 -9
  308. package/dist/integrations/pi/engine/settings-bridge.d.ts +5 -0
  309. package/dist/integrations/pi/engine/settings-bridge.js +15 -0
  310. package/dist/integrations/pi/engine/settings-port.js +11 -15
  311. package/dist/integrations/pi/engine/view-state.d.ts +42 -0
  312. package/dist/integrations/pi/engine/view-state.js +126 -0
  313. package/dist/integrations/pi/engine/workflow-contexts.js +10 -1
  314. package/dist/integrations/pi/engine/workflow-runner.js +74 -5
  315. package/dist/integrations/pi/engine/workflow-support.d.ts +12 -0
  316. package/dist/integrations/pi/engine/workflow-support.js +36 -0
  317. package/dist/integrations/pi/engine/workflows.d.ts +3 -1
  318. package/dist/integrations/pi/engine/workflows.js +1 -0
  319. package/dist/integrations/pi/startup-public.js +257 -310
  320. package/dist/integrations/pi/startup-public.manifest.json +564 -440
  321. package/dist/integrations/pi/tui-runtime/adapter.d.ts +6 -0
  322. package/dist/integrations/pi/tui-runtime/adapter.js +32 -1
  323. package/dist/integrations/pi/tui-runtime/contracts.d.ts +5 -0
  324. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +12 -1
  325. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +31 -2
  326. package/dist/native/darwin-arm64/manifest.json +10 -7
  327. package/dist/native/darwin-arm64/process-guardian.node +0 -0
  328. package/dist/native/darwin-arm64/terminal-host-THIRD-PARTY-NOTICES.txt +10500 -0
  329. package/dist/native/darwin-arm64/terminal-host.manifest.json +46 -0
  330. package/dist/native/darwin-arm64/terminal-host.node +0 -0
  331. package/dist/native/darwin-x64/manifest.json +23 -0
  332. package/dist/native/darwin-x64/process-guardian.node +0 -0
  333. package/dist/native/darwin-x64/terminal-host-THIRD-PARTY-NOTICES.txt +10737 -0
  334. package/dist/native/darwin-x64/terminal-host.manifest.json +46 -0
  335. package/dist/native/darwin-x64/terminal-host.node +0 -0
  336. package/dist/native/linux-x64/manifest.json +10 -7
  337. package/dist/native/linux-x64/process-guardian.node +0 -0
  338. package/dist/native/linux-x64/terminal-host-THIRD-PARTY-NOTICES.txt +11226 -0
  339. package/dist/native/linux-x64/terminal-host.manifest.json +46 -0
  340. package/dist/native/linux-x64/terminal-host.node +0 -0
  341. package/dist/native/win32-x64/manifest.json +10 -7
  342. package/dist/native/win32-x64/process-guardian.node +0 -0
  343. package/dist/native/win32-x64/terminal-host-THIRD-PARTY-NOTICES.txt +10757 -0
  344. package/dist/native/win32-x64/terminal-host.manifest.json +46 -0
  345. package/dist/native/win32-x64/terminal-host.node +0 -0
  346. package/dist/product-identity.d.ts +3 -3
  347. package/dist/product-identity.js +4 -4
  348. package/dist/product-identity.json +16 -2
  349. package/dist/runtime-payload-inventory.json +6330 -6677
  350. package/dist/ui/apps/host.d.ts +2 -0
  351. package/dist/ui/apps/host.js +7 -1
  352. package/dist/ui/components/dialog-panel.d.ts +17 -8
  353. package/dist/ui/components/dialog-panel.js +117 -41
  354. package/dist/ui/components/index.d.ts +5 -5
  355. package/dist/ui/components/index.js +4 -4
  356. package/dist/ui/components/line-input.d.ts +4 -1
  357. package/dist/ui/components/line-input.js +3 -1
  358. package/dist/ui/components/prompt-input.d.ts +11 -8
  359. package/dist/ui/components/prompt-input.js +15 -13
  360. package/dist/ui/components/scrollbar.d.ts +1 -1
  361. package/dist/ui/components/scrollbar.js +1 -1
  362. package/dist/ui/components/selection-copy.d.ts +3 -3
  363. package/dist/ui/components/selection-copy.js +16 -1
  364. package/dist/ui/components/spans.js +2 -2
  365. package/dist/ui/components/submitted-prompt.d.ts +9 -6
  366. package/dist/ui/components/submitted-prompt.js +20 -12
  367. package/dist/ui/components/surface.js +4 -2
  368. package/dist/ui/components/text-selection.d.ts +1 -2
  369. package/dist/ui/components/text-selection.js +5 -2
  370. package/dist/ui/components/text.d.ts +3 -6
  371. package/dist/ui/components/text.js +6 -8
  372. package/dist/ui/components/transcript-viewport.d.ts +9 -2
  373. package/dist/ui/components/transcript-viewport.js +179 -58
  374. package/dist/ui/settings/declarations.d.ts +90 -16
  375. package/dist/ui/settings/declarations.js +67 -14
  376. package/dist/ui/settings/early-accent.d.ts +81 -0
  377. package/dist/ui/settings/early-accent.js +50 -0
  378. package/dist/ui/settings/index.d.ts +4 -2
  379. package/dist/ui/settings/index.js +2 -1
  380. package/dist/ui/settings/manager.d.ts +16 -3
  381. package/dist/ui/settings/manager.js +122 -33
  382. package/dist/ui/settings/migrations.d.ts +6 -0
  383. package/dist/ui/settings/migrations.js +73 -0
  384. package/dist/ui/settings/profile-document.d.ts +26 -0
  385. package/dist/ui/settings/profile-document.js +164 -0
  386. package/dist/ui/settings/progress-palette.generated.d.ts +139 -0
  387. package/dist/ui/settings/progress-palette.generated.js +139 -0
  388. package/dist/ui/settings/sections.d.ts +4 -0
  389. package/dist/ui/settings/sections.js +9 -3
  390. package/docs/architecture/boundaries.md +24 -9
  391. package/docs/architecture/evidence/resident-tabs/linux-x64.md +37 -0
  392. package/docs/architecture/evidence/resident-tabs/macos-arm64.md +36 -0
  393. package/docs/architecture/evidence/resident-tabs/macos-x64.md +35 -0
  394. package/docs/architecture/evidence/resident-tabs/windows-x64.md +36 -0
  395. package/docs/architecture/internal-naming.md +3 -1
  396. package/docs/architecture/process-guardian-provenance.md +18 -10
  397. package/docs/architecture/project-structure.md +8 -0
  398. package/docs/architecture/resident-tabs-requirements.md +18 -0
  399. package/docs/architecture/resident-tabs.md +649 -0
  400. package/docs/architecture/response-copy-delivery.md +1 -1
  401. package/docs/architecture/terminal-host-proof-gate.md +2 -0
  402. package/docs/architecture/terminal-host-provenance.md +16 -4
  403. package/docs/architecture/tool-image-presentation.md +2 -1
  404. package/docs/architecture/toolchain.md +11 -9
  405. package/docs/ci-release-runbook.md +14 -7
  406. package/docs/features/launch-profiles.md +11 -8
  407. package/docs/features/prompt-history.md +41 -20
  408. package/docs/manual-resident-tabs-acceptance.md +51 -0
  409. package/docs/openspec-archive-automation.md +49 -22
  410. package/docs/validation.md +49 -9
  411. package/package.json +19 -6
  412. package/dist/foundation/process-containment/darwin-process-inspector.d.ts +0 -5
  413. package/dist/foundation/process-containment/darwin-process-inspector.js +0 -7
  414. package/dist/foundation/process-containment/native-guardian-containment.js +0 -152
  415. package/dist/foundation/process-containment/windows-process-inspector.d.ts +0 -19
  416. package/dist/foundation/process-containment/windows-process-inspector.js +0 -56
  417. package/dist/native/darwin-arm64/process-guardian +0 -0
  418. package/dist/native/linux-x64/process-guardian +0 -0
  419. package/dist/native/win32-x64/process-guardian.exe +0 -0
@@ -1,22 +1,30 @@
1
1
  import { displayWidth, truncateToWidth } from "./text.js";
2
- /** Visible width of the submitted-prompt prefix (`❯ `). */
3
- export const SUBMITTED_PROMPT_PREFIX_WIDTH = 2;
4
- const TIMESTAMP_MARGIN = 3;
5
- const MIN_USEFUL_CONTENT_WIDTH = 8;
6
- /** Formats transcript metadata, never render time, as local 24-hour HH:mm. */
7
- export function formatSubmittedPromptTime(source) {
2
+ /** Deterministic local hour/minute presentation shared by A1-owned time labels. */
3
+ export function formatLocalTime(source, format = "8:00 PM") {
8
4
  const date = source instanceof Date ? source : new Date(source);
9
5
  if (!Number.isFinite(date.getTime()))
10
6
  return null;
11
- return `${String(date.getHours()).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
7
+ const hour = date.getHours();
8
+ const minute = String(date.getMinutes()).padStart(2, "0");
9
+ if (format === "20:00")
10
+ return `${String(hour).padStart(2, "0")}:${minute}`;
11
+ return `${hour % 12 || 12}:${minute} ${hour < 12 ? "AM" : "PM"}`;
12
+ }
13
+ /** Visible width of the submitted-prompt prefix (` ❯ `). */
14
+ export const SUBMITTED_PROMPT_PREFIX_WIDTH = 3;
15
+ const TIMESTAMP_MARGIN = 3;
16
+ const MIN_USEFUL_CONTENT_WIDTH = 8;
17
+ /** Formats transcript metadata, never render time, in the active A1 time format. */
18
+ export function formatSubmittedPromptTime(source, format = "8:00 PM") {
19
+ return formatLocalTime(source, format);
12
20
  }
13
21
  /**
14
22
  * Computes the width at which the prompt's Markdown body must be rendered.
15
23
  * The timestamp is omitted rather than allowing it to crowd useful content.
16
24
  */
17
- export function submittedPromptLayout(width, source) {
25
+ export function submittedPromptLayout(width, source, format = "8:00 PM") {
18
26
  const boundedWidth = Math.max(1, width);
19
- const timestamp = source === undefined || source === null ? null : formatSubmittedPromptTime(source);
27
+ const timestamp = source === undefined || source === null ? null : formatSubmittedPromptTime(source, format);
20
28
  const timestampReserve = timestamp === null ? 0 : displayWidth(timestamp) + TIMESTAMP_MARGIN;
21
29
  const canShowTimestamp = timestamp !== null
22
30
  && boundedWidth - SUBMITTED_PROMPT_PREFIX_WIDTH - timestampReserve >= MIN_USEFUL_CONTENT_WIDTH;
@@ -30,11 +38,11 @@ export function submittedPromptLayout(width, source) {
30
38
  * Continuations align below the content, not below the prefix, and no row can
31
39
  * exceed the supplied terminal width even when the content renderer misbehaves.
32
40
  */
33
- export function composeSubmittedPromptRows(contentRows, width, source, style = {}) {
41
+ export function composeSubmittedPromptRows(contentRows, width, source, style = {}, format = "8:00 PM") {
34
42
  if (width <= 0)
35
43
  return [];
36
- const layout = submittedPromptLayout(width, source);
37
- const prefix = (style.prefix ?? identity)("❯ ");
44
+ const layout = submittedPromptLayout(width, source, format);
45
+ const prefix = (style.prefix ?? identity)(" ❯ ");
38
46
  const rows = (contentRows.length === 0 ? [""] : contentRows).map((row, index) => {
39
47
  const content = truncateToWidth(row, layout.contentWidth);
40
48
  return `${index === 0 ? prefix : " ".repeat(SUBMITTED_PROMPT_PREFIX_WIDTH)}${content}`;
@@ -29,10 +29,12 @@ export function withScrollbarRail(lines, geometry, contentWidth, theme, options
29
29
  */
30
30
  export function renderEmptyState(message, mark, height, width, theme) {
31
31
  const middle = Math.floor(height / 2);
32
+ const messageRow = Math.min(Math.max(0, height - 1), middle + 1);
33
+ const markRow = messageRow - 1;
32
34
  return Array.from({ length: Math.max(0, height) }, (_line, index) => {
33
- if (index === middle - 1)
35
+ if (index === markRow)
34
36
  return centre(theme.fg("muted", mark), mark, width);
35
- return index === middle ? centre(theme.fg("muted", message), message, width) : "";
37
+ return index === messageRow ? centre(theme.fg("muted", message), message, width) : "";
36
38
  });
37
39
  }
38
40
  function centre(painted, raw, width) {
@@ -1,4 +1,3 @@
1
- /** A reported pointer cell plus its grapheme-aligned zero-based boundaries. */
2
1
  export interface TextSelectionPoint {
3
2
  readonly line: number;
4
3
  readonly column: number;
@@ -28,7 +27,6 @@ export interface TextSelectionLineContent {
28
27
  readonly to?: number;
29
28
  readonly selectable?: boolean;
30
29
  }
31
- /** Ordered zero-based, half-open display-column boundaries. */
32
30
  export interface OrderedTextSelection {
33
31
  readonly start: TextSelectionPoint;
34
32
  readonly end: TextSelectionPoint;
@@ -45,6 +43,7 @@ export interface TextSelectionPressInput {
45
43
  readonly now?: number;
46
44
  }
47
45
  export declare const TEXT_SELECTION_MULTI_CLICK_MS = 500;
46
+ export declare function paintTextSelection(line: string, from: number, to: number, widthOf?: (text: string) => number, clearInverse?: boolean): string;
48
47
  export declare function orderedTextSelection(selection: TextSelection | undefined): OrderedTextSelection | undefined;
49
48
  export declare function pressTextSelection(input: TextSelectionPressInput): {
50
49
  readonly selection?: TextSelection;
@@ -1,6 +1,11 @@
1
+ import { backgroundSgrSpan } from "./spans.js";
1
2
  import { displayWidth, stripAnsi } from "./text.js";
2
3
  const GRAPHEMES = new Intl.Segmenter(undefined, { granularity: "grapheme" });
3
4
  export const TEXT_SELECTION_MULTI_CLICK_MS = 500;
5
+ const TEXT_SELECTION_BACKGROUND = "\u001b[48;2;38;79;120m";
6
+ export function paintTextSelection(line, from, to, widthOf = displayWidth, clearInverse = false) {
7
+ return backgroundSgrSpan(line, from, to, `${clearInverse ? "\u001b[27m" : ""}${TEXT_SELECTION_BACKGROUND}`, "\u001b[49m", widthOf);
8
+ }
4
9
  export function orderedTextSelection(selection) {
5
10
  if (selection === undefined)
6
11
  return undefined;
@@ -17,8 +22,6 @@ export function orderedTextSelection(selection) {
17
22
  }
18
23
  if (!selection.cell && selection.dragged !== true)
19
24
  return undefined;
20
- // Invariant: an accepted drag includes both endpoint graphemes, even after returning
21
- // to its anchor. Only an unextended point press is empty; paint and copy stay half-open.
22
25
  const anchorFirst = comparePoints(anchor, head) <= 0;
23
26
  const first = anchorFirst ? anchor : head;
24
27
  const last = anchorFirst ? head : anchor;
@@ -1,11 +1,8 @@
1
- /**
2
- * Display-width text handling. Terminals lay out by column, not by code unit,
3
- * so measuring with `String.length` mis-sizes CJK, emoji, and combining marks,
4
- * and counting styling escapes as visible width breaks every layout that uses
5
- * colour.
6
- */
1
+ /** Terminal-column geometry: preserve graphemes, Unicode cell widths and ANSI styling. */
7
2
  /** Removes styling sequences so only visible characters remain. */
8
3
  export declare function stripAnsi(text: string): string;
4
+ /** Width of one grapheme cluster: two for emoji, else the widest code point it contains. */
5
+ export declare function graphemeWidth(grapheme: string): number;
9
6
  export interface DisplayColumnRange {
10
7
  readonly from: number;
11
8
  readonly to: number;
@@ -1,9 +1,4 @@
1
- /**
2
- * Display-width text handling. Terminals lay out by column, not by code unit,
3
- * so measuring with `String.length` mis-sizes CJK, emoji, and combining marks,
4
- * and counting styling escapes as visible width breaks every layout that uses
5
- * colour.
6
- */
1
+ /** Terminal-column geometry: preserve graphemes, Unicode cell widths and ANSI styling. */
7
2
  const ANSI_PATTERN = /\[[0-9;:?]*[ -/]*[@-~]|[\]_][^]*(?:|\\)|[@-Z\\-_]/g;
8
3
  const SEGMENTER = new Intl.Segmenter(undefined, { granularity: "grapheme" });
9
4
  const WORD_SEGMENTER = new Intl.Segmenter(undefined, { granularity: "word" });
@@ -76,7 +71,7 @@ function couldBeEmoji(grapheme) {
76
71
  grapheme.length > 1);
77
72
  }
78
73
  /** Width of one grapheme cluster: two for emoji, else the widest code point it contains. */
79
- function graphemeWidth(grapheme) {
74
+ export function graphemeWidth(grapheme) {
80
75
  if (couldBeEmoji(grapheme) && RGI_EMOJI_PATTERN.test(grapheme))
81
76
  return 2;
82
77
  let width = 0;
@@ -126,8 +121,11 @@ export function displayColumnSlice(text, requestedFrom, requestedTo) {
126
121
  }
127
122
  /** Columns this text occupies once styling is removed. */
128
123
  export function displayWidth(text) {
124
+ const plain = stripAnsi(text);
125
+ if (!/[^\x20-\x7e]/u.test(plain))
126
+ return plain.length;
129
127
  let width = 0;
130
- for (const { segment } of SEGMENTER.segment(stripAnsi(text)))
128
+ for (const { segment } of SEGMENTER.segment(plain))
131
129
  width += graphemeWidth(segment);
132
130
  return width;
133
131
  }
@@ -6,6 +6,8 @@ export interface TranscriptPromptAnchor {
6
6
  readonly lastRow: number;
7
7
  /** The source first row, including its submitted-prompt styling and timestamp. */
8
8
  readonly sourceRow: string;
9
+ /** Right-edge metadata cells omitted from semantic prompt copies. */
10
+ readonly copySuffixWidth?: number;
9
11
  /** Optional source-styled row used only while prominent and not hovered. */
10
12
  readonly prominentSourceRow?: string;
11
13
  }
@@ -36,6 +38,11 @@ export interface TranscriptViewportFrameInput {
36
38
  /** Final transient rows to bottom-align with unused viewport space while content fits. */
37
39
  readonly bottomAlignedTailRowCount?: number;
38
40
  readonly dockRows: readonly string[];
41
+ /** Zero-based dock rows admitted to frame copying, classified before dock composition. */
42
+ readonly copyableDockRows?: readonly {
43
+ readonly row: number;
44
+ readonly prompt?: "first" | "continuation";
45
+ }[];
39
46
  readonly promptAnchors: readonly TranscriptPromptAnchor[];
40
47
  readonly width: number;
41
48
  readonly height: number;
@@ -171,7 +178,7 @@ export declare class TranscriptViewport {
171
178
  releaseSelection(): boolean;
172
179
  clearSelection(): boolean;
173
180
  selectedText(): string | null;
174
- /** Captures visible selected text, not off-screen history. */
181
+ /** Captures selected text, including document rows of a visible selection scrolled off-screen. */
175
182
  captureSelectedText(): SelectionCopySnapshot | null;
176
183
  scrollBy(lines: number, now?: number): boolean;
177
184
  scrollTo(position: number, now?: number): boolean;
@@ -184,6 +191,6 @@ export declare class TranscriptViewport {
184
191
  clearTransient(): void;
185
192
  compose(input: TranscriptViewportFrameInput): TranscriptViewportFrame;
186
193
  /** Reuses an established transcript frame when only same-height dock rows changed. */
187
- composeDockOnly(dockRows: readonly string[], width: number, height: number): TranscriptViewportFrame | null;
194
+ composeDockOnly(dockRows: readonly string[], width: number, height: number, copyableDockRows?: TranscriptViewportFrameInput["copyableDockRows"]): TranscriptViewportFrame | null;
188
195
  }
189
196
  export declare function assertTranscriptViewportFrameDescriptor(descriptor: TranscriptViewportFrameDescriptor): void;
@@ -1,9 +1,13 @@
1
1
  import { MAX_COPY_SOURCE_UNITS, selectionCopyLineContent } from "./selection-copy.js";
2
2
  import { isThumbRow, scrollbarGeometry, scrollbarPresentation, } from "./scrollbar.js";
3
- import { backgroundSgrSpan, overlaySpan } from "./spans.js";
3
+ import { overlaySpan } from "./spans.js";
4
4
  import { faint, truncateToWidth, displayWidth, stripAnsi } from "./text.js";
5
- import { extendTextSelection, orderedTextSelection, pressTextSelection, releaseTextSelection, textSelectionLineExtendColumn, textSelectionPointAt, textSelectionText, usefulTextLineContent, } from "./text-selection.js";
5
+ import { extendTextSelection, orderedTextSelection, paintTextSelection, pressTextSelection, releaseTextSelection, textSelectionLineExtendColumn, textSelectionPointAt, textSelectionText, usefulTextLineContent, } from "./text-selection.js";
6
6
  const CONTROL_STYLE_RESET = "\u001b]8;;\u001b\\\u001b[0m";
7
+ // Protocol: upstream OSC 133 zones are layout annotations, not fullscreen cursor commands.
8
+ // Styling/padding can move them away from the row prefix Pi strips; 133;A then advances a real
9
+ // terminal parser to a fresh line. The custom viewport owns prompt anchors separately.
10
+ const VIEWPORT_PROMPT_ZONES = /\u001b\]133;[ABC](?:\u0007|\u001b\\)/gu;
7
11
  // Invariant: scrollbar chrome closes source links and decoration without clearing
8
12
  // the row surface painted beneath its dedicated, non-semantic gutter.
9
13
  const GUTTER_DECORATION_RESET = "\u001b]8;;\u001b\\\u001b[22;23;24;25;27;28;29;39;54;55m";
@@ -11,6 +15,19 @@ const IDENTITY_ROW = (row) => row;
11
15
  function documentSelectionAnchor(row, source, liveFromBottom) {
12
16
  return { kind: "document", row, source, identity: stripAnsi(source).trimEnd(), liveFromBottom };
13
17
  }
18
+ function sameSelectionRowAnchor(left, right) {
19
+ if (left.kind !== right.kind)
20
+ return false;
21
+ if (left.kind === "document" && right.kind === "document") {
22
+ return left.row === right.row && left.source === right.source && left.liveFromBottom === right.liveFromBottom;
23
+ }
24
+ if (left.kind === "screen" && right.kind === "screen") {
25
+ return left.row === right.row && left.source === right.source;
26
+ }
27
+ if (left.kind === "transient" && right.kind === "transient")
28
+ return left.fromBottom === right.fromBottom;
29
+ return left.kind === "dock" && right.kind === "dock" && left.fromBottom === right.fromBottom;
30
+ }
14
31
  function viewportSelectionAnchor(row, source, selectableDocumentRowCount, documentRowCount) {
15
32
  return row < selectableDocumentRowCount
16
33
  ? documentSelectionAnchor(row, source)
@@ -26,7 +43,7 @@ const PLAIN_THEME = {
26
43
  sticky: (text, hovered) => hovered ? `\u001b[7m${text}\u001b[27m` : text,
27
44
  quietSticky: faint,
28
45
  bottomControl: (text, hovered) => hovered ? `\u001b[7m${text}\u001b[27m` : `\u001b[7m${text}\u001b[27m`,
29
- selection: (line, from, to) => backgroundSgrSpan(line, from, to),
46
+ selection: paintTextSelection,
30
47
  };
31
48
  /**
32
49
  * A1-owned viewport state. It knows only rows and semantic prompt anchors; Pi
@@ -63,6 +80,7 @@ export class TranscriptViewport {
63
80
  #contentWidth = 0;
64
81
  #selectionWidth = 0;
65
82
  #viewportHeight = 0;
83
+ #copyableDockRows = new Map();
66
84
  #firstSelectableRow = 0;
67
85
  #selectionRowAnchors = [];
68
86
  #frameId = 0;
@@ -135,7 +153,12 @@ export class TranscriptViewport {
135
153
  this.scrollBy(1, now);
136
154
  else if (autoScroll && frameRow <= 1 && this.#scrollTop > 0)
137
155
  this.scrollBy(-1, now);
138
- const line = clamp(frameRow - 1, 0, this.#selectionRows.length - 1);
156
+ const pointerLine = clamp(frameRow - 1, 0, this.#selectionRows.length - 1);
157
+ // Invariant: a pinned prompt alias is chrome; an upward drag reaching it keeps the pointer
158
+ // column on the first visible content row.
159
+ const line = pointerLine < this.#firstSelectableRow && pointerLine < selection.anchor.line
160
+ ? this.#firstSelectableRow
161
+ : pointerLine;
139
162
  const selectionWidth = line < (this.#frame?.hits.viewportHeight ?? 0)
140
163
  ? this.#contentWidth
141
164
  : this.#selectionWidth;
@@ -146,12 +169,13 @@ export class TranscriptViewport {
146
169
  ? { line, column: targetColumn }
147
170
  : textSelectionPointAt(line, targetColumn, this.#selectionRows[line] ?? "");
148
171
  const next = extendTextSelection(selection, point);
149
- if (next !== selection) {
150
- const headAnchor = this.#selectionAnchorAt(line);
151
- if (headAnchor === undefined || this.#selectionAnchors === undefined) {
152
- this.clearSelection();
153
- return true;
154
- }
172
+ const headAnchor = this.#selectionAnchorAt(line);
173
+ if (headAnchor === undefined || this.#selectionAnchors === undefined) {
174
+ this.clearSelection();
175
+ return true;
176
+ }
177
+ // Invariant: edge auto-scroll changes the document row under a still pointer; that advances the head.
178
+ if (next !== selection || !sameSelectionRowAnchor(this.#selectionAnchors.head, headAnchor)) {
155
179
  this.#selection = next;
156
180
  this.#selectionAnchors = { ...this.#selectionAnchors, head: headAnchor };
157
181
  this.#selectionRevision += 1;
@@ -179,35 +203,80 @@ export class TranscriptViewport {
179
203
  return true;
180
204
  }
181
205
  selectedText() {
182
- const selection = this.#visibleSelection();
183
- if (selection === undefined)
206
+ const visible = this.#visibleSelection();
207
+ if (visible === undefined)
184
208
  return null;
185
- // Invariant: the blue range spans the complete frame, but automatic and Ctrl+C frame copy
186
- // admit only persistent transcript rows. Transient status, suggestions, input, and footer
187
- // chrome remain visually selectable without becoming clipboard payload.
188
- const copiedLines = Array.from({ length: Math.max(0, selection.end.line - selection.start.line + 1) }, (_value, index) => selection.start.line + index).filter(line => {
209
+ const offscreen = offscreenSelectionRows(this.#selection, this.#selectionAnchors, this.#scrollTop, this.#firstSelectableRow, this.#viewportHeight, this.#documentRows.length);
210
+ // Rationale: edge auto-scroll grows a drag beyond one screen. Paint stays clipped to the
211
+ // frame, while copy reads the selected document rows past either viewport edge and beneath
212
+ // the floating bottom control.
213
+ const selectionRows = [];
214
+ const rowAnchors = [];
215
+ const controlLine = (this.#frame?.hits.bottom?.row ?? 0) - 1;
216
+ const pushDocumentRow = (row) => {
217
+ const source = this.#documentRows[row] ?? "";
218
+ selectionRows.push(truncateToWidth(source, this.#contentWidth));
219
+ rowAnchors.push(documentSelectionAnchor(row, source));
220
+ };
221
+ const pushBelow = () => {
222
+ for (let row = offscreen.below?.from ?? 0; row <= (offscreen.below?.to ?? -1); row += 1)
223
+ pushDocumentRow(row);
224
+ };
225
+ for (let row = offscreen.above?.from ?? 0; row <= (offscreen.above?.to ?? -1); row += 1)
226
+ pushDocumentRow(row);
227
+ if (offscreen.belowFirst)
228
+ pushBelow();
229
+ for (let line = visible.start.line; line <= visible.end.line; line += 1) {
189
230
  const anchor = this.#selectionRowAnchors[line];
190
- return anchor?.kind === "document" && anchor.row < this.#selectableDocumentRowCount;
231
+ if (line === controlLine && anchor?.kind === "document")
232
+ pushDocumentRow(anchor.row);
233
+ else {
234
+ selectionRows.push(this.#selectionRows[line] ?? "");
235
+ rowAnchors.push(anchor);
236
+ }
237
+ }
238
+ if (!offscreen.belowFirst)
239
+ pushBelow();
240
+ const offscreenStart = offscreen.above !== undefined || offscreen.belowFirst === true;
241
+ const offscreenEnd = offscreen.below !== undefined && !offscreen.belowFirst;
242
+ const selection = {
243
+ ...visible,
244
+ start: { line: 0, column: offscreenStart ? offscreen.startColumn ?? 0 : visible.start.column },
245
+ end: {
246
+ line: selectionRows.length - 1,
247
+ column: offscreenEnd ? offscreen.endColumn ?? Number.MAX_SAFE_INTEGER : visible.end.column,
248
+ },
249
+ };
250
+ const copiedLines = Array.from({ length: Math.max(0, selection.end.line - selection.start.line + 1) }, (_value, index) => selection.start.line + index).filter(line => {
251
+ const anchor = rowAnchors[line];
252
+ return anchor?.kind === "document" && anchor.row < this.#selectableDocumentRowCount
253
+ || anchor?.kind === "dock" && this.#copyableDockRows.has(anchor.fromBottom);
191
254
  });
192
255
  if (copiedLines.length === 0)
193
256
  return null;
194
- // Rationale: a prompt selected by itself uses semantic prompt text. Once surrounding transcript text
195
- // participates, preserve the prompt's visible prefix, alignment, and timestamp in the bulk range.
196
- const prompt = this.#promptAnchors.find(candidate => copiedLines.every(line => {
197
- const anchor = this.#selectionRowAnchors[line];
257
+ const transcriptLines = copiedLines.filter(line => rowAnchors[line]?.kind === "document");
258
+ const prompt = transcriptLines.length === 0 ? undefined : this.#promptAnchors.find(candidate => transcriptLines.every(line => {
259
+ const anchor = rowAnchors[line];
198
260
  return anchor?.kind === "document" && anchor.row >= candidate.firstRow && anchor.row <= candidate.lastRow;
199
261
  }));
200
262
  const included = new Set(copiedLines);
201
- const text = textSelectionText(selection, this.#selectionRows, line => {
202
- const row = this.#selectionRows[line] ?? "";
203
- const anchor = this.#selectionRowAnchors[line];
204
- return prompt !== undefined && anchor?.kind === "document"
205
- ? selectionCopyLineContent(row, anchor.row === prompt.firstRow ? "first" : "continuation")
206
- : usefulTextLineContent(row);
263
+ const text = textSelectionText(selection, selectionRows, line => {
264
+ const row = selectionRows[line] ?? "";
265
+ const anchor = rowAnchors[line];
266
+ const dock = anchor?.kind === "dock" ? this.#copyableDockRows.get(anchor.fromBottom) : undefined;
267
+ if (prompt !== undefined && anchor?.kind === "document") {
268
+ const first = anchor.row === prompt.firstRow;
269
+ const copyRow = first && (prompt.copySuffixWidth ?? 0) > 0
270
+ ? truncateToWidth(row, Math.max(0, displayWidth(row) - (prompt.copySuffixWidth ?? 0)))
271
+ : row;
272
+ return selectionCopyLineContent(copyRow, first ? "first" : "continuation");
273
+ }
274
+ // Invariant: the dock editor has no prefix; transcript prompts still carry chrome.
275
+ return dock?.prompt !== undefined ? usefulTextLineContent(row, 1) : usefulTextLineContent(row);
207
276
  }, line => included.has(line));
208
277
  return text.length === 0 ? null : text;
209
278
  }
210
- /** Captures visible selected text, not off-screen history. */
279
+ /** Captures selected text, including document rows of a visible selection scrolled off-screen. */
211
280
  captureSelectedText() {
212
281
  if (!this.#copyableSelection)
213
282
  return null;
@@ -315,6 +384,7 @@ export class TranscriptViewport {
315
384
  this.#contentWidth = 0;
316
385
  this.#selectionWidth = 0;
317
386
  this.#viewportHeight = 0;
387
+ this.#copyableDockRows.clear();
318
388
  this.clearTransient();
319
389
  this.#frame = null;
320
390
  }
@@ -330,6 +400,7 @@ export class TranscriptViewport {
330
400
  const theme = input.theme ?? PLAIN_THEME;
331
401
  const previousDescriptor = this.#frame?.descriptor ?? null;
332
402
  const dock = input.dockRows.length > height ? input.dockRows.slice(-height) : [...input.dockRows];
403
+ this.#copyableDockRows = copyableDockRowsBySuffix(input.dockRows, input.copyableDockRows);
333
404
  const viewportHeight = Math.max(0, height - dock.length);
334
405
  const bottomAlignedTailRowCount = clamp(input.bottomAlignedTailRowCount ?? 0, 0, input.documentRows.length);
335
406
  const transientAlignmentGapRows = bottomAlignedTailRowCount > 0
@@ -356,7 +427,7 @@ export class TranscriptViewport {
356
427
  contentLength: documentRows.length,
357
428
  viewportHeight,
358
429
  scroll: this.#scrollTop,
359
- // Compatibility: the session rail deliberately starts one line below the viewport top.
430
+ // Invariant: the rail keeps its top gap; the shell owns the spacing above the dock.
360
431
  trackHeight: Math.max(0, viewportHeight - 1),
361
432
  });
362
433
  const presentation = scrollbarPresentation({
@@ -414,8 +485,6 @@ export class TranscriptViewport {
414
485
  visible[0] = quiet && !this.#stickyHovered ? theme.quietSticky(sticky) : sticky;
415
486
  visibleSource[0] = sourceRow;
416
487
  }
417
- // Invariant: selection uses exact visible source rows within the rendered
418
- // content boundary; paint-only guards and the rail gutter stay presentation-only.
419
488
  this.#selectionRows = [
420
489
  ...visibleSource.map(row => truncateToWidth(row, contentWidth)),
421
490
  ...dock,
@@ -426,7 +495,6 @@ export class TranscriptViewport {
426
495
  ? viewportSelectionAnchor(documentRow, documentRows[documentRow] ?? "", this.#selectableDocumentRowCount, documentRows.length)
427
496
  : { kind: "screen", row, source: this.#selectionRows[row] ?? "" };
428
497
  });
429
- // Invariant: a pinned prompt is chrome over its hidden source row, which clips like off-screen rows.
430
498
  this.#firstSelectableRow = stickyActive && viewportHeight > 0 ? 1 : 0;
431
499
  this.#selectionRowAnchors = [
432
500
  ...visibleAnchors,
@@ -463,7 +531,7 @@ export class TranscriptViewport {
463
531
  const bottomHovered = pointer !== undefined && pointer.row === bottomHit.row
464
532
  && pointer.column >= bottomHit.columnStart && pointer.column <= bottomHit.columnEnd;
465
533
  control = { row, left, text: `${CONTROL_STYLE_RESET}${theme.bottomControl(label, bottomHovered)}` };
466
- // Invariant: the control floats above selection; its cells are never selected or copied.
534
+ // Invariant: the control floats above selection; copy restores the text beneath it.
467
535
  selectionRows[row] = overlaySpan(padRowPreservingBackground(selectionRows[row] ?? "", width), left, left + labelWidth, " ".repeat(labelWidth));
468
536
  }
469
537
  }
@@ -501,7 +569,7 @@ export class TranscriptViewport {
501
569
  // Invariant: paint the rail after selection over the gutter's continued row
502
570
  // background. Source content and selection still end at the preceding cell.
503
571
  let railCell = "";
504
- if (row < viewportHeight && presentation.visible && geometry !== null && row > 0) {
572
+ if (row > 0 && row < viewportHeight && presentation.visible && geometry !== null) {
505
573
  const trackRow = row - 1;
506
574
  const thumb = isThumbRow(geometry, trackRow);
507
575
  const glyph = thumb ? presentation.thumbGlyph : presentation.trackGlyph;
@@ -523,7 +591,7 @@ export class TranscriptViewport {
523
591
  return overlayWidth === 0 ? withControl : overlaySpan(padRowPreservingBackground(withControl, width), overlayLimit - overlayWidth, overlayLimit, `${GUTTER_DECORATION_RESET}${overlayText}`, { inheritStartStyle: true });
524
592
  });
525
593
  rowRecomputed ||= !final.reused;
526
- frameRows[row] = final.value;
594
+ frameRows[row] = final.value.replace(VIEWPORT_PROMPT_ZONES, "");
527
595
  (rowRecomputed ? recomputedRows : reusedRows).push(row + 1);
528
596
  const state = `${width}\u0000${row}\u0000${painted}\u0000${rangeKey}\u0000${range === null ? "" : selectionPainterId}\u0000${railCell}\u0000${overlayText}\u0000${rowControl?.text ?? ""}`;
529
597
  visibleStates.push(state);
@@ -609,7 +677,7 @@ export class TranscriptViewport {
609
677
  return frame;
610
678
  }
611
679
  /** Reuses an established transcript frame when only same-height dock rows changed. */
612
- composeDockOnly(dockRows, width, height) {
680
+ composeDockOnly(dockRows, width, height, copyableDockRows = []) {
613
681
  const previous = this.#frame;
614
682
  const boundedWidth = Math.max(1, width);
615
683
  const boundedHeight = Math.max(0, height);
@@ -624,19 +692,10 @@ export class TranscriptViewport {
624
692
  || !sameRectangle(previous.descriptor.transcript, expectedTranscript))
625
693
  return null;
626
694
  const descriptor = {
695
+ ...previous.descriptor,
627
696
  frameId: ++this.#frameId,
628
- width: boundedWidth,
629
- height: boundedHeight,
630
- transcript: expectedTranscript,
631
- dock: expectedDock,
632
697
  previousDocumentRange: previous.descriptor.nextDocumentRange,
633
- nextDocumentRange: previous.descriptor.nextDocumentRange,
634
698
  previousFollowingEnd: previous.followingEnd,
635
- followingEnd: previous.followingEnd,
636
- transientRowCount: previous.descriptor.transientRowCount,
637
- transientAlignmentGapRows: previous.descriptor.transientAlignmentGapRows,
638
- bottomAlignedTailRowCount: previous.descriptor.bottomAlignedTailRowCount,
639
- liveTailRows: previous.descriptor.liveTailRows,
640
699
  verticalShiftRows: 0,
641
700
  safeVerticalShift: false,
642
701
  selectionRevision: this.#selectionRevision,
@@ -645,13 +704,10 @@ export class TranscriptViewport {
645
704
  };
646
705
  assertTranscriptViewportFrameDescriptor(descriptor);
647
706
  this.#selectionRows = [...this.#selectionRows.slice(0, viewportHeight), ...dock].slice(0, boundedHeight);
707
+ this.#copyableDockRows = copyableDockRowsBySuffix(dockRows, copyableDockRows);
648
708
  const frame = {
649
- rows: [...previous.rows.slice(0, viewportHeight), ...dock].slice(0, boundedHeight),
650
- contentWidth: previous.contentWidth,
651
- scrollTop: previous.scrollTop,
652
- maxScroll: previous.maxScroll,
653
- followingEnd: previous.followingEnd,
654
- hits: previous.hits,
709
+ ...previous,
710
+ rows: [...previous.rows.slice(0, viewportHeight), ...dock.map(row => row.replace(VIEWPORT_PROMPT_ZONES, ""))].slice(0, boundedHeight),
655
711
  descriptor,
656
712
  selectionDamage: {
657
713
  revision: this.#selectionRevision,
@@ -706,7 +762,7 @@ export class TranscriptViewport {
706
762
  const anchors = this.#selectionAnchors;
707
763
  if (selection === undefined || anchors === undefined)
708
764
  return;
709
- const project = (anchor) => {
765
+ const project = (anchor, moving) => {
710
766
  if (anchor.kind === "dock") {
711
767
  const dockIndex = dockRows.length - anchor.fromBottom - 1;
712
768
  return dockIndex < 0 || dockIndex >= dockRows.length
@@ -748,7 +804,7 @@ export class TranscriptViewport {
748
804
  // Concurrency: a streaming chunk may replace or reflow the pointer's current live-tail
749
805
  // row before the next motion report. During the held gesture only, retain its distance
750
806
  // from the persistent tail; release restores identity-only projection.
751
- if (selection.selecting && anchor.liveFromBottom !== undefined && this.#liveTailStartRow !== undefined) {
807
+ if (selection.selecting && moving && anchor.liveFromBottom !== undefined && this.#liveTailStartRow !== undefined) {
752
808
  const documentRow = this.#selectableDocumentRowCount - anchor.liveFromBottom - 1;
753
809
  if (documentRow >= this.#liveTailStartRow && documentRow < this.#selectableDocumentRowCount) {
754
810
  const visible = this.#selectionRowAnchors.findIndex(candidate => candidate?.kind === "document" && candidate.row === documentRow);
@@ -760,10 +816,18 @@ export class TranscriptViewport {
760
816
  }
761
817
  }
762
818
  }
819
+ // Concurrency: streaming may restyle a held endpoint's row; it keeps its document index.
820
+ // Following the tail would drag the press row toward the newest output.
821
+ if (selection.selecting && anchor.row >= 0 && anchor.row < documentRows.length) {
822
+ return {
823
+ line: anchor.row - this.#scrollTop,
824
+ anchor: documentSelectionAnchor(anchor.row, documentRows[anchor.row] ?? "", anchor.liveFromBottom),
825
+ };
826
+ }
763
827
  return undefined;
764
828
  };
765
- const projectedAnchor = project(anchors.anchor);
766
- const projectedHead = project(anchors.head);
829
+ const projectedAnchor = project(anchors.anchor, false);
830
+ const projectedHead = project(anchors.head, true);
767
831
  if (projectedAnchor === undefined || projectedHead === undefined) {
768
832
  this.clearSelection();
769
833
  return;
@@ -783,11 +847,59 @@ export class TranscriptViewport {
783
847
  // Invariant: mixed viewport/dock ranges project across the same complete frame regardless
784
848
  // of origin. Document-only ranges remain clipped to the scrollable viewport when off-screen.
785
849
  const rows = crossesDock ? this.#selectionRows.length : this.#viewportHeight;
786
- return visibleTextSelection(orderedTextSelection(this.#selection), rows, this.#firstSelectableRow);
850
+ const ordered = orderedTextSelection(dockOrderedSelection(this.#selection, anchors, this.#viewportHeight));
851
+ return visibleTextSelection(ordered, rows, this.#firstSelectableRow);
787
852
  }
788
853
  #updateCopyableSelection() {
789
- this.#copyableSelection = this.selectedText() !== null;
854
+ // Performance: off-screen rows count as copyable by range alone; capture trims whitespace later.
855
+ const offscreen = offscreenSelectionRows(this.#selection, this.#selectionAnchors, this.#scrollTop, this.#firstSelectableRow, this.#viewportHeight, this.#documentRows.length);
856
+ const selectable = [offscreen.above, offscreen.below]
857
+ .some(range => range !== undefined && range.from < this.#selectableDocumentRowCount);
858
+ this.#copyableSelection = selectable && this.#visibleSelection() !== undefined || this.selectedText() !== null;
859
+ }
860
+ }
861
+ /**
862
+ * Invariant: dock rows follow the whole transcript, so a document endpoint scrolled below the
863
+ * viewport orders before every dock row instead of at its numeric frame line among them.
864
+ */
865
+ function dockOrderedSelection(selection, anchors, viewportHeight) {
866
+ if (selection === undefined || anchors === undefined || anchors.anchor.kind !== "dock" && anchors.head.kind !== "dock") {
867
+ return selection;
790
868
  }
869
+ const place = (point, kind) => kind === "document" && point.line >= viewportHeight ? { line: viewportHeight, column: 1, from: 0, to: 0 } : point;
870
+ return { ...selection, anchor: place(selection.anchor, anchors.anchor.kind), head: place(selection.head, anchors.head.kind) };
871
+ }
872
+ /** Document rows of a selection whose endpoints lie beyond the visible viewport edges. */
873
+ function offscreenSelectionRows(selection, anchors, scrollTop, firstSelectableRow, viewportHeight, documentRowCount) {
874
+ const ordered = orderedTextSelection(dockOrderedSelection(selection, anchors, viewportHeight));
875
+ if (selection === undefined || ordered === undefined || anchors === undefined)
876
+ return {};
877
+ const placed = dockOrderedSelection(selection, anchors, viewportHeight);
878
+ const anchorFirst = placed.anchor.line < placed.head.line
879
+ || placed.anchor.line === placed.head.line && placed.anchor.column <= placed.head.column;
880
+ const top = anchorFirst ? anchors.anchor : anchors.head;
881
+ const bottom = anchorFirst ? anchors.head : anchors.anchor;
882
+ const topPoint = anchorFirst ? selection.anchor : selection.head;
883
+ const bottomPoint = anchorFirst ? selection.head : selection.anchor;
884
+ const firstVisibleRow = scrollTop + firstSelectableRow;
885
+ const pastVisibleRow = scrollTop + viewportHeight;
886
+ const columns = {
887
+ startColumn: selection.fullRow ? 0 : topPoint.from ?? Math.max(0, topPoint.column - 1),
888
+ endColumn: selection.fullRow ? Number.MAX_SAFE_INTEGER : bottomPoint.to ?? bottomPoint.column,
889
+ };
890
+ if (top.kind === "document" && bottom.kind === "dock" && top.row >= pastVisibleRow) {
891
+ return { ...columns, below: { from: top.row, to: documentRowCount - 1 }, belowFirst: true };
892
+ }
893
+ return {
894
+ ...columns,
895
+ ...(top.kind === "document" && top.row < firstVisibleRow && ordered.start.line < firstSelectableRow
896
+ ? { above: { from: top.row, to: firstVisibleRow - 1 } }
897
+ : {}),
898
+ ...(top.kind === "document" && bottom.kind === "document" && bottom.row >= pastVisibleRow
899
+ && ordered.end.line >= viewportHeight
900
+ ? { below: { from: pastVisibleRow, to: bottom.row } }
901
+ : {}),
902
+ };
791
903
  }
792
904
  function visibleTextSelection(selection, rowCount, firstRow) {
793
905
  if (selection === undefined || rowCount <= firstRow || selection.end.line < firstRow || selection.start.line >= rowCount)
@@ -963,6 +1075,15 @@ function assertDocumentRange(range, label) {
963
1075
  function sameRectangle(left, right) {
964
1076
  return left === null ? right === null : right !== null && left.rowStart === right.rowStart && left.rowEnd === right.rowEnd;
965
1077
  }
1078
+ function copyableDockRowsBySuffix(dockRows, declarations) {
1079
+ const result = new Map();
1080
+ for (const declaration of declarations ?? []) {
1081
+ if (!Number.isSafeInteger(declaration.row) || declaration.row < 0 || declaration.row >= dockRows.length)
1082
+ continue;
1083
+ result.set(dockRows.length - declaration.row - 1, declaration.prompt === undefined ? {} : { prompt: declaration.prompt });
1084
+ }
1085
+ return result;
1086
+ }
966
1087
  function clamp(value, minimum, maximum) {
967
1088
  return Math.min(Math.max(value, minimum), maximum);
968
1089
  }