@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,45 @@
1
+ import type { RenderedDoc } from '../../../core/termrender/termrender.js';
2
+ import type { ReviewState } from './state.js';
3
+ /** Width prose is rendered at for a given terminal width: 2-col left
4
+ * margin + 2-col gutter before the content, capped for readability. */
5
+ export declare function renderWidthForCols(cols: number): number;
6
+ /** The body rectangle a rendered row is painted into: the terminal minus the
7
+ * 4-col gutter prefix. Diagram blocks render at this width (no prose cap),
8
+ * and every emitted body row is contained within it. */
9
+ export declare function contentWidthForCols(cols: number): number;
10
+ /** Body width left after an optional line-number gutter. */
11
+ export declare function bodyWidth(cols: number, gutterW?: number): number;
12
+ /** The mapped render this surface paints: prose at the readability cap,
13
+ * diagrams at the full body width. */
14
+ export declare function renderReviewDoc(content: string, cols: number): RenderedDoc;
15
+ /** Widest painted row, in display cells, for a body window. */
16
+ export declare function widestVisibleRow(doc: RenderedDoc, scroll: number, bodyHeight: number): number;
17
+ /** How far the body can pan right, given what is currently on screen. Zero
18
+ * when nothing visible overflows — which is also what makes h/l contextual:
19
+ * the keys only pan while an overflowing row is in view. */
20
+ export declare function maxHScroll(state: ReviewState, doc: RenderedDoc, cols: number, rows: number, gutterW?: number): number;
21
+ /** Pan the body horizontally, clamped to what is currently reachable. The
22
+ * stored offset is only ever clamped against the live window, so vertical
23
+ * scrolling and resize can never leave it pointing past the content. */
24
+ export declare function panBy(state: ReviewState, delta: number, doc: RenderedDoc, cols: number, rows: number, gutterW?: number): ReviewState;
25
+ /** Cells one h/l press pans by — a chunk large enough to cross a diagram in a
26
+ * few presses, small enough to keep orientation. */
27
+ export declare const PAN_STEP = 8;
28
+ /** Reserved (non-body) rows for each mode's fixed header/footer chrome. Kept in
29
+ * sync with renderReviewFrame so scroll math can clamp before a repaint — the
30
+ * compose case counts the same hard-wrapped input lines the frame renders. */
31
+ export declare function reservedRows(state: ReviewState, cols: number): number;
32
+ export declare function renderReviewFrame(state: ReviewState, fileLabel: string, doc: RenderedDoc, cols: number, rows: number, opts?: {
33
+ lineNumbers?: boolean;
34
+ notice?: string;
35
+ }): string[];
36
+ export interface ReviewSurfaceKind {
37
+ /** `markdown` renders the file AS a document; `code` renders it as a
38
+ * syntax-highlighted source panel with a line-number gutter. */
39
+ doc: 'markdown' | 'code';
40
+ /** Fence language for `doc: 'code'` (see `fenceLanguageFor`). */
41
+ language?: string;
42
+ }
43
+ /** How a reviewed file is presented: markdown renders as a document, anything
44
+ * else as a syntax-highlighted source panel. */
45
+ export declare function docSurface(absFile: string): ReviewSurfaceKind;
@@ -0,0 +1,215 @@
1
+ import stringWidth from 'string-width';
2
+ import { renderMarkdownBlockAware } from '../../../core/termrender/termrender.js';
3
+ import { fenceLanguageFor, isMarkdownFile } from '../../../core/termrender/code-doc.js';
4
+ import { renderInputBuffer } from '../tui/render.js';
5
+ import { BOLD, CYAN, DIM, ESC, RESET, YELLOW, centerHorizontal, clipLine, hline, panLine, sanitize, truncate, visibleWidth } from '../tui/ansi.js';
6
+ import { commentedUnitSet, selectedUnitBounds } from './state.js';
7
+ // ── Rendering (pure) ─────────────────────────────────────────────────────────
8
+ /** Width prose is rendered at for a given terminal width: 2-col left
9
+ * margin + 2-col gutter before the content, capped for readability. */
10
+ export function renderWidthForCols(cols) {
11
+ return Math.min(Math.max(20, cols - 6), 120);
12
+ }
13
+ /** The body rectangle a rendered row is painted into: the terminal minus the
14
+ * 4-col gutter prefix. Diagram blocks render at this width (no prose cap),
15
+ * and every emitted body row is contained within it. */
16
+ export function contentWidthForCols(cols) {
17
+ return Math.max(20, cols - 4);
18
+ }
19
+ /** Body width left after an optional line-number gutter. */
20
+ export function bodyWidth(cols, gutterW = 0) {
21
+ return Math.max(1, contentWidthForCols(cols) - (gutterW > 0 ? gutterW + 1 : 0));
22
+ }
23
+ /** The mapped render this surface paints: prose at the readability cap,
24
+ * diagrams at the full body width. */
25
+ export function renderReviewDoc(content, cols) {
26
+ return renderMarkdownBlockAware(content, renderWidthForCols(cols), contentWidthForCols(cols));
27
+ }
28
+ /** Body rows as they are actually painted. Vertical-scroll indicators replace
29
+ * their endpoint rows, so content behind one cannot advertise or claim h/l. */
30
+ function paintedBodyRows(doc, scroll, bodyHeight) {
31
+ const rows = [];
32
+ for (let i = 0; i < bodyHeight; i++) {
33
+ const abs = scroll + i;
34
+ rows.push(abs < doc.lines.length ? { abs, line: doc.lines[abs] } : { abs: null, line: '' });
35
+ }
36
+ if (scroll > 0 && rows.length > 0)
37
+ rows[0] = { abs: null, line: ` ${DIM}↑ ${scroll} more above${RESET}` };
38
+ const remaining = doc.lines.length - (scroll + bodyHeight);
39
+ if (remaining > 0 && rows.length > 0)
40
+ rows[rows.length - 1] = { abs: null, line: ` ${DIM}↓ ${remaining} more below${RESET}` };
41
+ return rows;
42
+ }
43
+ /** Widest painted row, in display cells, for a body window. */
44
+ export function widestVisibleRow(doc, scroll, bodyHeight) {
45
+ let widest = 0;
46
+ for (const row of paintedBodyRows(doc, scroll, bodyHeight))
47
+ widest = Math.max(widest, visibleWidth(row.line));
48
+ return widest;
49
+ }
50
+ /** How far the body can pan right, given what is currently on screen. Zero
51
+ * when nothing visible overflows — which is also what makes h/l contextual:
52
+ * the keys only pan while an overflowing row is in view. */
53
+ export function maxHScroll(state, doc, cols, rows, gutterW = 0) {
54
+ const bodyHeight = Math.max(1, rows - reservedRows(state, cols));
55
+ const maxScroll = Math.max(0, doc.lines.length - bodyHeight);
56
+ const scroll = Math.max(0, Math.min(state.scroll, maxScroll));
57
+ return Math.max(0, widestVisibleRow(doc, scroll, bodyHeight) - bodyWidth(cols, gutterW));
58
+ }
59
+ /** Pan the body horizontally, clamped to what is currently reachable. The
60
+ * stored offset is only ever clamped against the live window, so vertical
61
+ * scrolling and resize can never leave it pointing past the content. */
62
+ export function panBy(state, delta, doc, cols, rows, gutterW = 0) {
63
+ const max = maxHScroll(state, doc, cols, rows, gutterW);
64
+ const next = Math.max(0, Math.min(state.hscroll + delta, max));
65
+ return next === state.hscroll ? state : { ...state, hscroll: next };
66
+ }
67
+ /** Cells one h/l press pans by — a chunk large enough to cross a diagram in a
68
+ * few presses, small enough to keep orientation. */
69
+ export const PAN_STEP = 8;
70
+ // Single-hue anchor tint (a dark neutral step below the CYAN gutter bar).
71
+ // termrender's only reset is `\x1b[0m`, so re-arming the background after each
72
+ // reset keeps the tint alive across inner styling. Heading rows carry their
73
+ // own background and won't show the tint — the gutter bar still marks them.
74
+ const TINT_BG = `${ESC}48;5;236m`;
75
+ function tintRow(row, width) {
76
+ const pad = Math.max(0, width - stringWidth(sanitize(row)));
77
+ return TINT_BG + row.replaceAll(RESET, RESET + TINT_BG) + ' '.repeat(pad) + RESET;
78
+ }
79
+ /** Reserved (non-body) rows for each mode's fixed header/footer chrome. Kept in
80
+ * sync with renderReviewFrame so scroll math can clamp before a repaint — the
81
+ * compose case counts the same hard-wrapped input lines the frame renders. */
82
+ export function reservedRows(state, cols) {
83
+ const header = 3; // blank, title, divider
84
+ if (state.mode === 'view')
85
+ return header + 1;
86
+ if (state.mode === 'compose') {
87
+ const c = state.compose;
88
+ const maxW = Math.min(Math.max(20, cols - 4), 120);
89
+ const bufLines = c ? renderInputBuffer(c.buffer, c.cursor, Math.max(10, maxW - 2)).length : 1;
90
+ return header + 3 + bufLines;
91
+ }
92
+ if (state.mode === 'list')
93
+ return header + Math.max(1, state.comments.length) + 2;
94
+ return header + 9; // help
95
+ }
96
+ export function renderReviewFrame(state, fileLabel, doc, cols, rows, opts) {
97
+ const maxW = Math.min(Math.max(20, cols - 4), 120);
98
+ const docW = renderWidthForCols(cols);
99
+ const header = [
100
+ '',
101
+ ` ${BOLD}${CYAN}Review — ${fileLabel}${RESET} ${DIM}${state.comments.length} comment${state.comments.length === 1 ? '' : 's'}${RESET}`,
102
+ ` ${DIM}${hline(maxW)}${RESET}`,
103
+ ];
104
+ const footer = [];
105
+ if (state.mode === 'compose' && state.compose) {
106
+ const c = state.compose;
107
+ const label = c.anchor.line === c.anchor.endLine ? `L${c.anchor.line}` : `L${c.anchor.line}-${c.anchor.endLine}`;
108
+ footer.push(` ${YELLOW}${c.editingId !== null ? 'Edit comment' : 'Comment'} on ${label}:${RESET}`);
109
+ for (const l of renderInputBuffer(c.buffer, c.cursor, Math.max(10, maxW - 2)))
110
+ footer.push(` ${l}`);
111
+ footer.push('');
112
+ footer.push(` ${DIM}enter${RESET} save ${DIM}^J/⌥⏎${RESET} newline ${DIM}esc${RESET} cancel`);
113
+ }
114
+ else if (state.mode === 'list') {
115
+ if (state.comments.length === 0) {
116
+ footer.push(` ${DIM}(no comments yet — space c to add one)${RESET}`);
117
+ }
118
+ else {
119
+ state.comments.forEach((c, i) => {
120
+ const loc = c.line === c.endLine ? `L${c.line}` : `L${c.line}-${c.endLine}`;
121
+ const cursor = i === state.listIndex ? `${CYAN}▸${RESET}` : ' ';
122
+ const text = truncate(c.comment.replace(/\n/g, ' / '), Math.max(10, maxW - 14));
123
+ footer.push(` ${cursor} ${DIM}[${loc}]${RESET} ${text}`);
124
+ });
125
+ }
126
+ footer.push('');
127
+ footer.push(` ${DIM}j/k${RESET} move ${DIM}enter/e${RESET} edit ${DIM}d${RESET} delete ${DIM}q/esc${RESET} close`);
128
+ }
129
+ else if (state.mode === 'help') {
130
+ footer.push(' Keys:');
131
+ footer.push(` ${DIM}j/k${RESET} move anchor ${DIM}shift-j/k${RESET} extend selection`);
132
+ footer.push(` ${DIM}u/d${RESET} scroll document ${DIM}h/l${RESET} pan visible wide diagrams`);
133
+ footer.push(` ${DIM}space c${RESET} compose comment ${DIM}space l${RESET} list comments`);
134
+ footer.push(` ${DIM}space u${RESET} undo last comment ${DIM}space e${RESET} edit in $EDITOR`);
135
+ footer.push(` ${DIM}space s${RESET} submit review`);
136
+ footer.push(` ${DIM}?${RESET} toggle this help ${DIM}esc${RESET} close/cancel`);
137
+ footer.push('');
138
+ footer.push(` ${DIM}esc / ?${RESET} close`);
139
+ }
140
+ else {
141
+ footer.push(` ${DIM}j/k${RESET} · ${DIM}shift-j/k${RESET} · ${DIM}u/d${RESET} · ${DIM}space c${RESET} · ${DIM}space l${RESET} · ` +
142
+ `${DIM}space u${RESET} · ${DIM}space e${RESET} · ${DIM}space s${RESET} submit · ${DIM}?${RESET} · ${DIM}esc${RESET}`);
143
+ }
144
+ if (opts?.notice !== undefined && footer.length > 0) {
145
+ footer[footer.length - 1] = ` ${YELLOW}${opts.notice}${RESET}`;
146
+ }
147
+ const reserved = header.length + footer.length;
148
+ const bodyHeight = Math.max(1, rows - reserved);
149
+ const maxScroll = Math.max(0, doc.lines.length - bodyHeight);
150
+ const scroll = Math.max(0, Math.min(state.scroll, maxScroll));
151
+ const gutterW = opts?.lineNumbers === true ? String(doc.lines.length).length : 0;
152
+ const contentW = bodyWidth(cols, gutterW);
153
+ // Effective pan: the stored offset, clamped to what this window can reach.
154
+ // Scrolling into narrow content parks the diagram offset rather than losing
155
+ // it, so scrolling back restores the same horizontal position.
156
+ const widest = widestVisibleRow(doc, scroll, bodyHeight);
157
+ const overflow = Math.max(0, widest - contentW);
158
+ const hscroll = Math.max(0, Math.min(state.hscroll, overflow));
159
+ const { lo, hi } = selectedUnitBounds(state);
160
+ const commented = commentedUnitSet(state);
161
+ const body = [];
162
+ for (const source of paintedBodyRows(doc, scroll, bodyHeight)) {
163
+ if (source.abs === null) {
164
+ // Indicator/fill rows reserve the same 4-col marker prefix and gutter a
165
+ // source row does, so the content column never shifts while scrolling.
166
+ body.push(` ${' '.repeat(gutterW > 0 ? gutterW + 1 : 0)}${source.line}`);
167
+ continue;
168
+ }
169
+ // Every body row is windowed into the body rectangle: a diagram wider than
170
+ // the pane pans instead of spilling past the right edge.
171
+ const row = panLine(source.line, hscroll, contentW);
172
+ const u = state.rowUnits[source.abs] ?? null;
173
+ // A row with no span is chrome (the code panel's border), not a source
174
+ // line — it gets blank gutter width rather than an invented line number.
175
+ const gutterLine = doc.spans[source.abs]?.[0];
176
+ const gutter = gutterW > 0
177
+ ? (gutterLine === undefined ? ' '.repeat(gutterW + 1) : `${DIM}${String(gutterLine).padStart(gutterW)}${RESET} `)
178
+ : '';
179
+ // Tint the prose column at minimum, and a wide row across what it occupies.
180
+ const tintW = Math.min(contentW, Math.max(docW, visibleWidth(row)));
181
+ if (u !== null && u >= lo && u <= hi)
182
+ body.push(` ${CYAN}▌${RESET} ${gutter}${tintRow(row, tintW)}`);
183
+ else if (u !== null && commented.has(u))
184
+ body.push(` ${YELLOW}▎${RESET} ${gutter}${row}`);
185
+ else
186
+ body.push(` ${gutter}${row}`);
187
+ }
188
+ while (body.length < bodyHeight)
189
+ body.push('');
190
+ // Keep the header, footer, and readable body rows in one stable centered
191
+ // column. A full-width diagram drops only its own row padding, so it can use
192
+ // the pane without shifting the surrounding review as it scrolls into view.
193
+ const readableFrameW = Math.min(cols, Math.max(maxW + 2, docW + 4 + (gutterW > 0 ? gutterW + 1 : 0)));
194
+ const centeredBody = body.map((line) => {
195
+ const frameW = visibleWidth(line) > readableFrameW ? cols : readableFrameW;
196
+ return centerHorizontal([line], cols, frameW)[0] ?? '';
197
+ });
198
+ const lines = [
199
+ ...centerHorizontal(header, cols, readableFrameW),
200
+ ...centeredBody,
201
+ ...centerHorizontal(footer, cols, readableFrameW),
202
+ ];
203
+ while (lines.length < rows)
204
+ lines.push('');
205
+ // The frame is contained by construction: no row may exceed the terminal, or
206
+ // it wraps and breaks the differ's one-line-per-row model.
207
+ return lines.slice(0, rows).map((line) => clipLine(line, cols));
208
+ }
209
+ /** How a reviewed file is presented: markdown renders as a document, anything
210
+ * else as a syntax-highlighted source panel. */
211
+ export function docSurface(absFile) {
212
+ return isMarkdownFile(absFile)
213
+ ? { doc: 'markdown' }
214
+ : { doc: 'code', language: fenceLanguageFor(absFile) };
215
+ }
@@ -0,0 +1,67 @@
1
+ /** A semantic keypress for the review surface. Textual commands retain their
2
+ * text because their meaning is mode-dependent: `j` navigates in view/list
3
+ * mode and inserts in compose mode, for example. */
4
+ export type ReviewKey = {
5
+ type: 'moveUnit';
6
+ delta: -1 | 1;
7
+ text: 'j' | 'k';
8
+ } | {
9
+ type: 'extendUnit';
10
+ delta: -1 | 1;
11
+ text: 'J' | 'K';
12
+ } | {
13
+ type: 'scrollPage';
14
+ delta: -1 | 1;
15
+ text?: 'u' | 'd';
16
+ } | {
17
+ type: 'pan';
18
+ delta: -1 | 1;
19
+ text?: 'h' | 'l';
20
+ } | {
21
+ type: 'leader';
22
+ text: ' ';
23
+ } | {
24
+ type: 'help';
25
+ text: '?';
26
+ } | {
27
+ type: 'listEdit';
28
+ text: 'e';
29
+ } | {
30
+ type: 'cancel';
31
+ text?: 'q';
32
+ } | {
33
+ type: 'confirm';
34
+ } | {
35
+ type: 'tab';
36
+ reverse: boolean;
37
+ } | {
38
+ type: 'composeNewline';
39
+ } | {
40
+ type: 'composeBackspace';
41
+ } | {
42
+ type: 'composeWordBackspace';
43
+ } | {
44
+ type: 'composeDelete';
45
+ } | {
46
+ type: 'composeHome';
47
+ } | {
48
+ type: 'composeEnd';
49
+ } | {
50
+ type: 'composeMove';
51
+ direction: 'wordLeft' | 'wordRight';
52
+ } | {
53
+ type: 'arrow';
54
+ direction: 'left' | 'right' | 'up' | 'down';
55
+ } | {
56
+ type: 'printable';
57
+ text: string;
58
+ } | {
59
+ type: 'paste';
60
+ text: string;
61
+ };
62
+ /** Return text that compose mode inserts. Semantic textual commands deliberately
63
+ * retain their payload so compose can preserve the old branch order. */
64
+ export declare function reviewKeyText(key: ReviewKey): string | undefined;
65
+ /** Match one complete pi-tui input chunk. pi-tui owns ESC/meta disambiguation;
66
+ * this function has neither terminal state nor a fallback raw-sequence parser. */
67
+ export declare function matchReviewKey(data: string): ReviewKey | null;
@@ -0,0 +1,130 @@
1
+ import { Key, decodeKittyPrintable, matchesKey, parseKey } from '@earendil-works/pi-tui';
2
+ /** pi-tui parses legacy ESC+lowercase as Alt+letter, but does not normalize
3
+ * the shifted uppercase form. Convert that complete two-byte form to the
4
+ * equivalent CSI-u key so all semantic matching stays in pi-tui. */
5
+ function normalizeLegacyShiftedMeta(data) {
6
+ if (data.length !== 2 || data[0] !== '\x1b' || !/[A-Z]/.test(data[1]))
7
+ return data;
8
+ return `\x1b[${data.charCodeAt(1)};4u`;
9
+ }
10
+ /** Return text that compose mode inserts. Semantic textual commands deliberately
11
+ * retain their payload so compose can preserve the old branch order. */
12
+ export function reviewKeyText(key) {
13
+ switch (key.type) {
14
+ case 'moveUnit':
15
+ case 'extendUnit':
16
+ case 'leader':
17
+ case 'help':
18
+ case 'listEdit':
19
+ case 'printable':
20
+ case 'paste':
21
+ return key.text;
22
+ case 'scrollPage':
23
+ case 'pan':
24
+ case 'cancel':
25
+ return key.text;
26
+ default:
27
+ return undefined;
28
+ }
29
+ }
30
+ /** Match one complete pi-tui input chunk. pi-tui owns ESC/meta disambiguation;
31
+ * this function has neither terminal state nor a fallback raw-sequence parser. */
32
+ export function matchReviewKey(data) {
33
+ const normalized = normalizeLegacyShiftedMeta(data);
34
+ // Compose-only chords precede their unmodified forms. The surface applies
35
+ // these only while composing, preserving the terminal-review mode ladder.
36
+ if (matchesKey(normalized, Key.ctrl('j')) || matchesKey(normalized, Key.alt('enter')))
37
+ return { type: 'composeNewline' };
38
+ if (matchesKey(normalized, Key.alt('backspace')) || matchesKey(normalized, Key.ctrl('w')))
39
+ return { type: 'composeWordBackspace' };
40
+ if (matchesKey(normalized, Key.backspace))
41
+ return { type: 'composeBackspace' };
42
+ if (matchesKey(normalized, Key.delete))
43
+ return { type: 'composeDelete' };
44
+ if (matchesKey(normalized, Key.alt('left')) || matchesKey(normalized, Key.ctrl('left')) || matchesKey(normalized, Key.super('left')) || matchesKey(normalized, Key.alt('b'))) {
45
+ return { type: 'composeMove', direction: 'wordLeft' };
46
+ }
47
+ if (matchesKey(normalized, Key.alt('right')) || matchesKey(normalized, Key.ctrl('right')) || matchesKey(normalized, Key.super('right')) || matchesKey(normalized, Key.alt('f'))) {
48
+ return { type: 'composeMove', direction: 'wordRight' };
49
+ }
50
+ if (matchesKey(normalized, Key.home) || matchesKey(normalized, Key.ctrl('a')))
51
+ return { type: 'composeHome' };
52
+ if (matchesKey(normalized, Key.end) || matchesKey(normalized, Key.ctrl('e')))
53
+ return { type: 'composeEnd' };
54
+ if (matchesKey(normalized, Key.shift('tab')))
55
+ return { type: 'tab', reverse: true };
56
+ if (matchesKey(normalized, Key.tab))
57
+ return { type: 'tab', reverse: false };
58
+ if (matchesKey(normalized, Key.enter))
59
+ return { type: 'confirm' };
60
+ if (matchesKey(normalized, Key.escape))
61
+ return { type: 'cancel' };
62
+ // Arrow keys remain distinct because each mode gives them its own meaning.
63
+ if (matchesKey(normalized, Key.up))
64
+ return { type: 'arrow', direction: 'up' };
65
+ if (matchesKey(normalized, Key.down))
66
+ return { type: 'arrow', direction: 'down' };
67
+ if (matchesKey(normalized, Key.left))
68
+ return { type: 'arrow', direction: 'left' };
69
+ if (matchesKey(normalized, Key.right))
70
+ return { type: 'arrow', direction: 'right' };
71
+ if (matchesKey(normalized, Key.pageUp))
72
+ return { type: 'scrollPage', delta: -1 };
73
+ if (matchesKey(normalized, Key.pageDown))
74
+ return { type: 'scrollPage', delta: 1 };
75
+ if (matchesKey(normalized, Key.shift('j')))
76
+ return { type: 'extendUnit', delta: 1, text: 'J' };
77
+ if (matchesKey(normalized, Key.shift('k')))
78
+ return { type: 'extendUnit', delta: -1, text: 'K' };
79
+ if (matchesKey(normalized, 'j'))
80
+ return { type: 'moveUnit', delta: 1, text: 'j' };
81
+ if (matchesKey(normalized, 'k'))
82
+ return { type: 'moveUnit', delta: -1, text: 'k' };
83
+ if (matchesKey(normalized, 'u'))
84
+ return { type: 'scrollPage', delta: -1, text: 'u' };
85
+ if (matchesKey(normalized, 'd'))
86
+ return { type: 'scrollPage', delta: 1, text: 'd' };
87
+ if (matchesKey(normalized, 'h'))
88
+ return { type: 'pan', delta: -1, text: 'h' };
89
+ if (matchesKey(normalized, 'l'))
90
+ return { type: 'pan', delta: 1, text: 'l' };
91
+ if (matchesKey(normalized, Key.space))
92
+ return { type: 'leader', text: ' ' };
93
+ if (matchesKey(normalized, Key.question))
94
+ return { type: 'help', text: '?' };
95
+ if (matchesKey(normalized, 'e'))
96
+ return { type: 'listEdit', text: 'e' };
97
+ if (matchesKey(normalized, 'q'))
98
+ return { type: 'cancel', text: 'q' };
99
+ const parsed = parseKey(normalized);
100
+ const text = printableText(data, parsed);
101
+ // Kitty reports question mark as Shift+Slash, so the unmodified-key matcher
102
+ // above cannot recognize it. Keep its text for compose through reviewKeyText.
103
+ if (text === '?')
104
+ return { type: 'help', text };
105
+ if (text !== undefined)
106
+ return { type: 'printable', text };
107
+ // A recognized but unhandled modified key (notably Alt+I) is not text or a
108
+ // paste. Its viewer-level owner may already have consumed it.
109
+ if (parsed !== undefined)
110
+ return null;
111
+ if ([...data].length > 1)
112
+ return { type: 'paste', text: data };
113
+ return null;
114
+ }
115
+ function printableText(data, parsed) {
116
+ const kitty = decodeKittyPrintable(data);
117
+ if (kitty !== undefined && isPrintable(kitty))
118
+ return kitty;
119
+ if (parsed !== undefined) {
120
+ const shifted = parsed.startsWith('shift+');
121
+ const candidate = shifted ? parsed.slice('shift+'.length) : parsed;
122
+ if ([...candidate].length === 1 && isPrintable(candidate)) {
123
+ return shifted && /^[a-z]$/.test(candidate) ? candidate.toUpperCase() : candidate;
124
+ }
125
+ }
126
+ return [...data].length === 1 && isPrintable(data) ? data : undefined;
127
+ }
128
+ function isPrintable(text) {
129
+ return !/\p{C}/u.test(text);
130
+ }
@@ -0,0 +1,10 @@
1
+ import type { TUI } from '@earendil-works/pi-tui';
2
+ import type { CanvasSource } from '../../../core/canvas/source.js';
3
+ import type { SurfaceHost } from '../../surfaces/host.js';
4
+ export interface ComposedReviewOptions {
5
+ reviewId: string;
6
+ tui: TUI;
7
+ canvasSource: CanvasSource;
8
+ }
9
+ /** Mount the canonical live-document and companion-conversation review. */
10
+ export declare function openComposedReview(host: SurfaceHost, opts: ComposedReviewOptions): Promise<void>;
@@ -0,0 +1,129 @@
1
+ import { ApiError } from '../../../api/errors.js';
2
+ import { CompanionRegion } from '../../conversation/region.js';
3
+ import { createCommentAuthority } from './comments-client.js';
4
+ import { ReviewCompositionComponent } from './composition.js';
5
+ import { DocumentRegion } from './document-region.js';
6
+ import { openLiveSource } from './live-source.js';
7
+ import { createReviewClient, ReviewTerminalError } from './review-client.js';
8
+ /** Mount the canonical live-document and companion-conversation review. */
9
+ export async function openComposedReview(host, opts) {
10
+ if (host.capabilities.remote) {
11
+ host.notice('The composed review is unavailable in a remote attach — the file and companion live on the host.');
12
+ return;
13
+ }
14
+ const reviewClient = createReviewClient();
15
+ let opened;
16
+ try {
17
+ opened = await reviewClient.open(opts.reviewId);
18
+ }
19
+ catch (error) {
20
+ host.notice(error instanceof ReviewTerminalError
21
+ ? terminalRefusalNotice(error)
22
+ : `couldn't open review: ${describeError(error)}`);
23
+ return;
24
+ }
25
+ let source;
26
+ try {
27
+ source = openLiveSource(opened.file);
28
+ }
29
+ catch (error) {
30
+ host.notice(`couldn't open ${opened.file}: ${describeError(error)}`);
31
+ return;
32
+ }
33
+ const comments = createCommentAuthority(opened.reviewId);
34
+ let handle;
35
+ let composition;
36
+ let submitting = false;
37
+ const documentRegion = new DocumentRegion({
38
+ reviewId: opened.reviewId,
39
+ absFile: opened.file,
40
+ cwd: opened.cwd,
41
+ source,
42
+ comments,
43
+ services: {
44
+ notice: (text) => host.notice(text),
45
+ suspendForChild: () => {
46
+ const resumeHost = host.suspendForChild();
47
+ const resumeComposition = composition?.suspendForChild() ?? (() => { });
48
+ let resumed = false;
49
+ return () => {
50
+ if (resumed)
51
+ return;
52
+ resumed = true;
53
+ resumeComposition();
54
+ resumeHost();
55
+ };
56
+ },
57
+ requestClose: () => handle?.close(),
58
+ submit: () => { void submit(); },
59
+ },
60
+ });
61
+ const companionRegion = new CompanionRegion({
62
+ companionNodeId: opened.companionNodeId,
63
+ tui: opts.tui,
64
+ canvasSource: opts.canvasSource,
65
+ reopenDormantCompanion: async () => {
66
+ await reviewClient.open(opened.reviewId);
67
+ },
68
+ onRequestClose: () => handle?.close(),
69
+ });
70
+ await documentRegion.open();
71
+ composition = new ReviewCompositionComponent({
72
+ document: documentRegion,
73
+ companion: companionRegion,
74
+ notice: (text) => host.notice(text),
75
+ onRequestClose: () => { },
76
+ });
77
+ handle = host.mount(composition);
78
+ composition.setHandle(handle);
79
+ void companionRegion.open();
80
+ async function submit() {
81
+ if (submitting)
82
+ return;
83
+ submitting = true;
84
+ try {
85
+ const result = await reviewClient.submit(opened.reviewId);
86
+ host.notice(approvalNotice(result));
87
+ handle?.close();
88
+ }
89
+ catch (error) {
90
+ const conflict = terminalConflictNotice(error);
91
+ if (conflict !== undefined) {
92
+ host.notice(conflict);
93
+ handle?.close();
94
+ return;
95
+ }
96
+ submitting = false;
97
+ host.notice(`couldn't submit review: ${describeError(error)}`);
98
+ }
99
+ }
100
+ }
101
+ function terminalRefusalNotice(error) {
102
+ if (error.state === 'approved')
103
+ return `This review was already approved. Result: ${error.resultPath ?? 'unknown'}`;
104
+ return error.reason === undefined || error.reason === '' ? 'This review was canceled.' : `This review was canceled: ${error.reason}`;
105
+ }
106
+ function approvalNotice(result) {
107
+ return result.changed
108
+ ? `Approved — the document changed during review. Result: ${result.resultPath}`
109
+ : `Approved — the document was not modified. Result: ${result.resultPath}`;
110
+ }
111
+ function terminalConflictNotice(error) {
112
+ if (!(error instanceof ApiError) || error.status !== 409 || error.code !== 'review_terminal_conflict')
113
+ return undefined;
114
+ const review = error.details?.review;
115
+ if (review === undefined)
116
+ return undefined;
117
+ if (review.state === 'approved')
118
+ return review.result_path === undefined
119
+ ? 'This review was already approved by someone else.'
120
+ : `This review was already approved by someone else. Result: ${review.result_path}`;
121
+ if (review.state === 'canceled')
122
+ return review.cancel_reason === undefined || review.cancel_reason === ''
123
+ ? 'This review was canceled before this submission landed.'
124
+ : `This review was canceled before this submission landed: ${review.cancel_reason}`;
125
+ return undefined;
126
+ }
127
+ function describeError(error) {
128
+ return error instanceof Error ? error.message : String(error);
129
+ }
@@ -0,0 +1,24 @@
1
+ /** The trailing delay used to collapse an editor's write/rename burst. */
2
+ export declare const COALESCE_MS = 120;
3
+ export type StaleReason = 'missing' | 'unreadable' | 'too-large' | 'binary';
4
+ export interface SourceSnapshot {
5
+ text: string;
6
+ lines: string[];
7
+ revision: number;
8
+ status: 'live' | 'stale';
9
+ staleReason?: StaleReason;
10
+ sha256: string;
11
+ loadedAt: string;
12
+ }
13
+ export interface LiveSource {
14
+ current(): SourceSnapshot;
15
+ /** The text captured when the surface opened. */
16
+ openText(): string;
17
+ /** Fires only when text changes or the live/stale status flips. */
18
+ onChange(fn: (next: SourceSnapshot, previous: SourceSnapshot) => void): void;
19
+ /** Read immediately, bypassing the directory watcher and coalescing timer. */
20
+ refreshNow(): void;
21
+ close(): void;
22
+ }
23
+ /** Watch the containing directory so atomic replacement of the file remains live. */
24
+ export declare function openLiveSource(absFile: string): LiveSource;