@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
@@ -1,57 +0,0 @@
1
- // Run with: node --import tsx/esm --test src/core/__tests__/full/broker-model-changed-broadcast.test.ts
2
- //
3
- // FULL TIER (real-boot-bound): tmux-free, but it boots a REAL broker process,
4
- // so it lives in full/ (CI), not the fast local loop.
5
- //
6
- // BUG-REGRESSION (real, observed 2026-06-11 in `crtr surface attach`): switching the
7
- // model (/model <provider/id> or the picker) visibly did nothing — the viewer's
8
- // status bar kept showing the OLD model until some unrelated event happened to
9
- // arrive.
10
- //
11
- // 3-PART HEADER:
12
- // (1) BUG IT LOCKS — pi emits no AgentSessionEvent for a model switch, and the
13
- // broker's `set_model`/`cycle_model` handlers replied with only a bare ack
14
- // to the REQUESTING client. The new model reached no viewer at all: the
15
- // broker now broadcasts a `model_changed` frame (mirroring
16
- // snapshot.state.model) to every client after the engine accepts the switch.
17
- // (2) WHY BROKER/SOCKET-LEVEL, NOT PANE — the regression is pure frame-plumbing
18
- // on view.sock: a controller `set_model` in, an ack + `model_changed`
19
- // fan-out. No tmux pane or TUI is involved, so the lock holds headlessly
20
- // (createHeadlessHarness + the fake engine, whose registry stub resolves
21
- // any `provider/id` and whose setModel stores what it is handed).
22
- // (3) HOW IT FAILS ON REGRESSION — pre-fix, NO `model_changed` frame ever
23
- // arrives at either the controller or the observer (both waits time out);
24
- // the ack alone still passing would not satisfy the broadcast asserts.
25
- import { test, before, after, afterEach } from 'node:test';
26
- import assert from 'node:assert/strict';
27
- import { createHeadlessHarness } from '../helpers/harness.js';
28
- import { createAttachKit } from '../helpers/broker-clients.js';
29
- let h;
30
- let id;
31
- const kit = createAttachKit(() => h);
32
- const { attachUntil } = kit;
33
- before(async () => {
34
- h = await createHeadlessHarness({ sessionPrefix: 'crtr-brkmodel' });
35
- const root = h.spawnRoot('model-changed-broadcast suite root');
36
- id = await h.spawnHeadlessChild(root, 'headless worker — model_changed broadcast gate');
37
- });
38
- after(async () => {
39
- if (h !== undefined)
40
- await h.dispose();
41
- });
42
- afterEach(() => {
43
- kit.closeAll();
44
- });
45
- test('set_model acks the requester and broadcasts model_changed to every viewer', async () => {
46
- const c = await attachUntil(id, 'controller', 'model-ctrl', (a) => a.welcome.role === 'controller', 'model-ctrl admitted controller');
47
- const o = await attachUntil(id, 'observer', 'model-obs', (a) => a.welcome.role === 'observer', 'model-obs admitted observer');
48
- c.send({ type: 'set_model', model: 'anthropic/fake-fable' });
49
- const ack = await c.waitFrame((f) => f.type === 'ack' && f.for === 'set_model', 'set_model ack');
50
- assert.ok(ack.type === 'ack' && ack.ok, 'set_model acked ok');
51
- // BOTH the requester and the observer hear the switch. Pre-fix: no
52
- // model_changed frame exists, so neither wait ever resolves.
53
- const cm = await c.waitFrame((f) => f.type === 'model_changed', 'controller receives model_changed');
54
- assert.ok(cm.type === 'model_changed' && cm.model?.id === 'fake-fable', 'controller sees the new model id');
55
- const om = await o.waitFrame((f) => f.type === 'model_changed', 'observer receives model_changed');
56
- assert.ok(om.type === 'model_changed' && om.model?.id === 'fake-fable', 'observer sees the new model id');
57
- });
@@ -1,80 +0,0 @@
1
- // Run with: node --import tsx/esm --test src/core/__tests__/full/broker-navigate-tree-rewelcome.test.ts
2
- //
3
- // FULL TIER (real-boot-bound): tmux-free, but it boots a REAL broker process,
4
- // so it lives in full/ (CI), not the fast local loop.
5
- //
6
- // BUG-REGRESSION (real, observed 2026-06-11 in `crtr surface attach`): double-Esc (or
7
- // /tree) opened the session-tree picker, but SELECTING an entry visibly did
8
- // nothing — the viewer stayed on the old transcript instead of traveling back
9
- // to the chosen point in time.
10
- //
11
- // 3-PART HEADER:
12
- // (1) BUG IT LOCKS — the broker's `navigate_tree` handler called
13
- // session.navigateTree() (which rewinds IN-PLACE: same session file, new
14
- // leaf, NO relayed AgentSessionEvent) and then only acked. Unlike the
15
- // session-replacing ops (new_session/switch_session/fork → runReplacement
16
- // → reWelcomeAll), it never re-snapshotted the viewers, so every attached
17
- // client kept rendering the abandoned branch. The navigated-to user
18
- // message's `editorText` (pi parity: the tree navigator restores it to the
19
- // editor) was dropped on the floor too.
20
- // (2) WHY BROKER/SOCKET-LEVEL, NOT PANE — the regression is pure frame-plumbing
21
- // on view.sock: a controller `navigate_tree` in, a re-`welcome` fan-out +
22
- // ack.detail out. No tmux pane or TUI is involved, so the lock holds
23
- // headlessly (createHeadlessHarness + the fake engine, whose navigateTree
24
- // pops the last accrued turn and returns `rewound-to:<targetId>`).
25
- // (3) HOW IT FAILS ON REGRESSION — pre-fix, NO second welcome ever arrives
26
- // (the re-welcome waits time out) and the navigate_tree ack carries no
27
- // detail; the rewound-history assert (the turn token gone from the new
28
- // snapshot) also goes red if the re-welcome serves a stale snapshot.
29
- import { test, before, after, afterEach } from 'node:test';
30
- import assert from 'node:assert/strict';
31
- import { createHeadlessHarness } from '../helpers/harness.js';
32
- import { createAttachKit, frameHas, tok } from '../helpers/broker-clients.js';
33
- let h;
34
- let id;
35
- const kit = createAttachKit(() => h);
36
- const { attachUntil } = kit;
37
- before(async () => {
38
- h = await createHeadlessHarness({ sessionPrefix: 'crtr-brknav' });
39
- const root = h.spawnRoot('navigate-tree-rewelcome suite root');
40
- id = await h.spawnHeadlessChild(root, 'headless worker — navigate-tree rewelcome gate');
41
- });
42
- after(async () => {
43
- if (h !== undefined)
44
- await h.dispose();
45
- });
46
- afterEach(() => {
47
- kit.closeAll();
48
- });
49
- const welcomes = (frames) => frames.filter((f) => f.type === 'welcome');
50
- test('navigate_tree re-welcomes every viewer onto the rewound transcript and acks the editor text', async () => {
51
- const c = await attachUntil(id, 'controller', 'nav-ctrl', (a) => a.welcome.role === 'controller', 'nav-ctrl admitted controller');
52
- // Accrue one observable turn so the rewind has something to drop.
53
- const token = tok('NAV-TURN');
54
- c.send({ type: 'prompt', text: token });
55
- await c.waitFrame((f) => f.type === 'agent_end' && frameHas(f, token), 'turn relayed before navigate');
56
- // The observer attaches AFTER the turn so its first welcome deterministically
57
- // holds the token (the pre-navigate baseline) — same accrual trick as G3.
58
- const o = await attachUntil(id, 'observer', 'nav-obs', (a) => frameHas(a.welcome, token), 'observer welcome holds the pre-navigate turn');
59
- c.send({ type: 'navigate_tree', targetId: 'entry-x' });
60
- // The ack carries the navigated-to user message's text in detail (the viewer
61
- // restores it to the editor). Pre-fix: ack had no detail.
62
- const ack = await c.waitFrame((f) => f.type === 'ack' && f.for === 'navigate_tree', 'navigate_tree ack');
63
- assert.ok(ack.type === 'ack' && ack.ok, 'navigate_tree acked ok');
64
- assert.equal(ack.type === 'ack' ? ack.detail : undefined, 'rewound-to:entry-x', 'ack.detail carries the rewound-to editor text');
65
- // BOTH viewers get re-welcomed onto the rewound history. Pre-fix: no second
66
- // welcome ever arrives (navigate_tree only acked).
67
- await h.waitFor(() => (welcomes(c.frames).length >= 2 ? true : null), {
68
- label: 'controller re-welcomed after navigate_tree',
69
- });
70
- await h.waitFor(() => (welcomes(o.frames).length >= 2 ? true : null), {
71
- label: 'observer re-welcomed after navigate_tree',
72
- });
73
- // The re-welcome serves the REWOUND transcript: the fake's navigateTree popped
74
- // the last accrued turn, so the token present in the observer's first welcome
75
- // must be gone from its second.
76
- const [first, second] = welcomes(o.frames);
77
- assert.ok(frameHas(first, token), 'pre-navigate welcome holds the turn');
78
- assert.ok(!frameHas(second, token), 're-welcome serves the rewound transcript (turn dropped)');
79
- assert.equal(second.snapshot.messages.length, first.snapshot.messages.length - 2, 're-welcome history is exactly one turn shorter (a turn = user + assistant = 2 tree messages)');
80
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,240 +0,0 @@
1
- // Run with: node --import tsx/esm --test src/core/__tests__/cascade-close.test.ts
2
- //
3
- // CASCADE CLOSE + exclusive-subtree ownership — a FAITHFUL integration test of
4
- // `crtr node lifecycle close` on a MIDDLE node, driven through the REAL CLI against a REAL
5
- // isolated tmux session with REAL fake-pi vehicles in REAL panes, asserting off
6
- // the canvas data layer and checked against the state-model ORACLE
7
- // (state-model.md §4 `node lifecycle close`, §5 cascade-close ownership, invariant 3,
8
- // ambiguity A5).
9
- //
10
- // WHY this exists alongside the unit `close.test.ts`: that test exercises
11
- // `closeNode()` in-process against the data layer with FABRICATED pane strings
12
- // (`pane:'%x'`) — it proves the closing-set fixpoint and the status flip, but it
13
- // never kills a real tmux pane, never boots a real vehicle, and never closes a
14
- // MIDDLE node with a live sideways-sibling subtree. This test fills exactly that
15
- // gap: it builds a real tree, closes the middle, and proves the reap is EXACTLY
16
- // the closed node's own subtree — nothing above (the ancestor) or sideways (a
17
- // sibling subtree) is touched, and the real broker engines actually die.
18
- //
19
- // VIEWER MODEL (a09b71f): a managed child boots as a detached headless BROKER
20
- // with NO viewer pane on spawn (a viewer is opened on demand via `surface node focus`).
21
- // So "the node is up" is broker-engine liveness — its recorded `pi_pid` is alive
22
- // — NOT pane presence. close tears that broker engine down (headlessBrokerHost
23
- // .teardown over view.sock), so we assert pid liveness, not panes.
24
- //
25
- // The tree (covers BOTH required shapes in one topology):
26
- //
27
- // A (resident root, in-process)
28
- // ├── B ◄── CLOSE TARGET (the middle node)
29
- // │ ├── C
30
- // │ │ └── E depth : A→B→C→E (deep chain)
31
- // │ └── D breadth: B has two children {C, D}
32
- // └── S sideways sibling subtree — MUST survive
33
- // └── G
34
- //
35
- // close(B) ⇒ exclusive subtree {B,C,D,E} canceled; A,S,G untouched.
36
- //
37
- // CRITICAL DELIVERABLE (ambiguity A5): the EXACT terminal status a cascade-
38
- // closed descendant receives under `node lifecycle close`. With the fixtures made
39
- // non-empty below: status === 'canceled', intent === null (cleared) — for the
40
- // cascade ROOT and EVERY descendant alike (`transition(id,'cancel')`,
41
- // close.ts → lifecycle.ts cancel row: status='canceled', intent=null, from '*').
42
- // This differs from the ancestor-RESET path (`reapDescendants` → `reap` → 'done')
43
- // — same act, different terminal status: A5's open question. We assert the close
44
- // side and report the confirmed fact; we do NOT change it.
45
- //
46
- // FLAG vs the task brief: the brief expected "subscription+parent edges removed"
47
- // on close. CURRENT behavior + the ORACLE (§4: "Nothing is deleted: pi sessions +
48
- // edges persist → revivable") + the CLI help ("their pi sessions and canvas edges
49
- // persist for a later revive") all say edges PERSIST. This test asserts the
50
- // CURRENT (persist) behavior and the report flags the contradiction; production
51
- // is NOT changed.
52
- import { test } from 'node:test';
53
- import assert from 'node:assert/strict';
54
- import { spawnSync } from 'node:child_process';
55
- import { mkdirSync, writeFileSync } from 'node:fs';
56
- import { join } from 'node:path';
57
- import { createHarness, hasTmux, TMUX_TIMEOUT_MS } from '../helpers/harness.js';
58
- import { isPidAlive } from '../../canvas/pid.js';
59
- function sessionExists(session) {
60
- return (spawnSync('tmux', ['has-session', '-t', session], {
61
- stdio: 'ignore',
62
- timeout: TMUX_TIMEOUT_MS,
63
- }).status === 0);
64
- }
65
- function seedAssistantSession(sessionFile) {
66
- mkdirSync(join(sessionFile, '..'), { recursive: true });
67
- writeFileSync(sessionFile, JSON.stringify({ type: 'message', message: { role: 'assistant', content: [{ type: 'text', text: 'hi' }] } }) + '\n');
68
- }
69
- test('cascade close: middle-node lifecycle close cancels EXACTLY its subtree, ancestor + sideways untouched, edges persist', { skip: !hasTmux() ? 'tmux unavailable' : false, timeout: 180_000 }, async () => {
70
- const h = await createHarness({ sessionPrefix: 'crtr-cascade' });
71
- try {
72
- // ===================================================================
73
- // BUILD — the real tree. A is the in-process resident root (no pane);
74
- // B,C,D,E,S,G are real managed children, each a real fake-pi in a real
75
- // backstage pane (spawnChild awaits each boot). Every `node new` seeds the
76
- // spine edge parent→child (active) + the spawned_by/parent provenance.
77
- // ===================================================================
78
- const A = h.spawnRoot('cascade-close root');
79
- const B = await h.spawnChild(A, 'middle node — the close target', { kind: 'developer' });
80
- const C = await h.spawnChild(B, 'B child one');
81
- const E = await h.spawnChild(C, 'deep leaf under C'); // depth: A→B→C→E
82
- const D = await h.spawnChild(B, 'B child two'); // breadth: B has {C, D}
83
- const S = await h.spawnChild(A, 'sideways sibling of B'); // sideways subtree
84
- const G = await h.spawnChild(S, 'child of the sideways sibling');
85
- const subtree = [B, C, D, E]; // B's exclusive subtree (the expected cancel set)
86
- const sideways = [S, G]; // a sibling subtree — must be wholly untouched
87
- // Make the close-path fixtures NON-EMPTY so close exercises cancel+notice
88
- // semantics instead of the new reap-empty path.
89
- for (const id of subtree) {
90
- const sessionFile = h.node(id).pi_session_file;
91
- assert.ok(sessionFile !== null && sessionFile !== undefined, `${id} has a session file`);
92
- seedAssistantSession(sessionFile);
93
- }
94
- // Pre-close sanity: every node live + present, spine wired as drawn.
95
- {
96
- for (const id of [B, C, D, E, S, G]) {
97
- assert.ok(h.status(id) === 'active' || h.status(id) === 'idle', `${id} live before close`);
98
- const pid = h.node(id).pi_pid;
99
- assert.ok(pid != null && isPidAlive(pid), `${id} broker engine alive before close`);
100
- }
101
- assert.ok(h.status(A) === 'active' || h.status(A) === 'idle', 'A (root) live before close');
102
- // Spine: A→{B,S}, B→{C,D}, C→{E}, S→{G} (all active spawn-seed edges).
103
- const subIds = (n) => h.subscriptions(n).map((s) => s.node_id).sort();
104
- assert.deepEqual(subIds(A), [B, S].sort(), 'A subscribes_to B and S');
105
- assert.deepEqual(subIds(B), [C, D].sort(), 'B subscribes_to C and D');
106
- assert.deepEqual(subIds(C), [E], 'C subscribes_to E');
107
- assert.deepEqual(subIds(S), [G], 'S subscribes_to G');
108
- // provenance edges (spawned_by / parent)
109
- for (const [child, parent] of [[B, A], [C, B], [E, C], [D, B], [S, A], [G, S]]) {
110
- assert.equal(h.node(child).parent, parent, `${child}.parent = ${parent}`);
111
- }
112
- }
113
- // Make A's inbox NON-EMPTY before the close so "ancestor inbox intact" is a
114
- // non-vacuous assertion: B pushes a routine update up its spine → A (B's
115
- // sole active subscriber). A is the in-process root with no live watcher,
116
- // so the pointer simply accumulates and must survive the close untouched.
117
- {
118
- const res = h.cli(B, ['push', 'update', 'progress from B before close']);
119
- assert.equal(res.code, 0, `B push update exit 0\n${res.stderr}`);
120
- }
121
- const aInboxBefore = h.inbox(A);
122
- assert.ok(aInboxBefore.some((e) => e.from === B && e.kind === 'update'), "A's inbox holds B's pre-close update (non-vacuous 'intact' baseline)");
123
- // ===================================================================
124
- // CLOSE the MIDDLE node B, through the REAL CLI (`crtr node lifecycle close --node B`,
125
- // run AS the root A). closeNode is synchronous in the subprocess: by the
126
- // time it returns, rows are flipped and panes are killed.
127
- // ===================================================================
128
- const closeRes = h.cli(A, ['node', 'lifecycle', 'close', '--node', B]);
129
- assert.equal(closeRes.code, 0, `node lifecycle close exit 0\n${closeRes.stderr}`);
130
- // The CLI's own rendered report (plain markdown): cascade root B, exactly
131
- // 4 closed, 0 spared (no spared clause is emitted when none were spared).
132
- assert.match(closeRes.stdout, new RegExp(`^Closed ${B} and its exclusive subtree — 4 node\\(s\\) closed\\.`), `close report names B as root, count=4, spared=0\n${closeRes.stdout}`);
133
- // ===================================================================
134
- // ASSERT 1 — the A5 DELIVERABLE: the EXACT terminal status of every
135
- // cascade-closed node. With the fixtures now non-empty, close exercises
136
- // cancel+notice semantics and the rows remain present as canceled husks.
137
- // ===================================================================
138
- for (const id of subtree) {
139
- const n = h.node(id);
140
- assert.equal(n.status, 'canceled', `${id} terminal status === 'canceled' (cancel event)`);
141
- assert.strictEqual(n.intent ?? null, null, `${id} intent cleared to null on cancel`);
142
- }
143
- // Pin the exact field tuple once more, explicitly, for the human decision:
144
- // a cascade-closed descendant under `node lifecycle close` reads (canceled, null) —
145
- // NOT (done, done) and NOT (done, null). This is the confirmed A5 fact.
146
- {
147
- const e = h.node(E); // the deepest descendant
148
- assert.deepEqual({ status: e.status, intent: e.intent ?? null }, { status: 'canceled', intent: null }, "deepest closed descendant E: (status,intent) === ('canceled', null)");
149
- }
150
- // ===================================================================
151
- // ASSERT 2 — broker ENGINE torn down for the ENTIRE subtree (the real
152
- // "node is up" invariant now: a closed node owns no live broker process).
153
- // close → headlessBrokerHost.teardown shut each broker down over view.sock.
154
- // ===================================================================
155
- for (const id of subtree) {
156
- await h.waitFor(() => {
157
- const pid = h.node(id)?.pi_pid ?? null;
158
- return pid === null || !isPidAlive(pid);
159
- }, { label: `${id} broker engine torn down by close` });
160
- const pid = h.node(id)?.pi_pid ?? null;
161
- assert.ok(pid === null || !isPidAlive(pid), `${id} broker engine destroyed by close`);
162
- }
163
- // ===================================================================
164
- // ASSERT 3 — EXCLUSIVE-SUBTREE OWNERSHIP: nothing ABOVE (A) and nothing
165
- // SIDEWAYS (S, G) was reaped. close(B) canceled EXACTLY B's own subtree.
166
- // ===================================================================
167
- // Ancestor A — lifecycle untouched (still the live resident root), but A is
168
- // the SURVIVING manager of the close-root B, so the wake doctrine fix WAKES
169
- // it: a "child closed" notice is fanned to a manager OUTSIDE the closing set
170
- // (D-1 — previously A heard nothing and a dormant A could hang forever).
171
- {
172
- const a = h.node(A);
173
- assert.equal(a.status, 'active', 'A (ancestor) still active — untouched by the cascade');
174
- assert.equal(a.lifecycle, 'resident', 'A still resident');
175
- assert.equal(a.intent ?? null, null, 'A intent untouched');
176
- // A's PRIOR entries are preserved; exactly ONE new child-closed entry
177
- // from the closed child B is appended (the doctrine wake).
178
- const aInbox = h.inbox(A);
179
- assert.deepEqual(aInbox.slice(0, aInboxBefore.length), aInboxBefore, "A's prior inbox entries are preserved across the close");
180
- const added = aInbox.slice(aInboxBefore.length);
181
- assert.equal(added.length, 1, 'exactly one new entry appended to the surviving manager A');
182
- assert.equal(added[0].from, B, 'the new entry is from the closed child B');
183
- assert.match(added[0].label, /closed/i, 'the new entry tells A its child B was closed');
184
- }
185
- // Sideways subtree S→G — wholly alive: status active AND broker engine alive.
186
- for (const id of sideways) {
187
- assert.equal(h.status(id), 'active', `${id} (sideways) still active — not canceled`);
188
- const pid = h.node(id).pi_pid;
189
- assert.ok(pid != null && isPidAlive(pid), `${id} (sideways) broker engine still alive`);
190
- }
191
- // The strong "EXACTLY its own subtree" closure: every node in the graph is
192
- // either in B's subtree (canceled) or untouched (active) — no over-reach.
193
- {
194
- const reaped = new Set(subtree);
195
- for (const id of [A, B, C, D, E, S, G]) {
196
- const want = reaped.has(id) ? 'canceled' : 'active';
197
- assert.equal(h.status(id), want, `${id} status === '${want}' (no over-/under-reach)`);
198
- }
199
- }
200
- // ===================================================================
201
- // ASSERT 4 — EDGES PERSIST (CURRENT behavior + ORACLE §4). close is a pause,
202
- // not a delete: a closed node keeps its spine + provenance edges so it can
203
- // be revived. (FLAGGED in the report: the task brief expected "edges
204
- // removed" — that contradicts current behavior; we assert persistence.)
205
- // ===================================================================
206
- {
207
- const subIds = (n) => h.subscriptions(n).map((s) => s.node_id).sort();
208
- // Ancestor's spine edge to the closed middle node survives.
209
- assert.ok(h.subscriptions(A).some((s) => s.node_id === B && s.active), 'A→B subscription edge PERSISTS after close (revivable)');
210
- // Intra-subtree spine edges survive too.
211
- assert.deepEqual(subIds(B), [C, D].sort(), 'B→{C,D} edges persist');
212
- assert.deepEqual(subIds(C), [E], 'C→E edge persists');
213
- // Provenance (spawned_by / parent) survives.
214
- for (const [child, parent] of [[B, A], [C, B], [E, C], [D, B]]) {
215
- assert.equal(h.node(child).parent, parent, `${child}.parent = ${parent} persists`);
216
- }
217
- // Sideways edges obviously untouched.
218
- assert.deepEqual(subIds(S), [G], 'S→G edge untouched');
219
- }
220
- // ===================================================================
221
- // ASSERT 5 — each closed node got its cancellation notice (the resume
222
- // breadcrumb), appended AFTER its watcher died (close.ts step 3). The root
223
- // B reads "CLOSED by the user"; descendants read "CANCELED — an ancestor…".
224
- // ===================================================================
225
- {
226
- const bNotice = h.inbox(B).at(-1);
227
- assert.equal(bNotice.from, null, "B's cancel notice is a system message");
228
- assert.match(bNotice.label, /CLOSED by the user/, 'B (cascade root) reads the CLOSED notice');
229
- assert.equal(bNotice.data?.['cascade_root'], B, "B notice records the cascade root");
230
- const eNotice = h.inbox(E).at(-1);
231
- assert.match(eNotice.label, /CANCELED/, 'E (descendant) reads the CANCELED notice');
232
- assert.equal(eNotice.data?.['cascade_root'], B, "E notice records B as the cascade root");
233
- }
234
- }
235
- finally {
236
- const session = h.session;
237
- await h.dispose();
238
- assert.equal(sessionExists(session), false, 'isolated session killed — no stray');
239
- }
240
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,126 +0,0 @@
1
- // Run with: node --import tsx/esm --test src/core/__tests__/full/detach-focus.test.ts
2
- //
3
- // `crtr node demote --detach` on a node with a live viewer (Alt+C → D).
4
- //
5
- // BROKER-CUT ADAPTATION (insights/runtime/broker-is-the-host, 2026-06-10): every node is a
6
- // detached headless broker. After a09b71f a managed child opens NO viewer on
7
- // spawn — a viewer is opened on demand via `surface node focus`, registering
8
- // its `crtr surface attach` VIEWER pane in the focuses table. The engine is NOT in a pane, so the
9
- // pre-cut "relocate the still-running pi pane to the backstage" behavior —
10
- // detachToBackground's engine break-pane/release path, and its isGenerating()
11
- // gate that released a non-generating node to dormant — is DELETED. The Bug-1
12
- // non-generating-release test that locked that gate is deleted with it (the
13
- // behavior no longer exists; nothing to invent coverage for).
14
- //
15
- // What SURVIVES and is locked here: `node demote --detach` flips the node
16
- // terminal IN PLACE and CLOSES its viewer pane + focus row, leaving the broker
17
- // ENGINE running untouched (reconnectable by a later `focus`). This drives the
18
- // REAL verb (subprocess, AS the node) — the actual Alt+C → D menu path — against
19
- // a live broker node genuinely focused in a viewer pane, and proves:
20
- // (a) lifecycle flips terminal in place,
21
- // (b) the broker engine keeps running (pi_pid alive, unchanged — NOT killed),
22
- // (c) the viewer pane is closed + its focus row dropped (no orphaned/phantom
23
- // viewport row — Invariant P / F5).
24
- import { test } from 'node:test';
25
- import assert from 'node:assert/strict';
26
- import { spawnSync } from 'node:child_process';
27
- import { mkdirSync, writeFileSync } from 'node:fs';
28
- import { join } from 'node:path';
29
- import { createHarness, hasTmux, TMUX_TIMEOUT_MS } from '../helpers/harness.js';
30
- import { paneTag, taggedViewerPanes, waitForOneTaggedViewer } from '../helpers/viewer-panes.js';
31
- import { getNode } from '../../canvas/canvas.js';
32
- import { closeDb } from '../../canvas/db.js';
33
- import { isPidAlive } from '../../canvas/pid.js';
34
- const SKIP = !hasTmux() ? 'tmux unavailable' : false;
35
- function sessionExists(session) {
36
- return (spawnSync('tmux', ['has-session', '-t', session], {
37
- stdio: 'ignore',
38
- timeout: TMUX_TIMEOUT_MS,
39
- }).status === 0);
40
- }
41
- function paneExistsReal(pane) {
42
- return ((spawnSync('tmux', ['display-message', '-p', '-t', pane, '#{pane_id}'], {
43
- encoding: 'utf8',
44
- timeout: TMUX_TIMEOUT_MS,
45
- }).stdout ?? '').trim() === pane);
46
- }
47
- // P1 moved the `surface node focus` viewer registry off the `focuses` DB table (the CLI
48
- // can no longer write canvas.db) onto the tmux `@crtr_node` pane tag a
49
- // `crtr surface attach` viewer self-sets on connect. These helpers read that
50
- // pane-tag registry — the ground truth for "which pane is a node's viewer".
51
- // `paneTag` / `taggedViewerPanes` / `waitForOneTaggedViewer` live in
52
- // helpers/viewer-panes.ts, shared with the other full-tier viewer tests.
53
- // Split a throwaway pane in the harness session; return its %id. The caller pane
54
- // `surface node focus` opens the viewer beside (a09b71f: spawn no longer auto-opens one).
55
- // Write an assistant message into a node's pi session so it is NOT an empty
56
- // shell — reapIfEmpty (0515e8d) tears output-less nodes down on detach, which
57
- // would defeat the "broker survives" contract this test locks.
58
- function seedAssistantSession(sessionFile) {
59
- mkdirSync(join(sessionFile, '..'), { recursive: true });
60
- writeFileSync(sessionFile, JSON.stringify({ type: 'message', message: { role: 'assistant', content: [{ type: 'text', text: 'hi' }] } }) + '\n');
61
- }
62
- function makePane(session) {
63
- const r = spawnSync('tmux', ['split-window', '-d', '-t', session, '-P', '-F', '#{pane_id}', 'sleep 100000'], { encoding: 'utf8', timeout: TMUX_TIMEOUT_MS });
64
- const pane = (r.stdout ?? '').trim();
65
- assert.ok(pane.startsWith('%'), `expected a %pane_id, got "${pane}" (stderr: ${r.stderr})`);
66
- return pane;
67
- }
68
- // ===========================================================================
69
- // `crtr node demote --detach` on a node with a live viewer (Alt+C → D).
70
- // ===========================================================================
71
- test('node demote --detach: flips terminal in place, CLOSES the viewer pane + focus row, broker engine keeps running', { skip: SKIP, timeout: 120_000 }, async () => {
72
- const h = await createHarness({ sessionPrefix: 'crtr-detach-focus' });
73
- try {
74
- // A resident root + a live terminal child B. spawnChild launches B's broker
75
- // but opens NO viewer (a09b71f) — so B has no focus row yet.
76
- const A = h.spawnRoot('resident root');
77
- const B = await h.spawnChild(A, 'do the work', { kind: 'developer' });
78
- const b0 = h.node(B);
79
- assert.equal(b0.lifecycle, 'terminal', 'B born terminal');
80
- assert.equal(b0.status, 'active', 'B active after boot');
81
- const brokerPid = b0.pi_pid;
82
- assert.ok(brokerPid != null && isPidAlive(brokerPid), 'B broker engine alive before detach');
83
- // Make B NON-EMPTY (it produced an assistant message) so `--detach`
84
- // exercises the "close the viewer, broker survives" contract and NOT the
85
- // reap-empty path (0515e8d), which would tear an output-less shell down.
86
- assert.ok(b0.pi_session_file != null, 'B has a session file');
87
- seedAssistantSession(b0.pi_session_file);
88
- // Put B genuinely "on screen": `surface node focus` opens its one `crtr surface attach`
89
- // VIEWER pane beside a caller pane in the harness session — the on-demand
90
- // viewer the detach then tears down.
91
- const caller = makePane(h.session);
92
- const focusRes = h.cli(B, ['surface', 'node', 'focus', B, '--pane', caller]);
93
- assert.equal(focusRes.code, 0, `surface node focus B exit 0\n${focusRes.stderr}`);
94
- // The viewer pane is the node's on-screen presence, registered by the
95
- // `@crtr_node` pane tag the attach client self-sets on connect (P1: the CLI
96
- // no longer writes the focuses DB table) — NOT a node-row pane (a broker
97
- // carries null placement). Wait for the tag so the real registry is live.
98
- const viewerPane = await waitForOneTaggedViewer(h.session, B);
99
- assert.equal(paneExistsReal(viewerPane), true, 'B viewer pane is live on screen');
100
- // --- Drive the REAL verb on the focused node (the Alt+C → D menu path). ---
101
- const res = h.cli(B, ['node', 'lifecycle', 'demote', '--node', B, '--pane', viewerPane, '--detach']);
102
- assert.equal(res.code, 0, `node demote --detach exit 0\n${res.stderr}`);
103
- assert.match(res.stdout, /viewer closed \(broker still running off-screen\)/, `the viewer was closed\n${res.stdout}`);
104
- closeDb();
105
- const b = getNode(B);
106
- // (a) lifecycle flipped to terminal IN PLACE (it was already terminal; the
107
- // demote is idempotent on lifecycle — the point is it does not end B).
108
- assert.equal(b.lifecycle, 'terminal', '(a) B lifecycle=terminal after the flip');
109
- assert.equal(b.status, 'active', '(a) detach does NOT end the node — B stays active');
110
- // (b) the broker ENGINE keeps running — detach closes only the viewer, never
111
- // the engine (the one-host invariant: the engine was never in a pane).
112
- assert.equal(b.pi_pid, brokerPid, "(b) B's broker pid is UNCHANGED (engine not killed/respawned)");
113
- assert.equal(isPidAlive(brokerPid), true, '(b) B broker engine still alive off-screen');
114
- // (c) the viewer pane is CLOSED and its focus row dropped — no orphaned /
115
- // phantom viewport (A3 hazard / Invariant P).
116
- await h.waitForPaneGone(B);
117
- assert.equal(paneExistsReal(viewerPane), false, '(c) B viewer pane closed');
118
- assert.deepEqual(taggedViewerPanes(h.session, B), [], '(c) B no longer occupies any viewer (untagged — Invariant P)');
119
- assert.equal(paneTag(viewerPane), '', '(c) NO phantom @crtr_node tag resolves on the closed viewer %id');
120
- }
121
- finally {
122
- const session = h.session;
123
- await h.dispose();
124
- assert.equal(sessionExists(session), false, 'isolated session killed — no stray');
125
- }
126
- });
@@ -1,107 +0,0 @@
1
- // Run with: CRTR_MAX_LIVE_BROKERS=1000 node --import tsx/esm --test src/core/__tests__/full/issue-146-yield-spawn-focus.test.ts
2
- //
3
- // Issue #146 composed regression: a parent yields while a child launch is in flight,
4
- // its first cycling broker dies before session_start, and real `surface node focus`
5
- // then requests a strict resume. The locked revive arbiter must keep the durable refresh
6
- // authoritative, retry as a fresh cycle, and commit its intent/note only after the
7
- // retry reaches session_start.
8
- import { test } from 'node:test';
9
- import assert from 'node:assert/strict';
10
- import { spawnSync } from 'node:child_process';
11
- import { existsSync } from 'node:fs';
12
- import { createHarness, hasTmux, TMUX_TIMEOUT_MS, } from '../helpers/harness.js';
13
- import { isPidAlive } from '../../canvas/pid.js';
14
- import { updateNode } from '../../canvas/canvas.js';
15
- import { readYieldMessage, yieldMessagePath } from '../../runtime/kickoff.js';
16
- import { FAIL_BEFORE_SESSION_START_ONCE } from '../fixtures/fake-engine.js';
17
- const SKIP = !hasTmux() ? 'tmux unavailable' : false;
18
- function makeCallerPane(session) {
19
- const result = spawnSync('tmux', ['split-window', '-d', '-t', session, '-P', '-F', '#{pane_id}', 'sleep 100000'], { encoding: 'utf8', timeout: TMUX_TIMEOUT_MS });
20
- const pane = (result.stdout ?? '').trim();
21
- assert.ok(pane.startsWith('%'), `expected a tmux pane id, got "${pane}" (stderr: ${result.stderr})`);
22
- return pane;
23
- }
24
- function outputField(stdout, name) {
25
- return stdout.match(new RegExp(`^- ${name}:\\s*(.*)$`, 'm'))?.[1]?.trim();
26
- }
27
- test('yield + concurrent child spawn + failed cycle + focus preserves fresh-refresh authority', { skip: SKIP, timeout: 180_000 }, async () => {
28
- const h = await createHarness({ sessionPrefix: 'crtr-issue146' });
29
- try {
30
- const root = h.spawnRoot('issue 146 acting root');
31
- const parent = await h.spawnHeadlessChild(root, 'issue 146 orchestrator parent', {
32
- kind: 'developer',
33
- mode: 'orchestrator',
34
- });
35
- // Keep this test-only orchestrator resident so the fake engine's automatic
36
- // kickoff turn cannot legitimately idle-release it after session_start; the
37
- // assertions below can then observe the confirmation commit itself.
38
- updateNode(parent, { lifecycle: 'resident' });
39
- const initial = h.node(parent);
40
- const oldPid = initial.pi_pid;
41
- const baseBoots = h.bootCount(parent);
42
- const baseCycles = initial.cycles ?? 0;
43
- assert.ok(initial.pi_session_file != null && existsSync(initial.pi_session_file), 'parent booted with a real session file');
44
- assert.equal(isPidAlive(oldPid), true, 'parent broker is alive before yielding');
45
- // spawnHeadlessChild drives real `node new` synchronously, then yields while
46
- // awaiting the child broker boot. Start it without awaiting so parent yield
47
- // overlaps that boot exactly as the reported issue did.
48
- const childBoot = h.spawnHeadlessChild(parent, 'issue 146 concurrent child');
49
- const note = `Issue #146 ${FAIL_BEFORE_SESSION_START_ONCE} retain this yield handoff`;
50
- const yielded = h.cli(parent, ['node', 'yield', note]);
51
- assert.equal(yielded.code, 0, `node yield should succeed\n--stderr--\n${yielded.stderr}`);
52
- assert.equal(h.node(parent)?.intent, 'refresh', 'yield durably records refresh intent');
53
- const child = await childBoot;
54
- assert.ok(h.subscriptions(parent).some((entry) => entry.node_id === child && entry.active), 'parent remains actively subscribed to the concurrently spawned child');
55
- // End the old engine turn through the real stophook. Its ChildProcess exit
56
- // automatically enqueues policy row 3 (refresh → respawn-fresh); no
57
- // liveness tick or grace is involved. The short-lived-exit throttle may
58
- // defer the replacement briefly, so observe the new pid rather than a
59
- // fixed clock.
60
- await h.stop(parent);
61
- await h.waitFor(() => !isPidAlive(oldPid), { label: 'yielded parent broker exited' });
62
- assert.equal(h.node(parent)?.intent, 'refresh', 'refresh intent survives the old broker exit');
63
- const failedCyclePid = await h.waitFor(() => {
64
- const pid = h.node(parent)?.pi_pid;
65
- return pid != null && pid !== oldPid ? pid : null;
66
- }, { label: 'exit-event refresh launch recorded its broker pid', timeoutMs: 30_000 });
67
- await h.waitFor(() => !isPidAlive(failedCyclePid), {
68
- label: 'one-shot cycling broker died before session_start',
69
- });
70
- // Capture before focus but assert afterward. This keeps the competing real
71
- // focus path non-vacuous even if one of these durable preconditions regresses.
72
- const preFocus = {
73
- cycles: h.node(parent)?.cycles,
74
- intent: h.node(parent)?.intent ?? null,
75
- cyclePending: h.node(parent)?.cycle_pending,
76
- note: readYieldMessage(parent),
77
- noteExists: existsSync(yieldMessagePath(parent)),
78
- boots: h.bootCount(parent),
79
- };
80
- const callerPane = makeCallerPane(h.session);
81
- const focused = h.cli(root, ['surface', 'node', 'focus', parent, '--pane', callerPane]);
82
- const confirmed = await h.awaitBoot(parent, { minCount: baseBoots + 1, timeoutMs: 120_000 });
83
- const final = h.node(parent);
84
- assert.equal(focused.code, 0, `surface node focus should succeed\n--stderr--\n${focused.stderr}`);
85
- assert.equal(outputField(focused.stdout, 'revived'), 'true', 'real focus drives the production resume=true revive entrypoint');
86
- assert.equal(preFocus.boots, baseBoots, 'failed cycling launch never reached session_start');
87
- assert.equal(preFocus.cycles, baseCycles + 1, 'first actual refresh launch increments cycles exactly once');
88
- assert.equal(preFocus.intent, 'refresh', 'refresh intent survives the pre-session_start failure');
89
- assert.equal(preFocus.cyclePending, true, 'failed cycling launch remains pending before confirmation');
90
- assert.equal(preFocus.note?.trim(), note, 'failed launch leaves the complete yield handoff durable');
91
- assert.equal(preFocus.noteExists, true, 'yield handoff file remains present before confirmation');
92
- assert.equal(confirmed.resuming, false, 'focus cannot reopen the old session while refresh is pending');
93
- assert.ok(confirmed.prompt !== null && confirmed.prompt.includes(note), 'successful cycling retry receives the original yield note');
94
- assert.equal(final.cycles, baseCycles + 2, 'focus retry increments from the locked latest cycle exactly once');
95
- assert.equal(final.cycle_pending, false, 'confirmed session_start clears the pending-cycle marker');
96
- assert.equal(final.intent ?? null, null, 'confirmed session_start commits the refresh intent');
97
- assert.equal(readYieldMessage(parent), null, 'confirmed session_start clears the one-shot yield handoff');
98
- assert.equal(existsSync(yieldMessagePath(parent)), false, 'yield handoff file is gone only after confirmation');
99
- const childState = h.node(child);
100
- assert.equal(childState.status, 'active', 'concurrent child remains booted');
101
- assert.ok(childState.pi_pid != null && isPidAlive(childState.pi_pid), 'concurrent child broker remains alive');
102
- assert.ok(h.subscriptions(parent).some((entry) => entry.node_id === child && entry.active), 'parent-child subscription survives the parent refresh');
103
- }
104
- finally {
105
- await h.dispose();
106
- }
107
- });
@@ -1 +0,0 @@
1
- export {};