@north-light/crouter 0.3.172 → 0.3.174

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 (673) hide show
  1. package/bin/runtime-selector.mjs +8 -1
  2. package/dist/api/__tests__/{client.test.js → serial/client.test.js} +2 -135
  3. package/dist/api/client.d.ts +12 -21
  4. package/dist/api/client.js +22 -31
  5. package/dist/api/dto/broker-ops.d.ts +158 -0
  6. package/dist/api/dto/broker-ops.js +6 -0
  7. package/dist/api/dto/crons.d.ts +6 -0
  8. package/dist/api/dto/human.d.ts +7 -1
  9. package/dist/api/dto/inbox.d.ts +1 -71
  10. package/dist/api/dto/inbox.js +1 -9
  11. package/dist/api/dto/nodes.d.ts +6 -7
  12. package/dist/api/dto/reviews.d.ts +1 -11
  13. package/dist/api/routes.d.ts +7 -4
  14. package/dist/api/routes.js +8 -5
  15. package/dist/build-root.js +3 -3
  16. package/dist/builtin-memory/04-base-worker.md +1 -4
  17. package/dist/builtin-memory/05-kinds/advisor/00-base.md +1 -5
  18. package/dist/builtin-memory/05-kinds/advisor/01-orchestrator.md +2 -7
  19. package/dist/builtin-memory/05-kinds/design/00-base.md +1 -6
  20. package/dist/builtin-memory/05-kinds/developer/00-base.md +1 -6
  21. package/dist/builtin-memory/05-kinds/explore/00-base.md +1 -4
  22. package/dist/builtin-memory/05-kinds/explore/01-orchestrator.md +1 -2
  23. package/dist/builtin-memory/05-kinds/general/00-base.md +1 -3
  24. package/dist/builtin-memory/05-kinds/plan/00-base.md +1 -6
  25. package/dist/builtin-memory/05-kinds/plan/reviewers/00-base.md +1 -2
  26. package/dist/builtin-memory/05-kinds/plan/reviewers/architecture-fit.md +1 -3
  27. package/dist/builtin-memory/05-kinds/plan/reviewers/code-smells.md +1 -3
  28. package/dist/builtin-memory/05-kinds/plan/reviewers/pattern-consistency.md +1 -3
  29. package/dist/builtin-memory/05-kinds/plan/reviewers/requirements-coverage.md +1 -3
  30. package/dist/builtin-memory/05-kinds/plan/reviewers/security.md +1 -4
  31. package/dist/builtin-memory/05-kinds/review/companion/00-base.md +2 -3
  32. package/dist/builtin-memory/05-kinds/spec/00-base.md +1 -2
  33. package/dist/builtin-memory/advisor/council.md +1 -6
  34. package/dist/builtin-memory/design.md +2 -7
  35. package/dist/builtin-memory/development.md +9 -14
  36. package/dist/builtin-memory/internal/marketplaces.md +2 -6
  37. package/dist/builtin-memory/internal/nodes-and-canvas.md +1 -1
  38. package/dist/builtin-memory/internal/plugins.md +2 -8
  39. package/dist/builtin-memory/internal/storage-tiers.md +1 -2
  40. package/dist/builtin-memory/testing.md +41 -0
  41. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/{provider-rotation.test.ts → serial/provider-rotation.test.ts} +106 -177
  42. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/claude-plugin-commands.ts +5 -15
  43. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/frontmatter-rules/index.ts +1 -28
  44. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +43 -88
  45. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +55 -0
  46. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +60 -0
  47. package/dist/cli.js +2 -2
  48. package/dist/clients/attach/__tests__/attach-remote-readonly.test.js +37 -131
  49. package/dist/clients/attach/__tests__/chat-view-snapshot-ordering.test.js +71 -152
  50. package/dist/clients/attach/__tests__/context-message.test.js +16 -174
  51. package/dist/clients/attach/__tests__/crtr-output.test.js +36 -2069
  52. package/dist/clients/attach/__tests__/diagram.test.js +2 -2
  53. package/dist/clients/attach/__tests__/edit-diff.test.js +0 -4
  54. package/dist/clients/attach/__tests__/file-review-focus.test.js +2 -1
  55. package/dist/clients/attach/__tests__/group-activity.test.js +40 -229
  56. package/dist/clients/attach/__tests__/oauth-dialog-lifecycle.test.js +26 -76
  57. package/dist/clients/attach/__tests__/prompt-preview.test.js +4 -70
  58. package/dist/clients/attach/__tests__/ref-autocomplete.test.js +11 -125
  59. package/dist/clients/attach/__tests__/titled-editor-preview.test.js +14 -205
  60. package/dist/clients/attach/command.d.ts +2 -1
  61. package/dist/clients/attach/command.js +81 -76
  62. package/dist/clients/attach/input/capabilities.d.ts +27 -0
  63. package/dist/clients/attach/input/capabilities.js +96 -0
  64. package/dist/clients/attach/input/controller.d.ts +20 -182
  65. package/dist/clients/attach/input/controller.js +128 -537
  66. package/dist/clients/attach/input/overlay-owner.d.ts +41 -0
  67. package/dist/clients/attach/input/overlay-owner.js +199 -0
  68. package/dist/clients/attach/overlays/file-review.d.ts +0 -4
  69. package/dist/clients/attach/overlays/file-review.js +13 -5
  70. package/dist/clients/attach/overlays/graph.js +2 -10
  71. package/dist/clients/attach/render/chat-view.d.ts +4 -3
  72. package/dist/clients/attach/render/chat-view.js +39 -33
  73. package/dist/clients/attach/render/group-activity.d.ts +1 -0
  74. package/dist/clients/attach/render/group-activity.js +20 -13
  75. package/dist/clients/attach/render/group-recap.js +12 -3
  76. package/dist/clients/attach/session/connection.js +9 -15
  77. package/dist/clients/attach/session/editor-inventory.d.ts +6 -5
  78. package/dist/clients/attach/session/editor-inventory.js +7 -8
  79. package/dist/clients/attach/session/file-links.d.ts +13 -0
  80. package/dist/clients/attach/session/file-links.js +107 -0
  81. package/dist/clients/attach/session/frame.d.ts +3 -0
  82. package/dist/clients/attach/session/frame.js +10 -1
  83. package/dist/clients/attach/session/frames.js +2 -3
  84. package/dist/clients/attach/session/input-wiring.d.ts +4 -1
  85. package/dist/clients/attach/session/input-wiring.js +15 -14
  86. package/dist/clients/attach/session/mouse.d.ts +6 -1
  87. package/dist/clients/attach/session/mouse.js +8 -5
  88. package/dist/clients/attach/session/profile-files.js +18 -12
  89. package/dist/clients/attach/session/reconnect.js +1 -1
  90. package/dist/clients/attach/session/state-sync.js +1 -2
  91. package/dist/clients/attach/session/surface-host.d.ts +3 -2
  92. package/dist/clients/attach/session/surface-host.js +4 -4
  93. package/dist/clients/attach/slash/dispatch.d.ts +8 -31
  94. package/dist/clients/attach/slash/dispatch.js +34 -81
  95. package/dist/clients/attach/viewer.js +820 -860
  96. package/dist/clients/conversation/projection.d.ts +79 -0
  97. package/dist/clients/conversation/projection.js +341 -0
  98. package/dist/clients/inbox/__tests__/serial/inbox-controller.test.js +159 -0
  99. package/dist/clients/inbox/__tests__/serial/mount-panel.test.js +151 -0
  100. package/dist/clients/inbox/controller.d.ts +0 -4
  101. package/dist/clients/inbox/controller.js +0 -2
  102. package/dist/clients/inbox/review/__tests__/review-core.test.js +4 -293
  103. package/dist/clients/inbox/review/__tests__/teardown-notice.test.js +100 -0
  104. package/dist/clients/inbox/review/comments-client.d.ts +3 -2
  105. package/dist/clients/inbox/review/comments-client.js +12 -12
  106. package/dist/clients/inbox/review/companion-pane.d.ts +30 -0
  107. package/dist/clients/inbox/review/companion-pane.js +86 -0
  108. package/dist/clients/inbox/review/document-surface.d.ts +182 -0
  109. package/dist/clients/inbox/review/{document-region.js → document-surface.js} +252 -48
  110. package/dist/clients/inbox/review/frame.js +5 -4
  111. package/dist/clients/inbox/review/launch.d.ts +8 -8
  112. package/dist/clients/inbox/review/launch.js +52 -92
  113. package/dist/clients/inbox/review/nvim.d.ts +2 -0
  114. package/dist/clients/inbox/review/nvim.js +14 -12
  115. package/dist/clients/inbox/review/review-client.d.ts +12 -8
  116. package/dist/clients/inbox/review/review-client.js +46 -35
  117. package/dist/clients/inbox/review-adapter.d.ts +3 -10
  118. package/dist/clients/inbox/review-adapter.js +27 -19
  119. package/dist/clients/inbox/surface.d.ts +0 -4
  120. package/dist/clients/inbox/surface.js +0 -2
  121. package/dist/clients/surfaces/host.d.ts +11 -3
  122. package/dist/commands/__tests__/api-client-cold-start-diagnostic.test.js +7 -34
  123. package/dist/commands/__tests__/human.test.js +11 -322
  124. package/dist/commands/api-client.d.ts +5 -5
  125. package/dist/commands/api-client.js +6 -85
  126. package/dist/commands/canvas-browse.js +3 -29
  127. package/dist/commands/canvas-config.js +1 -1
  128. package/dist/commands/canvas-use.js +3 -3
  129. package/dist/commands/canvas.js +1 -1
  130. package/dist/commands/cron.js +5 -1
  131. package/dist/commands/human/queue.d.ts +0 -4
  132. package/dist/commands/human/queue.js +7 -40
  133. package/dist/commands/memory/list.d.ts +14 -0
  134. package/dist/commands/memory/list.js +35 -31
  135. package/dist/commands/memory/read.d.ts +7 -0
  136. package/dist/commands/memory/read.js +14 -8
  137. package/dist/commands/node/bash.d.ts +1 -0
  138. package/dist/commands/node/bash.js +198 -0
  139. package/dist/commands/node/create.d.ts +23 -0
  140. package/dist/commands/node/create.js +207 -0
  141. package/dist/commands/node/inspect.d.ts +2 -0
  142. package/dist/commands/node/inspect.js +302 -0
  143. package/dist/commands/node/lifecycle.d.ts +4 -0
  144. package/dist/commands/node/lifecycle.js +415 -0
  145. package/dist/commands/node/message.d.ts +1 -0
  146. package/dist/commands/node/message.js +164 -0
  147. package/dist/commands/node/pyramid.d.ts +2 -0
  148. package/dist/commands/node/pyramid.js +79 -0
  149. package/dist/commands/node/subscription.d.ts +1 -0
  150. package/dist/commands/node/subscription.js +82 -0
  151. package/dist/commands/node/wait.d.ts +1 -0
  152. package/dist/commands/node/wait.js +159 -0
  153. package/dist/commands/node-lifecycle-revive.js +10 -57
  154. package/dist/commands/node.d.ts +0 -42
  155. package/dist/commands/node.js +11 -2065
  156. package/dist/commands/search.js +1 -1
  157. package/dist/commands/surface/node/cycle.d.ts +1 -0
  158. package/dist/commands/surface/node/cycle.js +83 -0
  159. package/dist/commands/surface/node/focus.d.ts +1 -0
  160. package/dist/commands/surface/node/focus.js +67 -0
  161. package/dist/commands/surface/node/id.d.ts +1 -0
  162. package/dist/commands/surface/node/id.js +38 -0
  163. package/dist/commands/surface/node/pin.d.ts +1 -0
  164. package/dist/commands/surface/node/pin.js +42 -0
  165. package/dist/commands/surface/node/placement.d.ts +46 -0
  166. package/dist/commands/surface/node/placement.js +124 -0
  167. package/dist/commands/surface-node.js +4 -1
  168. package/dist/commands/surface-reload.js +1 -2
  169. package/dist/commands/surface-tmux-spread.js +1 -1
  170. package/dist/commands/surface.js +5 -20
  171. package/dist/commands/sys/__tests__/setup-core.test.js +18 -271
  172. package/dist/commands/sys/config.js +6 -6
  173. package/dist/commands/sys/logs.js +1 -1
  174. package/dist/commands/sys/panels/broker-limits-panel.d.ts +17 -0
  175. package/dist/commands/sys/panels/broker-limits-panel.js +104 -0
  176. package/dist/commands/sys/panels/dependencies-panel.d.ts +14 -0
  177. package/dist/commands/sys/panels/dependencies-panel.js +80 -0
  178. package/dist/commands/sys/panels/keybindings-panel.d.ts +56 -0
  179. package/dist/commands/sys/panels/keybindings-panel.js +703 -0
  180. package/dist/commands/sys/panels/keys-panel.d.ts +16 -0
  181. package/dist/commands/sys/panels/keys-panel.js +60 -0
  182. package/dist/commands/sys/panels/models-panel.d.ts +77 -0
  183. package/dist/commands/sys/panels/models-panel.js +647 -0
  184. package/dist/commands/sys/panels/panel.d.ts +45 -0
  185. package/dist/commands/sys/panels/panel.js +137 -0
  186. package/dist/commands/sys/panels/plugins-panel.d.ts +16 -0
  187. package/dist/commands/sys/panels/plugins-panel.js +80 -0
  188. package/dist/commands/sys/panels/prefs-panel.d.ts +21 -0
  189. package/dist/commands/sys/panels/prefs-panel.js +85 -0
  190. package/dist/commands/sys/panels/provider-panel.d.ts +62 -0
  191. package/dist/commands/sys/panels/provider-panel.js +538 -0
  192. package/dist/commands/sys/settings-shell.d.ts +55 -0
  193. package/dist/commands/sys/settings-shell.js +400 -0
  194. package/dist/commands/sys/settings.d.ts +2 -0
  195. package/dist/commands/sys/settings.js +31 -0
  196. package/dist/commands/sys/setup-core.d.ts +3 -33
  197. package/dist/commands/sys/setup-core.js +27 -78
  198. package/dist/commands/sys/setup-settings-runner.d.ts +24 -0
  199. package/dist/commands/sys/setup-settings-runner.js +63 -0
  200. package/dist/commands/sys/setup-wizard.d.ts +26 -125
  201. package/dist/commands/sys/setup-wizard.js +209 -2473
  202. package/dist/commands/sys/setup.js +5 -7
  203. package/dist/commands/sys.js +3 -2
  204. package/dist/core/__tests__/broker-extension-canvas-db-boundary.test.js +50 -0
  205. package/dist/core/__tests__/broker-launch-candidates.test.js +20 -9
  206. package/dist/core/__tests__/broker-preflight.test.js +1 -1
  207. package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +108 -27
  208. package/dist/core/__tests__/canvas-inbox-watcher.test.js +14 -0
  209. package/dist/core/__tests__/canvas.test.js +2 -36
  210. package/dist/core/__tests__/close.test.js +14 -3
  211. package/dist/core/__tests__/context-intro.test.js +32 -143
  212. package/dist/core/__tests__/cron-broker-capacity.test.js +22 -3
  213. package/dist/core/__tests__/daemon-boot.test.js +2 -20
  214. package/dist/core/__tests__/daemon-wedge.test.js +1 -1
  215. package/dist/core/__tests__/dead-node-policy-table.test.js +1 -18
  216. package/dist/core/__tests__/fixtures/fake-engine.d.ts +1 -1
  217. package/dist/core/__tests__/fixtures/fake-engine.js +2 -2
  218. package/dist/core/__tests__/fixtures/fake-pi-host.js +2 -2
  219. package/dist/core/__tests__/focuses.test.js +4 -98
  220. package/dist/core/__tests__/helpers/broker-clients.d.ts +0 -3
  221. package/dist/core/__tests__/helpers/broker-clients.js +0 -14
  222. package/dist/core/__tests__/helpers/harness.d.ts +0 -8
  223. package/dist/core/__tests__/helpers/harness.js +7 -87
  224. package/dist/core/__tests__/helpers/viewer-panes.js +1 -1
  225. package/dist/core/__tests__/inline-memory-refs.test.js +5 -134
  226. package/dist/core/__tests__/kickoff.test.js +1 -1
  227. package/dist/core/__tests__/memory-resolver-precedence.test.js +29 -1
  228. package/dist/core/__tests__/migration.test.js +35 -48
  229. package/dist/core/__tests__/on-read-dedup-resume.test.js +22 -12
  230. package/dist/core/__tests__/passive-subscription.test.js +26 -49
  231. package/dist/core/__tests__/preview-registry-sync.test.js +1 -2
  232. package/dist/core/__tests__/prune.test.js +94 -1
  233. package/dist/core/__tests__/review-model-floor.test.js +0 -32
  234. package/dist/core/__tests__/seam/broker-attach-multiclient.test.js +255 -0
  235. package/dist/core/__tests__/{full → seam}/broker-attach-stream.test.js +39 -7
  236. package/dist/core/__tests__/{full → seam}/broker-crash-teardown.test.js +30 -29
  237. package/dist/core/__tests__/{full → seam}/broker-pane-resolution.test.js +54 -5
  238. package/dist/core/__tests__/{full → seam}/broker-provider-retry.test.js +134 -82
  239. package/dist/core/__tests__/{full → seam}/broker-whip-interrupt.test.js +15 -4
  240. package/dist/core/__tests__/{full/idle-release-settlement.test.js → seam/dormancy-release.test.js} +69 -17
  241. package/dist/core/__tests__/{full/yield-message-transaction.test.js → seam/yield-refresh-transaction.test.js} +31 -9
  242. package/dist/core/__tests__/secrets.test.js +1 -7
  243. package/dist/core/__tests__/{broker-fork-seam.test.js → serial/broker-fork-seam.test.js} +58 -7
  244. package/dist/core/__tests__/{broker-sdk-wiring.test.js → serial/broker-sdk-wiring.test.js} +18 -162
  245. package/dist/core/__tests__/{broker-snapshot-history.test.js → serial/broker-snapshot-history.test.js} +9 -9
  246. package/dist/core/__tests__/{command-plugins.test.js → serial/command-plugins.test.js} +105 -15
  247. package/dist/core/__tests__/{deferred-no-wake.test.js → serial/deferred-no-wake.test.js} +23 -20
  248. package/dist/core/__tests__/{flagship-lifecycle.test.js → serial/flagship-lifecycle.test.js} +7 -7
  249. package/dist/core/__tests__/{host-teardown-process-group.test.js → serial/host-teardown-process-group.test.js} +6 -6
  250. package/dist/core/__tests__/{human-deliver-e2e.test.js → serial/human-deliver-e2e.test.js} +12 -12
  251. package/dist/core/__tests__/{live-mutation.test.js → serial/live-mutation.test.js} +5 -5
  252. package/dist/core/__tests__/{refresh-stall-recycle.test.js → serial/refresh-stall-recycle.test.js} +5 -14
  253. package/dist/core/__tests__/{revive.test.js → serial/revive.test.js} +15 -100
  254. package/dist/core/__tests__/{spawn-root.test.js → serial/spawn-root.test.js} +32 -15
  255. package/dist/core/__tests__/serial/subscription-delivery.test.js +126 -0
  256. package/dist/core/__tests__/serial/tmux-surface.test.js +256 -0
  257. package/dist/core/__tests__/{worktree.test.js → serial/worktree.test.js} +15 -15
  258. package/dist/core/__tests__/session-model.test.js +0 -18
  259. package/dist/core/__tests__/spawn-worktree-id-conflict.test.js +9 -0
  260. package/dist/core/__tests__/watchdog-abort-arms-retry.test.js +50 -0
  261. package/dist/core/broker-client/__tests__/transport-relay.test.js +15 -16
  262. package/dist/core/broker-client/__tests__/transport-socket.test.js +28 -0
  263. package/dist/core/broker-client/client.d.ts +2 -2
  264. package/dist/core/broker-client/client.js +4 -7
  265. package/dist/core/broker-client/transport-relay.d.ts +13 -19
  266. package/dist/core/broker-client/transport-relay.js +19 -34
  267. package/dist/core/broker-client/transport-socket.d.ts +2 -2
  268. package/dist/core/broker-client/transport-socket.js +9 -2
  269. package/dist/core/broker-client/transport.d.ts +7 -3
  270. package/dist/core/broker-client/transport.js +4 -4
  271. package/dist/core/canvas/__tests__/attention.test.js +1 -18
  272. package/dist/core/canvas/__tests__/remote-canvas-source.test.js +7 -64
  273. package/dist/core/canvas/__tests__/remote-transport.test.js +2 -3
  274. package/dist/core/canvas/__tests__/render-remote.test.js +7 -52
  275. package/dist/core/canvas/browse/app.d.ts +2 -17
  276. package/dist/core/canvas/browse/app.js +16 -88
  277. package/dist/core/canvas/browse/model.d.ts +0 -4
  278. package/dist/core/canvas/browse/model.js +1 -12
  279. package/dist/core/canvas/browse/render.js +6 -3
  280. package/dist/core/canvas/crons.d.ts +8 -5
  281. package/dist/core/canvas/crons.js +7 -6
  282. package/dist/core/canvas/extensions.d.ts +7 -3
  283. package/dist/core/canvas/extensions.js +16 -4
  284. package/dist/core/canvas/nav-model.d.ts +0 -4
  285. package/dist/core/canvas/nav-model.js +2 -14
  286. package/dist/core/canvas/node-order.d.ts +3 -0
  287. package/dist/core/canvas/node-order.js +12 -0
  288. package/dist/core/canvas/remote-canvas-source.d.ts +3 -6
  289. package/dist/core/canvas/remote-canvas-source.js +8 -15
  290. package/dist/core/command.js +11 -4
  291. package/dist/core/config.js +3 -1
  292. package/dist/core/events/envelope.js +1 -1
  293. package/dist/core/events/read.js +7 -21
  294. package/dist/core/events/source.d.ts +0 -2
  295. package/dist/core/events/source.js +0 -16
  296. package/dist/core/events/types.d.ts +1 -1
  297. package/dist/core/fault-classifier.d.ts +1 -1
  298. package/dist/core/feed/passive.d.ts +0 -11
  299. package/dist/core/feed/passive.js +1 -62
  300. package/dist/core/human/__tests__/{inbox-core.test.js → serial/inbox-core.test.js} +6 -6
  301. package/dist/core/keybindings/__tests__/resolve.test.js +1 -96
  302. package/dist/core/keybindings/background-bash.js +3 -4
  303. package/dist/core/keybindings/catalog.js +1 -1
  304. package/dist/core/memory/inline-ref-grammar.js +3 -3
  305. package/dist/core/memory-resolver.d.ts +11 -25
  306. package/dist/core/memory-resolver.js +51 -33
  307. package/dist/core/model-routes.d.ts +15 -0
  308. package/dist/core/model-routes.js +12 -0
  309. package/dist/core/pool-credential-store.js +1 -1
  310. package/dist/core/preview-registry.js +8 -9
  311. package/dist/core/profiles/__tests__/root-profile.test.js +4 -14
  312. package/dist/core/review/realize.d.ts +0 -13
  313. package/dist/core/review/realize.js +0 -40
  314. package/dist/core/review/types.d.ts +1 -1
  315. package/dist/core/runtime/__tests__/engine-route.test.js +2 -2
  316. package/dist/core/runtime/bearings.js +1 -11
  317. package/dist/core/runtime/broker/client-registry.d.ts +33 -0
  318. package/dist/core/runtime/broker/client-registry.js +164 -0
  319. package/dist/core/runtime/broker/daemon-ops.d.ts +19 -0
  320. package/dist/core/runtime/broker/daemon-ops.js +49 -0
  321. package/dist/core/runtime/broker/event-projection.d.ts +42 -0
  322. package/dist/core/runtime/broker/event-projection.js +178 -0
  323. package/dist/core/runtime/broker/fault-retry.d.ts +39 -0
  324. package/dist/core/runtime/broker/fault-retry.js +277 -0
  325. package/dist/core/runtime/broker/frame-dispatch.d.ts +238 -0
  326. package/dist/core/runtime/broker/frame-dispatch.js +1537 -0
  327. package/dist/core/runtime/broker/inbox.d.ts +22 -0
  328. package/dist/core/runtime/broker/inbox.js +167 -0
  329. package/dist/core/runtime/broker/passive.d.ts +16 -0
  330. package/dist/core/runtime/broker/passive.js +44 -0
  331. package/dist/core/runtime/broker/read-ops.d.ts +23 -0
  332. package/dist/core/runtime/broker/read-ops.js +150 -0
  333. package/dist/core/runtime/broker/rebind.d.ts +74 -0
  334. package/dist/core/runtime/broker/rebind.js +211 -0
  335. package/dist/core/runtime/broker/tool-groups.d.ts +39 -0
  336. package/dist/core/runtime/broker/tool-groups.js +244 -0
  337. package/dist/core/runtime/broker-extension-render.d.ts +11 -0
  338. package/dist/core/runtime/broker-extension-render.js +181 -0
  339. package/dist/core/runtime/broker-persona-guidance.d.ts +13 -0
  340. package/dist/core/runtime/broker-persona-guidance.js +58 -0
  341. package/dist/core/runtime/broker-protocol.d.ts +1 -1
  342. package/dist/core/runtime/broker-protocol.js +1 -1
  343. package/dist/core/runtime/broker.d.ts +5 -196
  344. package/dist/core/runtime/broker.js +276 -3059
  345. package/dist/core/runtime/canvas-extensions.js +11 -2
  346. package/dist/core/runtime/fault.js +1 -1
  347. package/dist/core/runtime/model-selection.d.ts +9 -0
  348. package/dist/core/runtime/model-selection.js +12 -0
  349. package/dist/core/runtime/model-swap.d.ts +3 -3
  350. package/dist/core/runtime/model-swap.js +33 -25
  351. package/dist/core/runtime/placement-tmux.d.ts +3 -14
  352. package/dist/core/runtime/placement-tmux.js +11 -80
  353. package/dist/core/runtime/placement.d.ts +4 -2
  354. package/dist/core/runtime/placement.js +7 -12
  355. package/dist/core/runtime/promote.d.ts +14 -1
  356. package/dist/core/runtime/promote.js +1 -1
  357. package/dist/core/runtime/reset.d.ts +1 -1
  358. package/dist/core/runtime/roadmap.js +1 -1
  359. package/dist/core/runtime/spawn.d.ts +8 -0
  360. package/dist/core/runtime/spawn.js +36 -6
  361. package/dist/core/runtime/stop-guard.d.ts +4 -3
  362. package/dist/core/runtime/stop-guard.js +36 -18
  363. package/dist/core/runtime/stop-signals.d.ts +4 -1
  364. package/dist/core/runtime/stream-watchdog.js +4 -5
  365. package/dist/core/runtime/structured-output.d.ts +15 -2
  366. package/dist/core/runtime/structured-output.js +35 -12
  367. package/dist/core/runtime/tmux-bindings.d.ts +25 -0
  368. package/dist/core/runtime/tmux-bindings.js +682 -0
  369. package/dist/core/runtime/tmux-chrome.d.ts +2 -1
  370. package/dist/core/runtime/tmux-chrome.js +3 -2
  371. package/dist/core/runtime/{tmux.d.ts → tmux-driver.d.ts} +18 -26
  372. package/dist/core/runtime/tmux-driver.js +598 -0
  373. package/dist/core/runtime/view-socket.d.ts +14 -0
  374. package/dist/core/runtime/view-socket.js +83 -0
  375. package/dist/core/session-model/session-state.d.ts +1 -2
  376. package/dist/core/session-model/session-state.js +5 -8
  377. package/dist/core/spawn.d.ts +1 -1
  378. package/dist/core/spawn.js +2 -2
  379. package/dist/core/substrate/gate.d.ts +1 -1
  380. package/dist/core/substrate/on-read-pure.d.ts +7 -0
  381. package/dist/core/substrate/on-read-pure.js +272 -0
  382. package/dist/core/termrender/termrender.js +32 -2
  383. package/dist/core/user-settings.d.ts +23 -1
  384. package/dist/core/user-settings.js +18 -1
  385. package/dist/daemon/api/__tests__/node-model-validation.test.js +134 -0
  386. package/dist/daemon/api/__tests__/review-terminal-conflict.test.js +98 -0
  387. package/dist/daemon/api/__tests__/{full → seam}/api-server.test.js +6 -48
  388. package/dist/daemon/api/__tests__/{full → seam}/b10-attach-modelauth.test.js +17 -44
  389. package/dist/daemon/api/__tests__/{full/push-parity.test.js → seam/leaf-api-parity.test.js} +61 -42
  390. package/dist/daemon/api/bridge.js +40 -81
  391. package/dist/daemon/api/handlers/broker-ops.d.ts +2 -0
  392. package/dist/daemon/api/handlers/broker-ops.js +383 -0
  393. package/dist/daemon/api/handlers/crons.js +9 -4
  394. package/dist/daemon/api/handlers/files.js +6 -7
  395. package/dist/daemon/api/handlers/inbox.js +2 -340
  396. package/dist/daemon/api/handlers/nodes.d.ts +10 -1
  397. package/dist/daemon/api/handlers/nodes.js +74 -39
  398. package/dist/daemon/api/handlers/review-comments.js +5 -1
  399. package/dist/daemon/api/handlers/reviews.js +0 -19
  400. package/dist/daemon/api/map.js +25 -4
  401. package/dist/daemon/api/router.js +2 -3
  402. package/dist/daemon/api/server.js +5 -7
  403. package/dist/daemon/cron-run.d.ts +4 -0
  404. package/dist/daemon/cron-run.js +30 -13
  405. package/dist/daemon/crtrd.d.ts +3 -58
  406. package/dist/daemon/crtrd.js +28 -1244
  407. package/dist/daemon/manage.js +0 -1
  408. package/dist/daemon/reconcilers/broker-supervision.d.ts +50 -0
  409. package/dist/daemon/reconcilers/broker-supervision.js +549 -0
  410. package/dist/daemon/reconcilers/cron-lane.d.ts +10 -0
  411. package/dist/daemon/reconcilers/cron-lane.js +32 -0
  412. package/dist/daemon/reconcilers/dormant-inbox.d.ts +18 -0
  413. package/dist/daemon/reconcilers/dormant-inbox.js +143 -0
  414. package/dist/daemon/reconcilers/storage-maintenance.d.ts +22 -0
  415. package/dist/daemon/reconcilers/storage-maintenance.js +213 -0
  416. package/dist/daemon/review/finish.js +2 -5
  417. package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +34 -53
  418. package/dist/pi-extensions/__tests__/canvas-recap.test.js +16 -113
  419. package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +72 -99
  420. package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.js +29 -12
  421. package/dist/pi-extensions/broker-local.d.ts +20 -0
  422. package/dist/pi-extensions/broker-local.js +89 -0
  423. package/dist/pi-extensions/canvas-context-intro.d.ts +3 -3
  424. package/dist/pi-extensions/canvas-context-intro.js +22 -11
  425. package/dist/pi-extensions/canvas-doc-substrate.js +17 -34
  426. package/dist/pi-extensions/canvas-goal-capture.js +7 -12
  427. package/dist/pi-extensions/canvas-inbox-watcher.js +124 -139
  428. package/dist/pi-extensions/canvas-passive-context.d.ts +3 -3
  429. package/dist/pi-extensions/canvas-passive-context.js +22 -18
  430. package/dist/pi-extensions/canvas-recap.d.ts +2 -2
  431. package/dist/pi-extensions/canvas-recap.js +48 -21
  432. package/dist/pi-extensions/canvas-review-boundary.js +10 -4
  433. package/dist/pi-extensions/canvas-stophook.d.ts +0 -5
  434. package/dist/pi-extensions/canvas-stophook.js +149 -431
  435. package/dist/pi-extensions/canvas-structured-output.js +52 -30
  436. package/dist/pi-extensions/envelope-merge.d.ts +13 -0
  437. package/dist/pi-extensions/envelope-merge.js +29 -0
  438. package/dist/shared/working-activity.d.ts +3 -2
  439. package/dist/shared/working-activity.js +3 -2
  440. package/dist/types.d.ts +6 -5
  441. package/dist/types.js +2 -2
  442. package/docs/compat/hearth-crtr-v1.md +4 -12
  443. package/docs/compat/hearth-crtr-v2.md +3 -11
  444. package/docs/compat/hearth-crtr-v3.md +4 -12
  445. package/docs/compat/hearth-crtr-v4.md +3 -11
  446. package/docs/compat/hearth-crtr-v5.md +3 -11
  447. package/docs/public-api.md +3 -7
  448. package/package.json +7 -49
  449. package/runtime.lock.json +2766 -14533
  450. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/claude-plugin-commands.test.ts +0 -49
  451. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/memory-slash-commands.test.ts +0 -194
  452. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/statusline.test.ts +0 -68
  453. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/frontmatter-rules/test.ts +0 -119
  454. package/dist/clients/attach/__tests__/attach-chrome-remote.test.js +0 -439
  455. package/dist/clients/attach/__tests__/attach-keybindings.test.js +0 -170
  456. package/dist/clients/attach/__tests__/crtr-output-coverage.test.js +0 -57
  457. package/dist/clients/attach/__tests__/editor-frame-title.test.js +0 -19
  458. package/dist/clients/attach/__tests__/input-controller-extension-command.test.js +0 -32
  459. package/dist/clients/attach/__tests__/markdown-headings.test.js +0 -35
  460. package/dist/clients/attach/__tests__/session-identity-refresh.test.js +0 -32
  461. package/dist/clients/conversation/conversation.d.ts +0 -65
  462. package/dist/clients/conversation/conversation.js +0 -318
  463. package/dist/clients/conversation/frames.d.ts +0 -30
  464. package/dist/clients/conversation/frames.js +0 -52
  465. package/dist/clients/conversation/region.d.ts +0 -51
  466. package/dist/clients/conversation/region.js +0 -265
  467. package/dist/clients/inbox/__tests__/inbox-controller.test.js +0 -247
  468. package/dist/clients/inbox/__tests__/mount-panel.test.js +0 -776
  469. package/dist/clients/inbox/review/__tests__/remap.test.js +0 -196
  470. package/dist/clients/inbox/review/columns.d.ts +0 -22
  471. package/dist/clients/inbox/review/columns.js +0 -40
  472. package/dist/clients/inbox/review/composition.d.ts +0 -60
  473. package/dist/clients/inbox/review/composition.js +0 -278
  474. package/dist/clients/inbox/review/document-region.d.ts +0 -120
  475. package/dist/clients/surfaces/region.d.ts +0 -16
  476. package/dist/clients/web/__tests__/push-engine.test.js +0 -158
  477. package/dist/clients/web/__tests__/push-registry.test.d.ts +0 -1
  478. package/dist/clients/web/__tests__/push-registry.test.js +0 -177
  479. package/dist/clients/web/dev-server.d.ts +0 -7
  480. package/dist/clients/web/dev-server.js +0 -46
  481. package/dist/clients/web/events.d.ts +0 -19
  482. package/dist/clients/web/events.js +0 -163
  483. package/dist/clients/web/push-engine.d.ts +0 -44
  484. package/dist/clients/web/push-engine.js +0 -125
  485. package/dist/clients/web/push-registry.d.ts +0 -85
  486. package/dist/clients/web/push-registry.js +0 -373
  487. package/dist/clients/web/server.d.ts +0 -19
  488. package/dist/clients/web/server.js +0 -661
  489. package/dist/clients/web/web-client/shared/protocol.d.ts +0 -214
  490. package/dist/clients/web/web-client/shared/protocol.js +0 -8
  491. package/dist/clients/web/web-cmd.d.ts +0 -2
  492. package/dist/clients/web/web-cmd.js +0 -141
  493. package/dist/commands/__tests__/api-canvas-source.test.d.ts +0 -1
  494. package/dist/commands/__tests__/api-canvas-source.test.js +0 -37
  495. package/dist/commands/__tests__/canvas-config.test.d.ts +0 -1
  496. package/dist/commands/__tests__/canvas-config.test.js +0 -107
  497. package/dist/commands/__tests__/node-no-kickoff-flag.test.d.ts +0 -1
  498. package/dist/commands/__tests__/node-no-kickoff-flag.test.js +0 -73
  499. package/dist/commands/__tests__/node-worktree-flag.test.d.ts +0 -1
  500. package/dist/commands/__tests__/node-worktree-flag.test.js +0 -49
  501. package/dist/commands/__tests__/search-contents.test.d.ts +0 -1
  502. package/dist/commands/__tests__/search-contents.test.js +0 -52
  503. package/dist/commands/memory/__tests__/lint.test.d.ts +0 -1
  504. package/dist/commands/memory/__tests__/lint.test.js +0 -15
  505. package/dist/commands/sys/__tests__/config-broker-thresholds.test.d.ts +0 -1
  506. package/dist/commands/sys/__tests__/config-broker-thresholds.test.js +0 -95
  507. package/dist/commands/sys/__tests__/config-keybindings.test.d.ts +0 -1
  508. package/dist/commands/sys/__tests__/config-keybindings.test.js +0 -55
  509. package/dist/commands/sys/__tests__/helpers/setup-runtime.d.ts +0 -5
  510. package/dist/commands/sys/__tests__/helpers/setup-runtime.js +0 -19
  511. package/dist/commands/sys/__tests__/setup-front-door.test.d.ts +0 -1
  512. package/dist/commands/sys/__tests__/setup-front-door.test.js +0 -102
  513. package/dist/commands/sys/__tests__/setup-models.test.d.ts +0 -1
  514. package/dist/commands/sys/__tests__/setup-models.test.js +0 -205
  515. package/dist/commands/sys/__tests__/setup-providers-viewport.test.d.ts +0 -1
  516. package/dist/commands/sys/__tests__/setup-providers-viewport.test.js +0 -155
  517. package/dist/commands/sys/__tests__/sync-deps.test.d.ts +0 -1
  518. package/dist/commands/sys/__tests__/sync-deps.test.js +0 -179
  519. package/dist/commands/sys/__tests__/sync-import.test.d.ts +0 -1
  520. package/dist/commands/sys/__tests__/sync-import.test.js +0 -315
  521. package/dist/core/__tests__/base-worker-prompt.test.d.ts +0 -1
  522. package/dist/core/__tests__/base-worker-prompt.test.js +0 -57
  523. package/dist/core/__tests__/command-plugins-surfaces.test.d.ts +0 -1
  524. package/dist/core/__tests__/command-plugins-surfaces.test.js +0 -359
  525. package/dist/core/__tests__/connection-reconnect-resume.test.d.ts +0 -1
  526. package/dist/core/__tests__/connection-reconnect-resume.test.js +0 -36
  527. package/dist/core/__tests__/finalization-migration.test.d.ts +0 -1
  528. package/dist/core/__tests__/finalization-migration.test.js +0 -38
  529. package/dist/core/__tests__/fixtures/extra-extension.d.ts +0 -1
  530. package/dist/core/__tests__/fixtures/extra-extension.js +0 -3
  531. package/dist/core/__tests__/fixtures/spawn-proof-target.test.d.ts +0 -1
  532. package/dist/core/__tests__/fixtures/spawn-proof-target.test.js +0 -15
  533. package/dist/core/__tests__/fork.test.d.ts +0 -1
  534. package/dist/core/__tests__/fork.test.js +0 -108
  535. package/dist/core/__tests__/full/broker-attach-limits.test.d.ts +0 -1
  536. package/dist/core/__tests__/full/broker-attach-limits.test.js +0 -147
  537. package/dist/core/__tests__/full/broker-deliver-ack.test.d.ts +0 -1
  538. package/dist/core/__tests__/full/broker-deliver-ack.test.js +0 -73
  539. package/dist/core/__tests__/full/broker-dialogs.test.d.ts +0 -1
  540. package/dist/core/__tests__/full/broker-dialogs.test.js +0 -180
  541. package/dist/core/__tests__/full/broker-display-snapshot.test.d.ts +0 -1
  542. package/dist/core/__tests__/full/broker-display-snapshot.test.js +0 -75
  543. package/dist/core/__tests__/full/broker-dormant-wake.test.d.ts +0 -1
  544. package/dist/core/__tests__/full/broker-dormant-wake.test.js +0 -130
  545. package/dist/core/__tests__/full/broker-model-changed-broadcast.test.d.ts +0 -1
  546. package/dist/core/__tests__/full/broker-model-changed-broadcast.test.js +0 -57
  547. package/dist/core/__tests__/full/broker-navigate-tree-rewelcome.test.d.ts +0 -1
  548. package/dist/core/__tests__/full/broker-navigate-tree-rewelcome.test.js +0 -80
  549. package/dist/core/__tests__/full/cascade-close.test.d.ts +0 -1
  550. package/dist/core/__tests__/full/cascade-close.test.js +0 -240
  551. package/dist/core/__tests__/full/detach-focus.test.d.ts +0 -1
  552. package/dist/core/__tests__/full/detach-focus.test.js +0 -126
  553. package/dist/core/__tests__/full/idle-release-settlement.test.d.ts +0 -1
  554. package/dist/core/__tests__/full/issue-146-yield-spawn-focus.test.d.ts +0 -1
  555. package/dist/core/__tests__/full/issue-146-yield-spawn-focus.test.js +0 -107
  556. package/dist/core/__tests__/full/park-clock-release.test.d.ts +0 -1
  557. package/dist/core/__tests__/full/park-clock-release.test.js +0 -56
  558. package/dist/core/__tests__/full/yield-message-transaction.test.d.ts +0 -1
  559. package/dist/core/__tests__/memory-index-render.test.d.ts +0 -1
  560. package/dist/core/__tests__/memory-index-render.test.js +0 -60
  561. package/dist/core/__tests__/model-routes.test.d.ts +0 -1
  562. package/dist/core/__tests__/model-routes.test.js +0 -41
  563. package/dist/core/__tests__/on-read-identity.test.d.ts +0 -1
  564. package/dist/core/__tests__/on-read-identity.test.js +0 -61
  565. package/dist/core/__tests__/phase4-review-migration.test.d.ts +0 -1
  566. package/dist/core/__tests__/phase4-review-migration.test.js +0 -100
  567. package/dist/core/__tests__/prune-to-limit.test.d.ts +0 -1
  568. package/dist/core/__tests__/prune-to-limit.test.js +0 -126
  569. package/dist/core/__tests__/reset.test.d.ts +0 -1
  570. package/dist/core/__tests__/reset.test.js +0 -69
  571. package/dist/core/__tests__/spawn-no-kickoff.test.d.ts +0 -1
  572. package/dist/core/__tests__/spawn-no-kickoff.test.js +0 -115
  573. package/dist/core/__tests__/steer-note.test.d.ts +0 -1
  574. package/dist/core/__tests__/steer-note.test.js +0 -41
  575. package/dist/core/__tests__/subcommand-tier.test.d.ts +0 -1
  576. package/dist/core/__tests__/subcommand-tier.test.js +0 -99
  577. package/dist/core/__tests__/subscription-delivery.test.js +0 -211
  578. package/dist/core/__tests__/test-runner-cheap-sharding.test.d.ts +0 -1
  579. package/dist/core/__tests__/test-runner-cheap-sharding.test.js +0 -97
  580. package/dist/core/__tests__/tmux-surface.test.js +0 -484
  581. package/dist/core/__tests__/wake-bearings.test.d.ts +0 -1
  582. package/dist/core/__tests__/wake-bearings.test.js +0 -102
  583. package/dist/core/canvas/__tests__/remote-event-stream.test.d.ts +0 -1
  584. package/dist/core/canvas/__tests__/remote-event-stream.test.js +0 -146
  585. package/dist/core/canvas/__tests__/source-resolve.test.d.ts +0 -1
  586. package/dist/core/canvas/__tests__/source-resolve.test.js +0 -77
  587. package/dist/core/canvas/browse/__tests__/model.test.d.ts +0 -1
  588. package/dist/core/canvas/browse/__tests__/model.test.js +0 -290
  589. package/dist/core/canvas/browse/__tests__/rebuild-coalescer.test.d.ts +0 -1
  590. package/dist/core/canvas/browse/__tests__/rebuild-coalescer.test.js +0 -134
  591. package/dist/core/canvas/browse/__tests__/render.test.d.ts +0 -1
  592. package/dist/core/canvas/browse/__tests__/render.test.js +0 -111
  593. package/dist/core/canvas/browse/rebuild-coalescer.d.ts +0 -7
  594. package/dist/core/canvas/browse/rebuild-coalescer.js +0 -61
  595. package/dist/core/canvas/remote-event-stream.d.ts +0 -24
  596. package/dist/core/canvas/remote-event-stream.js +0 -94
  597. package/dist/core/feed/__tests__/coalesce-human.test.d.ts +0 -1
  598. package/dist/core/feed/__tests__/coalesce-human.test.js +0 -36
  599. package/dist/core/feed/__tests__/empty-node-guard.test.d.ts +0 -1
  600. package/dist/core/feed/__tests__/empty-node-guard.test.js +0 -45
  601. package/dist/core/host-exports/__tests__/export-prunes-boot-skill.test.d.ts +0 -1
  602. package/dist/core/host-exports/__tests__/export-prunes-boot-skill.test.js +0 -84
  603. package/dist/core/human/__tests__/visible-paths.test.d.ts +0 -1
  604. package/dist/core/human/__tests__/visible-paths.test.js +0 -28
  605. package/dist/core/keybindings/__tests__/inbox-affordance.test.d.ts +0 -1
  606. package/dist/core/keybindings/__tests__/inbox-affordance.test.js +0 -38
  607. package/dist/core/review/__tests__/project.test.d.ts +0 -1
  608. package/dist/core/review/__tests__/project.test.js +0 -71
  609. package/dist/core/runtime/__tests__/command-expansion.test.d.ts +0 -1
  610. package/dist/core/runtime/__tests__/command-expansion.test.js +0 -25
  611. package/dist/core/runtime/__tests__/session-visibility.test.d.ts +0 -1
  612. package/dist/core/runtime/__tests__/session-visibility.test.js +0 -119
  613. package/dist/core/runtime/__tests__/spawn-at-given-id.test.d.ts +0 -1
  614. package/dist/core/runtime/__tests__/spawn-at-given-id.test.js +0 -34
  615. package/dist/core/runtime/tmux.js +0 -1314
  616. package/dist/daemon/api/__tests__/full/push-parity.test.d.ts +0 -1
  617. package/dist/daemon/api/__tests__/full/worktree-parity.test.d.ts +0 -1
  618. package/dist/daemon/api/__tests__/full/worktree-parity.test.js +0 -160
  619. package/dist/daemon/api/__tests__/inbox.test.d.ts +0 -1
  620. package/dist/daemon/api/__tests__/inbox.test.js +0 -489
  621. package/dist/web-client/apple-touch-icon.png +0 -0
  622. package/dist/web-client/assets/fragment-mono-latin-400-normal-BYwT3kSJ.woff +0 -0
  623. package/dist/web-client/assets/fragment-mono-latin-400-normal-yxdJ5AmL.woff2 +0 -0
  624. package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-BbKYyvR9.woff2 +0 -0
  625. package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-CT4YFKeK.woff +0 -0
  626. package/dist/web-client/assets/index-CCPaLeW7.css +0 -2
  627. package/dist/web-client/assets/index-kyOWsnZK.js +0 -86
  628. package/dist/web-client/assets/martian-mono-cyrillic-wght-normal-B84CD5C_.woff2 +0 -0
  629. package/dist/web-client/assets/martian-mono-latin-ext-wght-normal-DlL6xMw5.woff2 +0 -0
  630. package/dist/web-client/assets/martian-mono-latin-wght-normal-5W32yIyr.woff2 +0 -0
  631. package/dist/web-client/assets/workbox-window.prod.es5-Bd17z0YL.js +0 -2
  632. package/dist/web-client/icon-192.png +0 -0
  633. package/dist/web-client/icon-512.png +0 -0
  634. package/dist/web-client/icon-maskable-512.png +0 -0
  635. package/dist/web-client/index.html +0 -17
  636. package/dist/web-client/manifest.webmanifest +0 -1
  637. package/dist/web-client/sw.js +0 -1
  638. /package/dist/api/__tests__/{client.test.d.ts → serial/client.test.d.ts} +0 -0
  639. /package/dist/clients/inbox/__tests__/{inbox-controller.test.d.ts → serial/inbox-controller.test.d.ts} +0 -0
  640. /package/dist/clients/inbox/__tests__/{mount-panel.test.d.ts → serial/mount-panel.test.d.ts} +0 -0
  641. /package/dist/clients/{attach/__tests__/attach-chrome-remote.test.d.ts → inbox/review/__tests__/teardown-notice.test.d.ts} +0 -0
  642. /package/dist/{clients/attach/__tests__/attach-keybindings.test.d.ts → core/__tests__/broker-extension-canvas-db-boundary.test.d.ts} +0 -0
  643. /package/dist/{clients/attach/__tests__/crtr-output-coverage.test.d.ts → core/__tests__/seam/broker-attach-multiclient.test.d.ts} +0 -0
  644. /package/dist/core/__tests__/{full → seam}/broker-attach-stream.test.d.ts +0 -0
  645. /package/dist/core/__tests__/{full → seam}/broker-crash-teardown.test.d.ts +0 -0
  646. /package/dist/core/__tests__/{full → seam}/broker-pane-resolution.test.d.ts +0 -0
  647. /package/dist/core/__tests__/{full → seam}/broker-provider-retry.test.d.ts +0 -0
  648. /package/dist/core/__tests__/{full → seam}/broker-whip-interrupt.test.d.ts +0 -0
  649. /package/dist/{clients/attach/__tests__/editor-frame-title.test.d.ts → core/__tests__/seam/dormancy-release.test.d.ts} +0 -0
  650. /package/dist/{clients/attach/__tests__/input-controller-extension-command.test.d.ts → core/__tests__/seam/yield-refresh-transaction.test.d.ts} +0 -0
  651. /package/dist/core/__tests__/{broker-fork-seam.test.d.ts → serial/broker-fork-seam.test.d.ts} +0 -0
  652. /package/dist/core/__tests__/{broker-sdk-wiring.test.d.ts → serial/broker-sdk-wiring.test.d.ts} +0 -0
  653. /package/dist/core/__tests__/{broker-snapshot-history.test.d.ts → serial/broker-snapshot-history.test.d.ts} +0 -0
  654. /package/dist/core/__tests__/{command-plugins.test.d.ts → serial/command-plugins.test.d.ts} +0 -0
  655. /package/dist/core/__tests__/{deferred-no-wake.test.d.ts → serial/deferred-no-wake.test.d.ts} +0 -0
  656. /package/dist/core/__tests__/{flagship-lifecycle.test.d.ts → serial/flagship-lifecycle.test.d.ts} +0 -0
  657. /package/dist/core/__tests__/{host-teardown-process-group.test.d.ts → serial/host-teardown-process-group.test.d.ts} +0 -0
  658. /package/dist/core/__tests__/{human-deliver-e2e.test.d.ts → serial/human-deliver-e2e.test.d.ts} +0 -0
  659. /package/dist/core/__tests__/{live-mutation.test.d.ts → serial/live-mutation.test.d.ts} +0 -0
  660. /package/dist/core/__tests__/{refresh-stall-recycle.test.d.ts → serial/refresh-stall-recycle.test.d.ts} +0 -0
  661. /package/dist/core/__tests__/{revive.test.d.ts → serial/revive.test.d.ts} +0 -0
  662. /package/dist/core/__tests__/{spawn-root.test.d.ts → serial/spawn-root.test.d.ts} +0 -0
  663. /package/dist/core/__tests__/{subscription-delivery.test.d.ts → serial/subscription-delivery.test.d.ts} +0 -0
  664. /package/dist/core/__tests__/{tmux-surface.test.d.ts → serial/tmux-surface.test.d.ts} +0 -0
  665. /package/dist/core/__tests__/{worktree.test.d.ts → serial/worktree.test.d.ts} +0 -0
  666. /package/dist/{clients/attach/__tests__/markdown-headings.test.d.ts → core/__tests__/watchdog-abort-arms-retry.test.d.ts} +0 -0
  667. /package/dist/{clients/attach/__tests__/session-identity-refresh.test.d.ts → core/broker-client/__tests__/transport-socket.test.d.ts} +0 -0
  668. /package/dist/core/human/__tests__/{inbox-core.test.d.ts → serial/inbox-core.test.d.ts} +0 -0
  669. /package/dist/{clients/inbox/review/__tests__/remap.test.d.ts → daemon/api/__tests__/node-model-validation.test.d.ts} +0 -0
  670. /package/dist/{clients/surfaces/region.js → daemon/api/__tests__/review-terminal-conflict.test.d.ts} +0 -0
  671. /package/dist/daemon/api/__tests__/{full → seam}/api-server.test.d.ts +0 -0
  672. /package/dist/daemon/api/__tests__/{full → seam}/b10-attach-modelauth.test.d.ts +0 -0
  673. /package/dist/{clients/web/__tests__/push-engine.test.d.ts → daemon/api/__tests__/seam/leaf-api-parity.test.d.ts} +0 -0
@@ -0,0 +1,151 @@
1
+ import { mountPanel } from '../../tui/panel.js';
2
+ import assert from 'node:assert/strict';
3
+ // Answer-integrity regressions: every case below is a way the panel once lost or
4
+ // invented an answer on the user's behalf.
5
+ function mkKey(partial) {
6
+ return {
7
+ ctrl: false,
8
+ meta: false,
9
+ upArrow: false,
10
+ downArrow: false,
11
+ leftArrow: false,
12
+ rightArrow: false,
13
+ wordLeft: false,
14
+ wordRight: false,
15
+ home: false,
16
+ end: false,
17
+ pageUp: false,
18
+ pageDown: false,
19
+ del: false,
20
+ return: false,
21
+ newline: false,
22
+ escape: false,
23
+ tab: false,
24
+ backspace: false,
25
+ ...partial,
26
+ };
27
+ }
28
+ const RETURN = mkKey({ return: true });
29
+ // ── An empty Enter in freetext-only mode records the response ─────────────────
30
+ // Regression: an empty buffer failed a truthy guard, so the response was never
31
+ // recorded, the deck could never reach a full response set, and onComplete
32
+ // never fired — leaving the deck permanently unfinishable.
33
+ const freetextOnlyDeck = {
34
+ title: 'Test deck',
35
+ interactions: [
36
+ { id: 'q1', title: 'Optional notes', subtitle: 'Optional notes requires your attention.', options: [], allowFreetext: true },
37
+ ],
38
+ };
39
+ let capturedFreetextEmpty = [];
40
+ const ftPanel = mountPanel({
41
+ deck: freetextOnlyDeck,
42
+ cols: 80,
43
+ rows: 24,
44
+ onComplete: (responses) => { capturedFreetextEmpty = responses; },
45
+ });
46
+ // Single-item deck starts directly in item-review (no overview). 'r' opens freetext.
47
+ ftPanel.handleKey('r', mkKey({}));
48
+ ftPanel.handleKey('', RETURN); // submit with an empty buffer
49
+ ftPanel.handleKey('', RETURN); // final phase → complete
50
+ assert.deepEqual(capturedFreetextEmpty, [{ id: 'q1', freetext: '' }], 'empty freetext Enter must record response and fire onComplete');
51
+ ftPanel.unmount();
52
+ // ── An empty Enter in comment mode records the response ───────────────────────
53
+ const commentDeck = {
54
+ title: 'Test deck',
55
+ interactions: [
56
+ {
57
+ id: 'c1', title: 'Approve deploy?', subtitle: 'Approve deploy? requires your attention.',
58
+ options: [{ id: 'yes', label: 'Yes', shortcut: 'y' }],
59
+ allowFreetext: true,
60
+ },
61
+ ],
62
+ };
63
+ let capturedCommentEmpty = [];
64
+ const cmPanel = mountPanel({
65
+ deck: commentDeck,
66
+ cols: 80,
67
+ rows: 24,
68
+ onComplete: (responses) => { capturedCommentEmpty = responses; },
69
+ });
70
+ // Navigate to the [c] row WITHOUT pre-attaching an option, then comment.
71
+ cmPanel.handleKey('j', mkKey({}));
72
+ cmPanel.handleKey('c', mkKey({}));
73
+ cmPanel.handleKey('', RETURN); // submit an empty comment, no option selected
74
+ cmPanel.handleKey('', RETURN); // final phase → complete
75
+ assert.deepEqual(capturedCommentEmpty, [{ id: 'c1', freetext: '' }], 'empty Enter in comment mode must record response and fire onComplete');
76
+ cmPanel.unmount();
77
+ // ── Option-shortcut letters typed in comment mode are text, never a choice ────
78
+ // Regression: pressing an option's shortcut while commenting submitted that
79
+ // option for the user instead of appending the character to the buffer.
80
+ const shortcutTypingDeck = {
81
+ title: 'Test deck',
82
+ interactions: [
83
+ {
84
+ id: 'q1', title: 'Approve?', subtitle: 'Approve? requires your attention.',
85
+ options: [
86
+ { id: 'yes', label: 'Yes', shortcut: 'y' },
87
+ { id: 'no', label: 'No', shortcut: 'n' },
88
+ ],
89
+ allowFreetext: true,
90
+ },
91
+ ],
92
+ };
93
+ let capturedShortcutTyping = [];
94
+ const stPanel = mountPanel({
95
+ deck: shortcutTypingDeck,
96
+ cols: 80,
97
+ rows: 24,
98
+ onComplete: (responses) => { capturedShortcutTyping = responses; },
99
+ });
100
+ stPanel.handleKey('j', mkKey({}));
101
+ stPanel.handleKey('j', mkKey({}));
102
+ stPanel.handleKey('c', mkKey({}));
103
+ // 'y' and 'n' are both option shortcuts; every character must reach the buffer.
104
+ for (const ch of 'yes no')
105
+ stPanel.handleKey(ch, mkKey({}));
106
+ stPanel.handleKey('', RETURN); // submit the comment — must carry no selectedOptionId
107
+ stPanel.handleKey('', RETURN); // final → complete
108
+ assert.deepEqual(capturedShortcutTyping, [{ id: 'q1', freetext: 'yes no' }], 'option-shortcut letters typed in comment mode must append to buffer, not select option');
109
+ stPanel.unmount();
110
+ // ── Multi-select needs an explicit confirm, and an empty Enter does nothing ───
111
+ // Two regressions on one deck: Enter with nothing toggled committed an empty
112
+ // set and finalized, and a confirmed set auto-finalized with no chance to
113
+ // review it.
114
+ const multiDeck = {
115
+ title: 'Test deck',
116
+ interactions: [
117
+ {
118
+ id: 'cs1', title: 'Pick toppings', subtitle: 'Pick toppings requires your attention.', multiSelect: true,
119
+ options: [
120
+ { id: 'mush', label: 'Mushroom', shortcut: 'a' },
121
+ { id: 'onion', label: 'Onion', shortcut: 'b' },
122
+ ],
123
+ },
124
+ ],
125
+ };
126
+ let multiFired = false;
127
+ let multiResponses = [];
128
+ const multiPanel = mountPanel({
129
+ deck: multiDeck,
130
+ cols: 80,
131
+ rows: 24,
132
+ onComplete: (responses) => { multiFired = true; multiResponses = responses; },
133
+ });
134
+ // Nothing toggled: Enter must be an inert no-op, not an empty answer.
135
+ multiPanel.handleKey('', RETURN);
136
+ assert.equal(multiFired, false, 'Enter with an empty multi-select set must NOT finalize');
137
+ const stillReview = multiPanel.render().join('\n');
138
+ assert.ok(stillReview.includes('Pick toppings'), 'after empty Enter, still on the interaction (no advance)');
139
+ assert.ok(!stillReview.includes('Summary'), 'after empty Enter, the deck did NOT advance to the Summary screen');
140
+ assert.ok(stillReview.toLowerCase().includes('select at least one'), 'empty multi-select Enter surfaces an inline hint');
141
+ // Toggle an option and confirm the set: the first Enter reviews, never submits.
142
+ multiPanel.handleKey(' ', mkKey({}));
143
+ multiPanel.handleKey('', RETURN);
144
+ assert.equal(multiFired, false, 'multi-select first Enter must NOT auto-finalize (lands on the confirm screen)');
145
+ assert.ok(multiPanel.render().join('\n').includes('Summary'), 'after confirming a multi-select set, the deck shows the Summary/confirm screen');
146
+ // A second deliberate Enter submits exactly the toggled set.
147
+ multiPanel.handleKey('', RETURN);
148
+ assert.equal(multiFired, true, 'second Enter on the Summary screen finalizes the multi-select deck');
149
+ assert.deepEqual(multiResponses, [{ id: 'cs1', selectedOptionIds: ['mush'] }], 'confirmed multi-select set returned on finalize');
150
+ multiPanel.unmount();
151
+ console.log('OK');
@@ -1,12 +1,8 @@
1
- import type { TUI } from '@earendil-works/pi-tui';
2
1
  import type { TicketSummary } from '../../core/human/types.js';
3
- import type { CanvasSource } from '../../core/canvas/source.js';
4
2
  import type { Key } from './tui/keys.js';
5
3
  import type { SurfaceHost } from '../surfaces/host.js';
6
4
  export interface InboxControllerOptions {
7
5
  host: SurfaceHost;
8
- tui: TUI;
9
- canvasSource: CanvasSource;
10
6
  /** Called whenever the rendered frame may have changed. */
11
7
  onDirty: () => void;
12
8
  /** Called after the controller has finished closing itself. */
@@ -230,8 +230,6 @@ export class InboxController {
230
230
  this.reviewAdapter = new ReviewAdapter({
231
231
  dir: item.dir,
232
232
  host: this.host,
233
- tui: this.options.tui,
234
- canvasSource: this.options.canvasSource,
235
233
  });
236
234
  try {
237
235
  await this.reviewAdapter.start();
@@ -1,298 +1,8 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import stringWidth from 'string-width';
3
- import { deriveAnchorUnits, remapUnitIndex, unitIndexForLine, unitRangeForSpan, } from '../anchors.js';
4
- import { closeList, commentedUnitSet, commitCompose, currentAnchor, deleteAtListIndex, ensureAnchorVisible, anchorRowRange, initReviewState, moveActiveUnit, moveListIndex, openComposeEdit, openComposeNew, openList, scrollBy, scrollToReveal, textBackspace, textEnd, textHome, textInsert, textVertical, textVerticalWrapped, textWordBackspace, textWordLeft, textWordRight, undoLast, } from '../state.js';
5
- import { maxHScroll, panBy, renderReviewFrame, } from '../frame.js';
6
- import { matchReviewKey } from '../keys.js';
7
- assert.equal(matchReviewKey('\x1bR'), null, 'legacy Alt+Shift+R remains viewer-global');
8
- assert.equal(matchReviewKey('\x1b[82;4u'), null, 'Kitty Alt+Shift+R remains viewer-global');
9
- assert.equal(matchReviewKey('\x1bi'), null, 'Alt+I remains owned outside the review surface');
10
- // A small doc: a heading, a two-bullet list, a paragraph. The list is ONE
11
- // top-level block but each bullet carries its own leaf span — so anchoring
12
- // steps bullet-to-bullet, not list-to-list.
13
- const sourceLines = ['# Title', '', '- line three', '- line four', '', 'line six'];
14
- const existingComment = {
15
- id: 'c1',
16
- revision: 1,
17
- line: 6,
18
- endLine: 6,
19
- lineText: 'line six',
20
- comment: 'note',
21
- status: 'open',
22
- authorKind: 'human',
23
- createdAt: 'now',
24
- anchorStatus: 'live',
25
- };
26
- const doc = {
27
- lines: ['TITLE', '', '• row three', '• row four', '', 'row six'],
28
- rows: [0, null, 1, 1, null, 2],
29
- spans: [[1, 1], null, [3, 3], [4, 4], null, [6, 6]],
30
- blocks: [
31
- { type: 'paragraph', start: 1, end: 1 },
32
- { type: 'paragraph', start: 3, end: 4 },
33
- { type: 'paragraph', start: 6, end: 6 },
34
- ],
35
- };
36
- const anchor = deriveAnchorUnits(doc);
37
- const { units } = anchor;
38
- // deriveAnchorUnits: one unit per leaf span run; rowUnits keys the painter.
39
- {
40
- assert.equal(units.length, 4, 'each bullet is its own unit — the list block splits');
41
- assert.deepEqual(units[0], { start: 1, end: 1, firstRow: 0, lastRow: 0 });
42
- assert.deepEqual(units[1], { start: 3, end: 3, firstRow: 2, lastRow: 2 });
43
- assert.deepEqual(units[2], { start: 4, end: 4, firstRow: 3, lastRow: 3 });
44
- assert.deepEqual(units[3], { start: 6, end: 6, firstRow: 5, lastRow: 5 });
45
- assert.deepEqual(anchor.rowUnits, [0, null, 1, 2, null, 3]);
46
- }
47
- // deriveAnchorUnits: consecutive rows sharing a span (a wrapped bullet)
48
- // collapse into one unit; a mapped row with no leaf span (an unmapped block)
49
- // anchors at its whole block's range; a separator between identical spans
50
- // still splits units.
51
- {
52
- const d = {
53
- lines: ['a1', 'a2 (wrapped)', '', 'chrome'],
54
- rows: [0, 0, null, 1],
55
- spans: [[2, 2], [2, 2], null, null],
56
- blocks: [
57
- { type: 'paragraph', start: 1, end: 3 },
58
- { type: 'paragraph', start: 5, end: 9 },
59
- ],
60
- };
61
- const a = deriveAnchorUnits(d);
62
- assert.deepEqual(a.units, [
63
- { start: 2, end: 2, firstRow: 0, lastRow: 1 },
64
- { start: 5, end: 9, firstRow: 3, lastRow: 3 },
65
- ]);
66
- assert.deepEqual(a.rowUnits, [0, 0, null, 1]);
67
- }
68
- // deriveAnchorUnits: a fully unmapped doc degrades to one whole-doc unit.
69
- {
70
- const d = { lines: ['x', 'y'], rows: [null, null], spans: [null, null], blocks: [{ type: 'paragraph', start: 1, end: 7 }] };
71
- const a = deriveAnchorUnits(d);
72
- assert.deepEqual(a.units, [{ start: 1, end: 7, firstRow: 0, lastRow: 1 }]);
73
- assert.deepEqual(a.rowUnits, [0, 0]);
74
- }
75
- // unitIndexForLine: containment, forward snap across gaps, clamp past the end.
76
- {
77
- assert.equal(unitIndexForLine(units, 1), 0);
78
- assert.equal(unitIndexForLine(units, 2), 1, 'a gap line snaps forward to the next unit');
79
- assert.equal(unitIndexForLine(units, 3), 1);
80
- assert.equal(unitIndexForLine(units, 4), 2);
81
- assert.equal(unitIndexForLine(units, 6), 3);
82
- assert.equal(unitIndexForLine(units, 99), 3, 'past the last unit clamps to the last unit');
83
- }
84
- // unitRangeForSpan: all units overlapping a source range (chrome units carry
85
- // their block's whole range, so a whole-fence comment covers every fence unit).
86
- {
87
- assert.deepEqual(unitRangeForSpan(units, 3, 4), { lo: 1, hi: 2 }, 'a two-bullet comment spans both bullet units');
88
- assert.deepEqual(unitRangeForSpan(units, 6, 6), { lo: 3, hi: 3 });
89
- assert.deepEqual(unitRangeForSpan(units, 2, 2), { lo: 1, hi: 1 }, 'a gap-only range snaps forward');
90
- const fence = deriveAnchorUnits({
91
- lines: ['┌─', 'code a', 'code b', '└─'],
92
- rows: [0, 0, 0, 0],
93
- spans: [[5, 10], [6, 6], [7, 7], [5, 10]],
94
- blocks: [{ type: 'paragraph', start: 5, end: 10 }],
95
- });
96
- assert.equal(fence.units.length, 4, 'fence = top chrome + per-line content + bottom chrome');
97
- assert.deepEqual(unitRangeForSpan(fence.units, 5, 10), { lo: 0, hi: 3 }, 'a whole-fence comment highlights every fence unit');
98
- // Narrowest-containing lookup: a code line resolves to its own unit even
99
- // though the whole-block chrome unit sits earlier in rendered order.
100
- assert.equal(unitIndexForLine(fence.units, 6), 1, 'a code line resolves to its leaf unit, not the fence chrome');
101
- assert.equal(unitIndexForLine(fence.units, 7), 2);
102
- assert.equal(unitIndexForLine(fence.units, 5), 0, 'the fence opener resolves to the chrome unit');
103
- // Resize remapping: an exact source-range match is preserved (chrome and
104
- // leaf units share source lines), else the narrowest containing unit wins.
105
- assert.equal(remapUnitIndex(fence.units, { start: 6, end: 6, firstRow: 9, lastRow: 9 }), 1, 'remap keeps a code-line anchor on its code line');
106
- assert.equal(remapUnitIndex(fence.units, { start: 5, end: 10, firstRow: 9, lastRow: 9 }), 0, 'remap keeps a chrome anchor on the identical-range unit');
107
- assert.equal(remapUnitIndex(fence.units, { start: 8, end: 9, firstRow: 0, lastRow: 0 }), 0, 'no exact match falls back to the best unit for its first line');
108
- }
109
- // Anchor motion: j/k move unit-to-unit; Shift+j/k extends across units.
110
- {
111
- let state = initReviewState(sourceLines, anchor, [], 0);
112
- assert.deepEqual(currentAnchor(state), { line: 1, endLine: 1 });
113
- state = moveActiveUnit(state, 1, false);
114
- assert.deepEqual(currentAnchor(state), { line: 3, endLine: 3 }, 'j moves to a single bullet, not the whole list');
115
- state = moveActiveUnit(state, 1, true);
116
- assert.deepEqual(currentAnchor(state), { line: 3, endLine: 4 }, 'shift+j extends the selection downward');
117
- state = moveActiveUnit(state, 1, true);
118
- assert.deepEqual(currentAnchor(state), { line: 3, endLine: 6 }, 'shift+j extends across the block boundary');
119
- state = moveActiveUnit(state, -3, true);
120
- assert.deepEqual(currentAnchor(state), { line: 1, endLine: 3 }, 'shift+k can extend the selection back past the anchor');
121
- state = moveActiveUnit(state, 1, false);
122
- assert.deepEqual(currentAnchor(state), { line: 3, endLine: 3 }, 'a plain j/k collapses the selection');
123
- // Bounds
124
- state = moveActiveUnit(state, -100, false);
125
- assert.equal(state.activeUnit, 0, 'anchor cannot move above the first unit');
126
- state = moveActiveUnit(state, 100, false);
127
- assert.equal(state.activeUnit, units.length - 1, 'anchor cannot move past the last unit');
128
- }
129
- // currentAnchor over chrome units takes the min/max across the selection.
130
- {
131
- const fence = deriveAnchorUnits({
132
- lines: ['┌─', 'code a', '└─'],
133
- rows: [0, 0, 0],
134
- spans: [[5, 8], [6, 6], [5, 8]],
135
- blocks: [{ type: 'paragraph', start: 5, end: 8 }],
136
- });
137
- let state = initReviewState(['', '', '', '', '```', 'a', 'b', '```'], fence, [], 0);
138
- state = moveActiveUnit(state, 1, false); // content line unit
139
- assert.deepEqual(currentAnchor(state), { line: 6, endLine: 6 });
140
- state = moveActiveUnit(state, 1, true); // extend onto bottom chrome (5-8)
141
- assert.deepEqual(currentAnchor(state), { line: 5, endLine: 8 }, 'chrome in the selection widens to the block range');
142
- }
143
- // An existing comment positions the initial anchor on its unit.
144
- {
145
- const state = initReviewState(sourceLines, anchor, [existingComment], 0);
146
- assert.equal(state.activeUnit, 3);
147
- }
148
- // Compose emits a daemon mutation payload without changing the projection.
149
- {
150
- let state = initReviewState(sourceLines, anchor, [], 0);
151
- state = moveActiveUnit(state, 1, false); // bullet unit → L3
152
- state = moveActiveUnit(state, 1, true); // extend → L3-4
153
- state = openComposeNew(state);
154
- assert.equal(state.mode, 'compose');
155
- assert.deepEqual(state.compose?.anchor, { line: 3, endLine: 4 });
156
- state = { ...state, compose: { ...state.compose, buffer: 'needs a rewrite' } };
157
- let committed = commitCompose(state);
158
- state = committed.state;
159
- assert.equal(state.mode, 'view');
160
- assert.deepEqual(committed.commit, { editingId: null, anchor: { line: 3, endLine: 4 }, text: 'needs a rewrite' });
161
- assert.deepEqual(state.comments, [], 'the daemon projection remains unchanged until refreshed');
162
- // A projection refresh supplies the daemon-created comment before later edits.
163
- state = { ...state, comments: [existingComment] };
164
- // Empty compose closes without a mutation.
165
- state = openComposeNew(state);
166
- committed = commitCompose(state);
167
- state = committed.state;
168
- assert.equal(committed.commit, null);
169
- assert.equal(state.mode, 'view');
170
- // Editing from the list preserves selection and identifies the comment for the daemon.
171
- state = moveActiveUnit(state, -100, false); // move anchor away first
172
- state = openList(state);
173
- state = openComposeEdit(state, 0);
174
- assert.equal(state.compose?.editingId, existingComment.id);
175
- assert.equal(state.activeUnit, 3, 'editing re-anchors onto the comment\'s last unit');
176
- assert.equal(state.selectionAnchor, null, 'a single-line comment selects one unit');
177
- state = { ...state, compose: { ...state.compose, buffer: 'edited note' } };
178
- committed = commitCompose(state);
179
- state = committed.state;
180
- assert.equal(state.mode, 'list', 'editing from the list returns to the list');
181
- assert.deepEqual(committed.commit, { editingId: existingComment.id, anchor: { line: 6, endLine: 6 }, text: 'edited note' });
182
- assert.deepEqual(state.comments, [existingComment], 'editing does not locally alter the projection');
183
- // The commented unit set marks every unit overlapped by the projection.
184
- assert.deepEqual([...commentedUnitSet(state)], [3]);
185
- state = closeList(state);
186
- assert.equal(state.mode, 'view');
187
- const undone = undoLast(state);
188
- assert.equal(undone.id, existingComment.id, 'undo identifies the daemon comment to remove');
189
- assert.deepEqual(undone.state.comments, [existingComment]);
190
- }
191
- // List navigation and delete-by-index identify daemon comments without changing the projection.
192
- {
193
- const secondComment = { ...existingComment, id: 'c2', line: 3, endLine: 3, lineText: '- line three', comment: 'second' };
194
- let state = initReviewState(sourceLines, anchor, [existingComment, secondComment], 0);
195
- state = openList(state);
196
- state = moveListIndex(state, 1);
197
- assert.equal(state.listIndex, 1);
198
- const deleted = deleteAtListIndex(state);
199
- assert.equal(deleted.id, secondComment.id);
200
- assert.deepEqual(deleted.state.comments, [existingComment, secondComment]);
201
- assert.equal(deleted.state.listIndex, 1);
202
- }
203
- // anchorRowRange: the rendered rows spanned by a unit range.
204
- {
205
- assert.deepEqual(anchorRowRange(units, 1, 2), { first: 2, last: 3 });
206
- assert.deepEqual(anchorRowRange(units, 0, 3), { first: 0, last: 5 });
207
- assert.equal(anchorRowRange(units, 9, 9), null);
208
- }
209
- // scrollToReveal: margin-aware reveal, top pin for oversize spans, clamping.
210
- {
211
- assert.equal(scrollToReveal(0, 10, 11, 8, 30, 2), 6, 'reveals a below-view anchor with a bottom margin');
212
- assert.equal(scrollToReveal(6, 1, 1, 8, 30, 2), 0, 'reveals an above-view anchor, clamped at the top');
213
- assert.equal(scrollToReveal(0, 4, 20, 8, 30), 3, 'a taller-than-view span pins its first row one below the indicator row');
214
- assert.equal(scrollToReveal(0, 0, 20, 8, 30), 0, 'an oversize span starting at the top pins at zero');
215
- assert.equal(scrollToReveal(3, 5, 6, 8, 30), 3, 'an already-visible anchor leaves the scroll untouched');
216
- assert.equal(scrollToReveal(50, 25, 25, 8, 30, 2), 22, 'a stale overshoot scroll is clamped into the document');
217
- // The margin yields before it may push the span's own edges out of view.
218
- assert.equal(scrollToReveal(0, 10, 16, 8, 30, 2), 10, 'down-reveal of a bodyHeight-1 span keeps its first row visible');
219
- assert.equal(scrollToReveal(20, 10, 16, 8, 30, 2), 9, 'up-reveal of a bodyHeight-1 span keeps its last row visible');
220
- assert.equal(scrollToReveal(0, 10, 10, 2, 30, 2), 10, 'a tiny viewport still shows the anchored row itself');
221
- }
222
- // ensureAnchorVisible follows the active unit's rendered rows.
223
- {
224
- let state = initReviewState(sourceLines, anchor, [], 0);
225
- state = { ...state, activeUnit: 3, scroll: 0 };
226
- state = ensureAnchorVisible(state, doc, 2);
227
- assert.equal(state.scroll, 4, 'the anchored unit\'s rows scroll into view');
228
- }
229
- // Scroll clamps to [0, totalLines - bodyHeight] and never goes negative.
230
- {
231
- let state = initReviewState(sourceLines, anchor, [], 0);
232
- state = scrollBy(state, -50, 10, 30);
233
- assert.equal(state.scroll, 0, 'scroll cannot go negative');
234
- state = scrollBy(state, 50, 10, 30);
235
- assert.equal(state.scroll, 20, 'scroll clamps to the maximum');
236
- state = scrollBy(state, 50, 10, 30);
237
- assert.equal(state.scroll, 20, 'scroll stays clamped on repeated overshoot');
238
- }
239
- // Multi-line text-buffer helpers used by the compose input.
240
- {
241
- let r = textInsert('', 0, 'hello');
242
- assert.deepEqual(r, { buffer: 'hello', cursor: 5 });
243
- r = textInsert(r.buffer, 5, '\nworld');
244
- assert.deepEqual(r, { buffer: 'hello\nworld', cursor: 11 });
245
- assert.equal(textHome(r.buffer, 11), 6, 'home jumps to the start of the current line');
246
- assert.equal(textEnd(r.buffer, 6), 11, 'end jumps to the end of the current line');
247
- assert.equal(textVertical(r.buffer, 8, -1), 2, 'up preserves the column on the previous line');
248
- r = textBackspace(r.buffer, 11);
249
- assert.deepEqual(r, { buffer: 'hello\nworl', cursor: 10 });
250
- }
251
- // Word motion and visual (wrapped) vertical motion in the compose box: alt+arrow
252
- // steps whole words, and up/down step the rows the box actually paints — a long
253
- // soft-wrapped comment is many visual rows even though it is one logical line.
254
- {
255
- const b = 'alpha beta gamma';
256
- assert.equal(textWordLeft(b, 16), 11, 'alt+left lands on the start of the word before the cursor');
257
- assert.equal(textWordLeft(b, 11), 6, 'alt+left from a word start skips to the previous word');
258
- assert.equal(textWordRight(b, 0), 5, 'alt+right lands just past the current word');
259
- assert.equal(textWordRight(b, 5), 10, 'alt+right skips the space then the next word');
260
- assert.deepEqual(textWordBackspace(b, 16), { buffer: 'alpha beta ', cursor: 11 }, 'alt+backspace erases one word');
261
- // width 6 wraps into rows 'alpha ' | 'beta g' | 'amma'.
262
- assert.equal(textVerticalWrapped(b, 2, 1, 6), 8, 'down moves to the next wrapped row, same column');
263
- assert.equal(textVerticalWrapped(b, 8, -1, 6), 2, 'up moves back to the previous wrapped row');
264
- assert.equal(textVerticalWrapped(b, 2, -1, 6), 2, 'up on the first row is a no-op');
265
- assert.equal(textVerticalWrapped(b, 15, 1, 6), 15, 'down on the last row is a no-op');
266
- assert.equal(textVerticalWrapped('ab\ncd', 1, 1, 40), 4, 'hard newlines still separate rows');
267
- }
268
- // Render frame: the anchor highlight (gutter bar + tint) covers exactly the
269
- // active unit's rows — one bullet, not the whole list — plus commented-unit
270
- // markers and a key-hints-only footer.
271
- {
272
- let state = initReviewState(sourceLines, anchor, [], 0);
273
- state = moveActiveUnit(state, 1, false); // first bullet (rendered row 2)
274
- const frame = renderReviewFrame(state, 'doc.md', doc, 60, 20);
275
- assert.equal(frame.length, 20, 'the frame always fills the requested row count');
276
- const joined = frame.join('\n');
277
- assert.match(joined, /Review — doc\.md/);
278
- assert.match(joined, /0 comments/);
279
- assert.ok(!joined.includes('Anchor:'), 'the view footer carries no anchor caption');
280
- // Header is 3 rows; body row i shows doc row scroll+i.
281
- const bodyRow2 = frame[3 + 2];
282
- const bodyRow3 = frame[3 + 3];
283
- const bodyRow0 = frame[3];
284
- assert.ok(bodyRow2.includes('▌') && bodyRow2.includes('\x1b[48;5;236m'), 'the anchored bullet row gets the gutter bar and tint');
285
- assert.ok(!bodyRow3.includes('▌'), 'the sibling bullet in the same list block is NOT highlighted');
286
- assert.ok(!bodyRow0.includes('▌'), 'non-anchored rows carry no anchor gutter');
287
- // A comment on the paragraph marks its rows with the commented gutter.
288
- state = {
289
- ...state,
290
- comments: [existingComment],
291
- };
292
- const frame2 = renderReviewFrame(state, 'doc.md', doc, 60, 20);
293
- assert.ok(frame2[3 + 5].includes('▎'), 'commented units get the comment gutter marker');
294
- assert.ok(!frame2[3 + 3].includes('▎'), 'uncommented sibling units carry no comment marker');
295
- }
3
+ import { deriveAnchorUnits } from '../anchors.js';
4
+ import { initReviewState } from '../state.js';
5
+ import { maxHScroll, panBy, renderReviewFrame } from '../frame.js';
296
6
  // ── Regression: a Mermaid diagram wider than the pane (reported bug) ────────
297
7
  // Wide diagram rows used to run past the terminal's right edge; the spillover
298
8
  // wrapped and was unreachable. Every emitted row must now fit the frame, and
@@ -313,6 +23,7 @@ const { units } = anchor;
313
23
  let s = initReviewState(['# t', '', 'diagram', '', 'tail'], deriveAnchorUnits(wideDoc), [], 0);
314
24
  const widths = (frame) => frame.map((line) => stringWidth(line));
315
25
  const frame = renderReviewFrame(s, 'doc.md', wideDoc, cols, 20);
26
+ assert.equal(frame.length, 20, 'the frame always fills the requested row count');
316
27
  assert.ok(Math.max(...widths(frame)) <= cols, 'every frame row fits inside the terminal');
317
28
  // The readable column stays centered while a full-pane diagram enters and
318
29
  // leaves the viewport; only the diagram rows claim the pane.
@@ -0,0 +1,100 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { ReviewDocumentSurface } from '../document-surface.js';
4
+ // The host's restoring close (`closeEntry(entry, restore=true)`) disposes every
5
+ // notice raised over the closing surface. A disposition stated before the close
6
+ // therefore never paints — the regression the E-10b activation rerun caught
7
+ // live. These tests pin the contract: teardown states its disposition only
8
+ // after the handle close, on both the mounted and the pre-mount path.
9
+ function liveSnapshot() {
10
+ const text = 'one line\n';
11
+ return {
12
+ text,
13
+ lines: ['one line'],
14
+ revision: 1,
15
+ status: 'live',
16
+ sha256: 'abc',
17
+ loadedAt: new Date().toISOString(),
18
+ };
19
+ }
20
+ function fakeSource() {
21
+ const snapshot = liveSnapshot();
22
+ return {
23
+ current: () => snapshot,
24
+ openText: () => snapshot.text,
25
+ onChange: () => { },
26
+ refreshNow: () => { },
27
+ close: () => { },
28
+ };
29
+ }
30
+ /** `align()` parks on the first await forever; teardown needs none of it. */
31
+ function fakeComments() {
32
+ return {
33
+ anchorBase: () => new Promise(() => { }),
34
+ list: () => new Promise(() => { }),
35
+ create: () => Promise.reject(new Error('unused')),
36
+ edit: () => Promise.reject(new Error('unused')),
37
+ resolve: () => Promise.reject(new Error('unused')),
38
+ reopen: () => Promise.reject(new Error('unused')),
39
+ remove: () => Promise.reject(new Error('unused')),
40
+ remapRanges: () => Promise.reject(new Error('unused')),
41
+ onChanged: () => () => { },
42
+ };
43
+ }
44
+ function makeSurface(events) {
45
+ const services = {
46
+ notice: (text) => events.push(`notice:${text}`),
47
+ suspendForChild: () => () => { },
48
+ requestClose: () => { },
49
+ submit: () => { },
50
+ cancel: () => { },
51
+ };
52
+ return new ReviewDocumentSurface({
53
+ review: { reviewId: 'r1', companionNodeId: 'c1', file: '/tmp/x.md', cwd: '/tmp' },
54
+ source: fakeSource(),
55
+ comments: fakeComments(),
56
+ callerPane: undefined,
57
+ services,
58
+ });
59
+ }
60
+ function fakeHandle(events) {
61
+ const onClose = [];
62
+ let closed = false;
63
+ return {
64
+ close: () => {
65
+ if (closed)
66
+ return;
67
+ closed = true;
68
+ for (const fn of onClose)
69
+ void fn();
70
+ events.push('close');
71
+ },
72
+ invalidate: () => { },
73
+ onClose: (fn) => { onClose.push(fn); },
74
+ };
75
+ }
76
+ describe('review teardown disposition notice', () => {
77
+ it('states the disposition after the close on the mounted path', () => {
78
+ const events = [];
79
+ const surface = makeSurface(events);
80
+ surface.setHandle(fakeHandle(events));
81
+ surface.teardown('Review canceled.');
82
+ assert.deepEqual(events, ['close', 'notice:Review canceled.']);
83
+ });
84
+ it('re-states a pre-mount disposition after the deferred close', () => {
85
+ const events = [];
86
+ const surface = makeSurface(events);
87
+ surface.teardown('Review canceled.');
88
+ assert.deepEqual(events, ['notice:Review canceled.']);
89
+ surface.setHandle(fakeHandle(events));
90
+ assert.deepEqual(events, ['notice:Review canceled.', 'close', 'notice:Review canceled.']);
91
+ });
92
+ it('is idempotent — a second teardown neither closes nor notices again', () => {
93
+ const events = [];
94
+ const surface = makeSurface(events);
95
+ surface.setHandle(fakeHandle(events));
96
+ surface.teardown('Review canceled.');
97
+ surface.teardown('Approved — the document was not modified. Result: /tmp/r');
98
+ assert.deepEqual(events, ['close', 'notice:Review canceled.']);
99
+ });
100
+ });
@@ -22,13 +22,14 @@ export declare class ReviewDocumentError extends Error {
22
22
  }
23
23
  /** The approved document coordinates every stored comment anchor is expressed against. */
24
24
  export interface AnchorBase {
25
- /** Canonical reviewed file the base was captured from; a region rejects a mismatched target. */
25
+ /** Canonical reviewed file the base was captured from; the review surface rejects a mismatched target. */
26
26
  file: string;
27
27
  /** Full base document text, the left side of the base→current remap done before first paint. */
28
28
  text: string;
29
29
  /** Content hash of `text`, and the `fromDocHash` of that first remap batch. */
30
30
  docHash: string;
31
31
  }
32
+ export type ReviewRequest = <T>(operation: () => Promise<T>) => Promise<T>;
32
33
  export interface CommentAuthority {
33
34
  anchorBase(): Promise<AnchorBase>;
34
35
  list(): Promise<AnchoredComment[]>;
@@ -63,4 +64,4 @@ export interface CommentAuthority {
63
64
  onChanged(fn: () => void): () => void;
64
65
  }
65
66
  /** The terminal's complete daemon seam for one review's comment projection. */
66
- export declare function createCommentAuthority(reviewId: string): CommentAuthority;
67
+ export declare function createCommentAuthority(reviewId: string, request: ReviewRequest): CommentAuthority;