@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
@@ -4,27 +4,15 @@ import { findRefCompletionContext, RefAwareAutocompleteProvider } from '../input
4
4
  function ref(name, shortForm = `${name} docs`) {
5
5
  return { name, kind: 'knowledge', scope: 'user', shortForm };
6
6
  }
7
- /** Records every call so delegation (vs. ref handling) is directly assertable. */
8
- class FakeDelegate {
9
- getSuggestionsCalls = [];
10
- applyCompletionCalls = [];
11
- shouldTriggerFileCompletionCalls = [];
12
- suggestions = { items: [{ value: 'reload', label: '/reload' }], prefix: '/' };
13
- shouldTrigger = false;
14
- async getSuggestions(lines, cursorLine, cursorCol, options) {
15
- this.getSuggestionsCalls.push([lines, cursorLine, cursorCol, options]);
16
- return this.suggestions;
17
- }
18
- applyCompletion(lines, cursorLine, cursorCol, item, prefix) {
19
- this.applyCompletionCalls.push([lines, cursorLine, cursorCol, item, prefix]);
20
- return { lines, cursorLine, cursorCol };
21
- }
22
- shouldTriggerFileCompletion(lines, cursorLine, cursorCol) {
23
- this.shouldTriggerFileCompletionCalls.push([lines, cursorLine, cursorCol]);
24
- return this.shouldTrigger;
25
- }
26
- }
27
- const opts = { signal: new AbortController().signal, force: false };
7
+ /** The wrapped provider; ref handling must never reach it in a ref context. */
8
+ const inertDelegate = {
9
+ async getSuggestions() { return null; },
10
+ applyCompletion(lines, cursorLine, cursorCol) { return { lines, cursorLine, cursorCol }; },
11
+ shouldTriggerFileCompletion() { return false; },
12
+ };
13
+ // The grammar boundary decides whether a typed '/' is a slash COMMAND or a
14
+ // memory REF. Getting it wrong either hides the command palette or turns
15
+ // ordinary prose ('http://', 'and/or') into a completion popup.
28
16
  test('findRefCompletionContext classifies leading, non-leading, and non-token caret positions', () => {
29
17
  // Leading: '/' is the very first character of the whole message.
30
18
  assert.deepEqual(findRefCompletionContext(['/de'], 0, 3), {
@@ -62,63 +50,8 @@ test('findRefCompletionContext classifies leading, non-leading, and non-token ca
62
50
  // Caret has moved past the token into trailing whitespace — not touching it.
63
51
  assert.equal(findRefCompletionContext(['/dev x'], 0, 5), null);
64
52
  });
65
- test('leading /de delegates verbatim and never surfaces refs, even when a matching ref exists', async () => {
66
- const delegate = new FakeDelegate();
67
- const provider = new RefAwareAutocompleteProvider([ref('dev')], delegate);
68
- const result = await provider.getSuggestions(['/de'], 0, 3, opts);
69
- assert.equal(result, delegate.suggestions);
70
- assert.equal(delegate.getSuggestionsCalls.length, 1);
71
- assert.deepEqual(delegate.getSuggestionsCalls[0], [['/de'], 0, 3, opts]);
72
- });
73
- test('non-leading /de mid-prose and at the start of a later line surfaces prefix-filtered refs', async () => {
74
- const delegate = new FakeDelegate();
75
- const refs = [ref('dev', 'dev stack docs'), ref('taste/foo', 'foo taste doc'), ref('other')];
76
- const provider = new RefAwareAutocompleteProvider(refs, delegate);
77
- const midProse = await provider.getSuggestions(['fix /de'], 0, 7, opts);
78
- assert.deepEqual(midProse, {
79
- items: [{ value: 'dev', label: '/dev', description: 'dev stack docs' }],
80
- prefix: 'de',
81
- });
82
- assert.equal(delegate.getSuggestionsCalls.length, 0);
83
- const laterLine = await provider.getSuggestions(['fix this', '/de'], 1, 3, opts);
84
- assert.deepEqual(laterLine, {
85
- items: [{ value: 'dev', label: '/dev', description: 'dev stack docs' }],
86
- prefix: 'de',
87
- });
88
- // Bare non-leading '/' offers the whole inventory. The returned `prefix`
89
- // strips the leading '/' (review Major 3 — see input/ref-autocomplete.ts) so
90
- // pi-tui's `tui.select.confirm` fallthrough never misclassifies a ref
91
- // completion as a leading-command completion and submits on Enter.
92
- const bare = await provider.getSuggestions(['fix /'], 0, 5, opts);
93
- assert.deepEqual(bare, {
94
- items: [
95
- { value: 'dev', label: '/dev', description: 'dev stack docs' },
96
- { value: 'taste/foo', label: '/taste:foo', description: 'foo taste doc' },
97
- { value: 'other', label: '/other', description: 'other docs' },
98
- ],
99
- prefix: '',
100
- });
101
- // Nested names are offered in colon surface form and filtered by it.
102
- const nested = await provider.getSuggestions(['see /tas'], 0, 8, opts);
103
- assert.deepEqual(nested, {
104
- items: [{ value: 'taste/foo', label: '/taste:foo', description: 'foo taste doc' }],
105
- prefix: 'tas',
106
- });
107
- assert.equal(delegate.getSuggestionsCalls.length, 0, 'no ref-context call ever reaches the wrapped provider');
108
- });
109
- test('boundary-invalid strings and no-match prefixes never enter ref mode', async () => {
110
- const delegate = new FakeDelegate();
111
- const provider = new RefAwareAutocompleteProvider([ref('dev')], delegate);
112
- await provider.getSuggestions(['see http://example.com'], 0, 12, opts);
113
- await provider.getSuggestions(['read and/or write'], 0, 10, opts);
114
- assert.equal(delegate.getSuggestionsCalls.length, 2, 'both boundary cases fell through to the delegate');
115
- const noMatch = await provider.getSuggestions(['fix /zz'], 0, 7, opts);
116
- assert.equal(noMatch, null, 'a non-leading ref context with no prefix match returns null, not delegate output');
117
- assert.equal(delegate.getSuggestionsCalls.length, 2, 'a real (non-matching) ref context still never delegates');
118
- });
119
- test('applying a ref completion replaces only the token, adds no separator, and never calls the delegate', () => {
120
- const delegate = new FakeDelegate();
121
- const provider = new RefAwareAutocompleteProvider([ref('dev')], delegate);
53
+ test('applying a ref completion replaces only the token and adds no separator', () => {
54
+ const provider = new RefAwareAutocompleteProvider([ref('dev')], inertDelegate);
122
55
  const line = 'before /de after';
123
56
  const cursorCol = line.indexOf('/de') + '/de'.length;
124
57
  const item = { value: 'dev', label: '/dev' };
@@ -126,51 +59,4 @@ test('applying a ref completion replaces only the token, adds no separator, and
126
59
  assert.deepEqual(result.lines, ['before /dev after']);
127
60
  assert.equal(result.cursorLine, 0);
128
61
  assert.equal(result.cursorCol, 'before /dev'.length);
129
- assert.equal(delegate.applyCompletionCalls.length, 0);
130
- });
131
- test('applying an item absent from the ref inventory in a real non-leading ref context delegates unchanged', () => {
132
- const delegate = new FakeDelegate();
133
- const provider = new RefAwareAutocompleteProvider([ref('dev')], delegate);
134
- // 'reload' is a command, not a ref — it can never legitimately arrive here,
135
- // but the provider must still refuse to treat it as a ref rather than
136
- // trusting every slash-valued item blindly.
137
- const item = { value: 'reload', label: '/reload' };
138
- const result = provider.applyCompletion(['fix /re'], 0, 7, item, '/re');
139
- assert.deepEqual(result, { lines: ['fix /re'], cursorLine: 0, cursorCol: 7 });
140
- assert.equal(delegate.applyCompletionCalls.length, 1);
141
- assert.deepEqual(delegate.applyCompletionCalls[0], [['fix /re'], 0, 7, item, '/re']);
142
- });
143
- test('applying at a leading-command position always delegates, regardless of item.value', () => {
144
- const delegate = new FakeDelegate();
145
- const provider = new RefAwareAutocompleteProvider([ref('re')], delegate);
146
- const item = { value: 're', label: '/re' };
147
- const result = provider.applyCompletion(['/re'], 0, 3, item, '/re');
148
- assert.deepEqual(result, { lines: ['/re'], cursorLine: 0, cursorCol: 3 });
149
- assert.equal(delegate.applyCompletionCalls.length, 1);
150
- assert.deepEqual(delegate.applyCompletionCalls[0], [['/re'], 0, 3, item, '/re']);
151
- });
152
- test('shouldTriggerFileCompletion is forced true only in a non-leading ref context', () => {
153
- const delegate = new FakeDelegate();
154
- const provider = new RefAwareAutocompleteProvider([ref('dev')], delegate);
155
- assert.equal(provider.shouldTriggerFileCompletion(['before /de after'], 0, 'before /de'.length), true);
156
- assert.equal(delegate.shouldTriggerFileCompletionCalls.length, 0);
157
- // Leading context delegates.
158
- delegate.shouldTrigger = true;
159
- assert.equal(provider.shouldTriggerFileCompletion(['/de'], 0, 3), true);
160
- assert.equal(delegate.shouldTriggerFileCompletionCalls.length, 1);
161
- // Non-token context (e.g. an '@' file-mention position) delegates too.
162
- delegate.shouldTrigger = false;
163
- const line = 'see @file.txt';
164
- assert.equal(provider.shouldTriggerFileCompletion([line], 0, line.length), false);
165
- assert.equal(delegate.shouldTriggerFileCompletionCalls.length, 2);
166
- });
167
- test('triggerCharacters passes through the wrapped provider unchanged', () => {
168
- class DelegateWithTrigger extends FakeDelegate {
169
- triggerCharacters = ['@'];
170
- }
171
- const delegate = new DelegateWithTrigger();
172
- const provider = new RefAwareAutocompleteProvider([ref('dev')], delegate);
173
- assert.deepEqual(provider.triggerCharacters, ['@']);
174
- const bare = new RefAwareAutocompleteProvider([ref('dev')], new FakeDelegate());
175
- assert.equal(bare.triggerCharacters, undefined);
176
62
  });
@@ -1,95 +1,18 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import test from 'node:test';
3
- import { CURSOR_MARKER, visibleWidth } from '@earendil-works/pi-tui';
3
+ import { visibleWidth } from '@earendil-works/pi-tui';
4
4
  import { RefAwareAutocompleteProvider } from '../input/ref-autocomplete.js';
5
5
  import { compactLoadedCommandPreview, TitledEditor } from '../input/titled-editor.js';
6
- const REF_STYLE_ON = '\x1b[4m\x1b[2m';
7
- const REF_STYLE_OFF = '\x1b[24m\x1b[22m';
8
- function stripAnsi(s) {
9
- return s
10
- .split(CURSOR_MARKER)
11
- .join('')
12
- .replace(/\x1b\[[0-9;]*m/g, '')
13
- .replace(/\x1b\][^\x07]*\x07/g, '');
14
- }
15
6
  function makeEditor(rows = 24) {
16
7
  const tui = { requestRender: () => { }, terminal: { rows } };
17
8
  const theme = { borderColor: (s) => s, selectList: {} };
18
9
  const keybindings = { matches: () => false };
19
10
  return new TitledEditor(tui, theme, keybindings);
20
11
  }
21
- test('loaded command disclosure stays bounded and points to the full inspector', () => {
22
- const lines = compactLoadedCommandPreview(Array.from({ length: 20 }, (_, i) => `instruction ${i}`).join('\n'), 32);
23
- assert.equal(lines.length, 8);
24
- assert.match(lines.at(-1), /truncated · inspect/);
25
- assert.ok(lines.every((line) => visibleWidth(line) <= 32));
26
- });
27
- test('short loaded command disclosure is not decorated as truncated', () => {
28
- assert.deepEqual(compactLoadedCommandPreview('one\ntwo', 32), ['one', 'two']);
29
- });
30
- test('inline disclosure strips hostile terminal controls while inspector text stays raw', () => {
31
- const lines = compactLoadedCommandPreview('safe\x1b[2J\x1b]8;;https://evil.example\x07link\x1b]8;;\x07\u0000', 32);
32
- const visible = lines.join('\n');
33
- assert.match(visible, /safelink/);
34
- assert.doesNotMatch(visible, /\x1b|\u0000|evil\.example/);
35
- });
36
- test('inline disclosure bounds huge work before wrapping and suppresses below usable inspect width', () => {
37
- const lines = compactLoadedCommandPreview('x'.repeat(1_000_000), 32);
38
- assert.equal(lines.length, 8);
39
- assert.match(lines.at(-1), /inspect/);
40
- assert.deepEqual(compactLoadedCommandPreview('ordinary prompt', 20), []);
41
- });
42
- test('down exhausts native editor movement and prompt history before yielding to the roster', { timeout: 1_000 }, () => {
43
- const tui = { requestRender: () => { }, terminal: { rows: 24 } };
44
- const theme = { borderColor: (s) => s, selectList: {} };
45
- const keybindings = {
46
- matches: (data, binding) => binding === 'tui.editor.cursorDown' && data === '\x1b[B',
47
- };
48
- const editor = new TitledEditor(tui, theme, keybindings);
49
- const internals = editor;
50
- let boundaryHits = 0;
51
- editor.onCursorDownAtBottom = () => { boundaryHits++; };
52
- editor.setText('this editor line is deliberately long enough to wrap several times');
53
- editor.render(20);
54
- internals.state.cursorLine = 0;
55
- internals.state.cursorCol = 0;
56
- editor.handleInput('\x1b[B');
57
- assert.ok(editor.getCursor().col > 0, 'a wrapped visual line consumes ↓');
58
- assert.equal(boundaryHits, 0);
59
- editor.setText('short line');
60
- editor.render(20);
61
- internals.state.cursorCol = 2;
62
- editor.handleInput('\x1b[B');
63
- assert.equal(editor.getCursor().col, editor.getText().length, 'the last visual line first moves to its end');
64
- assert.equal(boundaryHits, 0);
65
- editor.handleInput('\x1b[B');
66
- assert.equal(boundaryHits, 1, 'only the true editor bottom yields to the roster');
67
- editor.addToHistory('previous prompt');
68
- editor.setText('');
69
- editor.render(20);
70
- editor.handleInput('\x1b[A');
71
- assert.equal(editor.getText(), 'previous prompt', '↑ opens the prior submitted prompt');
72
- editor.handleInput('\x1b[B');
73
- assert.equal(editor.getText(), '', '↓ returns from history to the draft');
74
- assert.equal(boundaryHits, 1, 'history navigation consumes ↓ before the roster');
75
- });
76
- test('resolved-ref candidates are underlined; unknown or boundary-invalid strings are untouched', () => {
77
- const editor = makeEditor();
78
- editor.setResolvedRefNames(['dev', 'taste/foo']);
79
- const text = 'check /dev. and /taste:foo and /nope and http://x and and/or';
80
- editor.setText(`placeholder\n${text}`);
81
- const internals = editor;
82
- internals.state.cursorLine = 0;
83
- internals.state.cursorCol = 0;
84
- const lines = editor.render(80);
85
- const body = lines[2]; // border(0) + placeholder(1) + the ref line(2)
86
- assert.equal(stripAnsi(body).trimEnd(), text, 'decoration never alters the visible text');
87
- assert.ok(body.includes(`${REF_STYLE_ON}/dev${REF_STYLE_OFF}`), 'trailing punctuation is trimmed from the highlighted span');
88
- assert.ok(body.includes(`${REF_STYLE_ON}/taste:foo${REF_STYLE_OFF}`), 'nested taste/foo highlights as its colon surface form');
89
- const onCount = body.split(REF_STYLE_ON).length - 1;
90
- assert.equal(onCount, 2, 'unknown (/nope) and boundary-invalid (http://x, and/or) strings get no decoration at all');
91
- });
92
- test("decoration never changes a rendered line's visible width", () => {
12
+ // The frame-width invariant: the viewer renders exactly `terminal.rows` lines
13
+ // with no overflow, so a decoration that changes a rendered line's visible
14
+ // width crashes the pane.
15
+ test("ref decoration never changes a rendered line's visible width", () => {
93
16
  const width = 40;
94
17
  const texts = [
95
18
  'ünïcödé prefix /dev then more text that wraps across the available width for sure',
@@ -109,78 +32,15 @@ test("decoration never changes a rendered line's visible width", () => {
109
32
  }
110
33
  }
111
34
  });
112
- test('cursor sweep across a resolved ref decorates outside the cursor cell and safely degrades inside it', () => {
113
- const text = 'go /dev now';
114
- // span for /dev is [3,7); decorated everywhere the cursor's own reverse-video
115
- // cell doesn't touch or straddle it (see decorateRow's before/after-cursor math).
116
- const decoratedCols = new Set([0, 1, 2, 7, 8, 9, 10, 11]);
117
- for (const paneFocused of [true, false]) {
118
- const editor = makeEditor();
119
- editor.setResolvedRefNames(['dev']);
120
- editor.focused = true; // component (TUI) focus controls CURSOR_MARKER emission
121
- editor.paneFocused = paneFocused; // terminal-pane focus controls solid vs muted cursor styling
122
- editor.setText(text);
123
- const internals = editor;
124
- for (let col = 0; col <= text.length; col++) {
125
- internals.state.cursorLine = 0;
126
- internals.state.cursorCol = col;
127
- const lines = editor.render(60);
128
- const body = lines[1];
129
- assert.equal(stripAnsi(body).trimEnd(), text, `text intact at col ${col} paneFocused=${paneFocused}`);
130
- const hasCursorMarkup = body.includes('\x1b[7m') || body.includes('\x1b[48;5;240m');
131
- assert.ok(hasCursorMarkup, `cursor cell present at col ${col} paneFocused=${paneFocused}`);
132
- const decorated = body.includes(REF_STYLE_ON);
133
- assert.equal(decorated, decoratedCols.has(col), `decoration at col ${col} paneFocused=${paneFocused}`);
134
- }
135
- }
136
- });
137
- test('chrome (loaded-command disclosure, title/info border, context badge) never carries ref decoration', () => {
138
- const editorA = makeEditor();
139
- const editorB = makeEditor();
140
- for (const editor of [editorA, editorB]) {
141
- editor.title = 'session';
142
- editor.info = 'cwd-info';
143
- editor.contextBadge = 'node-1';
144
- editor.loadedCommand = { name: 'dev', content: 'do the thing', inspectHint: 'ctrl+i' };
145
- editor.setText('please use /dev to continue');
146
- }
147
- editorB.setResolvedRefNames(['dev']);
148
- const linesA = editorA.render(60);
149
- const linesB = editorB.render(60);
150
- assert.equal(linesA.length, linesB.length, 'decoration never adds or removes lines');
151
- let diffCount = 0;
152
- let diffIndex = -1;
153
- for (let i = 0; i < linesA.length; i++) {
154
- if (linesA[i] !== linesB[i]) {
155
- diffCount++;
156
- diffIndex = i;
157
- }
158
- }
159
- assert.equal(diffCount, 1, 'decoration touches exactly the one content row carrying the ref, nothing else');
160
- assert.ok(linesB[diffIndex].includes(REF_STYLE_ON), 'the differing row is in fact the decorated one');
161
- });
162
- test('terminal suppression combines a trimmed local-command rule and a separate untrimmed engine-command rule (Minor 10)', () => {
163
- const editor = makeEditor();
164
- editor.setResolvedRefNames(['dev']);
165
- // The LOCAL viewer rule is checked against TRIMMED text (mirrors
166
- // slash/dispatch.ts's own `text.trim()`-based dispatch parse) — leading
167
- // whitespace is tolerated.
168
- editor.setLocalCommandNames(['dev']);
169
- editor.setText(' /dev something /dev');
170
- assert.ok(!editor.render(60)[1].includes(REF_STYLE_ON), 'local-command rule suppresses even with leading whitespace (trimmed rule)');
171
- // The SAME leading-whitespace text is NOT suppressed by the ENGINE rule —
172
- // it mirrors the broker's own `isLeadingEngineCommand`, which requires the
173
- // RAW text itself (no trim) to start with '/'.
174
- editor.setLocalCommandNames([]);
175
- editor.setEngineCommandNames(['dev']);
176
- assert.ok(editor.render(60)[1].includes(REF_STYLE_ON), 'engine rule does not tolerate leading whitespace — decoration is not suppressed');
177
- // Without leading whitespace the engine (untrimmed) rule suppresses too.
178
- editor.setText('/dev something /dev');
179
- assert.ok(!editor.render(60)[1].includes(REF_STYLE_ON), 'engine rule suppresses once the raw text itself starts with /');
180
- editor.setEngineCommandNames([]);
181
- assert.ok(editor.render(60)[1].includes(REF_STYLE_ON), 'decoration resumes once neither the local nor the engine rule matches');
35
+ // An untrusted command body reaches the inline disclosure verbatim; a live
36
+ // escape sequence there would repaint or hyperlink the user's terminal.
37
+ test('inline disclosure strips hostile terminal controls', () => {
38
+ const lines = compactLoadedCommandPreview('safe\x1b[2J\x1b]8;;https://evil.example\x07link\x1b]8;;\x07\u0000', 32);
39
+ const visible = lines.join('\n');
40
+ assert.match(visible, /safelink/);
41
+ assert.doesNotMatch(visible, /\x1b|\u0000|evil\.example/);
182
42
  });
183
- test('Enter-confirming a non-leading ref completion accepts the token and returns to editing, never submits (Major 3)', async () => {
43
+ test('Enter-confirming a non-leading ref completion accepts the token and returns to editing, never submits', async () => {
184
44
  const editor = makeEditor();
185
45
  editor.focused = true;
186
46
  let submitted;
@@ -206,7 +66,7 @@ test('Enter-confirming a non-leading ref completion accepts the token and return
206
66
  assert.equal(editor.getText(), 'hey check /dev', 'the token was replaced in place, not submitted as typed');
207
67
  assert.equal(submitted, undefined, 'Enter-confirming a ref completion must never submit the message');
208
68
  });
209
- test('a real Enter submission preserves raw leading/trailing whitespace end-to-end (Major 4)', () => {
69
+ test('a real Enter submission preserves raw leading/trailing whitespace end-to-end', () => {
210
70
  const editor = makeEditor();
211
71
  let submitted;
212
72
  editor.onSubmit = (text) => {
@@ -217,54 +77,3 @@ test('a real Enter submission preserves raw leading/trailing whitespace end-to-e
217
77
  assert.equal(submitted, ' hello world ', 'onSubmit receives the exact untrimmed text, not the base editor\'s trimmed copy');
218
78
  assert.equal(editor.getText(), '', 'submitValue still resets editor state as usual');
219
79
  });
220
- test('a resolved ref wider than the editor renders plain, without corrupting width', () => {
221
- const name = 'x'.repeat(40);
222
- const width = 20;
223
- const plain = makeEditor();
224
- const decorated = makeEditor();
225
- decorated.setResolvedRefNames([name]);
226
- plain.setText(`/${name}`);
227
- decorated.setText(`/${name}`);
228
- const linesPlain = plain.render(width);
229
- const linesDecorated = decorated.render(width);
230
- assert.deepEqual(linesDecorated, linesPlain, 'a span that never fits inside one wrapped chunk is left entirely undecorated');
231
- });
232
- test('a non-leading ref-grammar character triggers autocomplete without an explicit Tab', async () => {
233
- const editor = makeEditor();
234
- editor.focused = true;
235
- const calls = [];
236
- const provider = {
237
- async getSuggestions(_lines, cursorLine, cursorCol) {
238
- calls.push({ cursorLine, cursorCol });
239
- const item = { value: 'dev', label: '/dev' };
240
- return { items: [item], prefix: '/' };
241
- },
242
- applyCompletion(lines, cursorLine, cursorCol) {
243
- return { lines, cursorLine, cursorCol };
244
- },
245
- };
246
- editor.setAutocompleteProvider(provider);
247
- editor.setText('hey check ');
248
- editor.handleInput('/');
249
- await new Promise((resolve) => setTimeout(resolve, 20));
250
- assert.equal(calls.length, 1, 'the bridge triggers exactly one suggestion request');
251
- assert.equal(calls[0].cursorCol, 'hey check /'.length);
252
- });
253
- test('a leading slash is unaffected by the trigger bridge (native path only, not doubled)', async () => {
254
- const editor = makeEditor();
255
- editor.focused = true;
256
- const calls = [];
257
- const provider = {
258
- async getSuggestions() {
259
- calls.push(1);
260
- return null;
261
- },
262
- applyCompletion(lines, cursorLine, cursorCol) {
263
- return { lines, cursorLine, cursorCol };
264
- },
265
- };
266
- editor.setAutocompleteProvider(provider);
267
- editor.handleInput('/');
268
- await new Promise((resolve) => setTimeout(resolve, 20));
269
- assert.equal(calls.length, 1, 'exactly one trigger from the native leading path, not doubled by the bridge');
270
- });
@@ -1,2 +1,3 @@
1
1
  import type { BranchDef } from '../../core/command.js';
2
- export declare function registerAttach(): BranchDef;
2
+ import type { SubTier } from '../../core/help.js';
3
+ export declare function registerAttach(namespace: string, tier: SubTier): BranchDef;
@@ -9,92 +9,97 @@
9
9
  // actually opens.
10
10
  import { defineBranch, defineLeaf } from '../../core/command.js';
11
11
  import { mark } from '../../core/timing.js';
12
- const attachToLeaf = defineLeaf({
13
- name: 'to',
14
- description: 'attach an interactive terminal viewer to a node (reviving it if dormant)',
15
- whenToUse: 'you want to WATCH or DRIVE a headless node live in this pane — it connects over the node\'s unix socket to the broker hosting the engine and renders the same chat stream. Normal local attaches are writable; use --observer for read-only, or --canvas for a remote read-only view. A DORMANT node is revived first: crtrd runs reviveNode server-side, then the viewer streams over the broker\'s socket. The configured detach shortcuts leave the engine running',
16
- help: {
17
- name: 'attach to',
18
- summary: 'attach a terminal viewer to a headless node\'s running broker (writable by default, --observer for read-only); configured detach shortcuts leave the engine running',
19
- params: [
20
- {
21
- kind: 'positional',
22
- name: 'node',
23
- required: true,
24
- constraint: 'Node id to attach to. A dormant node is revived (server-side) before the viewer connects.',
25
- },
26
- {
27
- kind: 'flag',
28
- name: 'observer',
29
- type: 'bool',
30
- required: false,
31
- default: false,
32
- constraint: 'Attach READ-ONLY: request the observer role. Default local attaches request the writable controller role.',
33
- },
34
- {
35
- kind: 'flag',
36
- name: 'canvas',
37
- type: 'string',
38
- required: false,
39
- constraint: 'Attach against a remote canvas target configured via `crtr canvas config add` instead of the local canvas — connects over a relayed WebSocket to the target\'s preview endpoint using the relay token from the 0600 secrets store. Omit for local (default): connects to the node\'s local unix socket, which must already exist in THIS machine\'s canvas.db. Does NOT honor `crtr canvas use` — this flag is the only way to attach remotely.',
40
- },
41
- ],
42
- output: [
43
- {
44
- name: 'note',
45
- type: 'string',
46
- required: false,
47
- constraint: 'Only set on the non-TTY/piped path (a static notice); the interactive path returns nothing.',
48
- },
49
- ],
50
- outputKind: 'object',
51
- effects: [
52
- 'Takes over the current pane in raw mode and renders the node\'s live engine stream until you use a configured detach shortcut or the broker exits.',
53
- 'As a writable controller: sends prompts/steers/dialog answers to the engine over the socket. As observer: read-only. Multiple writable local viewers may drive the same broker.',
54
- 'A dormant node is revived server-side (crtrd runs reviveNode) before the viewer connects; this LOCAL process NEVER spawns pi and NEVER writes the session — it holds only a socket to the broker.',
55
- 'Outside a TTY (piped): prints a short notice and exits 0 — attach is an interactive program, not a pipe stage.',
56
- ],
57
- },
58
- run: async (input) => {
59
- const nodeId = input['node'];
60
- const observer = input['observer'] ?? false;
61
- const canvasName = input['canvas'];
62
- // attach IS the in-pane interactive program — it only needs a TTY (crtr is
63
- // tmux-only, but the pane itself is the surface). Non-TTY (piped) → static
64
- // notice + exit, never a non-tmux interactive fallback. Guarded BEFORE the
65
- // heavy import so a piped invocation never pays the viewer's load cost.
66
- if (!process.stdout.isTTY) {
67
- return {
68
- note: `crtr surface attach is an interactive terminal viewer — run it in a tmux pane (a TTY), not a pipe. Node: ${nodeId}`,
69
- };
70
- }
71
- // The viewer runtime (the pi-coding-agent-heavy bundle) loads only here.
72
- mark('viewer.bundle_import_start');
73
- const { runAttach } = await import('./viewer.js');
74
- mark('viewer.bundle_loaded');
75
- await runAttach(nodeId, observer, canvasName);
76
- // The session has sent its final broker frame and restored the terminal.
77
- // Force this one-shot viewer process out now: pi's bundled UI dependencies
78
- // can retain libuv handles after their visible work is finished. The exit
79
- // handler registered by teardown still runs, so terminal restoration remains
80
- // safe if the normal path raced a signal.
81
- process.exit(0);
82
- },
83
- render: (result) => (result['note'] !== undefined ? String(result['note']) : ''),
84
- });
85
- export function registerAttach() {
12
+ function attachToLeaf(namespace) {
13
+ return defineLeaf({
14
+ name: 'to',
15
+ description: 'attach an interactive terminal viewer to a node (reviving it if dormant)',
16
+ whenToUse: 'you want to WATCH or DRIVE a headless node live in this pane — it connects over the node\'s unix socket to the broker hosting the engine and renders the same chat stream. Normal local attaches are writable; use --observer for read-only, or --canvas for a remote read-only view. A DORMANT node is revived first: crtrd runs reviveNode server-side, then the viewer streams over the broker\'s socket. The configured detach shortcuts leave the engine running',
17
+ help: {
18
+ name: `${namespace} attach to`,
19
+ summary: 'attach a terminal viewer to a headless node\'s running broker (writable by default, --observer for read-only); configured detach shortcuts leave the engine running',
20
+ params: [
21
+ {
22
+ kind: 'positional',
23
+ name: 'node',
24
+ required: true,
25
+ constraint: 'Node id to attach to. A dormant node is revived (server-side) before the viewer connects.',
26
+ },
27
+ {
28
+ kind: 'flag',
29
+ name: 'observer',
30
+ type: 'bool',
31
+ required: false,
32
+ default: false,
33
+ constraint: 'Attach READ-ONLY: request the observer role. Default local attaches request the writable controller role.',
34
+ },
35
+ {
36
+ kind: 'flag',
37
+ name: 'canvas',
38
+ type: 'string',
39
+ required: false,
40
+ constraint: 'Attach against a remote canvas target configured via `crtr canvas config add` instead of the local canvas — connects over a relayed WebSocket to the target\'s preview endpoint using the relay token from the 0600 secrets store. Omit for local (default): connects to the node\'s local unix socket, which must already exist in THIS machine\'s canvas.db. Does NOT honor `crtr canvas use` — this flag is the only way to attach remotely.',
41
+ },
42
+ ],
43
+ output: [
44
+ {
45
+ name: 'note',
46
+ type: 'string',
47
+ required: false,
48
+ constraint: 'Only set on the non-TTY/piped path (a static notice); the interactive path returns nothing.',
49
+ },
50
+ ],
51
+ outputKind: 'object',
52
+ effects: [
53
+ 'Takes over the current pane in raw mode and renders the node\'s live engine stream until you use a configured detach shortcut or the broker exits.',
54
+ 'As a writable controller: sends prompts/steers/dialog answers to the engine over the socket. As observer: read-only. Multiple writable local viewers may drive the same broker.',
55
+ 'A dormant node is revived server-side (crtrd runs reviveNode) before the viewer connects; this LOCAL process NEVER spawns pi and NEVER writes the session — it holds only a socket to the broker.',
56
+ 'Outside a TTY (piped): prints a short notice and exits 0 — attach is an interactive program, not a pipe stage.',
57
+ ],
58
+ },
59
+ run: async (input) => {
60
+ const nodeId = input['node'];
61
+ const observer = input['observer'] ?? false;
62
+ const canvasName = input['canvas'];
63
+ // attach IS the in-pane interactive program — it only needs a TTY (crtr is
64
+ // tmux-only, but the pane itself is the surface). Non-TTY (piped) → static
65
+ // notice + exit, never a non-tmux interactive fallback. Guarded BEFORE the
66
+ // heavy import so a piped invocation never pays the viewer's load cost.
67
+ if (!process.stdout.isTTY) {
68
+ return {
69
+ note: `crtr surface attach is an interactive terminal viewer — run it in a tmux pane (a TTY), not a pipe. Node: ${nodeId}`,
70
+ };
71
+ }
72
+ // The viewer runtime (the pi-coding-agent-heavy bundle) loads only here.
73
+ mark('viewer.bundle_import_start');
74
+ const { runAttach } = await import('./viewer.js');
75
+ mark('viewer.bundle_loaded');
76
+ await runAttach(nodeId, observer, canvasName);
77
+ // The session has sent its final broker frame and restored the terminal.
78
+ // Force this one-shot viewer process out now: pi's bundled UI dependencies
79
+ // can retain libuv handles after their visible work is finished. The exit
80
+ // handler registered by teardown still runs, so terminal restoration remains
81
+ // safe if the normal path raced a signal.
82
+ process.exit(0);
83
+ },
84
+ render: (result) => (result['note'] !== undefined ? String(result['note']) : ''),
85
+ });
86
+ }
87
+ export function registerAttach(namespace, tier) {
86
88
  return defineBranch({
87
89
  name: 'attach',
90
+ description: 'a terminal viewer for a headless node — connect over its socket and drive (or watch) the live engine',
91
+ whenToUse: 'you want to open a headless node live in this pane — watch its engine stream and drive it by typing, without the node ever running pi in your window. A dormant node is revived server-side (crtrd runs reviveNode) before the viewer connects over a unix socket; this local process never starts the engine itself. Configured detach shortcuts leave the engine running.',
92
+ tier,
88
93
  rootEntry: {
89
94
  concept: 'a terminal viewer for a headless node — connect over its socket and drive (or watch) the live engine',
90
95
  desc: 'attach a terminal viewer to a headless node',
91
96
  useWhen: 'you want to open a headless node live in this pane — watch its engine stream and drive it by typing, without the node ever running pi in your window. A dormant node is revived server-side (crtrd runs reviveNode) before the viewer connects over a unix socket; this local process never starts the engine itself. Configured detach shortcuts leave the engine running.',
92
97
  },
93
98
  help: {
94
- name: 'attach',
99
+ name: `${namespace} attach`,
95
100
  summary: 'attach a terminal viewer to a headless node\'s running broker',
96
101
  model: 'The branch opens a viewer in the current pane. A TTY is required; piped invocation prints a notice and exits. Normal local attaches request the writable controller role; --observer and --canvas are read-only. Multiple local writable viewers may watch and drive one broker. Configured detach shortcuts detach cleanly and the engine runs on. A dormant node is revived server-side (crtrd runs reviveNode) before the viewer connects. If the broker exits, the viewer holds the pane and auto-reconnects — through a yield/refresh relaunch, and across dormancy until the node wakes again — reporting "broker gone" and exiting only when the node is terminal (done/dead/canceled) or deleted. This local process NEVER spawns pi or writes the session — it holds only a socket to the broker. --canvas <name> is the escape hatch for a node hosted on a different machine\'s canvas — see the leaf\'s own -h.',
97
102
  },
98
- children: [attachToLeaf],
103
+ children: [attachToLeaf(namespace)],
99
104
  });
100
105
  }
@@ -0,0 +1,27 @@
1
+ import type { ClientRole, ClientToBroker } from '../../../core/runtime/broker-protocol.js';
2
+ /** Actions the attach input surface may perform. Frame-level broker enforcement
3
+ * remains authoritative; this is the viewer-side refusal contract. */
4
+ export type ViewerOperation = 'engine-drive' | 'dequeue' | 'wake-dormant' | 'auth' | 'canvas-resume' | 'local-canvas-inspect' | 'canvas-inbox';
5
+ export interface ViewerCapabilities {
6
+ readonly role: ClientRole;
7
+ readonly remote: boolean;
8
+ readonly nodeId: string;
9
+ readonly profileId: string | undefined;
10
+ readonly permittedOperations: ReadonlySet<ViewerOperation>;
11
+ permits(operation: ViewerOperation): boolean;
12
+ refusal(operation: ViewerOperation, command?: string): string | undefined;
13
+ }
14
+ export interface ViewerCapabilityInput {
15
+ role: ClientRole;
16
+ remote: boolean;
17
+ nodeId: string;
18
+ profileId: string | undefined;
19
+ }
20
+ /** Build the one authority for a viewer session. Remote viewers are observers
21
+ * even when a caller supplied a controller role; keep that invariant local to
22
+ * this construction boundary. */
23
+ export declare function createViewerCapabilities(input: ViewerCapabilityInput): ViewerCapabilities;
24
+ /** The slash dispatcher asks the capability model for a command's operation;
25
+ * commands with no returned operation are viewer-local/read-only. */
26
+ export declare function viewerOperationForFrame(frame: ClientToBroker): ViewerOperation | undefined;
27
+ export declare function viewerOperationForSlash(name: string, builtin: boolean, canvas: boolean): ViewerOperation | undefined;