@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
@@ -1,90 +1,20 @@
1
- // attach-remote-readonly.test.ts — Phase 3 review Major 1: a REMOTE attach
1
+ // attach-remote-readonly.test.ts — a REMOTE attach
2
2
  // (`crtr surface attach --canvas <name>`) must be a strictly VIEW-ONLY
3
- // surface. Three defenses are proven independently here:
3
+ // surface. Two defenses are proven here:
4
4
  //
5
- // A. slash/dispatch.ts's REMOTE_SAFE_BUILTIN_NAMES gate — a remote attach
6
- // never even dispatches a mutating builtin slash command.
7
- // B. input/controller.ts's central `emitCommand` choke point — even if a
8
- // caller somehow got past A, the REAL InputController (constructed
9
- // against fakes, not stubbed out) never lets a drive frame reach
10
- // `hooks.onCommand`, for every input path (submit, `!bash`, Esc-abort,
11
- // and every direct keybinding).
12
- // C. viewer.ts's `resolveHelloRole` — the hello handshake always
13
- // claims 'observer' for a remote attach, regardless of `--observer`.
5
+ // A. input/controller.ts's central `emitCommand` choke point — the REAL
6
+ // InputController (constructed against fakes, not stubbed out) never
7
+ // lets a drive frame reach `hooks.onCommand`, for every input path
8
+ // (submit, `!bash`, Esc-abort, every direct keybinding, and dequeue).
9
+ // The same paths emit normally when remote is false, proving the guard
10
+ // is conditional rather than a dead wiring.
11
+ // B. viewer.ts's `resolveHelloRole` — the hello handshake always claims
12
+ // 'observer' for a remote attach, regardless of `--observer`.
14
13
  import { test } from 'node:test';
15
14
  import assert from 'node:assert/strict';
16
- import { dispatchSlashCommand } from '../slash/dispatch.js';
17
15
  import { InputController } from '../input/controller.js';
16
+ import { createViewerCapabilities } from '../input/capabilities.js';
18
17
  import { resolveHelloRole } from '../session/connection.js';
19
- // ---------------------------------------------------------------------------
20
- // Half A — slash-command gate
21
- // ---------------------------------------------------------------------------
22
- function fakeSlashContext(remote, nodeId) {
23
- const notices = [];
24
- const sent = [];
25
- const ctx = {
26
- send: (frame) => sent.push(frame),
27
- notify: (m) => notices.push(m),
28
- cwd: '/tmp/does-not-matter',
29
- nodeId,
30
- remote,
31
- };
32
- return { ctx, notices, sent };
33
- }
34
- const MUTATING_BUILTINS = [
35
- '/new', '/compact', '/name test', '/model', '/resume', '/fork', '/tree',
36
- '/settings', '/share', '/clone', '/import', '/reload', '/scoped-models',
37
- '/login', '/logout', '/export',
38
- ];
39
- test('dispatchSlashCommand blocks every mutating/wrong-host builtin in remote mode, never sending a frame', () => {
40
- const { ctx, notices, sent } = fakeSlashContext(true, 'a');
41
- for (const cmd of MUTATING_BUILTINS) {
42
- notices.length = 0;
43
- const handled = dispatchSlashCommand(cmd, ctx);
44
- assert.equal(handled, true, `${cmd} must be handled (blocked, never forwarded to the engine as a prompt)`);
45
- assert.equal(notices.length, 1, `${cmd} must notify exactly once, got: ${JSON.stringify(notices)}`);
46
- assert.match(notices[0], /not available for a remote attach/, `${cmd} must produce the remote-block notice, got: ${notices[0]}`);
47
- }
48
- assert.equal(sent.length, 0, 'no command frame must ever reach ctx.send for a blocked remote builtin');
49
- });
50
- test('the same builtins dispatch normally in local mode (remote unaffected proof)', () => {
51
- const { ctx, sent } = fakeSlashContext(false, '');
52
- assert.equal(dispatchSlashCommand('/name a-new-name', ctx), true);
53
- assert.equal(dispatchSlashCommand('/new', ctx), true);
54
- const types = sent.map((f) => f.type);
55
- assert.ok(types.includes('set_session_name'), `expected set_session_name in local mode, got ${JSON.stringify(types)}`);
56
- assert.ok(types.includes('new_session'), `expected new_session in local mode, got ${JSON.stringify(types)}`);
57
- });
58
- test('/copy /session /changelog /hotkeys /quit remain reachable in remote mode (not blocked by the gate)', () => {
59
- const { ctx, notices } = fakeSlashContext(true, 'a');
60
- notices.length = 0;
61
- ctx.state = { model: 'test-model' };
62
- dispatchSlashCommand('/session', ctx);
63
- assert.equal(notices.length, 1);
64
- assert.ok(!/not available for a remote attach/.test(notices[0]), `/session must not hit the remote-block notice, got: ${notices[0]}`);
65
- notices.length = 0;
66
- dispatchSlashCommand('/changelog', ctx);
67
- assert.equal(notices.length, 1);
68
- assert.ok(!/not available for a remote attach/.test(notices[0]));
69
- notices.length = 0;
70
- dispatchSlashCommand('/hotkeys', ctx);
71
- assert.equal(notices.length, 1);
72
- assert.ok(!/not available for a remote attach/.test(notices[0]));
73
- notices.length = 0;
74
- let copied = false;
75
- ctx.onCopy = () => { copied = true; };
76
- dispatchSlashCommand('/copy', ctx);
77
- assert.equal(copied, true, '/copy must reach its onCopy hook in remote mode');
78
- notices.length = 0;
79
- let quit = false;
80
- ctx.onQuit = () => { quit = true; };
81
- dispatchSlashCommand('/quit', ctx);
82
- assert.equal(quit, true, '/quit must reach its onQuit hook in remote mode');
83
- });
84
- // ---------------------------------------------------------------------------
85
- // Half B — InputController's central emitCommand gate, against a REAL
86
- // InputController built from minimal fakes.
87
- // ---------------------------------------------------------------------------
88
18
  function fakeEditor() {
89
19
  const actions = new Map();
90
20
  let text = '';
@@ -101,88 +31,64 @@ function fakeEditor() {
101
31
  };
102
32
  return { obj, actions, setText: (t) => { text = t; } };
103
33
  }
104
- function fakeTui() {
105
- return {
34
+ function buildController(remote) {
35
+ const sent = [];
36
+ const notices = [];
37
+ const editor = fakeEditor();
38
+ const tui = {
106
39
  requestRender: () => { },
107
40
  setFocus: () => { },
108
41
  showOverlay: () => ({ hide: () => { } }),
109
42
  start: () => { },
110
43
  stop: () => { },
111
44
  };
112
- }
113
- function buildController(remote) {
114
- const sent = [];
115
- const notices = [];
116
- const editor = fakeEditor();
117
- const tui = fakeTui();
118
45
  const ic = new InputController(tui, editor.obj, {}, {
119
46
  onCommand: (f) => sent.push(f),
120
47
  onDialogResponse: () => { },
121
48
  onNotice: (m) => notices.push(m),
122
- remote,
123
- });
49
+ }, createViewerCapabilities({ role: 'controller', remote, nodeId: 'test', profileId: undefined }));
124
50
  return { ic, editor, sent, notices };
125
51
  }
126
- test('InputController never emits a drive frame to onCommand when remote is true — every input path', () => {
127
- const { ic, editor, sent, notices } = buildController(true);
128
- // 1. Text submission → would have been `prompt`.
52
+ /** Drive every input path that can produce a broker frame. */
53
+ function driveEveryInputPath(built) {
54
+ const { ic, editor } = built;
129
55
  editor.setText('');
130
- editor.obj.onSubmit('hello');
131
- assert.equal(sent.length, 0);
132
- // 2. `!` bash → would have been `bash`.
56
+ editor.obj.onSubmit('hello'); // → prompt
133
57
  editor.setText('');
134
- editor.obj.onSubmit('!ls');
135
- assert.equal(sent.length, 0);
136
- // 3. Esc while streaming → would have been `abort`.
58
+ editor.obj.onSubmit('!ls'); // → bash
137
59
  ic.setState({ isStreaming: true });
138
- editor.obj.onEscape();
139
- assert.equal(sent.length, 0);
140
- // 4. Direct keybindings → new_session, cycle_model×2, cycle_thinking.
60
+ editor.obj.onEscape(); // → abort
141
61
  editor.actions.get('app.session.new')();
142
62
  editor.actions.get('app.model.cycleForward')();
143
63
  editor.actions.get('app.model.cycleBackward')();
144
64
  editor.actions.get('app.thinking.cycle')();
65
+ }
66
+ test('InputController never emits a drive frame to onCommand when remote is true — every input path', () => {
67
+ const built = buildController(true);
68
+ const { editor, sent, notices } = built;
69
+ driveEveryInputPath(built);
145
70
  assert.equal(sent.length, 0, `remote InputController must never emit a frame, got: ${JSON.stringify(sent)}`);
146
- // 5. The gate must have actually fired (proves the hooks weren't simply
147
- // never wired — a real block happened).
71
+ // The gate must have actually fired — proves the hooks weren't simply never wired.
148
72
  assert.ok(notices.some((n) => /Read-only remote attach/.test(n)), `expected a "Read-only remote attach" notice, got: ${JSON.stringify(notices)}`);
149
- // 6. `app.message.dequeue` → handleDequeue's own remote guard (a second
150
- // frame type, `dequeue`, not covered by the direct-keybinding block above).
73
+ // `app.message.dequeue` has its own remote guard for a second frame type.
151
74
  notices.length = 0;
152
75
  editor.actions.get('app.message.dequeue')();
153
76
  assert.equal(sent.length, 0, `remote dequeue must never emit a frame, got: ${JSON.stringify(sent)}`);
154
77
  assert.ok(notices.some((n) => /Read-only remote attach/.test(n)), `expected a "Read-only remote attach" notice from dequeue, got: ${JSON.stringify(notices)}`);
155
78
  });
156
- test('InputController emits the SAME drive frames normally when remote is false (local unaffected proof)', () => {
157
- const { ic, editor, sent, notices } = buildController(false);
158
- editor.setText('');
159
- editor.obj.onSubmit('hello');
160
- editor.setText('');
161
- editor.obj.onSubmit('!ls');
162
- ic.setState({ isStreaming: true });
163
- editor.obj.onEscape();
164
- editor.actions.get('app.session.new')();
165
- editor.actions.get('app.model.cycleForward')();
166
- editor.actions.get('app.model.cycleBackward')();
167
- editor.actions.get('app.thinking.cycle')();
168
- // `app.message.dequeue` locally never hits the remote guard (it falls
169
- // through to the "not available in this viewer" branch since the fake
170
- // hooks supply no `onRequest`) — proves handleDequeue's remote check is
171
- // remote-conditional, not an unconditional block.
79
+ test('InputController emits the same drive frames normally when remote is false (guard is conditional)', () => {
80
+ const built = buildController(false);
81
+ const { editor, sent, notices } = built;
82
+ driveEveryInputPath(built);
172
83
  notices.length = 0;
173
84
  editor.actions.get('app.message.dequeue')();
174
85
  assert.ok(!notices.some((n) => /Read-only remote attach/.test(n)), `local dequeue must not hit the read-only remote notice, got: ${JSON.stringify(notices)}`);
175
86
  const types = sent.map((f) => f.type);
176
- assert.ok(types.includes('prompt'), `expected prompt, got ${JSON.stringify(types)}`);
177
- assert.ok(types.includes('bash'), `expected bash, got ${JSON.stringify(types)}`);
178
- assert.ok(types.includes('abort'), `expected abort, got ${JSON.stringify(types)}`);
179
- assert.ok(types.includes('new_session'), `expected new_session, got ${JSON.stringify(types)}`);
87
+ for (const expected of ['prompt', 'bash', 'abort', 'new_session', 'cycle_thinking']) {
88
+ assert.ok(types.includes(expected), `expected ${expected}, got ${JSON.stringify(types)}`);
89
+ }
180
90
  assert.equal(types.filter((t) => t === 'cycle_model').length, 2, `expected two cycle_model frames, got ${JSON.stringify(types)}`);
181
- assert.ok(types.includes('cycle_thinking'), `expected cycle_thinking, got ${JSON.stringify(types)}`);
182
91
  });
183
- // ---------------------------------------------------------------------------
184
- // Half C — hello role
185
- // ---------------------------------------------------------------------------
186
92
  test('resolveHelloRole always claims observer for remote, regardless of --observer', () => {
187
93
  assert.equal(resolveHelloRole(true, false), 'observer');
188
94
  assert.equal(resolveHelloRole(true, true), 'observer');
@@ -11,12 +11,14 @@
11
11
  // 2. A second welcome delivered while the first build is suspended must
12
12
  // supersede it outright: the newest snapshot wins and the stale build
13
13
  // abandons itself instead of appending into the replaced transcript.
14
- // 3. Rebuilding from a welcome snapshot must settle any live bash component;
14
+ // 3. A tool result landing after a snapshot yield must repaint the tool row;
15
+ // it used to stay cached in its pending state.
16
+ // 4. Rebuilding from a welcome snapshot must settle any live bash component;
15
17
  // otherwise its unmounted Loader keeps requesting renders every 80 ms.
16
18
  import assert from 'node:assert/strict';
17
19
  import test from 'node:test';
18
20
  import { Container, TUI } from '@earendil-works/pi-tui';
19
- import { AssistantMessageComponent, ToolExecutionComponent, UserMessageComponent, initTheme, } from '@earendil-works/pi-coding-agent';
21
+ import { AssistantMessageComponent, UserMessageComponent, initTheme, } from '@earendil-works/pi-coding-agent';
20
22
  import { ChatView } from '../render/chat-view.js';
21
23
  /** A headless terminal so TUI.requestRender's scheduled writes are no-ops (the
22
24
  * test only inspects component state, never real output). */
@@ -62,156 +64,6 @@ function assistantSnapshot(count, tag) {
62
64
  }
63
65
  const countOf = (children, ctor) => children.filter((c) => c instanceof ctor).length;
64
66
  initTheme(undefined, false);
65
- test('folded tools are separated from preceding assistant prose and thinking', async () => {
66
- const tui = new TUI(fakeTerminal());
67
- const container = new Container();
68
- const view = new ChatView(tui, container, { hideThinking: false });
69
- const internals = view;
70
- internals.foldSettledTools = true;
71
- await view.applySnapshot({
72
- messages: [
73
- { role: 'assistant', content: [{ type: 'text', text: 'Prose.' }, { type: 'toolCall', id: 'text-tool', name: 'bash', arguments: { command: 'true' } }] },
74
- { role: 'toolResult', toolCallId: 'text-tool', toolName: 'bash', content: [{ type: 'text', text: '' }], isError: false },
75
- { role: 'assistant', content: [{ type: 'thinking', thinking: 'Think.' }, { type: 'toolCall', id: 'thinking-tool', name: 'bash', arguments: { command: 'true' } }] },
76
- { role: 'toolResult', toolCallId: 'thinking-tool', toolName: 'bash', content: [{ type: 'text', text: '' }], isError: false },
77
- ],
78
- stats: {},
79
- state: { isStreaming: false },
80
- });
81
- internals.applyToolDisplay();
82
- const separators = internals.historyContainer.children.filter((child) => child.render(80).length === 1 && child.render(80)[0] === '');
83
- assert.equal(separators.length, 2, 'both visible assistant blocks receive a folded-tool gap');
84
- });
85
- test('live bash animation survives history caching and stops on a welcome snapshot', async () => {
86
- let renderRequests = 0;
87
- const tui = {
88
- requestRender: () => { renderRequests += 1; },
89
- terminal: { rows: 24 },
90
- };
91
- const container = new Container();
92
- const view = new ChatView(tui, container);
93
- view.bashStart('sleep 999');
94
- const component = view.bashComponent;
95
- try {
96
- const firstFrame = container.render(80).join('\n');
97
- await new Promise((resolve) => setTimeout(resolve, 120));
98
- const nextFrame = container.render(80).join('\n');
99
- assert.notEqual(nextFrame, firstFrame, 'history caching froze the live bash animation');
100
- await view.applySnapshot({
101
- messages: [],
102
- stats: {},
103
- state: { isStreaming: false },
104
- });
105
- const settledRenderRequests = renderRequests;
106
- await new Promise((resolve) => setTimeout(resolve, 200));
107
- assert.equal(renderRequests, settledRenderRequests, 'the unmounted bash loader kept requesting renders');
108
- }
109
- finally {
110
- // Ensure a regression fails cleanly instead of leaving the loader interval
111
- // alive until the test runner timeout.
112
- component.setComplete(undefined, true);
113
- }
114
- });
115
- test('dormant broker settlement clears a working activity without an agent event', () => {
116
- const { view, internals } = makeChatView();
117
- try {
118
- view.handleEvent({ type: 'agent_start' });
119
- assert.ok(internals.activityLoader, 'agent start shows working activity');
120
- view.settleRun();
121
- assert.equal(internals.activityLoader, undefined, 'dormant settlement clears working activity');
122
- }
123
- finally {
124
- view.dispose();
125
- }
126
- });
127
- test('activity renders keep history cached while streaming updates invalidate it', async () => {
128
- const tui = {
129
- requestRender() { },
130
- terminal: { rows: 24 },
131
- };
132
- const container = new Container();
133
- const view = new ChatView(tui, container);
134
- try {
135
- await view.applySnapshot({
136
- messages: [{
137
- role: 'assistant',
138
- content: [{ type: 'text', text: 'before' }],
139
- }],
140
- stats: {},
141
- state: { isStreaming: true },
142
- });
143
- const history = view.historyContainer;
144
- const assistant = history.children.find((child) => child instanceof AssistantMessageComponent);
145
- assert.ok(assistant);
146
- const originalRender = assistant.render.bind(assistant);
147
- let assistantRenderCount = 0;
148
- assistant.render = (width) => {
149
- assistantRenderCount += 1;
150
- return originalRender(width);
151
- };
152
- container.render(80);
153
- const cachedRenderCount = assistantRenderCount;
154
- container.render(80);
155
- container.render(80);
156
- assert.equal(assistantRenderCount, cachedRenderCount, 'activity-only renders rebuilt the transcript');
157
- view.handleEvent({
158
- type: 'message_update',
159
- message: { role: 'assistant', content: [{ type: 'text', text: 'after' }] },
160
- });
161
- const updatedLines = container.render(80);
162
- assert.equal(assistantRenderCount, cachedRenderCount + 1, 'streaming update did not invalidate history');
163
- assert.match(updatedLines.join('\n'), /after/);
164
- }
165
- finally {
166
- view.dispose();
167
- }
168
- });
169
- test('a tool result after a snapshot yield invalidates the cached pending tool', async () => {
170
- const tui = {
171
- requestRender() { },
172
- terminal: { rows: 24 },
173
- };
174
- const container = new Container();
175
- const view = new ChatView(tui, container);
176
- const messages = [
177
- {
178
- role: 'assistant',
179
- content: [{ type: 'toolCall', id: 'tool-1', name: 'unknown', arguments: {} }],
180
- stopReason: 'endTurn',
181
- },
182
- ...Array.from({ length: 49 }, (_, i) => ({
183
- role: 'assistant',
184
- content: [{ type: 'text', text: `filler-${i}` }],
185
- stopReason: 'endTurn',
186
- })),
187
- {
188
- role: 'toolResult',
189
- toolCallId: 'tool-1',
190
- toolName: 'unknown',
191
- content: [{ type: 'text', text: 'complete' }],
192
- isError: false,
193
- },
194
- ];
195
- const build = view.applySnapshot({
196
- messages,
197
- stats: {},
198
- state: { isStreaming: false },
199
- });
200
- const history = view.historyContainer;
201
- const tool = history.children.find((child) => child instanceof ToolExecutionComponent);
202
- assert.ok(tool, 'tool call rendered before the snapshot yield');
203
- const originalRender = tool.render.bind(tool);
204
- let toolRenderCount = 0;
205
- tool.render = (width) => {
206
- toolRenderCount += 1;
207
- return originalRender(width);
208
- };
209
- container.render(80);
210
- const pendingRenderCount = toolRenderCount;
211
- await build;
212
- container.render(80);
213
- assert.equal(toolRenderCount, pendingRenderCount + 1, 'completed tool result remained cached as pending');
214
- });
215
67
  test('live turn frames arriving during a yielded welcome replay after the build and keep live state', async () => {
216
68
  const { view, historyChildren, internals } = makeChatView();
217
69
  // Start a large non-streaming catch-up: it appends the first chunk of
@@ -254,3 +106,70 @@ test('a second welcome delivered mid-build supersedes the first and the stale bu
254
106
  assert.equal(countOf(children, AssistantMessageComponent), 3, 'newest welcome wins; no interleaved stale tail');
255
107
  assert.equal(internals.applyingSnapshot, false, 'gate released');
256
108
  });
109
+ test('a tool result after a snapshot yield repaints the tool row instead of staying pending', async () => {
110
+ const tui = {
111
+ requestRender() { },
112
+ terminal: { rows: 24 },
113
+ };
114
+ const container = new Container();
115
+ const view = new ChatView(tui, container);
116
+ const messages = [
117
+ {
118
+ role: 'assistant',
119
+ content: [{ type: 'toolCall', id: 'tool-1', name: 'unknown', arguments: {} }],
120
+ stopReason: 'endTurn',
121
+ },
122
+ ...Array.from({ length: 49 }, (_, i) => ({
123
+ role: 'assistant',
124
+ content: [{ type: 'text', text: `filler-${i}` }],
125
+ stopReason: 'endTurn',
126
+ })),
127
+ {
128
+ role: 'toolResult',
129
+ toolCallId: 'tool-1',
130
+ toolName: 'unknown',
131
+ content: [{ type: 'text', text: 'RESULT-LANDED' }],
132
+ isError: false,
133
+ },
134
+ ];
135
+ const build = view.applySnapshot({
136
+ messages,
137
+ stats: {},
138
+ state: { isStreaming: false },
139
+ });
140
+ // Render mid-build so the pending tool row lands in the render cache.
141
+ const pending = container.render(80).join('\n');
142
+ assert.doesNotMatch(pending, /RESULT-LANDED/, 'the result has not arrived yet mid-build');
143
+ await build;
144
+ assert.match(container.render(80).join('\n'), /RESULT-LANDED/, 'completed tool result remained cached as pending');
145
+ });
146
+ test('live bash animation survives history caching and stops on a welcome snapshot', async () => {
147
+ let renderRequests = 0;
148
+ const tui = {
149
+ requestRender: () => { renderRequests += 1; },
150
+ terminal: { rows: 24 },
151
+ };
152
+ const container = new Container();
153
+ const view = new ChatView(tui, container);
154
+ view.bashStart('sleep 999');
155
+ const component = view.bashComponent;
156
+ try {
157
+ const firstFrame = container.render(80).join('\n');
158
+ await new Promise((resolve) => setTimeout(resolve, 120));
159
+ const nextFrame = container.render(80).join('\n');
160
+ assert.notEqual(nextFrame, firstFrame, 'history caching froze the live bash animation');
161
+ await view.applySnapshot({
162
+ messages: [],
163
+ stats: {},
164
+ state: { isStreaming: false },
165
+ });
166
+ const settledRenderRequests = renderRequests;
167
+ await new Promise((resolve) => setTimeout(resolve, 200));
168
+ assert.equal(renderRequests, settledRenderRequests, 'the unmounted bash loader kept requesting renders');
169
+ }
170
+ finally {
171
+ // Ensure a regression fails cleanly instead of leaving the loader interval
172
+ // alive until the test runner timeout.
173
+ component.setComplete(undefined, true);
174
+ }
175
+ });