@north-light/crouter 0.3.173 → 0.3.175

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 (674) 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} +27 -179
  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 +7 -1
  46. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +9 -1
  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/memory/write.js +13 -12
  138. package/dist/commands/node/bash.d.ts +1 -0
  139. package/dist/commands/node/bash.js +198 -0
  140. package/dist/commands/node/create.d.ts +23 -0
  141. package/dist/commands/node/create.js +207 -0
  142. package/dist/commands/node/inspect.d.ts +2 -0
  143. package/dist/commands/node/inspect.js +302 -0
  144. package/dist/commands/node/lifecycle.d.ts +4 -0
  145. package/dist/commands/node/lifecycle.js +415 -0
  146. package/dist/commands/node/message.d.ts +1 -0
  147. package/dist/commands/node/message.js +164 -0
  148. package/dist/commands/node/pyramid.d.ts +2 -0
  149. package/dist/commands/node/pyramid.js +79 -0
  150. package/dist/commands/node/subscription.d.ts +1 -0
  151. package/dist/commands/node/subscription.js +82 -0
  152. package/dist/commands/node/wait.d.ts +1 -0
  153. package/dist/commands/node/wait.js +159 -0
  154. package/dist/commands/node-lifecycle-revive.js +10 -57
  155. package/dist/commands/node.d.ts +0 -42
  156. package/dist/commands/node.js +11 -2065
  157. package/dist/commands/search.js +1 -1
  158. package/dist/commands/surface/node/cycle.d.ts +1 -0
  159. package/dist/commands/surface/node/cycle.js +83 -0
  160. package/dist/commands/surface/node/focus.d.ts +1 -0
  161. package/dist/commands/surface/node/focus.js +67 -0
  162. package/dist/commands/surface/node/id.d.ts +1 -0
  163. package/dist/commands/surface/node/id.js +38 -0
  164. package/dist/commands/surface/node/pin.d.ts +1 -0
  165. package/dist/commands/surface/node/pin.js +42 -0
  166. package/dist/commands/surface/node/placement.d.ts +46 -0
  167. package/dist/commands/surface/node/placement.js +124 -0
  168. package/dist/commands/surface-node.js +4 -1
  169. package/dist/commands/surface-reload.js +1 -2
  170. package/dist/commands/surface-tmux-spread.js +1 -1
  171. package/dist/commands/surface.js +5 -20
  172. package/dist/commands/sys/__tests__/setup-core.test.js +18 -271
  173. package/dist/commands/sys/config.js +6 -6
  174. package/dist/commands/sys/logs.js +1 -1
  175. package/dist/commands/sys/panels/broker-limits-panel.d.ts +17 -0
  176. package/dist/commands/sys/panels/broker-limits-panel.js +104 -0
  177. package/dist/commands/sys/panels/dependencies-panel.d.ts +14 -0
  178. package/dist/commands/sys/panels/dependencies-panel.js +80 -0
  179. package/dist/commands/sys/panels/keybindings-panel.d.ts +56 -0
  180. package/dist/commands/sys/panels/keybindings-panel.js +703 -0
  181. package/dist/commands/sys/panels/keys-panel.d.ts +16 -0
  182. package/dist/commands/sys/panels/keys-panel.js +60 -0
  183. package/dist/commands/sys/panels/models-panel.d.ts +77 -0
  184. package/dist/commands/sys/panels/models-panel.js +647 -0
  185. package/dist/commands/sys/panels/panel.d.ts +45 -0
  186. package/dist/commands/sys/panels/panel.js +137 -0
  187. package/dist/commands/sys/panels/plugins-panel.d.ts +16 -0
  188. package/dist/commands/sys/panels/plugins-panel.js +80 -0
  189. package/dist/commands/sys/panels/prefs-panel.d.ts +21 -0
  190. package/dist/commands/sys/panels/prefs-panel.js +85 -0
  191. package/dist/commands/sys/panels/provider-panel.d.ts +62 -0
  192. package/dist/commands/sys/panels/provider-panel.js +538 -0
  193. package/dist/commands/sys/settings-shell.d.ts +55 -0
  194. package/dist/commands/sys/settings-shell.js +400 -0
  195. package/dist/commands/sys/settings.d.ts +2 -0
  196. package/dist/commands/sys/settings.js +31 -0
  197. package/dist/commands/sys/setup-core.d.ts +3 -33
  198. package/dist/commands/sys/setup-core.js +27 -78
  199. package/dist/commands/sys/setup-settings-runner.d.ts +24 -0
  200. package/dist/commands/sys/setup-settings-runner.js +63 -0
  201. package/dist/commands/sys/setup-wizard.d.ts +26 -125
  202. package/dist/commands/sys/setup-wizard.js +209 -2473
  203. package/dist/commands/sys/setup.js +5 -7
  204. package/dist/commands/sys.js +3 -2
  205. package/dist/core/__tests__/broker-extension-canvas-db-boundary.test.js +50 -0
  206. package/dist/core/__tests__/broker-launch-candidates.test.js +20 -9
  207. package/dist/core/__tests__/broker-preflight.test.js +1 -1
  208. package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +108 -27
  209. package/dist/core/__tests__/canvas-inbox-watcher.test.js +14 -0
  210. package/dist/core/__tests__/canvas.test.js +2 -36
  211. package/dist/core/__tests__/close.test.js +14 -3
  212. package/dist/core/__tests__/context-intro.test.js +32 -143
  213. package/dist/core/__tests__/cron-broker-capacity.test.js +22 -3
  214. package/dist/core/__tests__/daemon-boot.test.js +2 -20
  215. package/dist/core/__tests__/daemon-wedge.test.js +1 -1
  216. package/dist/core/__tests__/dead-node-policy-table.test.js +1 -18
  217. package/dist/core/__tests__/fixtures/fake-engine.d.ts +1 -1
  218. package/dist/core/__tests__/fixtures/fake-engine.js +2 -2
  219. package/dist/core/__tests__/fixtures/fake-pi-host.js +2 -2
  220. package/dist/core/__tests__/focuses.test.js +4 -98
  221. package/dist/core/__tests__/helpers/broker-clients.d.ts +0 -3
  222. package/dist/core/__tests__/helpers/broker-clients.js +0 -14
  223. package/dist/core/__tests__/helpers/harness.d.ts +0 -8
  224. package/dist/core/__tests__/helpers/harness.js +7 -87
  225. package/dist/core/__tests__/helpers/viewer-panes.js +1 -1
  226. package/dist/core/__tests__/inline-memory-refs.test.js +5 -134
  227. package/dist/core/__tests__/kickoff.test.js +1 -1
  228. package/dist/core/__tests__/memory-resolver-precedence.test.js +29 -1
  229. package/dist/core/__tests__/migration.test.js +35 -48
  230. package/dist/core/__tests__/on-read-dedup-resume.test.js +22 -12
  231. package/dist/core/__tests__/passive-subscription.test.js +26 -49
  232. package/dist/core/__tests__/preview-registry-sync.test.js +1 -2
  233. package/dist/core/__tests__/prune.test.js +94 -1
  234. package/dist/core/__tests__/review-model-floor.test.js +0 -32
  235. package/dist/core/__tests__/seam/broker-attach-multiclient.test.js +255 -0
  236. package/dist/core/__tests__/{full → seam}/broker-attach-stream.test.js +39 -7
  237. package/dist/core/__tests__/{full → seam}/broker-crash-teardown.test.js +30 -29
  238. package/dist/core/__tests__/{full → seam}/broker-pane-resolution.test.js +54 -5
  239. package/dist/core/__tests__/{full → seam}/broker-provider-retry.test.js +134 -82
  240. package/dist/core/__tests__/{full → seam}/broker-whip-interrupt.test.js +15 -4
  241. package/dist/core/__tests__/{full/idle-release-settlement.test.js → seam/dormancy-release.test.js} +69 -17
  242. package/dist/core/__tests__/{full/yield-message-transaction.test.js → seam/yield-refresh-transaction.test.js} +31 -9
  243. package/dist/core/__tests__/secrets.test.js +1 -7
  244. package/dist/core/__tests__/{broker-fork-seam.test.js → serial/broker-fork-seam.test.js} +58 -7
  245. package/dist/core/__tests__/{broker-sdk-wiring.test.js → serial/broker-sdk-wiring.test.js} +18 -162
  246. package/dist/core/__tests__/{broker-snapshot-history.test.js → serial/broker-snapshot-history.test.js} +9 -9
  247. package/dist/core/__tests__/{command-plugins.test.js → serial/command-plugins.test.js} +105 -15
  248. package/dist/core/__tests__/{deferred-no-wake.test.js → serial/deferred-no-wake.test.js} +23 -20
  249. package/dist/core/__tests__/{flagship-lifecycle.test.js → serial/flagship-lifecycle.test.js} +7 -7
  250. package/dist/core/__tests__/{host-teardown-process-group.test.js → serial/host-teardown-process-group.test.js} +6 -6
  251. package/dist/core/__tests__/{human-deliver-e2e.test.js → serial/human-deliver-e2e.test.js} +12 -12
  252. package/dist/core/__tests__/{live-mutation.test.js → serial/live-mutation.test.js} +5 -5
  253. package/dist/core/__tests__/{refresh-stall-recycle.test.js → serial/refresh-stall-recycle.test.js} +5 -14
  254. package/dist/core/__tests__/{revive.test.js → serial/revive.test.js} +15 -100
  255. package/dist/core/__tests__/{spawn-root.test.js → serial/spawn-root.test.js} +32 -15
  256. package/dist/core/__tests__/serial/subscription-delivery.test.js +126 -0
  257. package/dist/core/__tests__/serial/tmux-surface.test.js +256 -0
  258. package/dist/core/__tests__/{worktree.test.js → serial/worktree.test.js} +15 -15
  259. package/dist/core/__tests__/session-model.test.js +0 -18
  260. package/dist/core/__tests__/spawn-worktree-id-conflict.test.js +9 -0
  261. package/dist/core/__tests__/watchdog-abort-arms-retry.test.js +50 -0
  262. package/dist/core/broker-client/__tests__/transport-relay.test.js +15 -16
  263. package/dist/core/broker-client/__tests__/transport-socket.test.js +28 -0
  264. package/dist/core/broker-client/client.d.ts +2 -2
  265. package/dist/core/broker-client/client.js +4 -7
  266. package/dist/core/broker-client/transport-relay.d.ts +13 -19
  267. package/dist/core/broker-client/transport-relay.js +19 -34
  268. package/dist/core/broker-client/transport-socket.d.ts +2 -2
  269. package/dist/core/broker-client/transport-socket.js +9 -2
  270. package/dist/core/broker-client/transport.d.ts +7 -3
  271. package/dist/core/broker-client/transport.js +4 -4
  272. package/dist/core/canvas/__tests__/attention.test.js +1 -18
  273. package/dist/core/canvas/__tests__/remote-canvas-source.test.js +7 -64
  274. package/dist/core/canvas/__tests__/remote-transport.test.js +2 -3
  275. package/dist/core/canvas/__tests__/render-remote.test.js +7 -52
  276. package/dist/core/canvas/browse/app.d.ts +2 -17
  277. package/dist/core/canvas/browse/app.js +16 -88
  278. package/dist/core/canvas/browse/model.d.ts +0 -4
  279. package/dist/core/canvas/browse/model.js +1 -12
  280. package/dist/core/canvas/browse/render.js +6 -3
  281. package/dist/core/canvas/crons.d.ts +8 -5
  282. package/dist/core/canvas/crons.js +7 -6
  283. package/dist/core/canvas/extensions.d.ts +7 -3
  284. package/dist/core/canvas/extensions.js +16 -4
  285. package/dist/core/canvas/nav-model.d.ts +0 -4
  286. package/dist/core/canvas/nav-model.js +2 -14
  287. package/dist/core/canvas/node-order.d.ts +3 -0
  288. package/dist/core/canvas/node-order.js +12 -0
  289. package/dist/core/canvas/remote-canvas-source.d.ts +3 -6
  290. package/dist/core/canvas/remote-canvas-source.js +8 -15
  291. package/dist/core/command.js +11 -4
  292. package/dist/core/config.js +3 -1
  293. package/dist/core/events/envelope.js +1 -1
  294. package/dist/core/events/read.js +7 -21
  295. package/dist/core/events/source.d.ts +0 -2
  296. package/dist/core/events/source.js +0 -16
  297. package/dist/core/events/types.d.ts +1 -1
  298. package/dist/core/fault-classifier.d.ts +1 -1
  299. package/dist/core/feed/passive.d.ts +0 -11
  300. package/dist/core/feed/passive.js +1 -62
  301. package/dist/core/human/__tests__/{inbox-core.test.js → serial/inbox-core.test.js} +6 -6
  302. package/dist/core/keybindings/__tests__/resolve.test.js +1 -96
  303. package/dist/core/keybindings/background-bash.js +3 -4
  304. package/dist/core/keybindings/catalog.js +1 -1
  305. package/dist/core/memory/inline-ref-grammar.js +3 -3
  306. package/dist/core/memory-resolver.d.ts +11 -25
  307. package/dist/core/memory-resolver.js +51 -33
  308. package/dist/core/model-routes.d.ts +15 -0
  309. package/dist/core/model-routes.js +12 -0
  310. package/dist/core/pool-credential-store.js +1 -1
  311. package/dist/core/preview-registry.js +8 -9
  312. package/dist/core/profiles/__tests__/root-profile.test.js +4 -14
  313. package/dist/core/review/realize.d.ts +0 -13
  314. package/dist/core/review/realize.js +0 -40
  315. package/dist/core/review/types.d.ts +1 -1
  316. package/dist/core/runtime/__tests__/engine-route.test.js +2 -2
  317. package/dist/core/runtime/bearings.js +1 -11
  318. package/dist/core/runtime/broker/client-registry.d.ts +33 -0
  319. package/dist/core/runtime/broker/client-registry.js +164 -0
  320. package/dist/core/runtime/broker/daemon-ops.d.ts +19 -0
  321. package/dist/core/runtime/broker/daemon-ops.js +49 -0
  322. package/dist/core/runtime/broker/event-projection.d.ts +42 -0
  323. package/dist/core/runtime/broker/event-projection.js +178 -0
  324. package/dist/core/runtime/broker/fault-retry.d.ts +39 -0
  325. package/dist/core/runtime/broker/fault-retry.js +277 -0
  326. package/dist/core/runtime/broker/frame-dispatch.d.ts +238 -0
  327. package/dist/core/runtime/broker/frame-dispatch.js +1537 -0
  328. package/dist/core/runtime/broker/inbox.d.ts +22 -0
  329. package/dist/core/runtime/broker/inbox.js +167 -0
  330. package/dist/core/runtime/broker/passive.d.ts +16 -0
  331. package/dist/core/runtime/broker/passive.js +44 -0
  332. package/dist/core/runtime/broker/read-ops.d.ts +23 -0
  333. package/dist/core/runtime/broker/read-ops.js +150 -0
  334. package/dist/core/runtime/broker/rebind.d.ts +74 -0
  335. package/dist/core/runtime/broker/rebind.js +211 -0
  336. package/dist/core/runtime/broker/tool-groups.d.ts +39 -0
  337. package/dist/core/runtime/broker/tool-groups.js +244 -0
  338. package/dist/core/runtime/broker-extension-render.d.ts +11 -0
  339. package/dist/core/runtime/broker-extension-render.js +181 -0
  340. package/dist/core/runtime/broker-persona-guidance.d.ts +13 -0
  341. package/dist/core/runtime/broker-persona-guidance.js +58 -0
  342. package/dist/core/runtime/broker-protocol.d.ts +1 -1
  343. package/dist/core/runtime/broker-protocol.js +1 -1
  344. package/dist/core/runtime/broker.d.ts +5 -196
  345. package/dist/core/runtime/broker.js +276 -3059
  346. package/dist/core/runtime/canvas-extensions.js +11 -2
  347. package/dist/core/runtime/fault.js +1 -1
  348. package/dist/core/runtime/model-selection.d.ts +9 -0
  349. package/dist/core/runtime/model-selection.js +12 -0
  350. package/dist/core/runtime/model-swap.d.ts +3 -3
  351. package/dist/core/runtime/model-swap.js +33 -25
  352. package/dist/core/runtime/placement-tmux.d.ts +3 -14
  353. package/dist/core/runtime/placement-tmux.js +11 -80
  354. package/dist/core/runtime/placement.d.ts +4 -2
  355. package/dist/core/runtime/placement.js +7 -12
  356. package/dist/core/runtime/promote.d.ts +14 -1
  357. package/dist/core/runtime/promote.js +1 -1
  358. package/dist/core/runtime/reset.d.ts +1 -1
  359. package/dist/core/runtime/roadmap.js +1 -1
  360. package/dist/core/runtime/spawn.d.ts +8 -0
  361. package/dist/core/runtime/spawn.js +36 -6
  362. package/dist/core/runtime/stop-guard.d.ts +4 -3
  363. package/dist/core/runtime/stop-guard.js +36 -18
  364. package/dist/core/runtime/stop-signals.d.ts +4 -1
  365. package/dist/core/runtime/stream-watchdog.js +4 -5
  366. package/dist/core/runtime/structured-output.d.ts +15 -2
  367. package/dist/core/runtime/structured-output.js +35 -12
  368. package/dist/core/runtime/tmux-bindings.d.ts +25 -0
  369. package/dist/core/runtime/tmux-bindings.js +682 -0
  370. package/dist/core/runtime/tmux-chrome.d.ts +2 -1
  371. package/dist/core/runtime/tmux-chrome.js +3 -2
  372. package/dist/core/runtime/{tmux.d.ts → tmux-driver.d.ts} +18 -26
  373. package/dist/core/runtime/tmux-driver.js +598 -0
  374. package/dist/core/runtime/view-socket.d.ts +14 -0
  375. package/dist/core/runtime/view-socket.js +83 -0
  376. package/dist/core/session-model/session-state.d.ts +1 -2
  377. package/dist/core/session-model/session-state.js +5 -8
  378. package/dist/core/spawn.d.ts +1 -1
  379. package/dist/core/spawn.js +2 -2
  380. package/dist/core/substrate/gate.d.ts +1 -1
  381. package/dist/core/substrate/on-read-pure.d.ts +7 -0
  382. package/dist/core/substrate/on-read-pure.js +272 -0
  383. package/dist/core/termrender/termrender.js +32 -2
  384. package/dist/core/user-settings.d.ts +23 -1
  385. package/dist/core/user-settings.js +18 -1
  386. package/dist/daemon/api/__tests__/node-model-validation.test.js +134 -0
  387. package/dist/daemon/api/__tests__/review-terminal-conflict.test.js +98 -0
  388. package/dist/daemon/api/__tests__/{full → seam}/api-server.test.js +6 -48
  389. package/dist/daemon/api/__tests__/{full → seam}/b10-attach-modelauth.test.js +17 -44
  390. package/dist/daemon/api/__tests__/{full/push-parity.test.js → seam/leaf-api-parity.test.js} +61 -42
  391. package/dist/daemon/api/bridge.js +40 -81
  392. package/dist/daemon/api/handlers/broker-ops.d.ts +2 -0
  393. package/dist/daemon/api/handlers/broker-ops.js +383 -0
  394. package/dist/daemon/api/handlers/crons.js +9 -4
  395. package/dist/daemon/api/handlers/files.js +6 -7
  396. package/dist/daemon/api/handlers/inbox.js +2 -340
  397. package/dist/daemon/api/handlers/nodes.d.ts +10 -1
  398. package/dist/daemon/api/handlers/nodes.js +74 -39
  399. package/dist/daemon/api/handlers/review-comments.js +5 -1
  400. package/dist/daemon/api/handlers/reviews.js +0 -19
  401. package/dist/daemon/api/map.js +25 -4
  402. package/dist/daemon/api/router.js +2 -3
  403. package/dist/daemon/api/server.js +5 -7
  404. package/dist/daemon/cron-run.d.ts +4 -0
  405. package/dist/daemon/cron-run.js +30 -13
  406. package/dist/daemon/crtrd.d.ts +3 -58
  407. package/dist/daemon/crtrd.js +28 -1244
  408. package/dist/daemon/manage.js +0 -1
  409. package/dist/daemon/reconcilers/broker-supervision.d.ts +50 -0
  410. package/dist/daemon/reconcilers/broker-supervision.js +549 -0
  411. package/dist/daemon/reconcilers/cron-lane.d.ts +10 -0
  412. package/dist/daemon/reconcilers/cron-lane.js +32 -0
  413. package/dist/daemon/reconcilers/dormant-inbox.d.ts +18 -0
  414. package/dist/daemon/reconcilers/dormant-inbox.js +143 -0
  415. package/dist/daemon/reconcilers/storage-maintenance.d.ts +22 -0
  416. package/dist/daemon/reconcilers/storage-maintenance.js +213 -0
  417. package/dist/daemon/review/finish.js +2 -5
  418. package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +34 -53
  419. package/dist/pi-extensions/__tests__/canvas-recap.test.js +16 -113
  420. package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +72 -99
  421. package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.js +29 -12
  422. package/dist/pi-extensions/broker-local.d.ts +20 -0
  423. package/dist/pi-extensions/broker-local.js +89 -0
  424. package/dist/pi-extensions/canvas-context-intro.d.ts +3 -3
  425. package/dist/pi-extensions/canvas-context-intro.js +22 -11
  426. package/dist/pi-extensions/canvas-doc-substrate.js +17 -34
  427. package/dist/pi-extensions/canvas-goal-capture.js +7 -12
  428. package/dist/pi-extensions/canvas-inbox-watcher.js +124 -139
  429. package/dist/pi-extensions/canvas-passive-context.d.ts +3 -3
  430. package/dist/pi-extensions/canvas-passive-context.js +22 -18
  431. package/dist/pi-extensions/canvas-recap.d.ts +2 -2
  432. package/dist/pi-extensions/canvas-recap.js +48 -21
  433. package/dist/pi-extensions/canvas-review-boundary.js +10 -4
  434. package/dist/pi-extensions/canvas-stophook.d.ts +0 -5
  435. package/dist/pi-extensions/canvas-stophook.js +149 -431
  436. package/dist/pi-extensions/canvas-structured-output.js +52 -30
  437. package/dist/pi-extensions/envelope-merge.d.ts +13 -0
  438. package/dist/pi-extensions/envelope-merge.js +29 -0
  439. package/dist/shared/working-activity.d.ts +3 -2
  440. package/dist/shared/working-activity.js +3 -2
  441. package/dist/types.d.ts +6 -5
  442. package/dist/types.js +2 -2
  443. package/docs/compat/hearth-crtr-v1.md +4 -12
  444. package/docs/compat/hearth-crtr-v2.md +3 -11
  445. package/docs/compat/hearth-crtr-v3.md +4 -12
  446. package/docs/compat/hearth-crtr-v4.md +3 -11
  447. package/docs/compat/hearth-crtr-v5.md +3 -11
  448. package/docs/public-api.md +3 -7
  449. package/package.json +7 -49
  450. package/runtime.lock.json +2766 -14533
  451. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/claude-plugin-commands.test.ts +0 -49
  452. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/memory-slash-commands.test.ts +0 -194
  453. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/statusline.test.ts +0 -68
  454. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/frontmatter-rules/test.ts +0 -119
  455. package/dist/clients/attach/__tests__/attach-chrome-remote.test.js +0 -439
  456. package/dist/clients/attach/__tests__/attach-keybindings.test.js +0 -170
  457. package/dist/clients/attach/__tests__/crtr-output-coverage.test.js +0 -57
  458. package/dist/clients/attach/__tests__/editor-frame-title.test.js +0 -19
  459. package/dist/clients/attach/__tests__/input-controller-extension-command.test.js +0 -32
  460. package/dist/clients/attach/__tests__/markdown-headings.test.js +0 -35
  461. package/dist/clients/attach/__tests__/session-identity-refresh.test.js +0 -32
  462. package/dist/clients/conversation/conversation.d.ts +0 -65
  463. package/dist/clients/conversation/conversation.js +0 -318
  464. package/dist/clients/conversation/frames.d.ts +0 -30
  465. package/dist/clients/conversation/frames.js +0 -52
  466. package/dist/clients/conversation/region.d.ts +0 -51
  467. package/dist/clients/conversation/region.js +0 -265
  468. package/dist/clients/inbox/__tests__/inbox-controller.test.js +0 -247
  469. package/dist/clients/inbox/__tests__/mount-panel.test.js +0 -776
  470. package/dist/clients/inbox/review/__tests__/remap.test.js +0 -196
  471. package/dist/clients/inbox/review/columns.d.ts +0 -22
  472. package/dist/clients/inbox/review/columns.js +0 -40
  473. package/dist/clients/inbox/review/composition.d.ts +0 -60
  474. package/dist/clients/inbox/review/composition.js +0 -278
  475. package/dist/clients/inbox/review/document-region.d.ts +0 -120
  476. package/dist/clients/surfaces/region.d.ts +0 -16
  477. package/dist/clients/web/__tests__/push-engine.test.js +0 -158
  478. package/dist/clients/web/__tests__/push-registry.test.d.ts +0 -1
  479. package/dist/clients/web/__tests__/push-registry.test.js +0 -177
  480. package/dist/clients/web/dev-server.d.ts +0 -7
  481. package/dist/clients/web/dev-server.js +0 -46
  482. package/dist/clients/web/events.d.ts +0 -19
  483. package/dist/clients/web/events.js +0 -163
  484. package/dist/clients/web/push-engine.d.ts +0 -44
  485. package/dist/clients/web/push-engine.js +0 -125
  486. package/dist/clients/web/push-registry.d.ts +0 -85
  487. package/dist/clients/web/push-registry.js +0 -373
  488. package/dist/clients/web/server.d.ts +0 -19
  489. package/dist/clients/web/server.js +0 -661
  490. package/dist/clients/web/web-client/shared/protocol.d.ts +0 -214
  491. package/dist/clients/web/web-client/shared/protocol.js +0 -8
  492. package/dist/clients/web/web-cmd.d.ts +0 -2
  493. package/dist/clients/web/web-cmd.js +0 -141
  494. package/dist/commands/__tests__/api-canvas-source.test.d.ts +0 -1
  495. package/dist/commands/__tests__/api-canvas-source.test.js +0 -37
  496. package/dist/commands/__tests__/canvas-config.test.d.ts +0 -1
  497. package/dist/commands/__tests__/canvas-config.test.js +0 -107
  498. package/dist/commands/__tests__/node-no-kickoff-flag.test.d.ts +0 -1
  499. package/dist/commands/__tests__/node-no-kickoff-flag.test.js +0 -73
  500. package/dist/commands/__tests__/node-worktree-flag.test.d.ts +0 -1
  501. package/dist/commands/__tests__/node-worktree-flag.test.js +0 -49
  502. package/dist/commands/__tests__/search-contents.test.d.ts +0 -1
  503. package/dist/commands/__tests__/search-contents.test.js +0 -52
  504. package/dist/commands/memory/__tests__/lint.test.d.ts +0 -1
  505. package/dist/commands/memory/__tests__/lint.test.js +0 -15
  506. package/dist/commands/sys/__tests__/config-broker-thresholds.test.d.ts +0 -1
  507. package/dist/commands/sys/__tests__/config-broker-thresholds.test.js +0 -95
  508. package/dist/commands/sys/__tests__/config-keybindings.test.d.ts +0 -1
  509. package/dist/commands/sys/__tests__/config-keybindings.test.js +0 -55
  510. package/dist/commands/sys/__tests__/helpers/setup-runtime.d.ts +0 -5
  511. package/dist/commands/sys/__tests__/helpers/setup-runtime.js +0 -19
  512. package/dist/commands/sys/__tests__/setup-front-door.test.d.ts +0 -1
  513. package/dist/commands/sys/__tests__/setup-front-door.test.js +0 -102
  514. package/dist/commands/sys/__tests__/setup-models.test.d.ts +0 -1
  515. package/dist/commands/sys/__tests__/setup-models.test.js +0 -205
  516. package/dist/commands/sys/__tests__/setup-providers-viewport.test.d.ts +0 -1
  517. package/dist/commands/sys/__tests__/setup-providers-viewport.test.js +0 -155
  518. package/dist/commands/sys/__tests__/sync-deps.test.d.ts +0 -1
  519. package/dist/commands/sys/__tests__/sync-deps.test.js +0 -179
  520. package/dist/commands/sys/__tests__/sync-import.test.d.ts +0 -1
  521. package/dist/commands/sys/__tests__/sync-import.test.js +0 -315
  522. package/dist/core/__tests__/base-worker-prompt.test.d.ts +0 -1
  523. package/dist/core/__tests__/base-worker-prompt.test.js +0 -57
  524. package/dist/core/__tests__/command-plugins-surfaces.test.d.ts +0 -1
  525. package/dist/core/__tests__/command-plugins-surfaces.test.js +0 -359
  526. package/dist/core/__tests__/connection-reconnect-resume.test.d.ts +0 -1
  527. package/dist/core/__tests__/connection-reconnect-resume.test.js +0 -36
  528. package/dist/core/__tests__/finalization-migration.test.d.ts +0 -1
  529. package/dist/core/__tests__/finalization-migration.test.js +0 -38
  530. package/dist/core/__tests__/fixtures/extra-extension.d.ts +0 -1
  531. package/dist/core/__tests__/fixtures/extra-extension.js +0 -3
  532. package/dist/core/__tests__/fixtures/spawn-proof-target.test.d.ts +0 -1
  533. package/dist/core/__tests__/fixtures/spawn-proof-target.test.js +0 -15
  534. package/dist/core/__tests__/fork.test.d.ts +0 -1
  535. package/dist/core/__tests__/fork.test.js +0 -108
  536. package/dist/core/__tests__/full/broker-attach-limits.test.d.ts +0 -1
  537. package/dist/core/__tests__/full/broker-attach-limits.test.js +0 -147
  538. package/dist/core/__tests__/full/broker-deliver-ack.test.d.ts +0 -1
  539. package/dist/core/__tests__/full/broker-deliver-ack.test.js +0 -73
  540. package/dist/core/__tests__/full/broker-dialogs.test.d.ts +0 -1
  541. package/dist/core/__tests__/full/broker-dialogs.test.js +0 -180
  542. package/dist/core/__tests__/full/broker-display-snapshot.test.d.ts +0 -1
  543. package/dist/core/__tests__/full/broker-display-snapshot.test.js +0 -75
  544. package/dist/core/__tests__/full/broker-dormant-wake.test.d.ts +0 -1
  545. package/dist/core/__tests__/full/broker-dormant-wake.test.js +0 -130
  546. package/dist/core/__tests__/full/broker-model-changed-broadcast.test.d.ts +0 -1
  547. package/dist/core/__tests__/full/broker-model-changed-broadcast.test.js +0 -57
  548. package/dist/core/__tests__/full/broker-navigate-tree-rewelcome.test.d.ts +0 -1
  549. package/dist/core/__tests__/full/broker-navigate-tree-rewelcome.test.js +0 -80
  550. package/dist/core/__tests__/full/cascade-close.test.d.ts +0 -1
  551. package/dist/core/__tests__/full/cascade-close.test.js +0 -240
  552. package/dist/core/__tests__/full/detach-focus.test.d.ts +0 -1
  553. package/dist/core/__tests__/full/detach-focus.test.js +0 -126
  554. package/dist/core/__tests__/full/idle-release-settlement.test.d.ts +0 -1
  555. package/dist/core/__tests__/full/issue-146-yield-spawn-focus.test.d.ts +0 -1
  556. package/dist/core/__tests__/full/issue-146-yield-spawn-focus.test.js +0 -107
  557. package/dist/core/__tests__/full/park-clock-release.test.d.ts +0 -1
  558. package/dist/core/__tests__/full/park-clock-release.test.js +0 -56
  559. package/dist/core/__tests__/full/yield-message-transaction.test.d.ts +0 -1
  560. package/dist/core/__tests__/memory-index-render.test.d.ts +0 -1
  561. package/dist/core/__tests__/memory-index-render.test.js +0 -60
  562. package/dist/core/__tests__/model-routes.test.d.ts +0 -1
  563. package/dist/core/__tests__/model-routes.test.js +0 -41
  564. package/dist/core/__tests__/on-read-identity.test.d.ts +0 -1
  565. package/dist/core/__tests__/on-read-identity.test.js +0 -61
  566. package/dist/core/__tests__/phase4-review-migration.test.d.ts +0 -1
  567. package/dist/core/__tests__/phase4-review-migration.test.js +0 -100
  568. package/dist/core/__tests__/prune-to-limit.test.d.ts +0 -1
  569. package/dist/core/__tests__/prune-to-limit.test.js +0 -126
  570. package/dist/core/__tests__/reset.test.d.ts +0 -1
  571. package/dist/core/__tests__/reset.test.js +0 -69
  572. package/dist/core/__tests__/spawn-no-kickoff.test.d.ts +0 -1
  573. package/dist/core/__tests__/spawn-no-kickoff.test.js +0 -115
  574. package/dist/core/__tests__/steer-note.test.d.ts +0 -1
  575. package/dist/core/__tests__/steer-note.test.js +0 -41
  576. package/dist/core/__tests__/subcommand-tier.test.d.ts +0 -1
  577. package/dist/core/__tests__/subcommand-tier.test.js +0 -99
  578. package/dist/core/__tests__/subscription-delivery.test.js +0 -211
  579. package/dist/core/__tests__/test-runner-cheap-sharding.test.d.ts +0 -1
  580. package/dist/core/__tests__/test-runner-cheap-sharding.test.js +0 -97
  581. package/dist/core/__tests__/tmux-surface.test.js +0 -484
  582. package/dist/core/__tests__/wake-bearings.test.d.ts +0 -1
  583. package/dist/core/__tests__/wake-bearings.test.js +0 -102
  584. package/dist/core/canvas/__tests__/remote-event-stream.test.d.ts +0 -1
  585. package/dist/core/canvas/__tests__/remote-event-stream.test.js +0 -146
  586. package/dist/core/canvas/__tests__/source-resolve.test.d.ts +0 -1
  587. package/dist/core/canvas/__tests__/source-resolve.test.js +0 -77
  588. package/dist/core/canvas/browse/__tests__/model.test.d.ts +0 -1
  589. package/dist/core/canvas/browse/__tests__/model.test.js +0 -290
  590. package/dist/core/canvas/browse/__tests__/rebuild-coalescer.test.d.ts +0 -1
  591. package/dist/core/canvas/browse/__tests__/rebuild-coalescer.test.js +0 -134
  592. package/dist/core/canvas/browse/__tests__/render.test.d.ts +0 -1
  593. package/dist/core/canvas/browse/__tests__/render.test.js +0 -111
  594. package/dist/core/canvas/browse/rebuild-coalescer.d.ts +0 -7
  595. package/dist/core/canvas/browse/rebuild-coalescer.js +0 -61
  596. package/dist/core/canvas/remote-event-stream.d.ts +0 -24
  597. package/dist/core/canvas/remote-event-stream.js +0 -94
  598. package/dist/core/feed/__tests__/coalesce-human.test.d.ts +0 -1
  599. package/dist/core/feed/__tests__/coalesce-human.test.js +0 -36
  600. package/dist/core/feed/__tests__/empty-node-guard.test.d.ts +0 -1
  601. package/dist/core/feed/__tests__/empty-node-guard.test.js +0 -45
  602. package/dist/core/host-exports/__tests__/export-prunes-boot-skill.test.d.ts +0 -1
  603. package/dist/core/host-exports/__tests__/export-prunes-boot-skill.test.js +0 -84
  604. package/dist/core/human/__tests__/visible-paths.test.d.ts +0 -1
  605. package/dist/core/human/__tests__/visible-paths.test.js +0 -28
  606. package/dist/core/keybindings/__tests__/inbox-affordance.test.d.ts +0 -1
  607. package/dist/core/keybindings/__tests__/inbox-affordance.test.js +0 -38
  608. package/dist/core/review/__tests__/project.test.d.ts +0 -1
  609. package/dist/core/review/__tests__/project.test.js +0 -71
  610. package/dist/core/runtime/__tests__/command-expansion.test.d.ts +0 -1
  611. package/dist/core/runtime/__tests__/command-expansion.test.js +0 -25
  612. package/dist/core/runtime/__tests__/session-visibility.test.d.ts +0 -1
  613. package/dist/core/runtime/__tests__/session-visibility.test.js +0 -119
  614. package/dist/core/runtime/__tests__/spawn-at-given-id.test.d.ts +0 -1
  615. package/dist/core/runtime/__tests__/spawn-at-given-id.test.js +0 -34
  616. package/dist/core/runtime/tmux.js +0 -1314
  617. package/dist/daemon/api/__tests__/full/push-parity.test.d.ts +0 -1
  618. package/dist/daemon/api/__tests__/full/worktree-parity.test.d.ts +0 -1
  619. package/dist/daemon/api/__tests__/full/worktree-parity.test.js +0 -160
  620. package/dist/daemon/api/__tests__/inbox.test.d.ts +0 -1
  621. package/dist/daemon/api/__tests__/inbox.test.js +0 -489
  622. package/dist/web-client/apple-touch-icon.png +0 -0
  623. package/dist/web-client/assets/fragment-mono-latin-400-normal-BYwT3kSJ.woff +0 -0
  624. package/dist/web-client/assets/fragment-mono-latin-400-normal-yxdJ5AmL.woff2 +0 -0
  625. package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-BbKYyvR9.woff2 +0 -0
  626. package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-CT4YFKeK.woff +0 -0
  627. package/dist/web-client/assets/index-CCPaLeW7.css +0 -2
  628. package/dist/web-client/assets/index-kyOWsnZK.js +0 -86
  629. package/dist/web-client/assets/martian-mono-cyrillic-wght-normal-B84CD5C_.woff2 +0 -0
  630. package/dist/web-client/assets/martian-mono-latin-ext-wght-normal-DlL6xMw5.woff2 +0 -0
  631. package/dist/web-client/assets/martian-mono-latin-wght-normal-5W32yIyr.woff2 +0 -0
  632. package/dist/web-client/assets/workbox-window.prod.es5-Bd17z0YL.js +0 -2
  633. package/dist/web-client/icon-192.png +0 -0
  634. package/dist/web-client/icon-512.png +0 -0
  635. package/dist/web-client/icon-maskable-512.png +0 -0
  636. package/dist/web-client/index.html +0 -17
  637. package/dist/web-client/manifest.webmanifest +0 -1
  638. package/dist/web-client/sw.js +0 -1
  639. /package/dist/api/__tests__/{client.test.d.ts → serial/client.test.d.ts} +0 -0
  640. /package/dist/clients/inbox/__tests__/{inbox-controller.test.d.ts → serial/inbox-controller.test.d.ts} +0 -0
  641. /package/dist/clients/inbox/__tests__/{mount-panel.test.d.ts → serial/mount-panel.test.d.ts} +0 -0
  642. /package/dist/clients/{attach/__tests__/attach-chrome-remote.test.d.ts → inbox/review/__tests__/teardown-notice.test.d.ts} +0 -0
  643. /package/dist/{clients/attach/__tests__/attach-keybindings.test.d.ts → core/__tests__/broker-extension-canvas-db-boundary.test.d.ts} +0 -0
  644. /package/dist/{clients/attach/__tests__/crtr-output-coverage.test.d.ts → core/__tests__/seam/broker-attach-multiclient.test.d.ts} +0 -0
  645. /package/dist/core/__tests__/{full → seam}/broker-attach-stream.test.d.ts +0 -0
  646. /package/dist/core/__tests__/{full → seam}/broker-crash-teardown.test.d.ts +0 -0
  647. /package/dist/core/__tests__/{full → seam}/broker-pane-resolution.test.d.ts +0 -0
  648. /package/dist/core/__tests__/{full → seam}/broker-provider-retry.test.d.ts +0 -0
  649. /package/dist/core/__tests__/{full → seam}/broker-whip-interrupt.test.d.ts +0 -0
  650. /package/dist/{clients/attach/__tests__/editor-frame-title.test.d.ts → core/__tests__/seam/dormancy-release.test.d.ts} +0 -0
  651. /package/dist/{clients/attach/__tests__/input-controller-extension-command.test.d.ts → core/__tests__/seam/yield-refresh-transaction.test.d.ts} +0 -0
  652. /package/dist/core/__tests__/{broker-fork-seam.test.d.ts → serial/broker-fork-seam.test.d.ts} +0 -0
  653. /package/dist/core/__tests__/{broker-sdk-wiring.test.d.ts → serial/broker-sdk-wiring.test.d.ts} +0 -0
  654. /package/dist/core/__tests__/{broker-snapshot-history.test.d.ts → serial/broker-snapshot-history.test.d.ts} +0 -0
  655. /package/dist/core/__tests__/{command-plugins.test.d.ts → serial/command-plugins.test.d.ts} +0 -0
  656. /package/dist/core/__tests__/{deferred-no-wake.test.d.ts → serial/deferred-no-wake.test.d.ts} +0 -0
  657. /package/dist/core/__tests__/{flagship-lifecycle.test.d.ts → serial/flagship-lifecycle.test.d.ts} +0 -0
  658. /package/dist/core/__tests__/{host-teardown-process-group.test.d.ts → serial/host-teardown-process-group.test.d.ts} +0 -0
  659. /package/dist/core/__tests__/{human-deliver-e2e.test.d.ts → serial/human-deliver-e2e.test.d.ts} +0 -0
  660. /package/dist/core/__tests__/{live-mutation.test.d.ts → serial/live-mutation.test.d.ts} +0 -0
  661. /package/dist/core/__tests__/{refresh-stall-recycle.test.d.ts → serial/refresh-stall-recycle.test.d.ts} +0 -0
  662. /package/dist/core/__tests__/{revive.test.d.ts → serial/revive.test.d.ts} +0 -0
  663. /package/dist/core/__tests__/{spawn-root.test.d.ts → serial/spawn-root.test.d.ts} +0 -0
  664. /package/dist/core/__tests__/{subscription-delivery.test.d.ts → serial/subscription-delivery.test.d.ts} +0 -0
  665. /package/dist/core/__tests__/{tmux-surface.test.d.ts → serial/tmux-surface.test.d.ts} +0 -0
  666. /package/dist/core/__tests__/{worktree.test.d.ts → serial/worktree.test.d.ts} +0 -0
  667. /package/dist/{clients/attach/__tests__/markdown-headings.test.d.ts → core/__tests__/watchdog-abort-arms-retry.test.d.ts} +0 -0
  668. /package/dist/{clients/attach/__tests__/session-identity-refresh.test.d.ts → core/broker-client/__tests__/transport-socket.test.d.ts} +0 -0
  669. /package/dist/core/human/__tests__/{inbox-core.test.d.ts → serial/inbox-core.test.d.ts} +0 -0
  670. /package/dist/{clients/inbox/review/__tests__/remap.test.d.ts → daemon/api/__tests__/node-model-validation.test.d.ts} +0 -0
  671. /package/dist/{clients/surfaces/region.js → daemon/api/__tests__/review-terminal-conflict.test.d.ts} +0 -0
  672. /package/dist/daemon/api/__tests__/{full → seam}/api-server.test.d.ts +0 -0
  673. /package/dist/daemon/api/__tests__/{full → seam}/b10-attach-modelauth.test.d.ts +0 -0
  674. /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,79 @@
1
+ import type { AgentSessionEvent } from '@earendil-works/pi-coding-agent';
2
+ import type { Message, ToolResultMessage } from '@earendil-works/pi-ai';
3
+ import type { BrokerSnapshot } from '../../core/runtime/broker-protocol.js';
4
+ import { type ToolGroupSummary } from '../../shared/tool-groups.js';
5
+ /** A persisted pi message or a crouter custom message carried on the broker wire. */
6
+ export type AnyMessage = Message | ({
7
+ role: string;
8
+ } & Record<string, unknown>);
9
+ export interface ConvState {
10
+ /** The full ordered transcript (snapshot history + streamed messages). */
11
+ messages: AnyMessage[];
12
+ /** Index of the assistant message currently streaming, or null. */
13
+ streamingIndex: number | null;
14
+ /** toolCallIds whose `tool_execution_*` is in flight (for an "executing…" badge). */
15
+ executingToolIds: ReadonlySet<string>;
16
+ /** Latest streaming/final result carried by tool_execution_* before the persisted toolResult message lands. */
17
+ partialToolResults: ReadonlyMap<string, ToolResultMessage>;
18
+ /** True between `agent_start` and `agent_end` (drives prompt-vs-steer + Stop). */
19
+ isStreaming: boolean;
20
+ /** A transient activity label (working / compacting / retrying), or null. */
21
+ activity: string | null;
22
+ /** Broker-selected normal label restored after temporary compaction/retry activity. */
23
+ workingActivity: string;
24
+ /** Texts still waiting to run — a writable view's steer/follow-up sent mid-turn
25
+ * (pi's `_steeringMessages` + `_followUpMessages`), authoritative from the
26
+ * engine's `queue_update` event. Drained (and removed here) the moment each
27
+ * one starts as a real `message_start`, so a queued row and the eventual
28
+ * transcript message never both show. */
29
+ queued: readonly string[];
30
+ /** Plain-text presentation recaps, keyed by the group's first tool-call id. */
31
+ toolGroupSummaries: Readonly<Record<string, string>>;
32
+ /** Canonical broker-owned completed tool-group summaries, keyed by the group's first tool-call id. */
33
+ toolGroupSummaryDetails: Readonly<Record<string, ToolGroupSummary>>;
34
+ }
35
+ export declare function initialConvState(): ConvState;
36
+ /** Rebuild the ephemeral reconciliation fields from a persisted transcript cache. */
37
+ export declare function restoreConvState(entry: {
38
+ messages: AnyMessage[];
39
+ isStreaming: boolean;
40
+ activity: string | null;
41
+ toolGroupSummaries: unknown;
42
+ }): ConvState;
43
+ /** Seed state from the broker's catch-up snapshot.
44
+ *
45
+ * `welcome.snapshot` is the PERSISTED history (`snapshotMessages()` in the
46
+ * broker), not the live in-memory array. During an active turn — after
47
+ * `message_start`, before `message_end` — the in-flight assistant message may
48
+ * not be persisted yet, so a mid-stream `welcome` can report
49
+ * `state.isStreaming: true` with no trailing assistant in the snapshot.
50
+ * Wholesale-replacing in that case (as we always did) drops the in-flight
51
+ * turn: `streamingIndex` resets to null and the next `message_update`/
52
+ * `message_end` has nothing to land on (see `reduce`).
53
+ *
54
+ * So: idle snapshots replace wholesale exactly as before. Streaming snapshots
55
+ * reconcile — if the persisted history already ends in an assistant, adopt
56
+ * it as the streaming target; otherwise adopt the caller-supplied `previous`
57
+ * state's in-flight assistant (a cache-first render or an earlier live
58
+ * session) if one exists, or synthesize an empty placeholder. Either way the
59
+ * first `message_update` REPLACES that message wholesale, so no duplicate or
60
+ * dropped turn results. */
61
+ export declare function applySnapshot(snapshot: BrokerSnapshot, previous?: ConvState): ConvState;
62
+ /** Apply the broker's random choice for the newly received user message. */
63
+ export declare function applyWorkingActivity(state: ConvState, activity: string): ConvState;
64
+ /** Apply one broker-published structured summary without touching transcript ordering. */
65
+ export declare function applyToolGroupSummary(state: ConvState, key: string, summary: ToolGroupSummary): ConvState;
66
+ export declare function bashStart(state: ConvState, command: string, excludeFromContext?: boolean): ConvState;
67
+ export declare function bashOutput(state: ConvState, chunk: string): ConvState;
68
+ export declare function bashEnd(state: ConvState, result: {
69
+ exitCode: number | undefined;
70
+ cancelled: boolean;
71
+ truncated: boolean;
72
+ fullOutputPath?: string;
73
+ }): ConvState;
74
+ /** Apply one broker→client AGENT event (an `AgentSessionEvent`) to the transcript.
75
+ * Broker control frames (welcome/model_changed/error/…) are handled by the hook,
76
+ * NOT here — only pi agent events reach this function. Returns a NEW state object
77
+ * (with fresh `messages`/`executingToolIds` only when they actually change) so
78
+ * React re-renders correctly. */
79
+ export declare function reduce(state: ConvState, event: AgentSessionEvent): ConvState;
@@ -0,0 +1,341 @@
1
+ // projection.ts — the surface-neutral reducer that turns a broker snapshot and
2
+ // its live frames into one ordered transcript model. Renderers retain their own
3
+ // folding and presentation; this module owns only wire-state reconciliation.
4
+ import { isInboxDigest } from '../../shared/generated-context.js';
5
+ import { normalizeToolGroupSummary, normalizeToolGroupSummaryRecord } from '../../shared/tool-groups.js';
6
+ import { DEFAULT_WORKING_ACTIVITY } from '../../shared/working-activity.js';
7
+ export function initialConvState() {
8
+ return {
9
+ messages: [],
10
+ streamingIndex: null,
11
+ executingToolIds: new Set(),
12
+ partialToolResults: new Map(),
13
+ isStreaming: false,
14
+ activity: null,
15
+ workingActivity: DEFAULT_WORKING_ACTIVITY,
16
+ queued: [],
17
+ toolGroupSummaries: {},
18
+ toolGroupSummaryDetails: {},
19
+ };
20
+ }
21
+ /** Rebuild the ephemeral reconciliation fields from a persisted transcript cache. */
22
+ export function restoreConvState(entry) {
23
+ const lastIndex = entry.messages.length - 1;
24
+ return {
25
+ ...initialConvState(),
26
+ messages: entry.messages,
27
+ streamingIndex: entry.isStreaming && lastIndex >= 0 ? lastIndex : null,
28
+ isStreaming: entry.isStreaming,
29
+ activity: entry.activity,
30
+ workingActivity: entry.isStreaming && entry.activity !== null ? entry.activity : DEFAULT_WORKING_ACTIVITY,
31
+ toolGroupSummaries: textToolGroupSummaries(entry.toolGroupSummaries),
32
+ toolGroupSummaryDetails: normalizeToolGroupSummaryRecord(entry.toolGroupSummaries),
33
+ };
34
+ }
35
+ /** Plain text of a user message (string content or concatenated text blocks),
36
+ * for inbox-digest detection. */
37
+ function userMessageText(m) {
38
+ const content = m.content;
39
+ if (typeof content === 'string')
40
+ return content;
41
+ if (Array.isArray(content)) {
42
+ return content
43
+ .filter((b) => !!b && b.type === 'text')
44
+ .map((b) => (typeof b.text === 'string' ? b.text : ''))
45
+ .join('');
46
+ }
47
+ return '';
48
+ }
49
+ /** Tag a `role:'user'` message as inbox-origin when its text matches the
50
+ * canvas-inbox-watcher coalesce digest; other messages pass through unchanged.
51
+ * The broker relays pi AgentMessages verbatim and never carries `origin` on the
52
+ * wire, so this is the sole writer of `origin:'inbox'` — recognized from the
53
+ * digest text. (Idempotent: a message already tagged is left as-is.) */
54
+ function tagInboxOrigin(m) {
55
+ if (roleOf(m) !== 'user')
56
+ return m;
57
+ if (m.origin)
58
+ return m;
59
+ if (!isInboxDigest(userMessageText(m)))
60
+ return m;
61
+ return { ...m, origin: 'inbox' };
62
+ }
63
+ /** An empty assistant message shaped so the next `message_update`/`message_end`
64
+ * (which replace, not append — see `reduce`'s `message_update` case) has a
65
+ * slot to land on. */
66
+ function placeholderAssistant() {
67
+ return { role: 'assistant', content: [] };
68
+ }
69
+ /** Seed state from the broker's catch-up snapshot.
70
+ *
71
+ * `welcome.snapshot` is the PERSISTED history (`snapshotMessages()` in the
72
+ * broker), not the live in-memory array. During an active turn — after
73
+ * `message_start`, before `message_end` — the in-flight assistant message may
74
+ * not be persisted yet, so a mid-stream `welcome` can report
75
+ * `state.isStreaming: true` with no trailing assistant in the snapshot.
76
+ * Wholesale-replacing in that case (as we always did) drops the in-flight
77
+ * turn: `streamingIndex` resets to null and the next `message_update`/
78
+ * `message_end` has nothing to land on (see `reduce`).
79
+ *
80
+ * So: idle snapshots replace wholesale exactly as before. Streaming snapshots
81
+ * reconcile — if the persisted history already ends in an assistant, adopt
82
+ * it as the streaming target; otherwise adopt the caller-supplied `previous`
83
+ * state's in-flight assistant (a cache-first render or an earlier live
84
+ * session) if one exists, or synthesize an empty placeholder. Either way the
85
+ * first `message_update` REPLACES that message wholesale, so no duplicate or
86
+ * dropped turn results. */
87
+ export function applySnapshot(snapshot, previous) {
88
+ const messages = snapshot.messages.map(tagInboxOrigin);
89
+ const toolGroupSummaryDetails = snapshotToolGroupSummaries(snapshot);
90
+ const toolGroupSummaries = summaryTexts(toolGroupSummaryDetails);
91
+ const isStreaming = snapshot.state?.isStreaming === true;
92
+ const workingActivity = snapshotWorkingActivity(snapshot);
93
+ if (!isStreaming) {
94
+ return {
95
+ messages,
96
+ streamingIndex: null,
97
+ executingToolIds: new Set(),
98
+ partialToolResults: new Map(),
99
+ isStreaming: false,
100
+ activity: null,
101
+ workingActivity,
102
+ queued: [],
103
+ toolGroupSummaries,
104
+ toolGroupSummaryDetails,
105
+ };
106
+ }
107
+ const lastIdx = messages.length - 1;
108
+ if (lastIdx >= 0 && roleOf(messages[lastIdx]) === 'assistant') {
109
+ // The in-flight assistant is already in the persisted snapshot — adopt it.
110
+ return {
111
+ messages,
112
+ streamingIndex: lastIdx,
113
+ executingToolIds: new Set(),
114
+ partialToolResults: new Map(),
115
+ isStreaming: true,
116
+ activity: workingActivity,
117
+ workingActivity,
118
+ queued: [],
119
+ toolGroupSummaries,
120
+ toolGroupSummaryDetails,
121
+ };
122
+ }
123
+ // Not persisted yet — adopt the previous in-flight assistant if one was
124
+ // already rendered, else synthesize a placeholder.
125
+ const cachedAssistant = previous && previous.streamingIndex !== null ? previous.messages[previous.streamingIndex] : undefined;
126
+ const inFlightAssistant = cachedAssistant && roleOf(cachedAssistant) === 'assistant' ? cachedAssistant : placeholderAssistant();
127
+ const withInFlight = [...messages, inFlightAssistant];
128
+ return {
129
+ messages: withInFlight,
130
+ streamingIndex: withInFlight.length - 1,
131
+ executingToolIds: new Set(),
132
+ partialToolResults: new Map(),
133
+ isStreaming: true,
134
+ activity: workingActivity,
135
+ workingActivity,
136
+ queued: [],
137
+ toolGroupSummaries,
138
+ toolGroupSummaryDetails,
139
+ };
140
+ }
141
+ function snapshotWorkingActivity(snapshot) {
142
+ const activity = snapshot.workingActivity;
143
+ return typeof activity === 'string' && activity.trim() !== '' ? activity : DEFAULT_WORKING_ACTIVITY;
144
+ }
145
+ /** Apply the broker's random choice for the newly received user message. */
146
+ export function applyWorkingActivity(state, activity) {
147
+ const next = activity.trim() === '' ? DEFAULT_WORKING_ACTIVITY : activity;
148
+ return state.workingActivity === next ? state : { ...state, workingActivity: next };
149
+ }
150
+ /** Snapshot additions are optional across broker generations. Invalid entries
151
+ * are absent rather than adapted, so every surface receives the canonical
152
+ * structured summary or no summary at all. */
153
+ function snapshotToolGroupSummaries(snapshot) {
154
+ return normalizeToolGroupSummaryRecord(snapshot.toolGroupSummaries);
155
+ }
156
+ /** The web's compact recap is a presentation derived from canonical broker data. */
157
+ function summaryTexts(summaries) {
158
+ return Object.fromEntries(Object.entries(summaries).map(([key, summary]) => [key, summary.bullets.join(' · ')]));
159
+ }
160
+ /** Legacy browser-cache entries retain their prior presentation strings; live
161
+ * snapshots and frames always rebuild these from the structured source. */
162
+ function textToolGroupSummaries(value) {
163
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
164
+ return {};
165
+ return Object.fromEntries(Object.entries(value).filter((entry) => typeof entry[1] === 'string'));
166
+ }
167
+ /** Apply one broker-published structured summary without touching transcript ordering. */
168
+ export function applyToolGroupSummary(state, key, summary) {
169
+ const normalized = key.trim() === '' ? null : normalizeToolGroupSummary(summary);
170
+ if (normalized === null)
171
+ return state;
172
+ return {
173
+ ...state,
174
+ toolGroupSummaries: { ...state.toolGroupSummaries, [key]: normalized.bullets.join(' · ') },
175
+ toolGroupSummaryDetails: { ...state.toolGroupSummaryDetails, [key]: normalized },
176
+ };
177
+ }
178
+ function roleOf(m) {
179
+ return m.role ?? '';
180
+ }
181
+ // ---------------------------------------------------------------------------
182
+ // `!` bash execution (broker bash_start/bash_output/bash_end frames). These are
183
+ // broker control frames, NOT AgentSessionEvents, so the hook routes them here
184
+ // explicitly. They build a synthetic `bashExecution` message in the transcript
185
+ // that mirrors the one pi persists to context — rendered by MessageView.
186
+ // ---------------------------------------------------------------------------
187
+ /** Index of the most recent bashExecution message (the active `!` run), or null. */
188
+ function lastBashIndex(state) {
189
+ for (let i = state.messages.length - 1; i >= 0; i--) {
190
+ if (roleOf(state.messages[i]) === 'bashExecution')
191
+ return i;
192
+ }
193
+ return null;
194
+ }
195
+ export function bashStart(state, command, excludeFromContext) {
196
+ const msg = {
197
+ role: 'bashExecution',
198
+ command,
199
+ output: '',
200
+ exitCode: undefined,
201
+ cancelled: false,
202
+ truncated: false,
203
+ excludeFromContext,
204
+ timestamp: Date.now(),
205
+ };
206
+ return { ...state, messages: [...state.messages, msg] };
207
+ }
208
+ export function bashOutput(state, chunk) {
209
+ const idx = lastBashIndex(state);
210
+ if (idx === null)
211
+ return state;
212
+ const messages = [...state.messages];
213
+ const m = messages[idx];
214
+ messages[idx] = { ...m, output: `${m.output ?? ''}${chunk}` };
215
+ return { ...state, messages };
216
+ }
217
+ export function bashEnd(state, result) {
218
+ const idx = lastBashIndex(state);
219
+ if (idx === null)
220
+ return state;
221
+ const messages = [...state.messages];
222
+ const m = messages[idx];
223
+ messages[idx] = {
224
+ ...m,
225
+ exitCode: result.exitCode,
226
+ cancelled: result.cancelled,
227
+ truncated: result.truncated,
228
+ fullOutputPath: result.fullOutputPath,
229
+ };
230
+ return { ...state, messages };
231
+ }
232
+ /** Apply one broker→client AGENT event (an `AgentSessionEvent`) to the transcript.
233
+ * Broker control frames (welcome/model_changed/error/…) are handled by the hook,
234
+ * NOT here — only pi agent events reach this function. Returns a NEW state object
235
+ * (with fresh `messages`/`executingToolIds` only when they actually change) so
236
+ * React re-renders correctly. */
237
+ export function reduce(state, event) {
238
+ switch (event.type) {
239
+ case 'agent_start':
240
+ return { ...state, isStreaming: true, activity: state.workingActivity };
241
+ case 'agent_end':
242
+ case 'agent_settled':
243
+ return {
244
+ ...state,
245
+ isStreaming: false,
246
+ activity: null,
247
+ streamingIndex: null,
248
+ executingToolIds: state.executingToolIds.size ? new Set() : state.executingToolIds,
249
+ };
250
+ case 'message_start': {
251
+ // User messages arrive complete on message_start (no streaming deltas), so
252
+ // tagging here is sufficient — update/end only mutate the assistant message.
253
+ const tagged = tagInboxOrigin(event.message);
254
+ const messages = [...state.messages, tagged];
255
+ const isAssistant = roleOf(tagged) === 'assistant';
256
+ let partialToolResults = state.partialToolResults;
257
+ if (roleOf(tagged) === 'toolResult') {
258
+ const id = tagged.toolCallId;
259
+ if (typeof id === 'string' && partialToolResults.has(id)) {
260
+ const next = new Map(partialToolResults);
261
+ next.delete(id);
262
+ partialToolResults = next;
263
+ }
264
+ }
265
+ return {
266
+ ...state,
267
+ messages,
268
+ partialToolResults,
269
+ streamingIndex: isAssistant ? messages.length - 1 : state.streamingIndex,
270
+ };
271
+ }
272
+ case 'message_update': {
273
+ // Only assistant messages stream. Replace the in-progress message with the
274
+ // event's full `message`. If we attached mid-stream (no message_start seen),
275
+ // adopt the last message when it is the assistant being streamed.
276
+ let idx = state.streamingIndex;
277
+ if (idx === null) {
278
+ const last = state.messages.length - 1;
279
+ if (last >= 0 && roleOf(state.messages[last]) === 'assistant')
280
+ idx = last;
281
+ }
282
+ if (idx === null)
283
+ return state;
284
+ const messages = [...state.messages];
285
+ messages[idx] = event.message;
286
+ return { ...state, messages, streamingIndex: idx };
287
+ }
288
+ case 'message_end': {
289
+ if (state.streamingIndex === null)
290
+ return state;
291
+ const messages = [...state.messages];
292
+ messages[state.streamingIndex] = event.message;
293
+ return { ...state, messages, streamingIndex: null };
294
+ }
295
+ case 'tool_execution_start': {
296
+ const next = new Set(state.executingToolIds);
297
+ next.add(event.toolCallId);
298
+ return { ...state, executingToolIds: next };
299
+ }
300
+ case 'tool_execution_update': {
301
+ const next = new Map(state.partialToolResults);
302
+ next.set(event.toolCallId, toolResultFromExecution(event.toolCallId, event.toolName, event.partialResult, false));
303
+ return { ...state, partialToolResults: next };
304
+ }
305
+ case 'tool_execution_end': {
306
+ const nextExecuting = new Set(state.executingToolIds);
307
+ nextExecuting.delete(event.toolCallId);
308
+ const nextResults = new Map(state.partialToolResults);
309
+ nextResults.set(event.toolCallId, toolResultFromExecution(event.toolCallId, event.toolName, event.result, event.isError));
310
+ return { ...state, executingToolIds: nextExecuting, partialToolResults: nextResults };
311
+ }
312
+ case 'compaction_start':
313
+ return { ...state, activity: 'Compacting context…' };
314
+ case 'compaction_end':
315
+ return { ...state, activity: state.isStreaming ? state.workingActivity : null };
316
+ case 'auto_retry_start':
317
+ return {
318
+ ...state,
319
+ activity: `Retrying (${event.attempt}/${event.maxAttempts}) in ${Math.ceil(event.delayMs / 1000)}s…`,
320
+ };
321
+ case 'auto_retry_end':
322
+ return { ...state, activity: state.isStreaming ? state.workingActivity : null };
323
+ case 'queue_update':
324
+ return { ...state, queued: [...event.steering, ...event.followUp] };
325
+ // turn_* / session_info_changed / thinking_level_changed — no transcript
326
+ // mutation in v1 (footer-only or covered by adjacent message events).
327
+ default:
328
+ return state;
329
+ }
330
+ }
331
+ function toolResultFromExecution(toolCallId, toolName, result, isError) {
332
+ const fields = typeof result === 'object' && result !== null ? result : {};
333
+ return {
334
+ role: 'toolResult',
335
+ toolCallId,
336
+ toolName,
337
+ ...fields,
338
+ content: Array.isArray(fields.content) ? fields.content : [],
339
+ isError,
340
+ };
341
+ }
@@ -0,0 +1,159 @@
1
+ import assert from 'node:assert/strict';
2
+ import { createServer } from 'node:http';
3
+ import { existsSync, mkdtempSync, realpathSync, rmSync } from 'node:fs';
4
+ import { tmpdir } from 'node:os';
5
+ import { join } from 'node:path';
6
+ import { claimExists } from '#core/human/claim';
7
+ import { ticketDir } from '#core/human/root';
8
+ import { cancelTicket, submitDeck, takeoverAndCompleteDeck } from '#core/human/tickets';
9
+ import { InboxController } from '../../controller.js';
10
+ const key = (part = {}) => ({ ctrl: false, meta: false, upArrow: false, downArrow: false, leftArrow: false, rightArrow: false, wordLeft: false, wordRight: false, home: false, end: false, pageUp: false, pageDown: false, del: false, return: false, newline: false, escape: false, tab: false, backspace: false, ...part });
11
+ function fakeHost() {
12
+ let closed = false;
13
+ const cleanup = [];
14
+ const handle = {
15
+ close() {
16
+ if (closed)
17
+ return;
18
+ closed = true;
19
+ for (const fn of cleanup)
20
+ void fn();
21
+ cleanup.length = 0;
22
+ },
23
+ invalidate() { },
24
+ onClose(fn) {
25
+ if (!closed)
26
+ cleanup.push(fn);
27
+ },
28
+ };
29
+ return {
30
+ capabilities: { remote: false, canFocusNode: false, selfPane: undefined },
31
+ mount() { return handle; },
32
+ notice() { },
33
+ suspendForChild() { return () => { }; },
34
+ focusNode: async () => false,
35
+ pickReviewFile: async () => null,
36
+ };
37
+ }
38
+ const makeController = (options) => new InboxController({ host: fakeHost(), onDirty: () => { }, onClosed: () => { }, ...options });
39
+ const tick = () => new Promise((resolve) => setImmediate(resolve));
40
+ function select(controller, dir) {
41
+ const count = controller.snapshot().items.length;
42
+ const matches = () => {
43
+ const selected = controller.snapshot().selectedDir;
44
+ return selected !== undefined && realpathSync(selected) === realpathSync(dir);
45
+ };
46
+ for (let i = 0; i < count && !matches(); i++)
47
+ controller.handleKey('j', key());
48
+ assert.ok(matches(), `expected ${dir} to be selectable`);
49
+ }
50
+ async function waitFor(predicate, message) {
51
+ const deadline = Date.now() + 1_000;
52
+ while (!predicate()) {
53
+ if (Date.now() >= deadline)
54
+ throw new Error(message);
55
+ await new Promise((resolve) => setTimeout(resolve, 10));
56
+ }
57
+ }
58
+ // The controller answers a ticket by crossing the daemon `/resolve` seam. This
59
+ // fake daemon plays back each failure the seam can return so the controller's
60
+ // unmount-or-retry decision is exercised against a real socket.
61
+ let mode = 'success';
62
+ async function startDaemon() {
63
+ const server = createServer(async (req, res) => {
64
+ if (!req.url?.endsWith('/resolve')) {
65
+ res.statusCode = 404;
66
+ res.end(JSON.stringify({ error: { code: 'not_found', message: 'not found' } }));
67
+ return;
68
+ }
69
+ if (mode === 'unreachable') {
70
+ res.statusCode = 503;
71
+ res.end(JSON.stringify({ error: { code: 'daemon_unavailable', message: 'offline' } }));
72
+ return;
73
+ }
74
+ const body = await new Promise((resolve) => {
75
+ let text = '';
76
+ req.on('data', (chunk) => { text += chunk; });
77
+ req.on('end', () => resolve(text));
78
+ });
79
+ const nodeId = req.url.split('/').at(-2);
80
+ if (mode === 'already_resolved') {
81
+ res.statusCode = 409;
82
+ res.end(JSON.stringify({ error: { code: 'ticket_already_resolved', message: 'ticket already resolved' } }));
83
+ return;
84
+ }
85
+ const request = JSON.parse(body);
86
+ if (request.responses === undefined)
87
+ throw new Error('expected a deck resolution');
88
+ takeoverAndCompleteDeck(ticketDir(nodeId), request.responses, { host: 'daemon', pid: 1 });
89
+ if (mode === 'delivery_failed') {
90
+ res.statusCode = 500;
91
+ res.end(JSON.stringify({ error: { code: 'delivery_failed', message: 'final report delivery failed' } }));
92
+ return;
93
+ }
94
+ res.end(JSON.stringify({ delivered: true, kind: 'deck' }));
95
+ });
96
+ await new Promise((resolve) => server.listen(join(process.env['CRTR_HOME'], 'crtrd.sock'), resolve));
97
+ return server;
98
+ }
99
+ const temp = mkdtempSync(join(tmpdir(), 'crtr-inbox-controller-'));
100
+ process.env['CRTR_HOME'] = temp;
101
+ const server = await startDaemon();
102
+ const deck = (id) => ({ title: id, source: { blockedSince: new Date().toISOString(), sessionName: 'Release planning', nodeId: 'node-private-123' }, interactions: [{ id: 'answer', title: 'Answer', subtitle: 'Answer requires your attention.', options: [{ id: 'yes', label: 'Yes', shortcut: 'y' }] }] });
103
+ try {
104
+ const first = submitDeck({ dir: ticketDir('first'), deck: deck('first') });
105
+ const active = makeController({ cols: 100, rows: 24 });
106
+ active.activate();
107
+ active.handleKey('y', key());
108
+ await waitFor(() => existsSync(join(first.dir, 'response.json')), 'a deck resolution crosses the controller daemon seam');
109
+ await waitFor(() => active.snapshot().screen === 'list', 'a successful daemon resolution unmounts the ticket');
110
+ active.close();
111
+ // A ticket arriving mid-edit must not move selection or clobber the freetext
112
+ // the user is part way through typing.
113
+ const editing = submitDeck({ dir: ticketDir('editing'), deck: { title: 'Editing', interactions: [{ id: 'note', title: 'Notes', subtitle: 'Notes require your attention.', options: [], allowFreetext: true }] } });
114
+ const editingController = makeController({ cols: 100, rows: 24 });
115
+ select(editingController, editing.dir);
116
+ editingController.activate();
117
+ editingController.handleKey('r', key());
118
+ for (const char of 'draft')
119
+ editingController.handleKey(char, key());
120
+ submitDeck({ dir: ticketDir('arrival'), deck: deck('arrival') });
121
+ editingController.rescan();
122
+ assert.equal(realpathSync(editingController.snapshot().selectedDir), realpathSync(editing.dir), 'arrival does not steal active selection');
123
+ assert.equal(editingController.snapshot().inputBuffer, 'draft', 'arrival does not alter freetext input');
124
+ editingController.close();
125
+ cancelTicket(editing.dir, { reason: 'done editing' });
126
+ const already = submitDeck({ dir: ticketDir('already'), deck: deck('already') });
127
+ const alreadyController = makeController({ cols: 100, rows: 24 });
128
+ alreadyController.activate();
129
+ cancelTicket(already.dir, { reason: 'resolved elsewhere' });
130
+ mode = 'already_resolved';
131
+ alreadyController.handleKey('y', key());
132
+ await waitFor(() => alreadyController.snapshot().screen === 'list', 'already_resolved unmounts instead of offering a stale resubmit');
133
+ assert.equal(claimExists(already.dir), true, 'already_resolved retains the daemon-taken claim');
134
+ alreadyController.close();
135
+ const delivery = submitDeck({ dir: ticketDir('delivery'), deck: deck('delivery') });
136
+ mode = 'delivery_failed';
137
+ const deliveryController = makeController({ cols: 100, rows: 24 });
138
+ deliveryController.activate();
139
+ deliveryController.handleKey('y', key());
140
+ await waitFor(() => deliveryController.snapshot().screen === 'list', 'delivery_failed unmounts because the canonical answer is already recorded');
141
+ assert.equal(existsSync(join(delivery.dir, 'response.json')), true, 'delivery_failed still leaves the canonical response on disk');
142
+ deliveryController.close();
143
+ const retry = submitDeck({ dir: ticketDir('retry'), deck: deck('retry') });
144
+ mode = 'unreachable';
145
+ const retryController = makeController({ cols: 100, rows: 24 });
146
+ retryController.activate();
147
+ retryController.handleKey('y', key());
148
+ await tick();
149
+ assert.equal(retryController.snapshot().screen, 'detail', 'unreachable keeps the mounted answer available for retry');
150
+ assert.equal(existsSync(join(retry.dir, 'response.json')), false, 'unreachable does not manufacture a local completion');
151
+ retryController.close();
152
+ }
153
+ finally {
154
+ server.closeAllConnections();
155
+ await new Promise((resolve) => server.close(() => resolve()));
156
+ rmSync(temp, { recursive: true, force: true });
157
+ delete process.env['CRTR_HOME'];
158
+ }
159
+ console.log('inbox controller tests passed');