@north-light/crouter 0.3.170 → 0.3.172

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 (670) hide show
  1. package/dist/api/client.d.ts +37 -11
  2. package/dist/api/client.js +84 -15
  3. package/dist/api/dto/human.d.ts +53 -39
  4. package/dist/api/dto/human.js +2 -3
  5. package/dist/api/dto/inbox.d.ts +0 -1
  6. package/dist/api/dto/nodes.d.ts +12 -0
  7. package/dist/api/dto/review-comments.d.ts +137 -0
  8. package/dist/api/dto/review-comments.js +5 -0
  9. package/dist/api/dto/reviews.d.ts +109 -0
  10. package/dist/api/dto/reviews.js +5 -0
  11. package/dist/api/index.d.ts +2 -0
  12. package/dist/api/index.js +2 -0
  13. package/dist/api/routes.d.ts +17 -4
  14. package/dist/api/routes.js +21 -5
  15. package/dist/build-root.d.ts +1 -16
  16. package/dist/build-root.js +1 -25
  17. package/dist/builtin-memory/00-runtime-base.md +7 -5
  18. package/dist/builtin-memory/04-base-worker.md +1 -1
  19. package/dist/builtin-memory/04-orchestration-kernel.md +7 -7
  20. package/dist/builtin-memory/05-kinds/design/00-base.md +1 -1
  21. package/dist/builtin-memory/05-kinds/design/01-orchestrator.md +1 -1
  22. package/dist/builtin-memory/05-kinds/developer/00-base.md +1 -1
  23. package/dist/builtin-memory/05-kinds/explore/00-base.md +1 -1
  24. package/dist/builtin-memory/05-kinds/plan/00-base.md +1 -1
  25. package/dist/builtin-memory/05-kinds/plan/01-orchestrator.md +1 -1
  26. package/dist/builtin-memory/05-kinds/review/00-base.md +1 -1
  27. package/dist/builtin-memory/05-kinds/review/companion/00-base.md +20 -0
  28. package/dist/builtin-memory/05-kinds/spec/00-base.md +3 -7
  29. package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +3 -3
  30. package/dist/builtin-memory/05-kinds/spec/requirements.md +3 -3
  31. package/dist/builtin-memory/design.md +2 -2
  32. package/dist/builtin-memory/insights/capture.md +50 -0
  33. package/dist/builtin-memory/insights/init.md +45 -0
  34. package/dist/builtin-memory/insights/listen.md +9 -0
  35. package/dist/builtin-memory/internal/agent-shaping.md +2 -2
  36. package/dist/builtin-memory/internal/nodes-and-canvas.md +1 -1
  37. package/dist/builtin-memory/internal/plugins.md +12 -11
  38. package/dist/builtin-memory/internal/storage-tiers.md +2 -2
  39. package/dist/builtin-memory/{planning.md → plan/roadmap.md} +3 -3
  40. package/dist/builtin-memory/plan.md +19 -0
  41. package/dist/builtin-memory/spec/guide.md +38 -0
  42. package/dist/builtin-memory/spec/requirements.md +31 -0
  43. package/dist/builtin-memory/spec/roadmap.md +35 -0
  44. package/dist/builtin-memory/spec.md +10 -86
  45. package/dist/builtin-pi-packages/pi-crtr-extensions/README.md +3 -4
  46. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/provider-rotation.test.ts +49 -5
  47. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +56 -0
  48. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +920 -0
  49. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +221 -156
  50. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/statusline.ts +4 -5
  51. package/dist/cli.js +2 -6
  52. package/dist/clients/attach/__tests__/attach-chrome-remote.test.js +7 -35
  53. package/dist/clients/attach/__tests__/attach-keybindings.test.js +32 -16
  54. package/dist/clients/attach/__tests__/context-message.test.js +142 -6
  55. package/dist/clients/attach/__tests__/crtr-output.test.js +29 -45
  56. package/dist/clients/attach/__tests__/diagram.test.js +1 -1
  57. package/dist/clients/attach/__tests__/file-review-focus.test.js +48 -0
  58. package/dist/clients/attach/__tests__/group-activity.test.js +266 -0
  59. package/dist/clients/attach/__tests__/input-controller-extension-command.test.js +32 -0
  60. package/dist/clients/attach/__tests__/session-identity-refresh.test.js +32 -0
  61. package/dist/clients/attach/__tests__/titled-editor-preview.test.js +1 -2
  62. package/dist/clients/attach/chrome/header.d.ts +10 -0
  63. package/dist/clients/attach/chrome/header.js +30 -0
  64. package/dist/clients/attach/chrome/recap.d.ts +7 -0
  65. package/dist/clients/attach/chrome/recap.js +19 -0
  66. package/dist/clients/attach/chrome/status-line.d.ts +3 -0
  67. package/dist/clients/attach/chrome/status-line.js +5 -0
  68. package/dist/clients/attach/chrome/widgets.js +11 -21
  69. package/dist/clients/attach/command.js +11 -7
  70. package/dist/clients/attach/config.d.ts +4 -0
  71. package/dist/clients/attach/config.js +3 -0
  72. package/dist/clients/attach/input/controller.d.ts +19 -0
  73. package/dist/clients/attach/input/controller.js +62 -28
  74. package/dist/clients/attach/input/titled-editor.d.ts +0 -4
  75. package/dist/clients/attach/input/titled-editor.js +2 -10
  76. package/dist/clients/attach/overlays/file-review.d.ts +9 -5
  77. package/dist/clients/attach/overlays/file-review.js +9 -70
  78. package/dist/clients/attach/overlays/help.d.ts +33 -0
  79. package/dist/clients/attach/overlays/help.js +204 -0
  80. package/dist/clients/attach/render/activity-slot.d.ts +4 -0
  81. package/dist/clients/attach/render/activity-slot.js +13 -0
  82. package/dist/clients/attach/render/chat-view.d.ts +117 -12
  83. package/dist/clients/attach/render/chat-view.js +604 -135
  84. package/dist/clients/attach/render/context-message.d.ts +2 -1
  85. package/dist/clients/attach/render/context-message.js +17 -13
  86. package/dist/clients/attach/render/crtr-output.js +1 -3
  87. package/dist/clients/attach/render/diagram.js +2 -2
  88. package/dist/clients/attach/render/edit-diff.d.ts +4 -1
  89. package/dist/clients/attach/render/edit-diff.js +7 -11
  90. package/dist/clients/attach/render/group-activity.d.ts +32 -0
  91. package/dist/clients/attach/render/group-activity.js +206 -0
  92. package/dist/clients/attach/render/group-recap.d.ts +10 -0
  93. package/dist/clients/attach/render/group-recap.js +93 -0
  94. package/dist/clients/attach/render/html-markdown.d.ts +17 -0
  95. package/dist/clients/attach/render/html-markdown.js +228 -0
  96. package/dist/clients/attach/render/measured-container.d.ts +96 -0
  97. package/dist/clients/attach/render/measured-container.js +322 -0
  98. package/dist/clients/attach/render/scroll-animation.d.ts +8 -0
  99. package/dist/clients/attach/render/scroll-animation.js +80 -0
  100. package/dist/clients/attach/render/tool-calls.js +6 -6
  101. package/dist/clients/attach/render/transcript-copy.d.ts +9 -0
  102. package/dist/clients/attach/render/transcript-copy.js +81 -0
  103. package/dist/clients/attach/render/viewport.d.ts +29 -0
  104. package/dist/clients/attach/render/viewport.js +159 -0
  105. package/dist/clients/attach/session/bindings.d.ts +10 -7
  106. package/dist/clients/attach/session/bindings.js +23 -8
  107. package/dist/clients/attach/session/connection.js +4 -5
  108. package/dist/clients/attach/session/context.d.ts +6 -4
  109. package/dist/clients/attach/session/frame.d.ts +34 -0
  110. package/dist/clients/attach/session/frame.js +176 -0
  111. package/dist/clients/attach/session/frames.d.ts +4 -1
  112. package/dist/clients/attach/session/frames.js +14 -1
  113. package/dist/clients/attach/session/identity.js +4 -3
  114. package/dist/clients/attach/session/input-wiring.d.ts +14 -4
  115. package/dist/clients/attach/session/input-wiring.js +15 -13
  116. package/dist/clients/attach/session/invariant.d.ts +9 -0
  117. package/dist/clients/attach/session/invariant.js +15 -0
  118. package/dist/clients/attach/session/keys.d.ts +10 -2
  119. package/dist/clients/attach/session/keys.js +13 -5
  120. package/dist/clients/attach/session/layout.d.ts +10 -8
  121. package/dist/clients/attach/session/layout.js +33 -34
  122. package/dist/clients/attach/session/mouse.d.ts +18 -0
  123. package/dist/clients/attach/session/mouse.js +64 -0
  124. package/dist/clients/attach/session/pane-tag.d.ts +3 -0
  125. package/dist/clients/attach/session/pane-tag.js +51 -8
  126. package/dist/clients/attach/session/reconnect.d.ts +3 -0
  127. package/dist/clients/attach/session/reconnect.js +42 -5
  128. package/dist/clients/attach/session/surface-frame.d.ts +20 -0
  129. package/dist/clients/attach/session/surface-frame.js +73 -0
  130. package/dist/clients/attach/session/surface-host.d.ts +64 -0
  131. package/dist/clients/attach/session/surface-host.js +255 -0
  132. package/dist/clients/attach/session/whip.d.ts +17 -0
  133. package/dist/clients/attach/session/whip.js +334 -0
  134. package/dist/clients/attach/slash/dispatch.d.ts +13 -1
  135. package/dist/clients/attach/slash/dispatch.js +51 -29
  136. package/dist/clients/attach/viewer.js +907 -819
  137. package/dist/clients/conversation/conversation.d.ts +65 -0
  138. package/dist/clients/conversation/conversation.js +318 -0
  139. package/dist/clients/conversation/frames.d.ts +30 -0
  140. package/dist/clients/conversation/frames.js +52 -0
  141. package/dist/clients/conversation/region.d.ts +51 -0
  142. package/dist/clients/conversation/region.js +265 -0
  143. package/dist/clients/conversation/submit.d.ts +38 -0
  144. package/dist/clients/conversation/submit.js +51 -0
  145. package/dist/clients/inbox/__tests__/inbox-controller.test.js +247 -0
  146. package/dist/clients/inbox/__tests__/mount-panel.test.js +776 -0
  147. package/dist/clients/inbox/controller.d.ts +79 -0
  148. package/dist/clients/inbox/controller.js +448 -0
  149. package/dist/clients/inbox/deck-adapter.d.ts +29 -0
  150. package/dist/clients/inbox/deck-adapter.js +62 -0
  151. package/dist/clients/inbox/layout.d.ts +8 -0
  152. package/dist/clients/inbox/layout.js +9 -0
  153. package/dist/clients/inbox/resolve.d.ts +10 -0
  154. package/dist/clients/inbox/resolve.js +34 -0
  155. package/dist/clients/inbox/review/__tests__/editor-roundtrip.test.js +29 -0
  156. package/dist/clients/inbox/review/__tests__/remap.test.js +196 -0
  157. package/dist/clients/inbox/review/__tests__/review-core.test.js +341 -0
  158. package/dist/clients/inbox/review/anchors.d.ts +41 -0
  159. package/dist/clients/inbox/review/anchors.js +89 -0
  160. package/dist/clients/inbox/review/columns.d.ts +22 -0
  161. package/dist/clients/inbox/review/columns.js +40 -0
  162. package/dist/clients/inbox/review/comments-client.d.ts +66 -0
  163. package/dist/clients/inbox/review/comments-client.js +98 -0
  164. package/dist/clients/inbox/review/composition.d.ts +60 -0
  165. package/dist/clients/inbox/review/composition.js +278 -0
  166. package/dist/clients/inbox/review/document-region.d.ts +120 -0
  167. package/dist/clients/inbox/review/document-region.js +902 -0
  168. package/dist/clients/inbox/review/frame.d.ts +45 -0
  169. package/dist/clients/inbox/review/frame.js +215 -0
  170. package/dist/clients/inbox/review/keys.d.ts +67 -0
  171. package/dist/clients/inbox/review/keys.js +130 -0
  172. package/dist/clients/inbox/review/launch.d.ts +10 -0
  173. package/dist/clients/inbox/review/launch.js +129 -0
  174. package/dist/clients/inbox/review/live-source.d.ts +24 -0
  175. package/dist/clients/inbox/review/live-source.js +160 -0
  176. package/dist/clients/inbox/review/nvim.d.ts +13 -0
  177. package/dist/clients/inbox/review/nvim.js +42 -0
  178. package/dist/clients/inbox/review/remap.d.ts +51 -0
  179. package/dist/clients/inbox/review/remap.js +157 -0
  180. package/dist/clients/inbox/review/review-client.d.ts +30 -0
  181. package/dist/clients/inbox/review/review-client.js +107 -0
  182. package/dist/clients/inbox/review/roundtrip.d.ts +5 -0
  183. package/dist/clients/inbox/review/roundtrip.js +36 -0
  184. package/dist/clients/inbox/review/state.d.ts +143 -0
  185. package/dist/clients/inbox/review/state.js +282 -0
  186. package/dist/clients/inbox/review-adapter.d.ts +29 -0
  187. package/dist/clients/inbox/review-adapter.js +92 -0
  188. package/dist/clients/inbox/review-visibility.d.ts +5 -0
  189. package/dist/clients/inbox/review-visibility.js +19 -0
  190. package/dist/clients/inbox/surface.d.ts +19 -0
  191. package/dist/clients/inbox/surface.js +128 -0
  192. package/dist/clients/inbox/tui/ansi.d.ts +66 -0
  193. package/dist/clients/inbox/tui/ansi.js +317 -0
  194. package/dist/clients/inbox/tui/clipboard.d.ts +2 -0
  195. package/dist/clients/inbox/tui/clipboard.js +26 -0
  196. package/dist/clients/inbox/tui/input.d.ts +7 -0
  197. package/dist/clients/inbox/tui/input.js +653 -0
  198. package/dist/clients/inbox/tui/keys.d.ts +28 -0
  199. package/dist/clients/inbox/tui/keys.js +111 -0
  200. package/dist/clients/inbox/tui/panel.d.ts +2 -0
  201. package/dist/clients/inbox/tui/panel.js +217 -0
  202. package/dist/clients/inbox/tui/render.d.ts +37 -0
  203. package/dist/clients/inbox/tui/render.js +476 -0
  204. package/dist/clients/inbox/tui/types.d.ts +57 -0
  205. package/dist/clients/inbox/tui/types.js +1 -0
  206. package/dist/clients/inbox/tui.d.ts +6 -0
  207. package/dist/clients/inbox/tui.js +74 -0
  208. package/dist/clients/surfaces/host.d.ts +66 -0
  209. package/dist/clients/surfaces/host.js +1 -0
  210. package/dist/clients/surfaces/region.d.ts +16 -0
  211. package/dist/clients/surfaces/region.js +1 -0
  212. package/dist/clients/web/__tests__/push-engine.test.js +14 -158
  213. package/dist/clients/web/dev-server.d.ts +3 -3
  214. package/dist/clients/web/dev-server.js +9 -23
  215. package/dist/clients/web/events.js +4 -6
  216. package/dist/clients/web/push-engine.d.ts +2 -66
  217. package/dist/clients/web/push-engine.js +30 -161
  218. package/dist/clients/web/push-registry.d.ts +0 -4
  219. package/dist/clients/web/push-registry.js +2 -7
  220. package/dist/clients/web/server.js +3 -35
  221. package/dist/clients/web/web-client/shared/protocol.d.ts +0 -108
  222. package/dist/clients/web/web-cmd.js +2 -2
  223. package/dist/commands/__tests__/human.test.js +27 -15
  224. package/dist/commands/api-client.js +3 -3
  225. package/dist/commands/canvas-browse.js +1 -1
  226. package/dist/commands/canvas-issue.js +1 -1
  227. package/dist/commands/canvas-use.js +1 -1
  228. package/dist/commands/human/doc.d.ts +2 -0
  229. package/dist/commands/human/doc.js +98 -0
  230. package/dist/commands/human/inbox.d.ts +2 -0
  231. package/dist/commands/human/inbox.js +101 -0
  232. package/dist/commands/human/prompts.d.ts +2 -3
  233. package/dist/commands/human/prompts.js +27 -180
  234. package/dist/commands/human/queue.d.ts +1 -5
  235. package/dist/commands/human/queue.js +54 -216
  236. package/dist/commands/human/review.d.ts +2 -0
  237. package/dist/commands/human/review.js +298 -0
  238. package/dist/commands/human/shared.d.ts +2 -69
  239. package/dist/commands/human/shared.js +1 -181
  240. package/dist/commands/human.js +15 -20
  241. package/dist/commands/memory/__tests__/lint.test.d.ts +1 -0
  242. package/dist/commands/memory/__tests__/lint.test.js +15 -0
  243. package/dist/commands/memory/delete.js +2 -2
  244. package/dist/commands/memory/lint.d.ts +1 -0
  245. package/dist/commands/memory/lint.js +21 -3
  246. package/dist/commands/memory/read.js +4 -4
  247. package/dist/commands/node.js +8 -7
  248. package/dist/commands/pkg/plugin-manage.js +143 -68
  249. package/dist/commands/surface-inspect.js +2 -2
  250. package/dist/commands/surface.js +6 -12
  251. package/dist/commands/sys/__tests__/setup-core.test.js +9 -5
  252. package/dist/commands/sys/__tests__/setup-front-door.test.js +7 -42
  253. package/dist/commands/sys/config.js +29 -3
  254. package/dist/commands/sys/feedback.js +1 -1
  255. package/dist/commands/sys/setup-core.d.ts +12 -11
  256. package/dist/commands/sys/setup-core.js +55 -46
  257. package/dist/commands/sys/setup-wizard.d.ts +4 -1
  258. package/dist/commands/sys/setup-wizard.js +50 -9
  259. package/dist/commands/sys/sync-deps.js +1 -1
  260. package/dist/commands/sys.js +4 -6
  261. package/dist/core/__tests__/broker-sdk-wiring.test.js +6 -1
  262. package/dist/core/__tests__/broker-snapshot-history.test.js +9 -1
  263. package/dist/core/__tests__/dead-node-policy-table.test.js +3 -4
  264. package/dist/core/__tests__/fixtures/fake-engine.d.ts +8 -5
  265. package/dist/core/__tests__/fixtures/fake-engine.js +28 -2
  266. package/dist/core/__tests__/full/broker-provider-retry.test.js +87 -2
  267. package/dist/core/__tests__/full/broker-whip-interrupt.test.d.ts +1 -0
  268. package/dist/core/__tests__/full/broker-whip-interrupt.test.js +39 -0
  269. package/dist/core/__tests__/full/detach-focus.test.js +1 -1
  270. package/dist/core/__tests__/human-deliver-e2e.test.js +64 -64
  271. package/dist/core/__tests__/human-deliver.test.js +71 -345
  272. package/dist/core/__tests__/inline-memory-refs.test.js +2 -12
  273. package/dist/core/__tests__/memory-resolver-precedence.test.js +12 -15
  274. package/dist/core/__tests__/migration.test.js +10 -0
  275. package/dist/core/__tests__/model-pin-durability.test.js +14 -0
  276. package/dist/core/__tests__/phase4-review-migration.test.d.ts +1 -0
  277. package/dist/core/__tests__/phase4-review-migration.test.js +100 -0
  278. package/dist/core/__tests__/phase4-review-store.test.d.ts +1 -0
  279. package/dist/core/__tests__/phase4-review-store.test.js +143 -0
  280. package/dist/core/__tests__/remote-canvas-target.test.js +2 -2
  281. package/dist/core/__tests__/revive.test.js +22 -53
  282. package/dist/core/__tests__/session-cycles.test.js +48 -18
  283. package/dist/core/__tests__/spawn-no-kickoff.test.js +8 -12
  284. package/dist/core/__tests__/stop-guard.test.js +16 -1
  285. package/dist/core/__tests__/tmux-surface.test.js +21 -25
  286. package/dist/core/asset-root.d.ts +7 -0
  287. package/dist/core/asset-root.js +18 -0
  288. package/dist/core/broker-client/client.d.ts +0 -7
  289. package/dist/core/broker-client/client.js +4 -10
  290. package/dist/core/broker-client/transport-relay.d.ts +3 -4
  291. package/dist/core/broker-client/transport-relay.js +3 -4
  292. package/dist/core/canvas/__tests__/attention.test.js +1 -1
  293. package/dist/core/canvas/__tests__/remote-canvas-source.test.js +1 -1
  294. package/dist/core/canvas/__tests__/remote-transport.test.d.ts +1 -0
  295. package/dist/core/{view/__tests__/transport-remote.test.js → canvas/__tests__/remote-transport.test.js} +2 -2
  296. package/dist/core/canvas/__tests__/render-remote.test.js +1 -1
  297. package/dist/core/canvas/attention.js +4 -4
  298. package/dist/core/canvas/canvas.d.ts +6 -11
  299. package/dist/core/canvas/canvas.js +11 -33
  300. package/dist/core/canvas/db.js +207 -38
  301. package/dist/core/canvas/extensions.d.ts +1 -1
  302. package/dist/core/canvas/extensions.js +8 -1
  303. package/dist/core/canvas/index.d.ts +0 -1
  304. package/dist/core/canvas/index.js +0 -1
  305. package/dist/core/canvas/nav-model.d.ts +1 -1
  306. package/dist/core/canvas/nav-model.js +1 -1
  307. package/dist/core/canvas/paths.d.ts +5 -0
  308. package/dist/core/canvas/paths.js +16 -0
  309. package/dist/core/canvas/remote-canvas-source.js +2 -2
  310. package/dist/core/canvas/remote-transport.d.ts +7 -0
  311. package/dist/core/{view/transport-remote.js → canvas/remote-transport.js} +3 -4
  312. package/dist/core/canvas/source.js +1 -1
  313. package/dist/core/canvas/status-glyph.js +4 -12
  314. package/dist/core/canvas/types.d.ts +10 -35
  315. package/dist/core/clipboard-text.d.ts +8 -0
  316. package/dist/core/clipboard-text.js +18 -0
  317. package/dist/core/command-manifests/registry.d.ts +1 -3
  318. package/dist/core/command-plugins/bundle.d.ts +29 -0
  319. package/dist/core/command-plugins/bundle.js +198 -0
  320. package/dist/core/command-plugins/discovery.d.ts +0 -8
  321. package/dist/core/command-plugins/discovery.js +2 -39
  322. package/dist/core/command-plugins/transport/http-fetch.d.ts +4 -30
  323. package/dist/core/command-plugins/transport/http-fetch.js +17 -95
  324. package/dist/core/command.d.ts +1 -13
  325. package/dist/core/command.js +1 -16
  326. package/dist/core/config.d.ts +4 -0
  327. package/dist/core/config.js +28 -3
  328. package/dist/core/document-lines.d.ts +4 -0
  329. package/dist/core/document-lines.js +6 -0
  330. package/dist/core/feed/feed.d.ts +2 -0
  331. package/dist/core/feed/feed.js +11 -7
  332. package/dist/core/human/__tests__/inbox-cancel-worker.d.ts +1 -0
  333. package/dist/core/human/__tests__/inbox-cancel-worker.js +7 -0
  334. package/dist/core/human/__tests__/inbox-claim-worker.d.ts +1 -0
  335. package/dist/core/human/__tests__/inbox-claim-worker.js +17 -0
  336. package/dist/core/human/__tests__/inbox-core.test.d.ts +1 -0
  337. package/dist/core/human/__tests__/inbox-core.test.js +144 -0
  338. package/dist/core/human/__tests__/inbox-stale-claim-worker.d.ts +1 -0
  339. package/dist/core/human/__tests__/inbox-stale-claim-worker.js +8 -0
  340. package/dist/core/human/__tests__/visible-paths.test.d.ts +1 -0
  341. package/dist/{clients/attach → core/human}/__tests__/visible-paths.test.js +9 -0
  342. package/dist/core/human/claim.d.ts +23 -0
  343. package/dist/core/human/claim.js +67 -0
  344. package/dist/core/human/convention.d.ts +30 -0
  345. package/dist/core/human/convention.js +202 -0
  346. package/dist/core/human/deck-factories.d.ts +8 -0
  347. package/dist/core/human/deck-factories.js +15 -0
  348. package/dist/core/human/deck-schema.d.ts +70 -0
  349. package/dist/core/human/deck-schema.js +92 -0
  350. package/dist/core/human/root.d.ts +7 -0
  351. package/dist/core/human/root.js +37 -0
  352. package/dist/core/human/scan.d.ts +3 -0
  353. package/dist/core/human/scan.js +76 -0
  354. package/dist/core/human/summary.d.ts +8 -0
  355. package/dist/core/human/summary.js +44 -0
  356. package/dist/core/human/tickets.d.ts +49 -0
  357. package/dist/core/human/tickets.js +190 -0
  358. package/dist/core/human/types.d.ts +136 -0
  359. package/dist/core/human/types.js +5 -0
  360. package/dist/{clients/attach → core/human}/visible-paths.d.ts +1 -1
  361. package/dist/{clients/attach → core/human}/visible-paths.js +3 -2
  362. package/dist/core/inspector/chrome.d.ts +6 -0
  363. package/dist/core/inspector/chrome.js +14 -0
  364. package/dist/core/inspector/contract.d.ts +105 -0
  365. package/dist/core/inspector/contract.js +1 -0
  366. package/dist/core/inspector/core.d.ts +4 -5
  367. package/dist/core/inspector/core.js +3 -5
  368. package/dist/core/inspector/host.d.ts +46 -0
  369. package/dist/core/{tui → inspector}/host.js +42 -208
  370. package/dist/core/inspector/text.d.ts +2 -2
  371. package/dist/core/inspector/transport.d.ts +6 -0
  372. package/dist/core/inspector/transport.js +36 -0
  373. package/dist/core/inspector/tui.d.ts +2 -2
  374. package/dist/core/inspector/tui.js +15 -15
  375. package/dist/core/keybindings/__tests__/inbox-affordance.test.js +11 -11
  376. package/dist/core/keybindings/__tests__/resolve.test.js +10 -19
  377. package/dist/core/keybindings/attach-control.d.ts +9 -3
  378. package/dist/core/keybindings/attach-control.js +3 -1
  379. package/dist/core/keybindings/catalog.d.ts +6 -5
  380. package/dist/core/keybindings/catalog.js +61 -133
  381. package/dist/core/keybindings/inbox.d.ts +5 -6
  382. package/dist/core/keybindings/inbox.js +9 -10
  383. package/dist/core/keybindings/index.d.ts +3 -3
  384. package/dist/core/keybindings/index.js +3 -3
  385. package/dist/core/keybindings/persistence.d.ts +5 -1
  386. package/dist/core/keybindings/persistence.js +24 -6
  387. package/dist/core/keybindings/resolve.d.ts +6 -0
  388. package/dist/core/keybindings/resolve.js +10 -3
  389. package/dist/core/memory/inline-ref-grammar.js +2 -3
  390. package/dist/core/memory-resolver.d.ts +27 -29
  391. package/dist/core/memory-resolver.js +45 -39
  392. package/dist/core/model-routes.d.ts +33 -0
  393. package/dist/core/model-routes.js +42 -3
  394. package/dist/core/preview-registry.js +17 -55
  395. package/dist/core/profiles/select.js +3 -3
  396. package/dist/core/{view/remote-canvas-target.d.ts → remote-canvas-target.d.ts} +2 -2
  397. package/dist/core/{view/remote-canvas-target.js → remote-canvas-target.js} +4 -4
  398. package/dist/core/review/__tests__/capture-origin.test.d.ts +1 -0
  399. package/dist/core/review/__tests__/capture-origin.test.js +139 -0
  400. package/dist/core/review/__tests__/comments.test.d.ts +1 -0
  401. package/dist/core/review/__tests__/comments.test.js +98 -0
  402. package/dist/core/review/__tests__/project.test.d.ts +1 -0
  403. package/dist/core/review/__tests__/project.test.js +71 -0
  404. package/dist/core/review/__tests__/remap.test.d.ts +1 -0
  405. package/dist/core/review/__tests__/remap.test.js +159 -0
  406. package/dist/core/review/__tests__/stage-identity.test.d.ts +1 -0
  407. package/dist/core/review/__tests__/stage-identity.test.js +140 -0
  408. package/dist/core/review/birth.d.ts +7 -0
  409. package/dist/core/review/birth.js +23 -0
  410. package/dist/core/review/comments.d.ts +69 -0
  411. package/dist/core/review/comments.js +295 -0
  412. package/dist/core/review/companion.d.ts +35 -0
  413. package/dist/core/review/companion.js +205 -0
  414. package/dist/core/review/document.d.ts +27 -0
  415. package/dist/core/review/document.js +138 -0
  416. package/dist/core/review/project.d.ts +13 -0
  417. package/dist/core/review/project.js +58 -0
  418. package/dist/core/review/realize.d.ts +19 -0
  419. package/dist/core/review/realize.js +217 -0
  420. package/dist/core/review/remap.d.ts +24 -0
  421. package/dist/core/review/remap.js +156 -0
  422. package/dist/core/review/signal.d.ts +5 -0
  423. package/dist/core/review/signal.js +31 -0
  424. package/dist/core/review/stage.d.ts +26 -0
  425. package/dist/core/review/stage.js +184 -0
  426. package/dist/core/review/store.d.ts +46 -0
  427. package/dist/core/review/store.js +163 -0
  428. package/dist/core/review/ticket-filter.d.ts +17 -0
  429. package/dist/core/review/ticket-filter.js +32 -0
  430. package/dist/core/review/types.d.ts +130 -0
  431. package/dist/core/review/types.js +23 -0
  432. package/dist/core/runtime/__tests__/session-visibility.test.d.ts +1 -0
  433. package/dist/core/runtime/__tests__/session-visibility.test.js +119 -0
  434. package/dist/core/runtime/bearings.d.ts +5 -17
  435. package/dist/core/runtime/bearings.js +88 -71
  436. package/dist/core/runtime/broker-protocol.d.ts +31 -8
  437. package/dist/core/runtime/broker.d.ts +15 -1
  438. package/dist/core/runtime/broker.js +573 -141
  439. package/dist/core/runtime/canvas-extensions.d.ts +4 -5
  440. package/dist/core/runtime/canvas-extensions.js +5 -5
  441. package/dist/core/runtime/front-door.js +4 -4
  442. package/dist/core/runtime/headless-pi.d.ts +24 -0
  443. package/dist/core/runtime/headless-pi.js +152 -0
  444. package/dist/core/runtime/kickoff.d.ts +1 -5
  445. package/dist/core/runtime/kickoff.js +1 -5
  446. package/dist/core/runtime/model-registry.d.ts +3 -0
  447. package/dist/core/runtime/model-registry.js +13 -0
  448. package/dist/core/runtime/naming-persist.d.ts +4 -0
  449. package/dist/core/runtime/naming-persist.js +27 -1
  450. package/dist/core/runtime/naming.d.ts +17 -12
  451. package/dist/core/runtime/naming.js +91 -140
  452. package/dist/core/runtime/node-read.js +19 -10
  453. package/dist/core/runtime/nodes.d.ts +9 -14
  454. package/dist/core/runtime/nodes.js +3 -53
  455. package/dist/core/runtime/package-health.d.ts +6 -21
  456. package/dist/core/runtime/package-health.js +12 -123
  457. package/dist/core/runtime/placement-tmux.d.ts +2 -1
  458. package/dist/core/runtime/placement-tmux.js +6 -4
  459. package/dist/core/runtime/placement.d.ts +1 -0
  460. package/dist/core/runtime/placement.js +4 -8
  461. package/dist/core/runtime/promote.js +3 -0
  462. package/dist/core/runtime/recap.d.ts +2 -7
  463. package/dist/core/runtime/recap.js +35 -69
  464. package/dist/core/runtime/revive.js +34 -77
  465. package/dist/core/runtime/session-cycles.d.ts +4 -0
  466. package/dist/core/runtime/session-cycles.js +14 -1
  467. package/dist/core/runtime/session-visibility.d.ts +37 -0
  468. package/dist/core/runtime/session-visibility.js +83 -0
  469. package/dist/core/runtime/spawn.js +10 -22
  470. package/dist/core/runtime/stop-guard.d.ts +1 -1
  471. package/dist/core/runtime/stop-guard.js +18 -13
  472. package/dist/core/runtime/surface-bg.js +1 -1
  473. package/dist/core/runtime/tmux-chrome.d.ts +1 -1
  474. package/dist/core/runtime/tmux-chrome.js +1 -1
  475. package/dist/core/runtime/tmux.d.ts +35 -7
  476. package/dist/core/runtime/tmux.js +439 -62
  477. package/dist/core/runtime/tool-group-summary.d.ts +19 -0
  478. package/dist/core/runtime/tool-group-summary.js +88 -0
  479. package/dist/core/scope.d.ts +2 -7
  480. package/dist/core/scope.js +9 -35
  481. package/dist/core/substrate/schema.d.ts +2 -2
  482. package/dist/core/termrender/code-doc.d.ts +12 -0
  483. package/dist/core/termrender/code-doc.js +92 -0
  484. package/dist/core/termrender/display.d.ts +12 -0
  485. package/dist/core/termrender/display.js +19 -0
  486. package/dist/core/termrender/termrender.d.ts +73 -0
  487. package/dist/core/termrender/termrender.js +795 -0
  488. package/dist/core/termrender/version.d.ts +1 -0
  489. package/dist/core/termrender/version.js +1 -0
  490. package/dist/core/tui/terminal.js +1 -2
  491. package/dist/core/user-settings.d.ts +71 -3
  492. package/dist/core/user-settings.js +83 -1
  493. package/dist/daemon/api/__tests__/inbox.test.js +44 -133
  494. package/dist/daemon/api/handlers/human.d.ts +0 -10
  495. package/dist/daemon/api/handlers/human.js +104 -702
  496. package/dist/daemon/api/handlers/inbox.js +113 -142
  497. package/dist/daemon/api/handlers/review-comments.d.ts +2 -0
  498. package/dist/daemon/api/handlers/review-comments.js +500 -0
  499. package/dist/daemon/api/handlers/reviews.d.ts +2 -0
  500. package/dist/daemon/api/handlers/reviews.js +287 -0
  501. package/dist/daemon/api/map.d.ts +22 -7
  502. package/dist/daemon/api/map.js +159 -11
  503. package/dist/daemon/api/server.js +4 -0
  504. package/dist/daemon/cron-run.js +6 -9
  505. package/dist/daemon/crtrd.js +17 -33
  506. package/dist/daemon/fleet.d.ts +1 -8
  507. package/dist/daemon/fleet.js +4 -30
  508. package/dist/daemon/human/finish.d.ts +14 -0
  509. package/dist/daemon/human/finish.js +115 -0
  510. package/dist/daemon/human/sweep.d.ts +6 -0
  511. package/dist/daemon/human/sweep.js +49 -0
  512. package/dist/daemon/messaging/node-message.d.ts +18 -0
  513. package/dist/daemon/messaging/node-message.js +70 -0
  514. package/dist/daemon/review/comment-notify.d.ts +26 -0
  515. package/dist/daemon/review/comment-notify.js +107 -0
  516. package/dist/daemon/review/deliver.d.ts +7 -0
  517. package/dist/daemon/review/deliver.js +56 -0
  518. package/dist/daemon/review/finish.d.ts +22 -0
  519. package/dist/daemon/review/finish.js +254 -0
  520. package/dist/daemon/review/sweep.d.ts +11 -0
  521. package/dist/daemon/review/sweep.js +120 -0
  522. package/dist/index.d.ts +2 -0
  523. package/dist/index.js +2 -2
  524. package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +42 -64
  525. package/dist/pi-extensions/__tests__/canvas-recap.test.d.ts +1 -0
  526. package/dist/pi-extensions/__tests__/canvas-recap.test.js +159 -0
  527. package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +16 -38
  528. package/dist/pi-extensions/__tests__/canvas-structured-output.test.d.ts +1 -0
  529. package/dist/pi-extensions/__tests__/canvas-structured-output.test.js +63 -0
  530. package/dist/pi-extensions/canvas-context-intro.d.ts +8 -11
  531. package/dist/pi-extensions/canvas-context-intro.js +50 -104
  532. package/dist/pi-extensions/canvas-recap.d.ts +15 -2
  533. package/dist/pi-extensions/canvas-recap.js +192 -69
  534. package/dist/pi-extensions/canvas-review-boundary.d.ts +59 -0
  535. package/dist/pi-extensions/canvas-review-boundary.js +81 -0
  536. package/dist/pi-extensions/canvas-stophook.d.ts +3 -3
  537. package/dist/pi-extensions/canvas-stophook.js +78 -128
  538. package/dist/pi-extensions/canvas-structured-output.js +52 -8
  539. package/dist/shared/generated-context.d.ts +29 -4
  540. package/dist/shared/generated-context.js +122 -7
  541. package/dist/shared/tool-groups.d.ts +23 -0
  542. package/dist/shared/tool-groups.js +60 -0
  543. package/dist/shared/working-activity.d.ts +8 -0
  544. package/dist/shared/working-activity.js +26 -0
  545. package/dist/types.d.ts +36 -2
  546. package/dist/types.js +51 -0
  547. package/dist/web-client/assets/index-CCPaLeW7.css +2 -0
  548. package/dist/web-client/assets/index-kyOWsnZK.js +86 -0
  549. package/dist/web-client/index.html +2 -2
  550. package/dist/web-client/sw.js +1 -1
  551. package/docs/compat/hearth-crtr-v4.md +2 -2
  552. package/docs/compat/hearth-crtr-v5.md +4 -2
  553. package/docs/public-api.md +3 -3
  554. package/package.json +21 -14
  555. package/runtime.lock.json +4661 -1453
  556. package/scripts/postinstall.mjs +15 -2
  557. package/dist/builtin-pi-packages/pi-mode-switch/README.md +0 -36
  558. package/dist/builtin-pi-packages/pi-mode-switch/bin/mode +0 -36
  559. package/dist/builtin-pi-packages/pi-mode-switch/extensions/index.ts +0 -449
  560. package/dist/builtin-pi-packages/pi-mode-switch/package.json +0 -14
  561. package/dist/builtin-pi-packages/pi-mode-switch/tsconfig.json +0 -9
  562. package/dist/builtin-views/_lib/states.mjs +0 -161
  563. package/dist/builtin-views/canvas/core.mjs +0 -657
  564. package/dist/builtin-views/canvas/text.mjs +0 -58
  565. package/dist/builtin-views/canvas/tui.mjs +0 -168
  566. package/dist/builtin-views/canvas/web.jsx +0 -121
  567. package/dist/builtin-views/chat/core.mjs +0 -684
  568. package/dist/builtin-views/chat/text.mjs +0 -101
  569. package/dist/builtin-views/chat/tui.mjs +0 -360
  570. package/dist/builtin-views/chat/web.jsx +0 -362
  571. package/dist/builtin-views/git-pr/core.mjs +0 -673
  572. package/dist/builtin-views/git-pr/text.mjs +0 -84
  573. package/dist/builtin-views/git-pr/tui.mjs +0 -301
  574. package/dist/builtin-views/git-pr/web.jsx +0 -216
  575. package/dist/builtin-views/inbox/_lib/render.mjs +0 -175
  576. package/dist/builtin-views/inbox/core.mjs +0 -1273
  577. package/dist/builtin-views/inbox/text.mjs +0 -73
  578. package/dist/builtin-views/inbox/tui.mjs +0 -314
  579. package/dist/builtin-views/inbox/web.jsx +0 -188
  580. package/dist/builtin-views/linkedin/core.mjs +0 -906
  581. package/dist/builtin-views/linkedin/text.mjs +0 -69
  582. package/dist/builtin-views/linkedin/tui.mjs +0 -413
  583. package/dist/builtin-views/linkedin/web.jsx +0 -206
  584. package/dist/builtin-views/prompt-review/core.mjs +0 -735
  585. package/dist/builtin-views/prompt-review/text.mjs +0 -15
  586. package/dist/builtin-views/prompt-review/tui.mjs +0 -196
  587. package/dist/builtin-views/prompt-review/web.jsx +0 -484
  588. package/dist/builtin-views/workspace-sidebar/__tests__/core.test.js +0 -50
  589. package/dist/builtin-views/workspace-sidebar/__tests__/core.test.ts +0 -53
  590. package/dist/builtin-views/workspace-sidebar/core.mjs +0 -670
  591. package/dist/builtin-views/workspace-sidebar/text.mjs +0 -53
  592. package/dist/builtin-views/workspace-sidebar/tui.mjs +0 -141
  593. package/dist/builtin-views/workspace-sidebar/web.jsx +0 -109
  594. package/dist/clients/attach/session/mode.d.ts +0 -25
  595. package/dist/clients/attach/session/mode.js +0 -97
  596. package/dist/commands/sys/promptstudio.d.ts +0 -2
  597. package/dist/commands/sys/promptstudio.js +0 -65
  598. package/dist/commands/view-cycle.d.ts +0 -2
  599. package/dist/commands/view-cycle.js +0 -130
  600. package/dist/commands/view-list.d.ts +0 -2
  601. package/dist/commands/view-list.js +0 -66
  602. package/dist/commands/view-new.d.ts +0 -2
  603. package/dist/commands/view-new.js +0 -74
  604. package/dist/commands/view-pick.d.ts +0 -6
  605. package/dist/commands/view-pick.js +0 -129
  606. package/dist/commands/view-run.d.ts +0 -2
  607. package/dist/commands/view-run.js +0 -214
  608. package/dist/commands/view.d.ts +0 -2
  609. package/dist/commands/view.js +0 -31
  610. package/dist/commands/workspace.d.ts +0 -2
  611. package/dist/commands/workspace.js +0 -165
  612. package/dist/core/__tests__/chat-view-reconnect.test.js +0 -105
  613. package/dist/core/__tests__/full/consult-startup-failure.test.js +0 -124
  614. package/dist/core/canvas/__tests__/human-work-outbox.test.js +0 -123
  615. package/dist/core/canvas/human-work-outbox.d.ts +0 -73
  616. package/dist/core/canvas/human-work-outbox.js +0 -261
  617. package/dist/core/command-plugins/store.d.ts +0 -16
  618. package/dist/core/command-plugins/store.js +0 -64
  619. package/dist/core/keybindings/__tests__/bespoke-consumers.test.js +0 -40
  620. package/dist/core/runtime/fault-recovery-nudge.d.ts +0 -3
  621. package/dist/core/runtime/fault-recovery-nudge.js +0 -3
  622. package/dist/core/tui/__tests__/host-keybindings.test.js +0 -113
  623. package/dist/core/tui/host.d.ts +0 -66
  624. package/dist/core/view/__tests__/transport-cache.test.js +0 -62
  625. package/dist/core/view/bridge.d.ts +0 -10
  626. package/dist/core/view/bridge.js +0 -31
  627. package/dist/core/view/chrome.d.ts +0 -9
  628. package/dist/core/view/chrome.js +0 -22
  629. package/dist/core/view/contract.d.ts +0 -205
  630. package/dist/core/view/contract.js +0 -23
  631. package/dist/core/view/loader.d.ts +0 -31
  632. package/dist/core/view/loader.js +0 -188
  633. package/dist/core/view/stream-local.d.ts +0 -3
  634. package/dist/core/view/stream-local.js +0 -231
  635. package/dist/core/view/transport-cache.d.ts +0 -8
  636. package/dist/core/view/transport-cache.js +0 -38
  637. package/dist/core/view/transport-local.d.ts +0 -7
  638. package/dist/core/view/transport-local.js +0 -83
  639. package/dist/core/view/transport-remote.d.ts +0 -2
  640. package/dist/core/view/transport.d.ts +0 -10
  641. package/dist/core/view/transport.js +0 -15
  642. package/dist/pi-extensions/naming-tool.d.ts +0 -24
  643. package/dist/pi-extensions/naming-tool.js +0 -67
  644. package/dist/prompts/view.d.ts +0 -7
  645. package/dist/prompts/view.js +0 -172
  646. package/dist/web/ViewChrome.d.ts +0 -7
  647. package/dist/web/ViewChrome.js +0 -28
  648. package/dist/web/ViewPane.d.ts +0 -39
  649. package/dist/web/ViewPane.js +0 -48
  650. package/dist/web/index.d.ts +0 -8
  651. package/dist/web/index.js +0 -22
  652. package/dist/web/runtime.d.ts +0 -39
  653. package/dist/web/runtime.js +0 -232
  654. package/dist/web/states.d.ts +0 -24
  655. package/dist/web/states.js +0 -24
  656. package/dist/web/transport-http.d.ts +0 -5
  657. package/dist/web/transport-http.js +0 -34
  658. package/dist/web/transport-stream.d.ts +0 -3
  659. package/dist/web/transport-stream.js +0 -204
  660. package/dist/web-client/assets/index-U_NZ66VE.js +0 -79
  661. package/dist/web-client/assets/index-aaeu4adv.css +0 -2
  662. /package/dist/{builtin-views/workspace-sidebar/__tests__/core.test.d.ts → clients/attach/__tests__/file-review-focus.test.d.ts} +0 -0
  663. /package/dist/clients/attach/__tests__/{visible-paths.test.d.ts → group-activity.test.d.ts} +0 -0
  664. /package/dist/{core/__tests__/chat-view-reconnect.test.d.ts → clients/attach/__tests__/input-controller-extension-command.test.d.ts} +0 -0
  665. /package/dist/{core/__tests__/full/consult-startup-failure.test.d.ts → clients/attach/__tests__/session-identity-refresh.test.d.ts} +0 -0
  666. /package/dist/{core/canvas/__tests__/human-work-outbox.test.d.ts → clients/inbox/__tests__/inbox-controller.test.d.ts} +0 -0
  667. /package/dist/{core/keybindings/__tests__/bespoke-consumers.test.d.ts → clients/inbox/__tests__/mount-panel.test.d.ts} +0 -0
  668. /package/dist/{core/tui/__tests__/host-keybindings.test.d.ts → clients/inbox/review/__tests__/editor-roundtrip.test.d.ts} +0 -0
  669. /package/dist/{core/view/__tests__/transport-cache.test.d.ts → clients/inbox/review/__tests__/remap.test.d.ts} +0 -0
  670. /package/dist/{core/view/__tests__/transport-remote.test.d.ts → clients/inbox/review/__tests__/review-core.test.d.ts} +0 -0
@@ -0,0 +1,176 @@
1
+ // session/frame.ts — the attach viewer's single full-pane TUI child.
2
+ //
3
+ // The frame owns the pane rectangle: transcript rows are virtualized between a
4
+ // bounded recap header and a cursor-first cockpit. Nothing mounted beneath this
5
+ // component may reach pi-tui as a separate child, or it can reintroduce terminal
6
+ // scrollback and lose the editor's hardware cursor.
7
+ import { CURSOR_MARKER } from '@earendil-works/pi-tui';
8
+ import { reportInvariant as report } from './invariant.js';
9
+ export const MIN_TRANSCRIPT_ROWS = 3;
10
+ export const HEADER_MAX_ROWS = 12;
11
+ export const EDITOR_MIN_ROWS = 1;
12
+ export const STATUS_ROWS = 1;
13
+ /** Crop `lines` to `alloc` rows, guaranteeing the CURSOR_MARKER row survives
14
+ * (§2.1). No marker → the tail is kept. */
15
+ export function cropAroundCursor(lines, alloc) {
16
+ const rows = Math.max(0, Math.floor(alloc));
17
+ if (lines.length <= rows)
18
+ return lines.slice();
19
+ if (rows === 0)
20
+ return [];
21
+ const marker = lines.findIndex((line) => line.includes(CURSOR_MARKER));
22
+ if (marker === -1)
23
+ return lines.slice(-rows);
24
+ const start = clamp(marker - Math.floor((rows - 1) / 2), 0, lines.length - rows);
25
+ const cropped = lines.slice(start, start + rows);
26
+ if (!cropped.some((line) => line.includes(CURSOR_MARKER))) {
27
+ // This should be unreachable for a positive allocation. Keep the cursor
28
+ // row rather than silently making pi-tui lose the hardware cursor.
29
+ reportInvariant('cursor crop discarded CURSOR_MARKER');
30
+ return [lines[marker]];
31
+ }
32
+ return cropped;
33
+ }
34
+ const SLOT_PRIORITY = [
35
+ 'activity',
36
+ 'queued',
37
+ 'aboveWidgets',
38
+ 'belowWidgets',
39
+ 'reports',
40
+ 'cockpitPadding',
41
+ ];
42
+ const SLOT_VISUAL_ORDER = [
43
+ 'cockpitPadding',
44
+ 'activity',
45
+ 'aboveWidgets',
46
+ 'queued',
47
+ 'editor',
48
+ 'pickerPanel',
49
+ 'belowWidgets',
50
+ 'reports',
51
+ 'footer',
52
+ ];
53
+ /** The TUI's ONE child. Renders exactly `terminal.rows` lines, every frame. */
54
+ export class ViewerFrame {
55
+ terminal;
56
+ parts;
57
+ viewportRows = 0;
58
+ constructor(terminal, parts) {
59
+ this.terminal = terminal;
60
+ this.parts = parts;
61
+ }
62
+ render(width) {
63
+ const rows = Math.max(0, this.terminal.rows);
64
+ const rendered = new Map();
65
+ for (const { slot, component } of this.parts.bottom)
66
+ rendered.set(slot, component.render(width));
67
+ const allocations = new Map();
68
+ const linesFor = (slot) => rendered.get(slot) ?? [];
69
+ const allocate = (slot, lines) => {
70
+ allocations.set(slot, lines);
71
+ };
72
+ let remaining = Math.min(rows, Math.max(EDITOR_MIN_ROWS + STATUS_ROWS, rows - MIN_TRANSCRIPT_ROWS));
73
+ const footerLines = linesFor('footer');
74
+ const statusAlloc = footerLines.length > 0 && remaining > EDITOR_MIN_ROWS ? STATUS_ROWS : 0;
75
+ allocate('footer', statusAlloc === 0 ? [] : footerLines.slice(-statusAlloc));
76
+ remaining -= statusAlloc;
77
+ const pickerLines = linesFor('pickerPanel');
78
+ const pickerReserve = pickerLines.length === 0 ? 0 : Math.min(pickerLines.length, Math.floor(remaining / 2));
79
+ const editorLines = linesFor('editor');
80
+ const editorAlloc = clamp(editorLines.length, EDITOR_MIN_ROWS, Math.max(EDITOR_MIN_ROWS, remaining - pickerReserve));
81
+ const editorSlice = cropAroundCursor(editorLines, editorAlloc);
82
+ allocate('editor', editorSlice);
83
+ remaining -= editorAlloc;
84
+ const pickerAlloc = Math.min(pickerLines.length, remaining);
85
+ allocate('pickerPanel', pickerLines.slice(0, pickerAlloc));
86
+ remaining -= pickerAlloc;
87
+ for (const slot of SLOT_PRIORITY) {
88
+ const lines = linesFor(slot);
89
+ if (lines.length <= remaining) {
90
+ allocate(slot, lines);
91
+ remaining -= lines.length;
92
+ }
93
+ else {
94
+ allocate(slot, []);
95
+ }
96
+ }
97
+ const bottomLines = SLOT_VISUAL_ORDER.flatMap((slot) => allocations.get(slot) ?? []);
98
+ const editorBottomOffset = SLOT_VISUAL_ORDER
99
+ .slice(0, SLOT_VISUAL_ORDER.indexOf('editor'))
100
+ .reduce((count, slot) => count + (allocations.get(slot)?.length ?? 0), 0);
101
+ let headerLines = this.parts.header.render(width).slice(0, HEADER_MAX_ROWS);
102
+ if (rows - bottomLines.length - headerLines.length < MIN_TRANSCRIPT_ROWS)
103
+ headerLines = [];
104
+ const viewportRows = Math.max(0, rows - headerLines.length - bottomLines.length);
105
+ this.viewportRows = viewportRows;
106
+ let viewportLines = this.parts.viewport.renderSlice(width, viewportRows);
107
+ let frame = [...headerLines, ...viewportLines, ...bottomLines];
108
+ // A misbehaving viewport is repaired in its own region only: transcript
109
+ // padding goes directly beneath the header, while excess drops from its top.
110
+ // The cockpit, including the editor's marker row, is never sliced here.
111
+ if (frame.length !== rows) {
112
+ reportInvariant(`frame rendered ${frame.length} rows; expected ${rows}`);
113
+ viewportLines = fitTranscript(viewportLines, viewportRows);
114
+ frame = [...headerLines, ...viewportLines, ...bottomLines];
115
+ }
116
+ if (frame.length !== rows)
117
+ reportInvariant(`frame correction rendered ${frame.length} rows; expected ${rows}`);
118
+ return this.ensureCursorMarker(frame, editorLines, editorSlice, editorBottomOffset, bottomLines.length, rows);
119
+ }
120
+ invalidate() {
121
+ this.parts.header.invalidate();
122
+ for (const { component } of this.parts.bottom)
123
+ component.invalidate();
124
+ this.parts.viewport.invalidate();
125
+ }
126
+ /** Rows the transcript viewport got in the last frame — the page size. */
127
+ lastViewportRows() {
128
+ return this.viewportRows;
129
+ }
130
+ /** Retain exactly one editor marker if the focused editor rendered one. */
131
+ ensureCursorMarker(frame, editorLines, editorSlice, editorBottomOffset, bottomRows, rows) {
132
+ const editorMarker = editorLines.find((line) => line.includes(CURSOR_MARKER));
133
+ const markerCount = countMarkers(frame);
134
+ if (editorMarker === undefined ? markerCount <= 1 : markerCount === 1)
135
+ return frame;
136
+ reportInvariant(editorMarker === undefined
137
+ ? `frame contains ${markerCount} CURSOR_MARKER sequences without one from the editor`
138
+ : `frame contains ${markerCount} CURSOR_MARKER sequences; expected exactly one`);
139
+ const repaired = frame.map(stripCursorMarkers);
140
+ if (editorMarker === undefined)
141
+ return repaired;
142
+ const markerLine = editorSlice.findIndex((line) => line.includes(CURSOR_MARKER));
143
+ const frameIndex = rows - bottomRows + editorBottomOffset + markerLine;
144
+ if (markerLine === -1 || frameIndex < 0 || frameIndex >= repaired.length) {
145
+ reportInvariant('unable to restore editor CURSOR_MARKER in composed frame');
146
+ return repaired;
147
+ }
148
+ const markerAt = editorSlice[markerLine].indexOf(CURSOR_MARKER);
149
+ const line = repaired[frameIndex];
150
+ repaired[frameIndex] = `${line.slice(0, markerAt)}${CURSOR_MARKER}${line.slice(markerAt)}`;
151
+ return repaired;
152
+ }
153
+ }
154
+ function clamp(value, min, max) {
155
+ return Math.min(max, Math.max(min, value));
156
+ }
157
+ /** Correct only the viewport allocation: top-pad short content or retain its tail. */
158
+ function fitTranscript(lines, rows) {
159
+ if (rows === 0)
160
+ return [];
161
+ if (lines.length === rows)
162
+ return lines.slice();
163
+ if (lines.length > rows)
164
+ return lines.slice(-rows);
165
+ return [...Array(rows - lines.length).fill(''), ...lines];
166
+ }
167
+ function countMarkers(lines) {
168
+ return lines.reduce((count, line) => count + line.split(CURSOR_MARKER).length - 1, 0);
169
+ }
170
+ function stripCursorMarkers(line) {
171
+ return line.split(CURSOR_MARKER).join('');
172
+ }
173
+ /** Invariants must surface in development without taking down an attached pane. */
174
+ function reportInvariant(message) {
175
+ report('attach-frame', message);
176
+ }
@@ -2,6 +2,7 @@ import type { AgentSessionEvent } from '@earendil-works/pi-coding-agent';
2
2
  import type { BrokerToClient, RpcExtensionUIRequest } from '../../../core/runtime/broker-protocol.js';
3
3
  import { type PreviewableCommand } from '../slash/prompt-preview.js';
4
4
  import type { AttachSession } from './context.js';
5
+ import type { ToolGroupSummary } from '../../../shared/tool-groups.js';
5
6
  export interface FrameEffects {
6
7
  /** Fold the frame through the shared reducer and repaint whatever slice of
7
8
  * chrome changed. Runs FIRST for every frame, before any case below. */
@@ -13,11 +14,13 @@ export interface FrameEffects {
13
14
  type: 'welcome';
14
15
  }>['snapshot']) => Promise<void> | void;
15
16
  handleEvent: (event: AgentSessionEvent) => void;
17
+ setWorkingActivity: (activity: string) => void;
16
18
  bashStart: (command: string, excludeFromContext?: boolean) => void;
17
19
  bashOutput: (chunk: string) => void;
18
20
  bashEnd: (frame: Extract<BrokerToClient, {
19
21
  type: 'bash_end';
20
22
  }>) => void;
23
+ applyToolGroupSummary: (key: string, summary: ToolGroupSummary) => void;
21
24
  };
22
25
  setNotice: (message: string) => void;
23
26
  /** Repaint the status line — for the frames whose footer effect is NOT
@@ -32,7 +35,7 @@ export interface FrameEffects {
32
35
  setCommands: (next?: ReadonlyArray<PreviewableCommand>) => void;
33
36
  /** Clear + refetch the memory-ref inventory, superseding anything in flight. */
34
37
  resetMemoryRefs: () => void;
35
- /** Re-read the node's persona/lifecycle from the canvas. */
38
+ /** Re-read the node's persona/lifecycle/icon from the canvas. */
36
39
  refreshNodeIdentity: () => void;
37
40
  /** Re-resolve user keybindings after a `/reload` (and re-install the tmux side). */
38
41
  reloadBindings: () => void;
@@ -81,7 +81,14 @@ export function createFrameHandler(ctx, fx) {
81
81
  /** A relayed AgentSessionEvent — everything not in the switch below. */
82
82
  const handleSessionEvent = (event) => {
83
83
  fx.chat.handleEvent(event);
84
- if (event.type === 'thinking_level_changed') {
84
+ if (event.type === 'session_info_changed') {
85
+ // Recap title regeneration persists a new canvas icon before changing the
86
+ // pi session name. Refreshing here lets the identity owner's onChanged
87
+ // repaint normalize that name with the matching icon instead of keeping
88
+ // the icon cached when this viewer attached.
89
+ fx.refreshNodeIdentity();
90
+ }
91
+ else if (event.type === 'thinking_level_changed') {
85
92
  fx.setNotice(fx.modelThinkingLabel() ?? `Thinking level: ${event.level}`);
86
93
  }
87
94
  else if (event.type === 'tool_execution_start' || event.type === 'tool_execution_end') {
@@ -127,6 +134,12 @@ export function createFrameHandler(ctx, fx) {
127
134
  fx.attachDialog(frame.pending_dialog);
128
135
  break;
129
136
  }
137
+ case 'tool_group_summary':
138
+ fx.chat.applyToolGroupSummary(frame.key, frame.summary);
139
+ break;
140
+ case 'working_activity':
141
+ fx.chat.setWorkingActivity(frame.activity);
142
+ break;
130
143
  case 'model_changed': {
131
144
  // The broker's own post-set_model/cycle_model announcement (pi emits no
132
145
  // engine event for a model switch) already moved the footer's model
@@ -1,11 +1,12 @@
1
1
  // session/identity.ts — the OWNER of the attached node's canvas identity
2
- // (kind/mode/lifecycle), which the editor's context badge and lifecycle chip
2
+ // (kind/mode/lifecycle/icon), which the editor's context badge and title chip
3
3
  // render from.
4
4
  //
5
5
  // It is the one connection fact that is NOT fixed at connect time: a remote
6
6
  // attach starts without an identity and fills it in from the relayed canvas,
7
- // and a fresh broker can report a new persona or lifecycle. Hence an owner with
8
- // a refresh verb rather than a value on `AttachSession`.
7
+ // and a fresh broker or regenerated title can reflect a new persona, lifecycle,
8
+ // or task icon. Hence an owner with a refresh verb rather than a value on
9
+ // `AttachSession`.
9
10
  export function createNodeIdentity(ctx, initial, hooks) {
10
11
  let identity = initial;
11
12
  return {
@@ -1,5 +1,7 @@
1
1
  import { InputController } from '../input/controller.js';
2
+ import type { ToolDisplayToggle } from '../render/chat-view.js';
2
3
  import type { KeybindingsManager } from '@earendil-works/pi-tui';
4
+ import type { CopyTarget } from '../render/transcript-copy.js';
3
5
  import type { AttachSession } from './context.js';
4
6
  /** What the input layer needs from the rest of the session. Everything here is
5
7
  * a getter or a command — never a value — so nothing can go stale. */
@@ -11,10 +13,10 @@ export interface InputWiringHooks {
11
13
  agentDir: () => string | undefined;
12
14
  /** True while the reconnect supervisor has classified the node as dormant. */
13
15
  isDormant: () => boolean;
14
- /** The last assistant message, for `/copy` (ChatView holds it). */
15
- lastAssistantText: () => string | undefined;
16
- /** Ctrl+O — flip global tool-output expansion; returns the new state. */
17
- toggleToolsExpanded: () => boolean;
16
+ /** Copy a viewer-local transcript target and surface its confirmation. */
17
+ copyTarget: (target: CopyTarget) => void;
18
+ /** Ctrl+O — toggles either collapsed summaries or tool-output expansion. */
19
+ toggleToolsExpanded: () => ToolDisplayToggle;
18
20
  /** `/fold-tools` — flip the fold-finished-tool-calls view setting; returns the
19
21
  * new state. */
20
22
  toggleFoldTools: () => boolean;
@@ -22,6 +24,12 @@ export interface InputWiringHooks {
22
24
  toggleThinking: () => boolean;
23
25
  /** `/graph` and the graph keybinding. */
24
26
  toggleGraph: () => void;
27
+ /** `/inbox` and the inbox attach control. */
28
+ toggleInbox: () => void;
29
+ /** `/hotkeys` and the help keybinding. */
30
+ toggleHelp: () => void;
31
+ /** `/mouse` — flip mouse wheel reporting and return the new state. */
32
+ toggleMouse: () => boolean;
25
33
  /** `/node-metadata` — open the viewer-owned Inspector dossier popup. */
26
34
  openNodeMetadata: () => void;
27
35
  /** `/quit` — detach this viewer; the engine keeps running. Must tear down
@@ -29,6 +37,8 @@ export interface InputWiringHooks {
29
37
  quit: () => void;
30
38
  /** `/color` — recolor the editor's name chip (`null` clears to default). */
31
39
  setChipColor: (color: string | null) => void;
40
+ /** A prompt or steer was accepted from the editor. */
41
+ onPromptSent: () => void;
32
42
  }
33
43
  /** Build the viewer's InputController with every hook answered. */
34
44
  export declare function createInputController(ctx: Pick<AttachSession, 'nodeId' | 'remote' | 'role' | 'meta' | 'socket' | 'tui' | 'editor' | 'containers'>, km: KeybindingsManager, hooks: InputWiringHooks): InputController;
@@ -13,7 +13,6 @@
13
13
  // can only be closed over from inside).
14
14
  import { InputController } from '../input/controller.js';
15
15
  import { cliClient } from '../../../commands/api-client.js';
16
- import { writeClipboardText } from '../../../core/clipboard-text.js';
17
16
  import { buildLoginPicker, buildLogoutPicker } from '../overlays/auth.js';
18
17
  import { defaultAgentDir } from '../config.js';
19
18
  /** Build the viewer's InputController with every hook answered. */
@@ -25,16 +24,6 @@ export function createInputController(ctx, km, hooks) {
25
24
  // mutate. Every mutating hook below is wired only when this is true; the
26
25
  // read-op channel (`onRequest`) and the read-only getters stay wired for all.
27
26
  const writable = !remote && role === 'controller';
28
- // `/copy` — the last assistant message (ChatView keeps it current from both
29
- // the welcome snapshot and the live stream) → the system clipboard.
30
- const copyLastAssistant = () => {
31
- const text = hooks.lastAssistantText();
32
- if (!text) {
33
- setNotice('Nothing to copy — no assistant message yet');
34
- return;
35
- }
36
- setNotice(writeClipboardText(text) ? 'Copied last message to clipboard' : 'Copy failed — no clipboard tool found');
37
- };
38
27
  // Auth pickers — viewer-local OAuth/API-key flows against the SAME auth.json
39
28
  // the broker uses (broker + viewer share a filesystem in the tmux-local attach
40
29
  // model), so they run entirely in this process and then tell the broker to
@@ -72,14 +61,27 @@ export function createInputController(ctx, km, hooks) {
72
61
  remote,
73
62
  role,
74
63
  onGraph: hooks.toggleGraph,
64
+ onInbox: hooks.toggleInbox,
65
+ onHelp: hooks.toggleHelp,
75
66
  onNodeMetadata: hooks.openNodeMetadata,
76
67
  onQuit: hooks.quit,
77
- onCopy: copyLastAssistant,
68
+ onCopy: () => hooks.copyTarget('last-assistant'),
69
+ onCopyTarget: hooks.copyTarget,
70
+ onToggleMouse: () => {
71
+ const on = hooks.toggleMouse();
72
+ setNotice(on ? 'Mouse: wheel scrolling on' : 'Mouse: off — tmux drag-select and copy-mode restored');
73
+ },
78
74
  onColor: hooks.setChipColor,
75
+ onPromptSent: hooks.onPromptSent,
79
76
  // Global display toggles (Ctrl+O tools / Ctrl+T thinking) — pure render
80
77
  // state owned by ChatView, surfaced as a footer notice mirroring pi's
81
78
  // status line.
82
- onToggleToolsExpand: () => setNotice(hooks.toggleToolsExpanded() ? 'Tool output: expanded' : 'Tool output: collapsed'),
79
+ onToggleToolsExpand: () => {
80
+ const result = hooks.toggleToolsExpanded();
81
+ setNotice(result.kind === 'summaries'
82
+ ? result.shown ? 'Tool calls: summarized' : 'Tool calls: shown'
83
+ : result.expanded ? 'Tool output: expanded' : 'Tool output: collapsed');
84
+ },
83
85
  onFoldTools: () => setNotice(hooks.toggleFoldTools()
84
86
  ? 'Finished tool calls: folded to one line'
85
87
  : 'Finished tool calls: shown in full'),
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The viewer owns the whole pane, so an invariant must never be written to the
3
+ * terminal: console output lands in the middle of the rendered frame, and a
4
+ * violation that repeats every render pushes real content into tmux scrollback
5
+ * — the exact corruption these invariants exist to catch. Records go to a
6
+ * rotating log beside the daemon's, one line per report:
7
+ * `~/.crouter/canvas/attach-invariants.log` (`CRTR_HOME`-relative).
8
+ */
9
+ export declare function reportInvariant(scope: string, message: string): void;
@@ -0,0 +1,15 @@
1
+ import { join } from 'node:path';
2
+ import { crtrHome } from '../../../core/canvas/paths.js';
3
+ import { appendRotatingRecord } from '../../../core/log.js';
4
+ /**
5
+ * The viewer owns the whole pane, so an invariant must never be written to the
6
+ * terminal: console output lands in the middle of the rendered frame, and a
7
+ * violation that repeats every render pushes real content into tmux scrollback
8
+ * — the exact corruption these invariants exist to catch. Records go to a
9
+ * rotating log beside the daemon's, one line per report:
10
+ * `~/.crouter/canvas/attach-invariants.log` (`CRTR_HOME`-relative).
11
+ */
12
+ export function reportInvariant(scope, message) {
13
+ const line = `${new Date().toISOString()} ${scope} ${message}`.replaceAll(/[\r\n]/g, ' ');
14
+ appendRotatingRecord(join(crtrHome(), 'attach-invariants.log'), line);
15
+ }
@@ -1,4 +1,4 @@
1
- import { type AttachBindings } from './bindings.js';
1
+ import { type AttachBindings, type AttachViewportActions } from './bindings.js';
2
2
  import type { AttachSession } from './context.js';
3
3
  export interface KeyHooks {
4
4
  /** The live binding snapshot — re-resolved by `/reload`, so read per key. */
@@ -7,18 +7,26 @@ export interface KeyHooks {
7
7
  detachHint: () => string | undefined;
8
8
  /** Terminal focus in/out — the roster owns the editor's cursor styling. */
9
9
  setPaneFocused: (focused: boolean) => void;
10
+ /** Whether a full-pane surface should receive all non-control input. */
11
+ hasExclusiveSurface: () => boolean;
12
+ /** Scroll actions for this session's transcript viewport. */
13
+ viewportActions: () => AttachViewportActions;
10
14
  /** The roster's chance at a chunk; true when it consumed it. */
11
15
  rosterHandleKey: (data: string) => boolean;
12
16
  setNotice: (message: string) => void;
13
17
  detach: () => void;
14
- cycleMode: () => void;
15
18
  toggleGraph: () => void;
19
+ toggleHelp: () => void;
20
+ /** Toggle the mounted inbox surface. */
21
+ toggleInbox: () => void;
16
22
  cycleModelLadder: (direction: 'forward' | 'backward') => void;
17
23
  inspectLoadedCommand: () => void;
18
24
  /** The file-review chord — open the transcript-file picker + review surface. */
19
25
  openFileReview: () => void;
20
26
  /** Search the current node's local profile project files. */
21
27
  openProfileFiles: () => void;
28
+ /** Play the whip animation and interrupt the focused agent with a command. */
29
+ whip: () => void;
22
30
  }
23
31
  /** Install the listener; returns the remover, which teardown MUST call. */
24
32
  export declare function installGlobalKeys(ctx: Pick<AttachSession, 'tui' | 'editor'>, hooks: KeyHooks): () => void;
@@ -3,11 +3,12 @@
3
3
  // A TUI input listener fires BEFORE the focused component and before any dialog
4
4
  // overlay, so the configured attach actions work regardless of what has focus.
5
5
  // That privilege is also the hazard: anything consumed here never reaches the
6
- // editor. Only terminal focus reports, a private crouter control input, the
7
- // roster while it holds the cursor, and a configured crtr binding may claim a
8
- // chunk; each returns ordinary editor input untouched when it does not apply.
6
+ // editor. Only terminal focus reports, a private crouter control input,
7
+ // viewport scroll bindings while the editor has focus, the roster while it holds
8
+ // the cursor, and a configured crtr binding may claim a chunk; each returns
9
+ // ordinary editor input untouched when it does not apply.
9
10
  import { extractAttachControlInput } from '../../../core/keybindings/index.js';
10
- import { dispatchAttachAction, dispatchAttachBinding } from './bindings.js';
11
+ import { dispatchAttachAction, dispatchAttachBinding, dispatchAttachViewportBinding, } from './bindings.js';
11
12
  import { FOCUS_IN, FOCUS_OUT } from './focus-events.js';
12
13
  /** Press the clear-or-detach binding twice inside this window to detach. */
13
14
  const CLEAR_OR_DETACH_MS = 1000;
@@ -29,14 +30,16 @@ export function installGlobalKeys(ctx, hooks) {
29
30
  hooks.setNotice(`Editor cleared — press ${hooks.detachHint()} again to detach`);
30
31
  tui.requestRender();
31
32
  },
32
- 'crtr.mode.cycle': hooks.cycleMode,
33
33
  'crtr.attach.graph.toggle': hooks.toggleGraph,
34
+ 'crtr.attach.help.toggle': hooks.toggleHelp,
35
+ 'crtr.attach.inbox.toggle': hooks.toggleInbox,
34
36
  // A plain broker frame, so this works locally and remotely alike; the broker gates observers on controller role.
35
37
  'crtr.attach.model-ladder.next': () => hooks.cycleModelLadder('forward'),
36
38
  'crtr.attach.model-ladder.previous': () => hooks.cycleModelLadder('backward'),
37
39
  'crtr.attach.command.inspect': hooks.inspectLoadedCommand,
38
40
  'crtr.attach.file-review': hooks.openFileReview,
39
41
  'crtr.attach.profile-files': hooks.openProfileFiles,
42
+ 'crtr.attach.whip': hooks.whip,
40
43
  };
41
44
  return tui.addInputListener((data) => {
42
45
  // Terminal focus reporting (DECSET 1004, enabled after tui.start; tmux forwards it per-pane with `focus-events on`). Pane focus drives the editor's fake cursor — solid block focused, hollow outline blurred — so a wall of attach panes shows exactly which one keys go to. The events are stripped rather than blanket-consumed in case the chunk coalesced them with real keystrokes.
@@ -51,6 +54,11 @@ export function installGlobalKeys(ctx, hooks) {
51
54
  dispatchAttachAction(control.actionId, actions);
52
55
  return control.remaining.length > 0 ? { data: control.remaining } : { consume: true };
53
56
  }
57
+ if (hooks.hasExclusiveSurface())
58
+ return undefined;
59
+ // Let focused pickers and overlays retain their native page navigation.
60
+ if (editor.focused && dispatchAttachViewportBinding(hooks.bindings(), data, hooks.viewportActions()))
61
+ return { consume: true };
54
62
  // Inline subagent scroll+swap: once the editor hands off at its ↓ boundary, ↑/↓ move over the manager/report roster and Enter dives into a node. An inactive roster never intercepts editor input.
55
63
  if (hooks.rosterHandleKey(data))
56
64
  return { consume: true };
@@ -1,8 +1,9 @@
1
- import { ProcessTerminal, TUI } from '@earendil-works/pi-tui';
2
- import type { KeybindingsManager } from '@earendil-works/pi-tui';
1
+ import { Container, type KeybindingsManager, type ProcessTerminal, type TUI } from '@earendil-works/pi-tui';
3
2
  import type { AttachPalette } from '../config.js';
4
3
  import { TitledEditor } from '../input/titled-editor.js';
4
+ import type { TranscriptViewport } from '../render/viewport.js';
5
5
  import type { AttachContainers } from './context.js';
6
+ import { ViewerFrame } from './frame.js';
6
7
  export interface AttachLayout {
7
8
  /** The process terminal behind the TUI — also the owner of the window title
8
9
  * and the negotiated keyboard protocol, both of which the orchestrator uses. */
@@ -10,11 +11,12 @@ export interface AttachLayout {
10
11
  readonly tui: TUI;
11
12
  readonly containers: AttachContainers;
12
13
  readonly editor: TitledEditor;
13
- /** Attach the containers to the TUI in render order and focus the editor.
14
- * Deferred to just before `tui.start()` so a signal landing mid-construction
15
- * cannot leave a half-mounted tree on screen. */
14
+ readonly frame: ViewerFrame;
15
+ /** Attach the single frame to the TUI and focus the editor. Deferred to just
16
+ * before `tui.start()` so a signal landing mid-construction cannot leave a
17
+ * half-mounted tree on screen. */
16
18
  mount(): void;
17
19
  }
18
- /** Build the TUI, its containers, and the editor. No behavior is wired here;
19
- * the orchestrator owns every callback. */
20
- export declare function createLayout(pal: AttachPalette, km: KeybindingsManager): AttachLayout;
20
+ /** Build the layout around the transcript viewport. The viewer creates the
21
+ * terminal and chat first because the viewport measures that chat source. */
22
+ export declare function createLayout(procTerminal: ProcessTerminal, tui: TUI, chat: Container, activity: Container, pal: AttachPalette, km: KeybindingsManager, viewport: TranscriptViewport): AttachLayout;
@@ -1,56 +1,55 @@
1
- // session/layout.ts — the viewer's visual skeleton: the TUI, the nine
2
- // containers it paints into, and the editor.
1
+ // session/layout.ts — the viewer's visual skeleton: its containers, editor,
2
+ // and one full-pane frame.
3
3
  //
4
4
  // Pure construction. Nothing here reads session state, talks to the socket, or
5
5
  // handles a key — a reader chasing behavior can skip this file entirely, and a
6
6
  // reader asking "where does this line get painted?" needs only this one.
7
7
  //
8
- // The render order is the whole point of the file, and it is asserted in ONE
9
- // place (`mount`). Top to bottom: chat · rule · queued · above-editor extension
10
- // widgets · editor · picker panel · below-editor extension widgets · roster ·
11
- // status bar. pi-tui anchors the viewport to the cursor at the BOTTOM, so
12
- // everything except the scrolling chat lives in the bottom-anchored chrome
13
- // stack — a "topmost" badge would scroll off into scrollback the instant the
14
- // transcript exceeded one screen, which is why the mode badge and the two
15
- // canvas panels sit directly above the queued panel rather than at the top.
16
- import { Container, ProcessTerminal, TUI } from '@earendil-works/pi-tui';
17
- import { DynamicBorder, getSelectListTheme } from '@earendil-works/pi-coding-agent';
8
+ // The render order is asserted in ONE place (`ViewerFrame`'s bottom list).
9
+ // Top to bottom: pinned recap header · virtualized chat · cockpit padding · fixed activity ·
10
+ // above-editor extension widgets · queued · editor · picker panel · below-editor
11
+ // extension widgets · roster · status bar. The frame owns the pane rectangle,
12
+ // so every region remains on screen and none can enter terminal scrollback.
13
+ import { Container, Spacer } from '@earendil-works/pi-tui';
14
+ import { getSelectListTheme } from '@earendil-works/pi-coding-agent';
18
15
  import { TitledEditor } from '../input/titled-editor.js';
19
- /** Build the TUI, its containers, and the editor. No behavior is wired here;
20
- * the orchestrator owns every callback. */
21
- export function createLayout(pal, km) {
22
- const procTerminal = new ProcessTerminal();
23
- const tui = new TUI(procTerminal);
16
+ import { ViewerFrame } from './frame.js';
17
+ /** Build the layout around the transcript viewport. The viewer creates the
18
+ * terminal and chat first because the viewport measures that chat source. */
19
+ export function createLayout(procTerminal, tui, chat, activity, pal, km, viewport) {
24
20
  const containers = {
25
- chat: new Container(),
26
- chrome: new Container(),
21
+ chat,
22
+ header: new Container(),
27
23
  aboveWidgets: new Container(),
24
+ activity,
28
25
  reports: new Container(),
29
26
  queued: new Container(),
30
27
  pickerPanel: new Container(),
31
28
  belowWidgets: new Container(),
32
29
  footer: new Container(),
33
30
  };
34
- // The themed rule dividing the scrolling chat from the fixed chrome below it.
35
- // `renderExtensionWidgets` re-derives this container's contents on every
36
- // widget change (the passive recap replaces the rule), so this is the seed,
37
- // not the sole writer.
38
- containers.chrome.addChild(new DynamicBorder(pal.border));
39
31
  const editorTheme = { borderColor: pal.border, selectList: getSelectListTheme() };
40
32
  // TitledEditor paints the session name into its top border (solid-background
41
33
  // chip) and tracks a thinking-level border color, both set from live state.
42
34
  const editor = new TitledEditor(tui, editorTheme, km, { paddingX: 1 });
35
+ const frame = new ViewerFrame(procTerminal, {
36
+ header: containers.header,
37
+ viewport,
38
+ bottom: [
39
+ { slot: 'cockpitPadding', component: new Spacer(1) },
40
+ { slot: 'activity', component: containers.activity },
41
+ { slot: 'aboveWidgets', component: containers.aboveWidgets },
42
+ { slot: 'queued', component: containers.queued },
43
+ { slot: 'editor', component: editor },
44
+ { slot: 'pickerPanel', component: containers.pickerPanel },
45
+ { slot: 'belowWidgets', component: containers.belowWidgets },
46
+ { slot: 'reports', component: containers.reports },
47
+ { slot: 'footer', component: containers.footer },
48
+ ],
49
+ });
43
50
  const mount = () => {
44
- tui.addChild(containers.chat);
45
- tui.addChild(containers.chrome);
46
- tui.addChild(containers.queued);
47
- tui.addChild(containers.aboveWidgets);
48
- tui.addChild(editor);
49
- tui.addChild(containers.pickerPanel);
50
- tui.addChild(containers.belowWidgets);
51
- tui.addChild(containers.reports);
52
- tui.addChild(containers.footer);
51
+ tui.addChild(frame);
53
52
  tui.setFocus(editor);
54
53
  };
55
- return { procTerminal, tui, containers, editor, mount };
54
+ return { procTerminal, tui, containers, editor, frame, mount };
56
55
  }
@@ -0,0 +1,18 @@
1
+ import type { TUI } from '@earendil-works/pi-tui';
2
+ import type { MouseModeDefault } from '../../../types.js';
3
+ /** Lines moved for one terminal wheel notch. */
4
+ export declare const WHEEL_LINES = 3;
5
+ export interface MouseReporting {
6
+ /** Reporting currently on. */
7
+ enabled(): boolean;
8
+ /** Flip, write the DECSET/DECRST, return the new state. */
9
+ toggle(): boolean;
10
+ /** Re-emit the current setting after another terminal program returned. */
11
+ reassert(): void;
12
+ /** Turn off unconditionally — teardown and process exit. */
13
+ disable(): void;
14
+ /** Install the SGR listener; returns the remover. */
15
+ install(tui: TUI, onWheel: (direction: 'up' | 'down', lines: number, column: number) => void): () => void;
16
+ }
17
+ /** Create per-viewer mouse reporting from the user's saved starting mode. */
18
+ export declare function createMouseReporting(write: (data: string) => void, defaultMode: MouseModeDefault): MouseReporting;