@north-light/crouter 0.3.172 → 0.3.174

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (673) hide show
  1. package/bin/runtime-selector.mjs +8 -1
  2. package/dist/api/__tests__/{client.test.js → serial/client.test.js} +2 -135
  3. package/dist/api/client.d.ts +12 -21
  4. package/dist/api/client.js +22 -31
  5. package/dist/api/dto/broker-ops.d.ts +158 -0
  6. package/dist/api/dto/broker-ops.js +6 -0
  7. package/dist/api/dto/crons.d.ts +6 -0
  8. package/dist/api/dto/human.d.ts +7 -1
  9. package/dist/api/dto/inbox.d.ts +1 -71
  10. package/dist/api/dto/inbox.js +1 -9
  11. package/dist/api/dto/nodes.d.ts +6 -7
  12. package/dist/api/dto/reviews.d.ts +1 -11
  13. package/dist/api/routes.d.ts +7 -4
  14. package/dist/api/routes.js +8 -5
  15. package/dist/build-root.js +3 -3
  16. package/dist/builtin-memory/04-base-worker.md +1 -4
  17. package/dist/builtin-memory/05-kinds/advisor/00-base.md +1 -5
  18. package/dist/builtin-memory/05-kinds/advisor/01-orchestrator.md +2 -7
  19. package/dist/builtin-memory/05-kinds/design/00-base.md +1 -6
  20. package/dist/builtin-memory/05-kinds/developer/00-base.md +1 -6
  21. package/dist/builtin-memory/05-kinds/explore/00-base.md +1 -4
  22. package/dist/builtin-memory/05-kinds/explore/01-orchestrator.md +1 -2
  23. package/dist/builtin-memory/05-kinds/general/00-base.md +1 -3
  24. package/dist/builtin-memory/05-kinds/plan/00-base.md +1 -6
  25. package/dist/builtin-memory/05-kinds/plan/reviewers/00-base.md +1 -2
  26. package/dist/builtin-memory/05-kinds/plan/reviewers/architecture-fit.md +1 -3
  27. package/dist/builtin-memory/05-kinds/plan/reviewers/code-smells.md +1 -3
  28. package/dist/builtin-memory/05-kinds/plan/reviewers/pattern-consistency.md +1 -3
  29. package/dist/builtin-memory/05-kinds/plan/reviewers/requirements-coverage.md +1 -3
  30. package/dist/builtin-memory/05-kinds/plan/reviewers/security.md +1 -4
  31. package/dist/builtin-memory/05-kinds/review/companion/00-base.md +2 -3
  32. package/dist/builtin-memory/05-kinds/spec/00-base.md +1 -2
  33. package/dist/builtin-memory/advisor/council.md +1 -6
  34. package/dist/builtin-memory/design.md +2 -7
  35. package/dist/builtin-memory/development.md +9 -14
  36. package/dist/builtin-memory/internal/marketplaces.md +2 -6
  37. package/dist/builtin-memory/internal/nodes-and-canvas.md +1 -1
  38. package/dist/builtin-memory/internal/plugins.md +2 -8
  39. package/dist/builtin-memory/internal/storage-tiers.md +1 -2
  40. package/dist/builtin-memory/testing.md +41 -0
  41. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/{provider-rotation.test.ts → serial/provider-rotation.test.ts} +106 -177
  42. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/claude-plugin-commands.ts +5 -15
  43. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/frontmatter-rules/index.ts +1 -28
  44. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +43 -88
  45. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +55 -0
  46. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +60 -0
  47. package/dist/cli.js +2 -2
  48. package/dist/clients/attach/__tests__/attach-remote-readonly.test.js +37 -131
  49. package/dist/clients/attach/__tests__/chat-view-snapshot-ordering.test.js +71 -152
  50. package/dist/clients/attach/__tests__/context-message.test.js +16 -174
  51. package/dist/clients/attach/__tests__/crtr-output.test.js +36 -2069
  52. package/dist/clients/attach/__tests__/diagram.test.js +2 -2
  53. package/dist/clients/attach/__tests__/edit-diff.test.js +0 -4
  54. package/dist/clients/attach/__tests__/file-review-focus.test.js +2 -1
  55. package/dist/clients/attach/__tests__/group-activity.test.js +40 -229
  56. package/dist/clients/attach/__tests__/oauth-dialog-lifecycle.test.js +26 -76
  57. package/dist/clients/attach/__tests__/prompt-preview.test.js +4 -70
  58. package/dist/clients/attach/__tests__/ref-autocomplete.test.js +11 -125
  59. package/dist/clients/attach/__tests__/titled-editor-preview.test.js +14 -205
  60. package/dist/clients/attach/command.d.ts +2 -1
  61. package/dist/clients/attach/command.js +81 -76
  62. package/dist/clients/attach/input/capabilities.d.ts +27 -0
  63. package/dist/clients/attach/input/capabilities.js +96 -0
  64. package/dist/clients/attach/input/controller.d.ts +20 -182
  65. package/dist/clients/attach/input/controller.js +128 -537
  66. package/dist/clients/attach/input/overlay-owner.d.ts +41 -0
  67. package/dist/clients/attach/input/overlay-owner.js +199 -0
  68. package/dist/clients/attach/overlays/file-review.d.ts +0 -4
  69. package/dist/clients/attach/overlays/file-review.js +13 -5
  70. package/dist/clients/attach/overlays/graph.js +2 -10
  71. package/dist/clients/attach/render/chat-view.d.ts +4 -3
  72. package/dist/clients/attach/render/chat-view.js +39 -33
  73. package/dist/clients/attach/render/group-activity.d.ts +1 -0
  74. package/dist/clients/attach/render/group-activity.js +20 -13
  75. package/dist/clients/attach/render/group-recap.js +12 -3
  76. package/dist/clients/attach/session/connection.js +9 -15
  77. package/dist/clients/attach/session/editor-inventory.d.ts +6 -5
  78. package/dist/clients/attach/session/editor-inventory.js +7 -8
  79. package/dist/clients/attach/session/file-links.d.ts +13 -0
  80. package/dist/clients/attach/session/file-links.js +107 -0
  81. package/dist/clients/attach/session/frame.d.ts +3 -0
  82. package/dist/clients/attach/session/frame.js +10 -1
  83. package/dist/clients/attach/session/frames.js +2 -3
  84. package/dist/clients/attach/session/input-wiring.d.ts +4 -1
  85. package/dist/clients/attach/session/input-wiring.js +15 -14
  86. package/dist/clients/attach/session/mouse.d.ts +6 -1
  87. package/dist/clients/attach/session/mouse.js +8 -5
  88. package/dist/clients/attach/session/profile-files.js +18 -12
  89. package/dist/clients/attach/session/reconnect.js +1 -1
  90. package/dist/clients/attach/session/state-sync.js +1 -2
  91. package/dist/clients/attach/session/surface-host.d.ts +3 -2
  92. package/dist/clients/attach/session/surface-host.js +4 -4
  93. package/dist/clients/attach/slash/dispatch.d.ts +8 -31
  94. package/dist/clients/attach/slash/dispatch.js +34 -81
  95. package/dist/clients/attach/viewer.js +820 -860
  96. package/dist/clients/conversation/projection.d.ts +79 -0
  97. package/dist/clients/conversation/projection.js +341 -0
  98. package/dist/clients/inbox/__tests__/serial/inbox-controller.test.js +159 -0
  99. package/dist/clients/inbox/__tests__/serial/mount-panel.test.js +151 -0
  100. package/dist/clients/inbox/controller.d.ts +0 -4
  101. package/dist/clients/inbox/controller.js +0 -2
  102. package/dist/clients/inbox/review/__tests__/review-core.test.js +4 -293
  103. package/dist/clients/inbox/review/__tests__/teardown-notice.test.js +100 -0
  104. package/dist/clients/inbox/review/comments-client.d.ts +3 -2
  105. package/dist/clients/inbox/review/comments-client.js +12 -12
  106. package/dist/clients/inbox/review/companion-pane.d.ts +30 -0
  107. package/dist/clients/inbox/review/companion-pane.js +86 -0
  108. package/dist/clients/inbox/review/document-surface.d.ts +182 -0
  109. package/dist/clients/inbox/review/{document-region.js → document-surface.js} +252 -48
  110. package/dist/clients/inbox/review/frame.js +5 -4
  111. package/dist/clients/inbox/review/launch.d.ts +8 -8
  112. package/dist/clients/inbox/review/launch.js +52 -92
  113. package/dist/clients/inbox/review/nvim.d.ts +2 -0
  114. package/dist/clients/inbox/review/nvim.js +14 -12
  115. package/dist/clients/inbox/review/review-client.d.ts +12 -8
  116. package/dist/clients/inbox/review/review-client.js +46 -35
  117. package/dist/clients/inbox/review-adapter.d.ts +3 -10
  118. package/dist/clients/inbox/review-adapter.js +27 -19
  119. package/dist/clients/inbox/surface.d.ts +0 -4
  120. package/dist/clients/inbox/surface.js +0 -2
  121. package/dist/clients/surfaces/host.d.ts +11 -3
  122. package/dist/commands/__tests__/api-client-cold-start-diagnostic.test.js +7 -34
  123. package/dist/commands/__tests__/human.test.js +11 -322
  124. package/dist/commands/api-client.d.ts +5 -5
  125. package/dist/commands/api-client.js +6 -85
  126. package/dist/commands/canvas-browse.js +3 -29
  127. package/dist/commands/canvas-config.js +1 -1
  128. package/dist/commands/canvas-use.js +3 -3
  129. package/dist/commands/canvas.js +1 -1
  130. package/dist/commands/cron.js +5 -1
  131. package/dist/commands/human/queue.d.ts +0 -4
  132. package/dist/commands/human/queue.js +7 -40
  133. package/dist/commands/memory/list.d.ts +14 -0
  134. package/dist/commands/memory/list.js +35 -31
  135. package/dist/commands/memory/read.d.ts +7 -0
  136. package/dist/commands/memory/read.js +14 -8
  137. package/dist/commands/node/bash.d.ts +1 -0
  138. package/dist/commands/node/bash.js +198 -0
  139. package/dist/commands/node/create.d.ts +23 -0
  140. package/dist/commands/node/create.js +207 -0
  141. package/dist/commands/node/inspect.d.ts +2 -0
  142. package/dist/commands/node/inspect.js +302 -0
  143. package/dist/commands/node/lifecycle.d.ts +4 -0
  144. package/dist/commands/node/lifecycle.js +415 -0
  145. package/dist/commands/node/message.d.ts +1 -0
  146. package/dist/commands/node/message.js +164 -0
  147. package/dist/commands/node/pyramid.d.ts +2 -0
  148. package/dist/commands/node/pyramid.js +79 -0
  149. package/dist/commands/node/subscription.d.ts +1 -0
  150. package/dist/commands/node/subscription.js +82 -0
  151. package/dist/commands/node/wait.d.ts +1 -0
  152. package/dist/commands/node/wait.js +159 -0
  153. package/dist/commands/node-lifecycle-revive.js +10 -57
  154. package/dist/commands/node.d.ts +0 -42
  155. package/dist/commands/node.js +11 -2065
  156. package/dist/commands/search.js +1 -1
  157. package/dist/commands/surface/node/cycle.d.ts +1 -0
  158. package/dist/commands/surface/node/cycle.js +83 -0
  159. package/dist/commands/surface/node/focus.d.ts +1 -0
  160. package/dist/commands/surface/node/focus.js +67 -0
  161. package/dist/commands/surface/node/id.d.ts +1 -0
  162. package/dist/commands/surface/node/id.js +38 -0
  163. package/dist/commands/surface/node/pin.d.ts +1 -0
  164. package/dist/commands/surface/node/pin.js +42 -0
  165. package/dist/commands/surface/node/placement.d.ts +46 -0
  166. package/dist/commands/surface/node/placement.js +124 -0
  167. package/dist/commands/surface-node.js +4 -1
  168. package/dist/commands/surface-reload.js +1 -2
  169. package/dist/commands/surface-tmux-spread.js +1 -1
  170. package/dist/commands/surface.js +5 -20
  171. package/dist/commands/sys/__tests__/setup-core.test.js +18 -271
  172. package/dist/commands/sys/config.js +6 -6
  173. package/dist/commands/sys/logs.js +1 -1
  174. package/dist/commands/sys/panels/broker-limits-panel.d.ts +17 -0
  175. package/dist/commands/sys/panels/broker-limits-panel.js +104 -0
  176. package/dist/commands/sys/panels/dependencies-panel.d.ts +14 -0
  177. package/dist/commands/sys/panels/dependencies-panel.js +80 -0
  178. package/dist/commands/sys/panels/keybindings-panel.d.ts +56 -0
  179. package/dist/commands/sys/panels/keybindings-panel.js +703 -0
  180. package/dist/commands/sys/panels/keys-panel.d.ts +16 -0
  181. package/dist/commands/sys/panels/keys-panel.js +60 -0
  182. package/dist/commands/sys/panels/models-panel.d.ts +77 -0
  183. package/dist/commands/sys/panels/models-panel.js +647 -0
  184. package/dist/commands/sys/panels/panel.d.ts +45 -0
  185. package/dist/commands/sys/panels/panel.js +137 -0
  186. package/dist/commands/sys/panels/plugins-panel.d.ts +16 -0
  187. package/dist/commands/sys/panels/plugins-panel.js +80 -0
  188. package/dist/commands/sys/panels/prefs-panel.d.ts +21 -0
  189. package/dist/commands/sys/panels/prefs-panel.js +85 -0
  190. package/dist/commands/sys/panels/provider-panel.d.ts +62 -0
  191. package/dist/commands/sys/panels/provider-panel.js +538 -0
  192. package/dist/commands/sys/settings-shell.d.ts +55 -0
  193. package/dist/commands/sys/settings-shell.js +400 -0
  194. package/dist/commands/sys/settings.d.ts +2 -0
  195. package/dist/commands/sys/settings.js +31 -0
  196. package/dist/commands/sys/setup-core.d.ts +3 -33
  197. package/dist/commands/sys/setup-core.js +27 -78
  198. package/dist/commands/sys/setup-settings-runner.d.ts +24 -0
  199. package/dist/commands/sys/setup-settings-runner.js +63 -0
  200. package/dist/commands/sys/setup-wizard.d.ts +26 -125
  201. package/dist/commands/sys/setup-wizard.js +209 -2473
  202. package/dist/commands/sys/setup.js +5 -7
  203. package/dist/commands/sys.js +3 -2
  204. package/dist/core/__tests__/broker-extension-canvas-db-boundary.test.js +50 -0
  205. package/dist/core/__tests__/broker-launch-candidates.test.js +20 -9
  206. package/dist/core/__tests__/broker-preflight.test.js +1 -1
  207. package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +108 -27
  208. package/dist/core/__tests__/canvas-inbox-watcher.test.js +14 -0
  209. package/dist/core/__tests__/canvas.test.js +2 -36
  210. package/dist/core/__tests__/close.test.js +14 -3
  211. package/dist/core/__tests__/context-intro.test.js +32 -143
  212. package/dist/core/__tests__/cron-broker-capacity.test.js +22 -3
  213. package/dist/core/__tests__/daemon-boot.test.js +2 -20
  214. package/dist/core/__tests__/daemon-wedge.test.js +1 -1
  215. package/dist/core/__tests__/dead-node-policy-table.test.js +1 -18
  216. package/dist/core/__tests__/fixtures/fake-engine.d.ts +1 -1
  217. package/dist/core/__tests__/fixtures/fake-engine.js +2 -2
  218. package/dist/core/__tests__/fixtures/fake-pi-host.js +2 -2
  219. package/dist/core/__tests__/focuses.test.js +4 -98
  220. package/dist/core/__tests__/helpers/broker-clients.d.ts +0 -3
  221. package/dist/core/__tests__/helpers/broker-clients.js +0 -14
  222. package/dist/core/__tests__/helpers/harness.d.ts +0 -8
  223. package/dist/core/__tests__/helpers/harness.js +7 -87
  224. package/dist/core/__tests__/helpers/viewer-panes.js +1 -1
  225. package/dist/core/__tests__/inline-memory-refs.test.js +5 -134
  226. package/dist/core/__tests__/kickoff.test.js +1 -1
  227. package/dist/core/__tests__/memory-resolver-precedence.test.js +29 -1
  228. package/dist/core/__tests__/migration.test.js +35 -48
  229. package/dist/core/__tests__/on-read-dedup-resume.test.js +22 -12
  230. package/dist/core/__tests__/passive-subscription.test.js +26 -49
  231. package/dist/core/__tests__/preview-registry-sync.test.js +1 -2
  232. package/dist/core/__tests__/prune.test.js +94 -1
  233. package/dist/core/__tests__/review-model-floor.test.js +0 -32
  234. package/dist/core/__tests__/seam/broker-attach-multiclient.test.js +255 -0
  235. package/dist/core/__tests__/{full → seam}/broker-attach-stream.test.js +39 -7
  236. package/dist/core/__tests__/{full → seam}/broker-crash-teardown.test.js +30 -29
  237. package/dist/core/__tests__/{full → seam}/broker-pane-resolution.test.js +54 -5
  238. package/dist/core/__tests__/{full → seam}/broker-provider-retry.test.js +134 -82
  239. package/dist/core/__tests__/{full → seam}/broker-whip-interrupt.test.js +15 -4
  240. package/dist/core/__tests__/{full/idle-release-settlement.test.js → seam/dormancy-release.test.js} +69 -17
  241. package/dist/core/__tests__/{full/yield-message-transaction.test.js → seam/yield-refresh-transaction.test.js} +31 -9
  242. package/dist/core/__tests__/secrets.test.js +1 -7
  243. package/dist/core/__tests__/{broker-fork-seam.test.js → serial/broker-fork-seam.test.js} +58 -7
  244. package/dist/core/__tests__/{broker-sdk-wiring.test.js → serial/broker-sdk-wiring.test.js} +18 -162
  245. package/dist/core/__tests__/{broker-snapshot-history.test.js → serial/broker-snapshot-history.test.js} +9 -9
  246. package/dist/core/__tests__/{command-plugins.test.js → serial/command-plugins.test.js} +105 -15
  247. package/dist/core/__tests__/{deferred-no-wake.test.js → serial/deferred-no-wake.test.js} +23 -20
  248. package/dist/core/__tests__/{flagship-lifecycle.test.js → serial/flagship-lifecycle.test.js} +7 -7
  249. package/dist/core/__tests__/{host-teardown-process-group.test.js → serial/host-teardown-process-group.test.js} +6 -6
  250. package/dist/core/__tests__/{human-deliver-e2e.test.js → serial/human-deliver-e2e.test.js} +12 -12
  251. package/dist/core/__tests__/{live-mutation.test.js → serial/live-mutation.test.js} +5 -5
  252. package/dist/core/__tests__/{refresh-stall-recycle.test.js → serial/refresh-stall-recycle.test.js} +5 -14
  253. package/dist/core/__tests__/{revive.test.js → serial/revive.test.js} +15 -100
  254. package/dist/core/__tests__/{spawn-root.test.js → serial/spawn-root.test.js} +32 -15
  255. package/dist/core/__tests__/serial/subscription-delivery.test.js +126 -0
  256. package/dist/core/__tests__/serial/tmux-surface.test.js +256 -0
  257. package/dist/core/__tests__/{worktree.test.js → serial/worktree.test.js} +15 -15
  258. package/dist/core/__tests__/session-model.test.js +0 -18
  259. package/dist/core/__tests__/spawn-worktree-id-conflict.test.js +9 -0
  260. package/dist/core/__tests__/watchdog-abort-arms-retry.test.js +50 -0
  261. package/dist/core/broker-client/__tests__/transport-relay.test.js +15 -16
  262. package/dist/core/broker-client/__tests__/transport-socket.test.js +28 -0
  263. package/dist/core/broker-client/client.d.ts +2 -2
  264. package/dist/core/broker-client/client.js +4 -7
  265. package/dist/core/broker-client/transport-relay.d.ts +13 -19
  266. package/dist/core/broker-client/transport-relay.js +19 -34
  267. package/dist/core/broker-client/transport-socket.d.ts +2 -2
  268. package/dist/core/broker-client/transport-socket.js +9 -2
  269. package/dist/core/broker-client/transport.d.ts +7 -3
  270. package/dist/core/broker-client/transport.js +4 -4
  271. package/dist/core/canvas/__tests__/attention.test.js +1 -18
  272. package/dist/core/canvas/__tests__/remote-canvas-source.test.js +7 -64
  273. package/dist/core/canvas/__tests__/remote-transport.test.js +2 -3
  274. package/dist/core/canvas/__tests__/render-remote.test.js +7 -52
  275. package/dist/core/canvas/browse/app.d.ts +2 -17
  276. package/dist/core/canvas/browse/app.js +16 -88
  277. package/dist/core/canvas/browse/model.d.ts +0 -4
  278. package/dist/core/canvas/browse/model.js +1 -12
  279. package/dist/core/canvas/browse/render.js +6 -3
  280. package/dist/core/canvas/crons.d.ts +8 -5
  281. package/dist/core/canvas/crons.js +7 -6
  282. package/dist/core/canvas/extensions.d.ts +7 -3
  283. package/dist/core/canvas/extensions.js +16 -4
  284. package/dist/core/canvas/nav-model.d.ts +0 -4
  285. package/dist/core/canvas/nav-model.js +2 -14
  286. package/dist/core/canvas/node-order.d.ts +3 -0
  287. package/dist/core/canvas/node-order.js +12 -0
  288. package/dist/core/canvas/remote-canvas-source.d.ts +3 -6
  289. package/dist/core/canvas/remote-canvas-source.js +8 -15
  290. package/dist/core/command.js +11 -4
  291. package/dist/core/config.js +3 -1
  292. package/dist/core/events/envelope.js +1 -1
  293. package/dist/core/events/read.js +7 -21
  294. package/dist/core/events/source.d.ts +0 -2
  295. package/dist/core/events/source.js +0 -16
  296. package/dist/core/events/types.d.ts +1 -1
  297. package/dist/core/fault-classifier.d.ts +1 -1
  298. package/dist/core/feed/passive.d.ts +0 -11
  299. package/dist/core/feed/passive.js +1 -62
  300. package/dist/core/human/__tests__/{inbox-core.test.js → serial/inbox-core.test.js} +6 -6
  301. package/dist/core/keybindings/__tests__/resolve.test.js +1 -96
  302. package/dist/core/keybindings/background-bash.js +3 -4
  303. package/dist/core/keybindings/catalog.js +1 -1
  304. package/dist/core/memory/inline-ref-grammar.js +3 -3
  305. package/dist/core/memory-resolver.d.ts +11 -25
  306. package/dist/core/memory-resolver.js +51 -33
  307. package/dist/core/model-routes.d.ts +15 -0
  308. package/dist/core/model-routes.js +12 -0
  309. package/dist/core/pool-credential-store.js +1 -1
  310. package/dist/core/preview-registry.js +8 -9
  311. package/dist/core/profiles/__tests__/root-profile.test.js +4 -14
  312. package/dist/core/review/realize.d.ts +0 -13
  313. package/dist/core/review/realize.js +0 -40
  314. package/dist/core/review/types.d.ts +1 -1
  315. package/dist/core/runtime/__tests__/engine-route.test.js +2 -2
  316. package/dist/core/runtime/bearings.js +1 -11
  317. package/dist/core/runtime/broker/client-registry.d.ts +33 -0
  318. package/dist/core/runtime/broker/client-registry.js +164 -0
  319. package/dist/core/runtime/broker/daemon-ops.d.ts +19 -0
  320. package/dist/core/runtime/broker/daemon-ops.js +49 -0
  321. package/dist/core/runtime/broker/event-projection.d.ts +42 -0
  322. package/dist/core/runtime/broker/event-projection.js +178 -0
  323. package/dist/core/runtime/broker/fault-retry.d.ts +39 -0
  324. package/dist/core/runtime/broker/fault-retry.js +277 -0
  325. package/dist/core/runtime/broker/frame-dispatch.d.ts +238 -0
  326. package/dist/core/runtime/broker/frame-dispatch.js +1537 -0
  327. package/dist/core/runtime/broker/inbox.d.ts +22 -0
  328. package/dist/core/runtime/broker/inbox.js +167 -0
  329. package/dist/core/runtime/broker/passive.d.ts +16 -0
  330. package/dist/core/runtime/broker/passive.js +44 -0
  331. package/dist/core/runtime/broker/read-ops.d.ts +23 -0
  332. package/dist/core/runtime/broker/read-ops.js +150 -0
  333. package/dist/core/runtime/broker/rebind.d.ts +74 -0
  334. package/dist/core/runtime/broker/rebind.js +211 -0
  335. package/dist/core/runtime/broker/tool-groups.d.ts +39 -0
  336. package/dist/core/runtime/broker/tool-groups.js +244 -0
  337. package/dist/core/runtime/broker-extension-render.d.ts +11 -0
  338. package/dist/core/runtime/broker-extension-render.js +181 -0
  339. package/dist/core/runtime/broker-persona-guidance.d.ts +13 -0
  340. package/dist/core/runtime/broker-persona-guidance.js +58 -0
  341. package/dist/core/runtime/broker-protocol.d.ts +1 -1
  342. package/dist/core/runtime/broker-protocol.js +1 -1
  343. package/dist/core/runtime/broker.d.ts +5 -196
  344. package/dist/core/runtime/broker.js +276 -3059
  345. package/dist/core/runtime/canvas-extensions.js +11 -2
  346. package/dist/core/runtime/fault.js +1 -1
  347. package/dist/core/runtime/model-selection.d.ts +9 -0
  348. package/dist/core/runtime/model-selection.js +12 -0
  349. package/dist/core/runtime/model-swap.d.ts +3 -3
  350. package/dist/core/runtime/model-swap.js +33 -25
  351. package/dist/core/runtime/placement-tmux.d.ts +3 -14
  352. package/dist/core/runtime/placement-tmux.js +11 -80
  353. package/dist/core/runtime/placement.d.ts +4 -2
  354. package/dist/core/runtime/placement.js +7 -12
  355. package/dist/core/runtime/promote.d.ts +14 -1
  356. package/dist/core/runtime/promote.js +1 -1
  357. package/dist/core/runtime/reset.d.ts +1 -1
  358. package/dist/core/runtime/roadmap.js +1 -1
  359. package/dist/core/runtime/spawn.d.ts +8 -0
  360. package/dist/core/runtime/spawn.js +36 -6
  361. package/dist/core/runtime/stop-guard.d.ts +4 -3
  362. package/dist/core/runtime/stop-guard.js +36 -18
  363. package/dist/core/runtime/stop-signals.d.ts +4 -1
  364. package/dist/core/runtime/stream-watchdog.js +4 -5
  365. package/dist/core/runtime/structured-output.d.ts +15 -2
  366. package/dist/core/runtime/structured-output.js +35 -12
  367. package/dist/core/runtime/tmux-bindings.d.ts +25 -0
  368. package/dist/core/runtime/tmux-bindings.js +682 -0
  369. package/dist/core/runtime/tmux-chrome.d.ts +2 -1
  370. package/dist/core/runtime/tmux-chrome.js +3 -2
  371. package/dist/core/runtime/{tmux.d.ts → tmux-driver.d.ts} +18 -26
  372. package/dist/core/runtime/tmux-driver.js +598 -0
  373. package/dist/core/runtime/view-socket.d.ts +14 -0
  374. package/dist/core/runtime/view-socket.js +83 -0
  375. package/dist/core/session-model/session-state.d.ts +1 -2
  376. package/dist/core/session-model/session-state.js +5 -8
  377. package/dist/core/spawn.d.ts +1 -1
  378. package/dist/core/spawn.js +2 -2
  379. package/dist/core/substrate/gate.d.ts +1 -1
  380. package/dist/core/substrate/on-read-pure.d.ts +7 -0
  381. package/dist/core/substrate/on-read-pure.js +272 -0
  382. package/dist/core/termrender/termrender.js +32 -2
  383. package/dist/core/user-settings.d.ts +23 -1
  384. package/dist/core/user-settings.js +18 -1
  385. package/dist/daemon/api/__tests__/node-model-validation.test.js +134 -0
  386. package/dist/daemon/api/__tests__/review-terminal-conflict.test.js +98 -0
  387. package/dist/daemon/api/__tests__/{full → seam}/api-server.test.js +6 -48
  388. package/dist/daemon/api/__tests__/{full → seam}/b10-attach-modelauth.test.js +17 -44
  389. package/dist/daemon/api/__tests__/{full/push-parity.test.js → seam/leaf-api-parity.test.js} +61 -42
  390. package/dist/daemon/api/bridge.js +40 -81
  391. package/dist/daemon/api/handlers/broker-ops.d.ts +2 -0
  392. package/dist/daemon/api/handlers/broker-ops.js +383 -0
  393. package/dist/daemon/api/handlers/crons.js +9 -4
  394. package/dist/daemon/api/handlers/files.js +6 -7
  395. package/dist/daemon/api/handlers/inbox.js +2 -340
  396. package/dist/daemon/api/handlers/nodes.d.ts +10 -1
  397. package/dist/daemon/api/handlers/nodes.js +74 -39
  398. package/dist/daemon/api/handlers/review-comments.js +5 -1
  399. package/dist/daemon/api/handlers/reviews.js +0 -19
  400. package/dist/daemon/api/map.js +25 -4
  401. package/dist/daemon/api/router.js +2 -3
  402. package/dist/daemon/api/server.js +5 -7
  403. package/dist/daemon/cron-run.d.ts +4 -0
  404. package/dist/daemon/cron-run.js +30 -13
  405. package/dist/daemon/crtrd.d.ts +3 -58
  406. package/dist/daemon/crtrd.js +28 -1244
  407. package/dist/daemon/manage.js +0 -1
  408. package/dist/daemon/reconcilers/broker-supervision.d.ts +50 -0
  409. package/dist/daemon/reconcilers/broker-supervision.js +549 -0
  410. package/dist/daemon/reconcilers/cron-lane.d.ts +10 -0
  411. package/dist/daemon/reconcilers/cron-lane.js +32 -0
  412. package/dist/daemon/reconcilers/dormant-inbox.d.ts +18 -0
  413. package/dist/daemon/reconcilers/dormant-inbox.js +143 -0
  414. package/dist/daemon/reconcilers/storage-maintenance.d.ts +22 -0
  415. package/dist/daemon/reconcilers/storage-maintenance.js +213 -0
  416. package/dist/daemon/review/finish.js +2 -5
  417. package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +34 -53
  418. package/dist/pi-extensions/__tests__/canvas-recap.test.js +16 -113
  419. package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +72 -99
  420. package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.js +29 -12
  421. package/dist/pi-extensions/broker-local.d.ts +20 -0
  422. package/dist/pi-extensions/broker-local.js +89 -0
  423. package/dist/pi-extensions/canvas-context-intro.d.ts +3 -3
  424. package/dist/pi-extensions/canvas-context-intro.js +22 -11
  425. package/dist/pi-extensions/canvas-doc-substrate.js +17 -34
  426. package/dist/pi-extensions/canvas-goal-capture.js +7 -12
  427. package/dist/pi-extensions/canvas-inbox-watcher.js +124 -139
  428. package/dist/pi-extensions/canvas-passive-context.d.ts +3 -3
  429. package/dist/pi-extensions/canvas-passive-context.js +22 -18
  430. package/dist/pi-extensions/canvas-recap.d.ts +2 -2
  431. package/dist/pi-extensions/canvas-recap.js +48 -21
  432. package/dist/pi-extensions/canvas-review-boundary.js +10 -4
  433. package/dist/pi-extensions/canvas-stophook.d.ts +0 -5
  434. package/dist/pi-extensions/canvas-stophook.js +149 -431
  435. package/dist/pi-extensions/canvas-structured-output.js +52 -30
  436. package/dist/pi-extensions/envelope-merge.d.ts +13 -0
  437. package/dist/pi-extensions/envelope-merge.js +29 -0
  438. package/dist/shared/working-activity.d.ts +3 -2
  439. package/dist/shared/working-activity.js +3 -2
  440. package/dist/types.d.ts +6 -5
  441. package/dist/types.js +2 -2
  442. package/docs/compat/hearth-crtr-v1.md +4 -12
  443. package/docs/compat/hearth-crtr-v2.md +3 -11
  444. package/docs/compat/hearth-crtr-v3.md +4 -12
  445. package/docs/compat/hearth-crtr-v4.md +3 -11
  446. package/docs/compat/hearth-crtr-v5.md +3 -11
  447. package/docs/public-api.md +3 -7
  448. package/package.json +7 -49
  449. package/runtime.lock.json +2766 -14533
  450. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/claude-plugin-commands.test.ts +0 -49
  451. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/memory-slash-commands.test.ts +0 -194
  452. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/statusline.test.ts +0 -68
  453. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/frontmatter-rules/test.ts +0 -119
  454. package/dist/clients/attach/__tests__/attach-chrome-remote.test.js +0 -439
  455. package/dist/clients/attach/__tests__/attach-keybindings.test.js +0 -170
  456. package/dist/clients/attach/__tests__/crtr-output-coverage.test.js +0 -57
  457. package/dist/clients/attach/__tests__/editor-frame-title.test.js +0 -19
  458. package/dist/clients/attach/__tests__/input-controller-extension-command.test.js +0 -32
  459. package/dist/clients/attach/__tests__/markdown-headings.test.js +0 -35
  460. package/dist/clients/attach/__tests__/session-identity-refresh.test.js +0 -32
  461. package/dist/clients/conversation/conversation.d.ts +0 -65
  462. package/dist/clients/conversation/conversation.js +0 -318
  463. package/dist/clients/conversation/frames.d.ts +0 -30
  464. package/dist/clients/conversation/frames.js +0 -52
  465. package/dist/clients/conversation/region.d.ts +0 -51
  466. package/dist/clients/conversation/region.js +0 -265
  467. package/dist/clients/inbox/__tests__/inbox-controller.test.js +0 -247
  468. package/dist/clients/inbox/__tests__/mount-panel.test.js +0 -776
  469. package/dist/clients/inbox/review/__tests__/remap.test.js +0 -196
  470. package/dist/clients/inbox/review/columns.d.ts +0 -22
  471. package/dist/clients/inbox/review/columns.js +0 -40
  472. package/dist/clients/inbox/review/composition.d.ts +0 -60
  473. package/dist/clients/inbox/review/composition.js +0 -278
  474. package/dist/clients/inbox/review/document-region.d.ts +0 -120
  475. package/dist/clients/surfaces/region.d.ts +0 -16
  476. package/dist/clients/web/__tests__/push-engine.test.js +0 -158
  477. package/dist/clients/web/__tests__/push-registry.test.d.ts +0 -1
  478. package/dist/clients/web/__tests__/push-registry.test.js +0 -177
  479. package/dist/clients/web/dev-server.d.ts +0 -7
  480. package/dist/clients/web/dev-server.js +0 -46
  481. package/dist/clients/web/events.d.ts +0 -19
  482. package/dist/clients/web/events.js +0 -163
  483. package/dist/clients/web/push-engine.d.ts +0 -44
  484. package/dist/clients/web/push-engine.js +0 -125
  485. package/dist/clients/web/push-registry.d.ts +0 -85
  486. package/dist/clients/web/push-registry.js +0 -373
  487. package/dist/clients/web/server.d.ts +0 -19
  488. package/dist/clients/web/server.js +0 -661
  489. package/dist/clients/web/web-client/shared/protocol.d.ts +0 -214
  490. package/dist/clients/web/web-client/shared/protocol.js +0 -8
  491. package/dist/clients/web/web-cmd.d.ts +0 -2
  492. package/dist/clients/web/web-cmd.js +0 -141
  493. package/dist/commands/__tests__/api-canvas-source.test.d.ts +0 -1
  494. package/dist/commands/__tests__/api-canvas-source.test.js +0 -37
  495. package/dist/commands/__tests__/canvas-config.test.d.ts +0 -1
  496. package/dist/commands/__tests__/canvas-config.test.js +0 -107
  497. package/dist/commands/__tests__/node-no-kickoff-flag.test.d.ts +0 -1
  498. package/dist/commands/__tests__/node-no-kickoff-flag.test.js +0 -73
  499. package/dist/commands/__tests__/node-worktree-flag.test.d.ts +0 -1
  500. package/dist/commands/__tests__/node-worktree-flag.test.js +0 -49
  501. package/dist/commands/__tests__/search-contents.test.d.ts +0 -1
  502. package/dist/commands/__tests__/search-contents.test.js +0 -52
  503. package/dist/commands/memory/__tests__/lint.test.d.ts +0 -1
  504. package/dist/commands/memory/__tests__/lint.test.js +0 -15
  505. package/dist/commands/sys/__tests__/config-broker-thresholds.test.d.ts +0 -1
  506. package/dist/commands/sys/__tests__/config-broker-thresholds.test.js +0 -95
  507. package/dist/commands/sys/__tests__/config-keybindings.test.d.ts +0 -1
  508. package/dist/commands/sys/__tests__/config-keybindings.test.js +0 -55
  509. package/dist/commands/sys/__tests__/helpers/setup-runtime.d.ts +0 -5
  510. package/dist/commands/sys/__tests__/helpers/setup-runtime.js +0 -19
  511. package/dist/commands/sys/__tests__/setup-front-door.test.d.ts +0 -1
  512. package/dist/commands/sys/__tests__/setup-front-door.test.js +0 -102
  513. package/dist/commands/sys/__tests__/setup-models.test.d.ts +0 -1
  514. package/dist/commands/sys/__tests__/setup-models.test.js +0 -205
  515. package/dist/commands/sys/__tests__/setup-providers-viewport.test.d.ts +0 -1
  516. package/dist/commands/sys/__tests__/setup-providers-viewport.test.js +0 -155
  517. package/dist/commands/sys/__tests__/sync-deps.test.d.ts +0 -1
  518. package/dist/commands/sys/__tests__/sync-deps.test.js +0 -179
  519. package/dist/commands/sys/__tests__/sync-import.test.d.ts +0 -1
  520. package/dist/commands/sys/__tests__/sync-import.test.js +0 -315
  521. package/dist/core/__tests__/base-worker-prompt.test.d.ts +0 -1
  522. package/dist/core/__tests__/base-worker-prompt.test.js +0 -57
  523. package/dist/core/__tests__/command-plugins-surfaces.test.d.ts +0 -1
  524. package/dist/core/__tests__/command-plugins-surfaces.test.js +0 -359
  525. package/dist/core/__tests__/connection-reconnect-resume.test.d.ts +0 -1
  526. package/dist/core/__tests__/connection-reconnect-resume.test.js +0 -36
  527. package/dist/core/__tests__/finalization-migration.test.d.ts +0 -1
  528. package/dist/core/__tests__/finalization-migration.test.js +0 -38
  529. package/dist/core/__tests__/fixtures/extra-extension.d.ts +0 -1
  530. package/dist/core/__tests__/fixtures/extra-extension.js +0 -3
  531. package/dist/core/__tests__/fixtures/spawn-proof-target.test.d.ts +0 -1
  532. package/dist/core/__tests__/fixtures/spawn-proof-target.test.js +0 -15
  533. package/dist/core/__tests__/fork.test.d.ts +0 -1
  534. package/dist/core/__tests__/fork.test.js +0 -108
  535. package/dist/core/__tests__/full/broker-attach-limits.test.d.ts +0 -1
  536. package/dist/core/__tests__/full/broker-attach-limits.test.js +0 -147
  537. package/dist/core/__tests__/full/broker-deliver-ack.test.d.ts +0 -1
  538. package/dist/core/__tests__/full/broker-deliver-ack.test.js +0 -73
  539. package/dist/core/__tests__/full/broker-dialogs.test.d.ts +0 -1
  540. package/dist/core/__tests__/full/broker-dialogs.test.js +0 -180
  541. package/dist/core/__tests__/full/broker-display-snapshot.test.d.ts +0 -1
  542. package/dist/core/__tests__/full/broker-display-snapshot.test.js +0 -75
  543. package/dist/core/__tests__/full/broker-dormant-wake.test.d.ts +0 -1
  544. package/dist/core/__tests__/full/broker-dormant-wake.test.js +0 -130
  545. package/dist/core/__tests__/full/broker-model-changed-broadcast.test.d.ts +0 -1
  546. package/dist/core/__tests__/full/broker-model-changed-broadcast.test.js +0 -57
  547. package/dist/core/__tests__/full/broker-navigate-tree-rewelcome.test.d.ts +0 -1
  548. package/dist/core/__tests__/full/broker-navigate-tree-rewelcome.test.js +0 -80
  549. package/dist/core/__tests__/full/cascade-close.test.d.ts +0 -1
  550. package/dist/core/__tests__/full/cascade-close.test.js +0 -240
  551. package/dist/core/__tests__/full/detach-focus.test.d.ts +0 -1
  552. package/dist/core/__tests__/full/detach-focus.test.js +0 -126
  553. package/dist/core/__tests__/full/idle-release-settlement.test.d.ts +0 -1
  554. package/dist/core/__tests__/full/issue-146-yield-spawn-focus.test.d.ts +0 -1
  555. package/dist/core/__tests__/full/issue-146-yield-spawn-focus.test.js +0 -107
  556. package/dist/core/__tests__/full/park-clock-release.test.d.ts +0 -1
  557. package/dist/core/__tests__/full/park-clock-release.test.js +0 -56
  558. package/dist/core/__tests__/full/yield-message-transaction.test.d.ts +0 -1
  559. package/dist/core/__tests__/memory-index-render.test.d.ts +0 -1
  560. package/dist/core/__tests__/memory-index-render.test.js +0 -60
  561. package/dist/core/__tests__/model-routes.test.d.ts +0 -1
  562. package/dist/core/__tests__/model-routes.test.js +0 -41
  563. package/dist/core/__tests__/on-read-identity.test.d.ts +0 -1
  564. package/dist/core/__tests__/on-read-identity.test.js +0 -61
  565. package/dist/core/__tests__/phase4-review-migration.test.d.ts +0 -1
  566. package/dist/core/__tests__/phase4-review-migration.test.js +0 -100
  567. package/dist/core/__tests__/prune-to-limit.test.d.ts +0 -1
  568. package/dist/core/__tests__/prune-to-limit.test.js +0 -126
  569. package/dist/core/__tests__/reset.test.d.ts +0 -1
  570. package/dist/core/__tests__/reset.test.js +0 -69
  571. package/dist/core/__tests__/spawn-no-kickoff.test.d.ts +0 -1
  572. package/dist/core/__tests__/spawn-no-kickoff.test.js +0 -115
  573. package/dist/core/__tests__/steer-note.test.d.ts +0 -1
  574. package/dist/core/__tests__/steer-note.test.js +0 -41
  575. package/dist/core/__tests__/subcommand-tier.test.d.ts +0 -1
  576. package/dist/core/__tests__/subcommand-tier.test.js +0 -99
  577. package/dist/core/__tests__/subscription-delivery.test.js +0 -211
  578. package/dist/core/__tests__/test-runner-cheap-sharding.test.d.ts +0 -1
  579. package/dist/core/__tests__/test-runner-cheap-sharding.test.js +0 -97
  580. package/dist/core/__tests__/tmux-surface.test.js +0 -484
  581. package/dist/core/__tests__/wake-bearings.test.d.ts +0 -1
  582. package/dist/core/__tests__/wake-bearings.test.js +0 -102
  583. package/dist/core/canvas/__tests__/remote-event-stream.test.d.ts +0 -1
  584. package/dist/core/canvas/__tests__/remote-event-stream.test.js +0 -146
  585. package/dist/core/canvas/__tests__/source-resolve.test.d.ts +0 -1
  586. package/dist/core/canvas/__tests__/source-resolve.test.js +0 -77
  587. package/dist/core/canvas/browse/__tests__/model.test.d.ts +0 -1
  588. package/dist/core/canvas/browse/__tests__/model.test.js +0 -290
  589. package/dist/core/canvas/browse/__tests__/rebuild-coalescer.test.d.ts +0 -1
  590. package/dist/core/canvas/browse/__tests__/rebuild-coalescer.test.js +0 -134
  591. package/dist/core/canvas/browse/__tests__/render.test.d.ts +0 -1
  592. package/dist/core/canvas/browse/__tests__/render.test.js +0 -111
  593. package/dist/core/canvas/browse/rebuild-coalescer.d.ts +0 -7
  594. package/dist/core/canvas/browse/rebuild-coalescer.js +0 -61
  595. package/dist/core/canvas/remote-event-stream.d.ts +0 -24
  596. package/dist/core/canvas/remote-event-stream.js +0 -94
  597. package/dist/core/feed/__tests__/coalesce-human.test.d.ts +0 -1
  598. package/dist/core/feed/__tests__/coalesce-human.test.js +0 -36
  599. package/dist/core/feed/__tests__/empty-node-guard.test.d.ts +0 -1
  600. package/dist/core/feed/__tests__/empty-node-guard.test.js +0 -45
  601. package/dist/core/host-exports/__tests__/export-prunes-boot-skill.test.d.ts +0 -1
  602. package/dist/core/host-exports/__tests__/export-prunes-boot-skill.test.js +0 -84
  603. package/dist/core/human/__tests__/visible-paths.test.d.ts +0 -1
  604. package/dist/core/human/__tests__/visible-paths.test.js +0 -28
  605. package/dist/core/keybindings/__tests__/inbox-affordance.test.d.ts +0 -1
  606. package/dist/core/keybindings/__tests__/inbox-affordance.test.js +0 -38
  607. package/dist/core/review/__tests__/project.test.d.ts +0 -1
  608. package/dist/core/review/__tests__/project.test.js +0 -71
  609. package/dist/core/runtime/__tests__/command-expansion.test.d.ts +0 -1
  610. package/dist/core/runtime/__tests__/command-expansion.test.js +0 -25
  611. package/dist/core/runtime/__tests__/session-visibility.test.d.ts +0 -1
  612. package/dist/core/runtime/__tests__/session-visibility.test.js +0 -119
  613. package/dist/core/runtime/__tests__/spawn-at-given-id.test.d.ts +0 -1
  614. package/dist/core/runtime/__tests__/spawn-at-given-id.test.js +0 -34
  615. package/dist/core/runtime/tmux.js +0 -1314
  616. package/dist/daemon/api/__tests__/full/push-parity.test.d.ts +0 -1
  617. package/dist/daemon/api/__tests__/full/worktree-parity.test.d.ts +0 -1
  618. package/dist/daemon/api/__tests__/full/worktree-parity.test.js +0 -160
  619. package/dist/daemon/api/__tests__/inbox.test.d.ts +0 -1
  620. package/dist/daemon/api/__tests__/inbox.test.js +0 -489
  621. package/dist/web-client/apple-touch-icon.png +0 -0
  622. package/dist/web-client/assets/fragment-mono-latin-400-normal-BYwT3kSJ.woff +0 -0
  623. package/dist/web-client/assets/fragment-mono-latin-400-normal-yxdJ5AmL.woff2 +0 -0
  624. package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-BbKYyvR9.woff2 +0 -0
  625. package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-CT4YFKeK.woff +0 -0
  626. package/dist/web-client/assets/index-CCPaLeW7.css +0 -2
  627. package/dist/web-client/assets/index-kyOWsnZK.js +0 -86
  628. package/dist/web-client/assets/martian-mono-cyrillic-wght-normal-B84CD5C_.woff2 +0 -0
  629. package/dist/web-client/assets/martian-mono-latin-ext-wght-normal-DlL6xMw5.woff2 +0 -0
  630. package/dist/web-client/assets/martian-mono-latin-wght-normal-5W32yIyr.woff2 +0 -0
  631. package/dist/web-client/assets/workbox-window.prod.es5-Bd17z0YL.js +0 -2
  632. package/dist/web-client/icon-192.png +0 -0
  633. package/dist/web-client/icon-512.png +0 -0
  634. package/dist/web-client/icon-maskable-512.png +0 -0
  635. package/dist/web-client/index.html +0 -17
  636. package/dist/web-client/manifest.webmanifest +0 -1
  637. package/dist/web-client/sw.js +0 -1
  638. /package/dist/api/__tests__/{client.test.d.ts → serial/client.test.d.ts} +0 -0
  639. /package/dist/clients/inbox/__tests__/{inbox-controller.test.d.ts → serial/inbox-controller.test.d.ts} +0 -0
  640. /package/dist/clients/inbox/__tests__/{mount-panel.test.d.ts → serial/mount-panel.test.d.ts} +0 -0
  641. /package/dist/clients/{attach/__tests__/attach-chrome-remote.test.d.ts → inbox/review/__tests__/teardown-notice.test.d.ts} +0 -0
  642. /package/dist/{clients/attach/__tests__/attach-keybindings.test.d.ts → core/__tests__/broker-extension-canvas-db-boundary.test.d.ts} +0 -0
  643. /package/dist/{clients/attach/__tests__/crtr-output-coverage.test.d.ts → core/__tests__/seam/broker-attach-multiclient.test.d.ts} +0 -0
  644. /package/dist/core/__tests__/{full → seam}/broker-attach-stream.test.d.ts +0 -0
  645. /package/dist/core/__tests__/{full → seam}/broker-crash-teardown.test.d.ts +0 -0
  646. /package/dist/core/__tests__/{full → seam}/broker-pane-resolution.test.d.ts +0 -0
  647. /package/dist/core/__tests__/{full → seam}/broker-provider-retry.test.d.ts +0 -0
  648. /package/dist/core/__tests__/{full → seam}/broker-whip-interrupt.test.d.ts +0 -0
  649. /package/dist/{clients/attach/__tests__/editor-frame-title.test.d.ts → core/__tests__/seam/dormancy-release.test.d.ts} +0 -0
  650. /package/dist/{clients/attach/__tests__/input-controller-extension-command.test.d.ts → core/__tests__/seam/yield-refresh-transaction.test.d.ts} +0 -0
  651. /package/dist/core/__tests__/{broker-fork-seam.test.d.ts → serial/broker-fork-seam.test.d.ts} +0 -0
  652. /package/dist/core/__tests__/{broker-sdk-wiring.test.d.ts → serial/broker-sdk-wiring.test.d.ts} +0 -0
  653. /package/dist/core/__tests__/{broker-snapshot-history.test.d.ts → serial/broker-snapshot-history.test.d.ts} +0 -0
  654. /package/dist/core/__tests__/{command-plugins.test.d.ts → serial/command-plugins.test.d.ts} +0 -0
  655. /package/dist/core/__tests__/{deferred-no-wake.test.d.ts → serial/deferred-no-wake.test.d.ts} +0 -0
  656. /package/dist/core/__tests__/{flagship-lifecycle.test.d.ts → serial/flagship-lifecycle.test.d.ts} +0 -0
  657. /package/dist/core/__tests__/{host-teardown-process-group.test.d.ts → serial/host-teardown-process-group.test.d.ts} +0 -0
  658. /package/dist/core/__tests__/{human-deliver-e2e.test.d.ts → serial/human-deliver-e2e.test.d.ts} +0 -0
  659. /package/dist/core/__tests__/{live-mutation.test.d.ts → serial/live-mutation.test.d.ts} +0 -0
  660. /package/dist/core/__tests__/{refresh-stall-recycle.test.d.ts → serial/refresh-stall-recycle.test.d.ts} +0 -0
  661. /package/dist/core/__tests__/{revive.test.d.ts → serial/revive.test.d.ts} +0 -0
  662. /package/dist/core/__tests__/{spawn-root.test.d.ts → serial/spawn-root.test.d.ts} +0 -0
  663. /package/dist/core/__tests__/{subscription-delivery.test.d.ts → serial/subscription-delivery.test.d.ts} +0 -0
  664. /package/dist/core/__tests__/{tmux-surface.test.d.ts → serial/tmux-surface.test.d.ts} +0 -0
  665. /package/dist/core/__tests__/{worktree.test.d.ts → serial/worktree.test.d.ts} +0 -0
  666. /package/dist/{clients/attach/__tests__/markdown-headings.test.d.ts → core/__tests__/watchdog-abort-arms-retry.test.d.ts} +0 -0
  667. /package/dist/{clients/attach/__tests__/session-identity-refresh.test.d.ts → core/broker-client/__tests__/transport-socket.test.d.ts} +0 -0
  668. /package/dist/core/human/__tests__/{inbox-core.test.d.ts → serial/inbox-core.test.d.ts} +0 -0
  669. /package/dist/{clients/inbox/review/__tests__/remap.test.d.ts → daemon/api/__tests__/node-model-validation.test.d.ts} +0 -0
  670. /package/dist/{clients/surfaces/region.js → daemon/api/__tests__/review-terminal-conflict.test.d.ts} +0 -0
  671. /package/dist/daemon/api/__tests__/{full → seam}/api-server.test.d.ts +0 -0
  672. /package/dist/daemon/api/__tests__/{full → seam}/b10-attach-modelauth.test.d.ts +0 -0
  673. /package/dist/{clients/web/__tests__/push-engine.test.d.ts → daemon/api/__tests__/seam/leaf-api-parity.test.d.ts} +0 -0
@@ -280,6 +280,46 @@ let activeStreamForProvider = defaultStreamForProvider;
280
280
  function streamForProvider(model, context, options) {
281
281
  return activeStreamForProvider(model, context, options);
282
282
  }
283
+ const ANTHROPIC_SERVER_SIDE_FALLBACK_BETA = "server-side-fallback-2026-07-01";
284
+ const ANTHROPIC_SERVER_SIDE_FALLBACK_PRIMARY_MODELS = new Set(["claude-fable-5", "claude-opus-5"]);
285
+ function supportsAnthropicServerSideFallback(model) {
286
+ return ANTHROPIC_SERVER_SIDE_FALLBACK_PRIMARY_MODELS.has(model.id);
287
+ }
288
+ function includesAnthropicBetaToken(value) {
289
+ return value.split(",").some((token) => token.trim() === ANTHROPIC_SERVER_SIDE_FALLBACK_BETA);
290
+ }
291
+ function appendAnthropicFallbackBeta(headers) {
292
+ if (headers instanceof Headers) {
293
+ const next = new Headers(headers);
294
+ const current = next.get("anthropic-beta");
295
+ if (current === null || !includesAnthropicBetaToken(current)) {
296
+ next.set("anthropic-beta", current === null ? ANTHROPIC_SERVER_SIDE_FALLBACK_BETA : `${current},${ANTHROPIC_SERVER_SIDE_FALLBACK_BETA}`);
297
+ }
298
+ return next;
299
+ }
300
+ if (Array.isArray(headers)) {
301
+ const next = headers.map(([name, value]) => [name, value]);
302
+ const index = next.findIndex(([name]) => name.toLowerCase() === "anthropic-beta");
303
+ if (index === -1)
304
+ next.push(["anthropic-beta", ANTHROPIC_SERVER_SIDE_FALLBACK_BETA]);
305
+ else if (!includesAnthropicBetaToken(next[index][1]))
306
+ next[index][1] = `${next[index][1]},${ANTHROPIC_SERVER_SIDE_FALLBACK_BETA}`;
307
+ return next;
308
+ }
309
+ const next = { ...(headers ?? {}) };
310
+ const headerName = Object.keys(next).find((name) => name.toLowerCase() === "anthropic-beta");
311
+ if (headerName === undefined)
312
+ next["anthropic-beta"] = ANTHROPIC_SERVER_SIDE_FALLBACK_BETA;
313
+ else if (!includesAnthropicBetaToken(next[headerName]))
314
+ next[headerName] = `${next[headerName]},${ANTHROPIC_SERVER_SIDE_FALLBACK_BETA}`;
315
+ return next;
316
+ }
317
+ function withAnthropicFallbackBeta(fetch) {
318
+ return (input, init) => {
319
+ const headers = init?.headers ?? (input instanceof Request ? input.headers : undefined);
320
+ return fetch(input, { ...init, headers: appendAnthropicFallbackBeta(headers) });
321
+ };
322
+ }
283
323
  /** Test-only seam: override the per-provider stream factory. Pass undefined to restore the default. */
284
324
  export function __setStreamForProviderForTest(fn) {
285
325
  activeStreamForProvider = fn ?? defaultStreamForProvider;
@@ -295,9 +335,24 @@ async function streamProviderAttempt(state, providerId, model, context, options,
295
335
  const attemptAt = Date.now();
296
336
  let observedStatus;
297
337
  let requestedRetryAfterMs;
338
+ const useAnthropicServerSideFallback = credential !== undefined
339
+ && providerId === ANTHROPIC_PROVIDER_ID
340
+ && supportsAnthropicServerSideFallback(model);
298
341
  const streamOptions = {
299
342
  ...options,
300
343
  ...(credential ? { apiKey: credential.access } : {}),
344
+ ...(useAnthropicServerSideFallback
345
+ ? {
346
+ onPayload: async (payload, payloadModel) => {
347
+ const callerPayload = await options?.onPayload?.(payload, payloadModel);
348
+ return { ...(callerPayload === undefined ? payload : callerPayload), fallbacks: "default" };
349
+ },
350
+ // `headers` would overwrite pi-ai's OAuth beta list. Compose at fetch time so the
351
+ // SDK's generated headers stay intact; replace this shim with pi-ai's `fallbacks`
352
+ // option when that upstream option ships.
353
+ fetch: withAnthropicFallbackBeta(options?.fetch ?? globalThis.fetch),
354
+ }
355
+ : {}),
301
356
  onResponse: async (response, responseModel) => {
302
357
  observedStatus = response.status;
303
358
  if (response.status === 429 || response.status === 503) {
@@ -7,6 +7,7 @@ import {
7
7
  type AuthEvent,
8
8
  type AuthPrompt,
9
9
  type Context,
10
+ type FetchFunction,
10
11
  type Model,
11
12
  type OAuthAuth,
12
13
  type SimpleStreamOptions,
@@ -397,6 +398,49 @@ function streamForProvider(model: Model<any>, context: Context, options: SimpleS
397
398
  return activeStreamForProvider(model, context, options);
398
399
  }
399
400
 
401
+ const ANTHROPIC_SERVER_SIDE_FALLBACK_BETA = "server-side-fallback-2026-07-01";
402
+ const ANTHROPIC_SERVER_SIDE_FALLBACK_PRIMARY_MODELS = new Set(["claude-fable-5", "claude-opus-5"]);
403
+
404
+ function supportsAnthropicServerSideFallback(model: Model<any>): boolean {
405
+ return ANTHROPIC_SERVER_SIDE_FALLBACK_PRIMARY_MODELS.has(model.id);
406
+ }
407
+
408
+ function includesAnthropicBetaToken(value: string): boolean {
409
+ return value.split(",").some((token) => token.trim() === ANTHROPIC_SERVER_SIDE_FALLBACK_BETA);
410
+ }
411
+
412
+ function appendAnthropicFallbackBeta(headers: HeadersInit | undefined): HeadersInit {
413
+ if (headers instanceof Headers) {
414
+ const next = new Headers(headers);
415
+ const current = next.get("anthropic-beta");
416
+ if (current === null || !includesAnthropicBetaToken(current)) {
417
+ next.set("anthropic-beta", current === null ? ANTHROPIC_SERVER_SIDE_FALLBACK_BETA : `${current},${ANTHROPIC_SERVER_SIDE_FALLBACK_BETA}`);
418
+ }
419
+ return next;
420
+ }
421
+
422
+ if (Array.isArray(headers)) {
423
+ const next = headers.map(([name, value]) => [name, value] as [string, string]);
424
+ const index = next.findIndex(([name]) => name.toLowerCase() === "anthropic-beta");
425
+ if (index === -1) next.push(["anthropic-beta", ANTHROPIC_SERVER_SIDE_FALLBACK_BETA]);
426
+ else if (!includesAnthropicBetaToken(next[index][1])) next[index][1] = `${next[index][1]},${ANTHROPIC_SERVER_SIDE_FALLBACK_BETA}`;
427
+ return next;
428
+ }
429
+
430
+ const next = { ...(headers ?? {}) } as Record<string, string>;
431
+ const headerName = Object.keys(next).find((name) => name.toLowerCase() === "anthropic-beta");
432
+ if (headerName === undefined) next["anthropic-beta"] = ANTHROPIC_SERVER_SIDE_FALLBACK_BETA;
433
+ else if (!includesAnthropicBetaToken(next[headerName])) next[headerName] = `${next[headerName]},${ANTHROPIC_SERVER_SIDE_FALLBACK_BETA}`;
434
+ return next;
435
+ }
436
+
437
+ function withAnthropicFallbackBeta(fetch: FetchFunction): FetchFunction {
438
+ return (input, init) => {
439
+ const headers = init?.headers ?? (input instanceof Request ? input.headers : undefined);
440
+ return fetch(input, { ...init, headers: appendAnthropicFallbackBeta(headers) });
441
+ };
442
+ }
443
+
400
444
  /** Test-only seam: override the per-provider stream factory. Pass undefined to restore the default. */
401
445
  export function __setStreamForProviderForTest(fn: typeof defaultStreamForProvider | undefined): void {
402
446
  activeStreamForProvider = fn ?? defaultStreamForProvider;
@@ -421,9 +465,25 @@ async function streamProviderAttempt(
421
465
  const attemptAt = Date.now();
422
466
  let observedStatus: number | undefined;
423
467
  let requestedRetryAfterMs: number | undefined;
468
+ const useAnthropicServerSideFallback =
469
+ credential !== undefined
470
+ && providerId === ANTHROPIC_PROVIDER_ID
471
+ && supportsAnthropicServerSideFallback(model);
424
472
  const streamOptions = {
425
473
  ...options,
426
474
  ...(credential ? { apiKey: credential.access } : {}),
475
+ ...(useAnthropicServerSideFallback
476
+ ? {
477
+ onPayload: async (payload: unknown, payloadModel: Model<any>) => {
478
+ const callerPayload = await options?.onPayload?.(payload, payloadModel);
479
+ return { ...((callerPayload === undefined ? payload : callerPayload) as Record<string, unknown>), fallbacks: "default" };
480
+ },
481
+ // `headers` would overwrite pi-ai's OAuth beta list. Compose at fetch time so the
482
+ // SDK's generated headers stay intact; replace this shim with pi-ai's `fallbacks`
483
+ // option when that upstream option ships.
484
+ fetch: withAnthropicFallbackBeta(options?.fetch ?? globalThis.fetch),
485
+ }
486
+ : {}),
427
487
  onResponse: async (response: { status: number; headers: Record<string, string> }, responseModel: Model<any>) => {
428
488
  observedStatus = response.status;
429
489
  if (response.status === 429 || response.status === 503) {
package/dist/cli.js CHANGED
@@ -49,8 +49,8 @@ async function main() {
49
49
  // Lazy command tree: load only the subtree this invocation dispatches into.
50
50
  // resolveRoot returns the full tree only for help/version/unknown, where
51
51
  // every subtree is genuinely needed (root -h, the unknown-path error). The
52
- // hot leaf-dispatch path loads one subtree, keeping the other 11 (and their
53
- // heavy deps — the attach TUI, web/vite) off cold-start.
52
+ // hot leaf-dispatch path loads one subtree, keeping the other 11 and their
53
+ // heavy dependencies — including the attach TUI — off cold-start.
54
54
  const root = await resolveRoot(process.argv[2]);
55
55
  mark('cli.root_resolved');
56
56
  provisionExports(root, process.argv);
@@ -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
+ });