@north-light/crouter 0.3.173 → 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} +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/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,484 +0,0 @@
1
- // Run with: node --import tsx/esm --test src/core/__tests__/tmux-surface.test.ts
2
- //
3
- // STEP 2 of the placement/focus migration: guards on the tmux Surface (driver).
4
- //
5
- // 1. The §2.2 HARD DRIVER INVARIANT (GREEN now): every create/placement verb
6
- // in the driver — after the broker-host cut gutted the engine-in-pane
7
- // relocate verbs (U9 deleted swap-pane/break-pane/join-pane/move-pane),
8
- // the survivors are new-window / split-window / respawn-pane — MUST pass an
9
- // explicit `-t` target.
10
- // Omitting `-t` lets tmux resolve against its GLOBAL current session, which
11
- // can leak a pane into a user session — the exact unbidden-window bug this
12
- // redesign kills. This guards the bug's blast radius and should pass today.
13
- //
14
- // 2. The §5.1 "only placement.ts / tmux-chrome.ts import tmux.ts" lint guard
15
- // (ENFORCED as of Step 8): every other module reaches the driver through
16
- // placement's re-exports or the tmux-chrome seam, so the only direct
17
- // importers are placement.ts + tmux-chrome.ts (tmux.ts itself excluded).
18
- import { test } from 'node:test';
19
- import assert from 'node:assert/strict';
20
- import { readFileSync, readdirSync, statSync, mkdtempSync, mkdirSync, writeFileSync, existsSync } from 'node:fs';
21
- import { spawnSync } from 'node:child_process';
22
- import { tmpdir } from 'node:os';
23
- import { fileURLToPath } from 'node:url';
24
- import { dirname, join, basename } from 'node:path';
25
- import { ensureSession } from '../runtime/placement.js';
26
- import { installTmuxBindings, legacyInboxKeyFile } from '../runtime/tmux-chrome.js';
27
- import { ATTACH_CONTROL_BINDINGS, resolveKeybindings } from '../keybindings/index.js';
28
- const __dirname = dirname(fileURLToPath(import.meta.url));
29
- const SRC_ROOT = join(__dirname, '..', '..'); // .../src
30
- const TMUX_TS = join(SRC_ROOT, 'core', 'runtime', 'tmux.ts');
31
- /** The placement verbs the §2.2 invariant governs. (swap-pane/break-pane/
32
- * join-pane/move-pane were deleted with the engine-in-pane host in the broker
33
- * cut; kept in the match set so a regression that re-introduces an untargeted
34
- * one is still caught.) */
35
- const PLACEMENT_VERBS = [
36
- 'new-window',
37
- 'split-window',
38
- 'swap-pane',
39
- 'break-pane',
40
- 'join-pane',
41
- 'move-pane',
42
- 'respawn-pane',
43
- ];
44
- /** The smallest `[ … ]` array literal that encloses `matchIdx`: scan back to the
45
- * nearest `[` (the array open — the verb is always its first element), then
46
- * forward with bracket-depth counting to the matching `]` (handles nested
47
- * arrays like splitWindow's `? [] : ['-h']`). Returns the array source slice. */
48
- function enclosingArray(src, matchIdx) {
49
- let open = matchIdx;
50
- while (open >= 0 && src[open] !== '[')
51
- open--;
52
- assert.ok(open >= 0, `no enclosing [ for the verb at index ${matchIdx}`);
53
- let depth = 0;
54
- for (let i = open; i < src.length; i++) {
55
- if (src[i] === '[')
56
- depth++;
57
- else if (src[i] === ']') {
58
- depth--;
59
- if (depth === 0)
60
- return src.slice(open, i + 1);
61
- }
62
- }
63
- throw new Error('unbalanced [ ] while bracket-matching the verb array');
64
- }
65
- test('§2.2 driver invariant: every placement verb in tmux.ts passes an explicit -t target', () => {
66
- const src = readFileSync(TMUX_TS, 'utf8');
67
- // Match only the QUOTED JS string forms (`'new-window'`, …) — these are real
68
- // args-array elements; the jsdoc prose mentions the verbs unquoted / in
69
- // backticks, so this never trips on a comment.
70
- const re = new RegExp(`'(${PLACEMENT_VERBS.join('|')})'`, 'g');
71
- let found = 0;
72
- for (let m = re.exec(src); m !== null; m = re.exec(src)) {
73
- found++;
74
- const verb = m[1];
75
- const arr = enclosingArray(src, m.index);
76
- // The invariant is "name a specific tmux object, never fall back to the
77
- // GLOBAL current one". `-t` targets a destination; `break-pane` (and the
78
- // deleted swap/join/move-pane) instead name their SOURCE with `-s` — which
79
- // satisfies the invariant identically. Accept either explicit target flag.
80
- assert.ok(arr.includes(`'-t'`) || arr.includes(`'-s'`), `tmux verb '${verb}' is invoked WITHOUT an explicit -t/-s target — a latent ` +
81
- `instance of the unbidden-window bug (§2.2). Offending args array:\n${arr}`);
82
- }
83
- // Sanity: the driver really does contain placement verbs (so a refactor that
84
- // renames them can't make this assertion vacuously pass). The broker cut left
85
- // three (new-window / split-window / respawn-pane).
86
- assert.ok(found >= 3, `expected to scan ≥3 placement verbs, saw ${found}`);
87
- });
88
- // ---------------------------------------------------------------------------
89
- // Lint guard — §5.1, ENFORCED. The driver (tmux.ts) is imported ONLY by
90
- // placement.ts (the sanctioned model-over-driver, which re-exports the verbs
91
- // other modules need) and the tmux-chrome.ts chrome seam. Every other module —
92
- // runtime, daemon, commands, stophook, AND tests — must route through those.
93
- // ---------------------------------------------------------------------------
94
- /** Every `.ts` file under `src` (recursively), excluding nothing. */
95
- function allTsFiles(dir) {
96
- const out = [];
97
- for (const entry of readdirSync(dir)) {
98
- const p = join(dir, entry);
99
- if (statSync(p).isDirectory())
100
- out.push(...allTsFiles(p));
101
- else if (entry.endsWith('.ts'))
102
- out.push(p);
103
- }
104
- return out;
105
- }
106
- /** Files (basename) sanctioned to import the driver, per §2.1. */
107
- const ALLOWED_IMPORTERS = new Set(['tmux.ts', 'placement.ts', 'placement-tmux.ts', 'tmux-chrome.ts']);
108
- function importsDriver(file) {
109
- const src = readFileSync(file, 'utf8');
110
- // A specifier whose basename is exactly `tmux.js` (so `tmux-chrome.js` is NOT
111
- // matched). Covers `from '...'` and `import('...')`.
112
- return [...src.matchAll(/(?:from|import\s*\()\s*'([^']+)'/g)].some((m) => basename(m[1]) === 'tmux.js');
113
- }
114
- test('§5.1 lint: only placement.ts / tmux-chrome.ts import the tmux driver', () => {
115
- const offenders = allTsFiles(SRC_ROOT)
116
- .filter((f) => !ALLOWED_IMPORTERS.has(basename(f)))
117
- .filter(importsDriver)
118
- .map((f) => f.slice(SRC_ROOT.length + 1));
119
- assert.deepEqual(offenders, [], `modules importing tmux.ts directly: ${offenders.join(', ')}`);
120
- });
121
- function isolatedTmux(socket, args) {
122
- const result = spawnSync('tmux', ['-S', socket, ...args], { encoding: 'utf8' });
123
- return { status: result.status, stdout: result.stdout ?? '', stderr: result.stderr ?? '' };
124
- }
125
- function tmuxBinding(socket, table, key) {
126
- const result = isolatedTmux(socket, ['list-keys', '-T', table]);
127
- if (result.status !== 0)
128
- return null;
129
- return result.stdout.split('\n').find((line) => {
130
- const match = line.match(/^bind-key\s+(?:-r\s+)?-T\s+\S+\s+(\S+)\s+/);
131
- return match?.[1] === key;
132
- }) ?? null;
133
- }
134
- test('tmux repairs corrupt bracketed-paste caps without replacing user overrides', (t) => {
135
- if (spawnSync('tmux', ['-V']).status !== 0) {
136
- t.skip('tmux is unavailable');
137
- return;
138
- }
139
- const name = `crtr-bracketed-paste-${process.pid}-${Date.now()}`;
140
- // `-f /dev/null`: boot a config-less isolated server so these binding tests are
141
- // hermetic. Without it the server sources the developer's ~/.tmux.conf, whose
142
- // own root-table bindings (e.g. M-j) pre-occupy keys these tests rebind onto —
143
- // the installer then correctly refuses to clobber the foreign binding and the
144
- // assertion fails on the dev's machine but not on a config-less CI runner.
145
- const boot = spawnSync('tmux', ['-L', name, '-f', '/dev/null', 'new-session', '-d', '-s', 'test'], { encoding: 'utf8' });
146
- assert.equal(boot.status, 0, boot.stderr);
147
- const socket = spawnSync('tmux', ['-L', name, 'display-message', '-p', '#{socket_path}'], { encoding: 'utf8' }).stdout.trim();
148
- assert.notEqual(socket, '');
149
- const priorTmux = process.env['TMUX'];
150
- process.env['TMUX'] = `${socket},1,0`;
151
- try {
152
- assert.equal(isolatedTmux(socket, ['set-option', '-s', 'terminal-overrides', 'xterm*:Tc']).status, 0);
153
- assert.equal(isolatedTmux(socket, ['set-option', '-sga', 'terminal-overrides', '*:Enbp=E[?2004h:Dsbp=E[?2004l']).status, 0);
154
- ensureSession('test', process.cwd());
155
- const repaired = isolatedTmux(socket, ['show-options', '-s', 'terminal-overrides']);
156
- assert.equal(repaired.status, 0, repaired.stderr);
157
- assert.match(repaired.stdout, /xterm\*:Tc/, 'unrelated user override must remain');
158
- assert.match(repaired.stdout, /Enbp=\\+E\[\?2004h/, 'a valid Enbp override must be appended');
159
- ensureSession('test', process.cwd());
160
- assert.equal(isolatedTmux(socket, ['show-options', '-s', 'terminal-overrides']).stdout, repaired.stdout, 'valid Enbp must make the repair idempotent');
161
- }
162
- finally {
163
- if (priorTmux === undefined)
164
- delete process.env['TMUX'];
165
- else
166
- process.env['TMUX'] = priorTmux;
167
- isolatedTmux(socket, ['kill-server']);
168
- }
169
- });
170
- test('tmux installer remaps owned pairs and preserves occupied user bindings', (t) => {
171
- if (spawnSync('tmux', ['-V']).status !== 0) {
172
- t.skip('tmux is unavailable');
173
- return;
174
- }
175
- const name = `crtr-keybindings-${process.pid}-${Date.now()}`;
176
- const boot = spawnSync('tmux', ['-L', name, '-f', '/dev/null', 'new-session', '-d', '-s', 'test'], { encoding: 'utf8' });
177
- assert.equal(boot.status, 0, boot.stderr);
178
- const socketResult = spawnSync('tmux', ['-L', name, 'display-message', '-p', '#{socket_path}'], { encoding: 'utf8' });
179
- const socket = socketResult.stdout.trim();
180
- assert.notEqual(socket, '');
181
- const priorTmux = process.env['TMUX'];
182
- process.env['TMUX'] = `${socket},1,0`;
183
- try {
184
- isolatedTmux(socket, ['bind-key', '-T', 'root', 'M-]', 'run-shell', `crtr surface node cycle --dir next --pane '#{pane_id}' >/dev/null 2>&1`]);
185
- const first = installTmuxBindings(resolveKeybindings());
186
- assert.equal(first.ok, true, JSON.stringify(first.diagnostics));
187
- assert.ok(first.installed.some((pair) => pair.table === 'root' && pair.key === 'M-]'));
188
- const defaultMenu = tmuxBinding(socket, 'root', 'M-c') ?? '';
189
- assert.match(defaultMenu, /display-menu/);
190
- assert.match(defaultMenu, /copy node id/);
191
- assert.match(defaultMenu, /surface node id --pane \{pane\}/);
192
- assert.match(defaultMenu, /fork into idle root/);
193
- assert.match(defaultMenu, /node fork --pane #\{pane_id\}/);
194
- const headings = ['-#[bold]Explore', '-#[bold]Current node', '-#[bold]Lifecycle', '-#[bold]System'];
195
- for (const heading of headings)
196
- assert.ok(defaultMenu.includes(heading), `missing heading ${heading}`);
197
- assert.deepEqual(headings.map((heading) => defaultMenu.indexOf(heading)), [...headings.map((heading) => defaultMenu.indexOf(heading))].sort((a, b) => a - b), 'prefix-menu groups should stay in their intended order');
198
- // Each later group is preceded by a horizontal-rule separator (a lone empty
199
- // item name between the previous group and the header).
200
- assert.ok((defaultMenu.match(/'' "-#\[bold\]/g) ?? []).length >= 3, defaultMenu);
201
- assert.ok(defaultMenu.indexOf('promote to orchestrator') > defaultMenu.indexOf('-#[bold]Lifecycle'));
202
- assert.match(defaultMenu, /"create ›" c .*display-menu.*idea.*bug/);
203
- assert.match(defaultMenu, /"Alt\+C to close" M-c refresh-client/);
204
- const explore = defaultMenu.indexOf('-#[bold]Explore');
205
- const currentNode = defaultMenu.indexOf('-#[bold]Current node');
206
- const lifecycle = defaultMenu.indexOf('-#[bold]Lifecycle');
207
- const system = defaultMenu.indexOf('-#[bold]System');
208
- for (const item of ['find node', 'canvas graph', 'go to manager', 'inspect ›', 'display ›']) {
209
- assert.ok(defaultMenu.indexOf(item) > explore && defaultMenu.indexOf(item) < currentNode, `${item} belongs in Explore`);
210
- }
211
- assert.match(defaultMenu, /"inspect ›" i .*display-menu.*metadata.*context \+ reports/);
212
- for (const item of ['background running bash', 'copy node id']) {
213
- assert.ok(defaultMenu.indexOf(item) > currentNode && defaultMenu.indexOf(item) < lifecycle, `${item} belongs to the current node`);
214
- }
215
- assert.ok(defaultMenu.indexOf('fork into idle root') > lifecycle && defaultMenu.indexOf('fork into idle root') < system, 'fork belongs in Lifecycle');
216
- assert.match(defaultMenu, /"display ›" z .*display-menu.*fold finished tool calls/);
217
- assert.match(defaultMenu, /"attach viewer ›" a .*display-menu.*search profile files/);
218
- // File review is reachable from the top-level menu and alt+shift+R only:
219
- // its attach-submenu selector ships unbound, so the row must not render.
220
- assert.doesNotMatch(defaultMenu, /"review a file" r /);
221
- assert.match(defaultMenu, /send-keys -l/);
222
- assert.match(defaultMenu, /crtr\.attach\.profile-files/, 'the menu path must work while the profile-files direct binding is disabled by default');
223
- // Matched with its selector, so the Explore group's "display ›" item
224
- // cannot satisfy this assertion by substring.
225
- assert.ok(defaultMenu.indexOf('settings , ') > system, 'settings belongs in System');
226
- assert.ok(defaultMenu.indexOf('create ›') > system, 'create belongs in System');
227
- // The inbox toggle installs at its default key (alt+i → M-i) in the same sweep.
228
- assert.match(tmuxBinding(socket, 'root', 'M-i') ?? '', /crtr human inbox toggle/);
229
- const attachMenuDisabled = Object.fromEntries(ATTACH_CONTROL_BINDINGS.map(({ menuId }) => [menuId, []]));
230
- const withoutAttach = installTmuxBindings(resolveKeybindings(attachMenuDisabled));
231
- assert.equal(withoutAttach.ok, true, JSON.stringify(withoutAttach.diagnostics));
232
- const menuWithoutAttach = tmuxBinding(socket, 'root', 'M-c') ?? '';
233
- assert.doesNotMatch(menuWithoutAttach, /attach viewer ›/, 'an empty attach submenu must hide its opener');
234
- assert.doesNotMatch(menuWithoutAttach, /search profile files/);
235
- const remapped = installTmuxBindings(resolveKeybindings({
236
- 'crtr.tmux.menu.open': ['alt+shift+z'],
237
- 'crtr.tmux.menu.graph': ['shift+z'],
238
- 'crtr.tmux.menu-global.fold-tools': ['alt+shift+f'],
239
- 'crtr.tmux.node.next': [],
240
- }));
241
- assert.equal(remapped.ok, true, JSON.stringify(remapped.diagnostics));
242
- assert.equal(tmuxBinding(socket, 'root', 'M-c'), null);
243
- assert.equal(tmuxBinding(socket, 'root', 'M-]'), null);
244
- assert.equal(tmuxBinding(socket, 'root', 'M-F'), null);
245
- assert.equal(tmuxBinding(socket, 'root', 'M-S-f'), null);
246
- const foldTools = tmuxBinding(socket, 'root', 'M-S-F') ?? '';
247
- assert.match(foldTools, /fold-tools/);
248
- assert.doesNotMatch(foldTools, /#\{pane_id\}/);
249
- const menu = tmuxBinding(socket, 'root', 'M-S-Z') ?? '';
250
- assert.match(menu, /canvas graph/);
251
- assert.match(menu, /Z/);
252
- assert.match(menu, /"Alt\+Shift\+Z to close" M-S-Z refresh-client/);
253
- const again = installTmuxBindings(resolveKeybindings({
254
- 'crtr.tmux.menu.open': ['alt+shift+y'],
255
- 'crtr.tmux.node.next': [],
256
- }));
257
- assert.equal(again.ok, true, JSON.stringify(again.diagnostics));
258
- isolatedTmux(socket, ['bind-key', '-T', 'root', 'M-S-Z', 'display-message', 'user-owned']);
259
- const occupied = installTmuxBindings(resolveKeybindings({ 'crtr.tmux.menu.open': ['alt+shift+z'] }));
260
- assert.equal(occupied.ok, true);
261
- assert.ok(occupied.diagnostics.some((diagnostic) => diagnostic.code === 'occupied' && diagnostic.bindingId === 'crtr.tmux.menu.open'));
262
- assert.match(tmuxBinding(socket, 'root', 'M-S-Z') ?? '', /user-owned/);
263
- }
264
- finally {
265
- if (priorTmux === undefined)
266
- delete process.env['TMUX'];
267
- else
268
- process.env['TMUX'] = priorTmux;
269
- isolatedTmux(socket, ['kill-server']);
270
- }
271
- });
272
- test('tmux installer replaces an untracked stale crouter menu even when a partial manifest exists', (t) => {
273
- if (spawnSync('tmux', ['-V']).status !== 0) {
274
- t.skip('tmux is unavailable');
275
- return;
276
- }
277
- const name = `crtr-stale-menu-${process.pid}-${Date.now()}`;
278
- const boot = spawnSync('tmux', ['-L', name, 'new-session', '-d', '-s', 'test'], { encoding: 'utf8' });
279
- assert.equal(boot.status, 0, boot.stderr);
280
- const socket = spawnSync('tmux', ['-L', name, 'display-message', '-p', '#{socket_path}'], { encoding: 'utf8' }).stdout.trim();
281
- assert.notEqual(socket, '');
282
- const priorTmux = process.env['TMUX'];
283
- process.env['TMUX'] = `${socket},1,0`;
284
- try {
285
- // Upgrade fixture: a later installer started a manifest with only M-i while
286
- // the older crouter M-c menu remained live but untracked. Its crouter-only
287
- // markers prove ownership; it deliberately lacks the new background item.
288
- isolatedTmux(socket, ['set-option', '-s', '@crtr_keybindings_manifest', JSON.stringify([{ table: 'root', key: 'M-i' }])]);
289
- isolatedTmux(socket, [
290
- 'bind-key', '-T', 'root', 'M-c', 'display-menu',
291
- 'promote to orchestrator', 'o', "run-shell 'crtr canvas chord'",
292
- 'new issue / todo', 'i', 'display-message stale',
293
- ]);
294
- const stale = tmuxBinding(socket, 'root', 'M-c') ?? '';
295
- assert.match(stale, /crtr canvas chord/);
296
- assert.doesNotMatch(stale, /background running bash/);
297
- const result = installTmuxBindings(resolveKeybindings());
298
- assert.equal(result.ok, true, JSON.stringify(result.diagnostics));
299
- assert.ok(!result.diagnostics.some((d) => d.bindingId === 'crtr.tmux.menu.open'), JSON.stringify(result.diagnostics));
300
- assert.match(tmuxBinding(socket, 'root', 'M-c') ?? '', /background running bash/);
301
- }
302
- finally {
303
- if (priorTmux === undefined)
304
- delete process.env['TMUX'];
305
- else
306
- process.env['TMUX'] = priorTmux;
307
- isolatedTmux(socket, ['kill-server']);
308
- }
309
- });
310
- test('tmux installer rebinds/disables the inbox toggle and adopts the legacy hl-owned M-i', (t) => {
311
- if (spawnSync('tmux', ['-V']).status !== 0) {
312
- t.skip('tmux is unavailable');
313
- return;
314
- }
315
- const name = `crtr-inbox-${process.pid}-${Date.now()}`;
316
- const boot = spawnSync('tmux', ['-L', name, '-f', '/dev/null', 'new-session', '-d', '-s', 'test'], { encoding: 'utf8' });
317
- assert.equal(boot.status, 0, boot.stderr);
318
- const socket = spawnSync('tmux', ['-L', name, 'display-message', '-p', '#{socket_path}'], { encoding: 'utf8' }).stdout.trim();
319
- assert.notEqual(socket, '');
320
- const priorTmux = process.env['TMUX'];
321
- const priorState = process.env['XDG_STATE_HOME'];
322
- const stateHome = mkdtempSync(join(tmpdir(), 'crtr-inbox-state-'));
323
- process.env['TMUX'] = `${socket},1,0`;
324
- process.env['XDG_STATE_HOME'] = stateHome;
325
- try {
326
- // Fixture: a surviving hl-owned M-i binding plus its flat inbox-key file —
327
- // the arrangement crouter's key ownership replaces — with no crouter
328
- // manifest yet. First reconciliation must take over M-i (crouter's inbox
329
- // toggle, tracked in the manifest) rather than report it foreign.
330
- isolatedTmux(socket, ['bind-key', '-T', 'root', 'M-i', 'run-shell', '-b', 'hl inbox toggle --quiet --tmux-socket "#{socket_path}"']);
331
- const legacyKeyDir = join(stateHome, 'humanloop');
332
- mkdirSync(legacyKeyDir, { recursive: true });
333
- const legacyKeyFile = join(legacyKeyDir, 'inbox-key');
334
- writeFileSync(legacyKeyFile, 'M-i\n');
335
- const first = installTmuxBindings(resolveKeybindings());
336
- assert.equal(first.ok, true, JSON.stringify(first.diagnostics));
337
- // Adopted, not foreign: M-i is now crouter's inbox toggle, no occupied diag.
338
- assert.ok(!first.diagnostics.some((d) => d.bindingId === 'crtr.tmux.inbox.toggle'), JSON.stringify(first.diagnostics));
339
- assert.match(tmuxBinding(socket, 'root', 'M-i') ?? '', /crtr human inbox toggle/);
340
- assert.ok(first.installed.some((pair) => pair.table === 'root' && pair.key === 'M-i'));
341
- // The obsolete flat key file is deleted by the cleanup.
342
- assert.equal(existsSync(legacyKeyFile), false, 'legacy inbox-key file should be removed');
343
- // Rebind to a custom key: the old M-i (crouter-owned via the manifest) is
344
- // dropped and the new key carries the same inbox command.
345
- const rebound = installTmuxBindings(resolveKeybindings({ 'crtr.tmux.inbox.toggle': ['alt+j'] }));
346
- assert.equal(rebound.ok, true, JSON.stringify(rebound.diagnostics));
347
- assert.equal(tmuxBinding(socket, 'root', 'M-i'), null);
348
- assert.match(tmuxBinding(socket, 'root', 'M-j') ?? '', /crtr human inbox toggle/);
349
- // Disable via empty gesture list: no inbox key installed at all, no error.
350
- const disabled = installTmuxBindings(resolveKeybindings({ 'crtr.tmux.inbox.toggle': [] }));
351
- assert.equal(disabled.ok, true, JSON.stringify(disabled.diagnostics));
352
- assert.equal(tmuxBinding(socket, 'root', 'M-i'), null);
353
- assert.equal(tmuxBinding(socket, 'root', 'M-j'), null);
354
- }
355
- finally {
356
- if (priorTmux === undefined)
357
- delete process.env['TMUX'];
358
- else
359
- process.env['TMUX'] = priorTmux;
360
- if (priorState === undefined)
361
- delete process.env['XDG_STATE_HOME'];
362
- else
363
- process.env['XDG_STATE_HOME'] = priorState;
364
- isolatedTmux(socket, ['kill-server']);
365
- }
366
- });
367
- test('tmux installer adopts the legacy hl-owned inbox key when a crouter manifest already exists', (t) => {
368
- if (spawnSync('tmux', ['-V']).status !== 0) {
369
- t.skip('tmux is unavailable');
370
- return;
371
- }
372
- const name = `crtr-inbox-upgrade-${process.pid}-${Date.now()}`;
373
- const boot = spawnSync('tmux', ['-L', name, '-f', '/dev/null', 'new-session', '-d', '-s', 'test'], { encoding: 'utf8' });
374
- assert.equal(boot.status, 0, boot.stderr);
375
- const socket = spawnSync('tmux', ['-L', name, 'display-message', '-p', '#{socket_path}'], { encoding: 'utf8' }).stdout.trim();
376
- assert.notEqual(socket, '');
377
- const priorTmux = process.env['TMUX'];
378
- const priorState = process.env['XDG_STATE_HOME'];
379
- const stateHome = mkdtempSync(join(tmpdir(), 'crtr-inbox-state-'));
380
- process.env['TMUX'] = `${socket},1,0`;
381
- process.env['XDG_STATE_HOME'] = stateHome;
382
- try {
383
- // Contract: an hl-owned inbox binding not tracked in the manifest must be
384
- // adopted even when a crouter manifest already exists. Force
385
- // `manifest.existed = true` with a non-empty option, then seed an untracked
386
- // hl-owned M-i binding + its key file.
387
- isolatedTmux(socket, ['set-option', '-s', '@crtr_keybindings_manifest', '[]']);
388
- isolatedTmux(socket, ['bind-key', '-T', 'root', 'M-i', 'run-shell', '-b', 'hl inbox toggle --quiet --tmux-socket "#{socket_path}"']);
389
- const legacyKeyDir = join(stateHome, 'humanloop');
390
- mkdirSync(legacyKeyDir, { recursive: true });
391
- const legacyKeyFile = join(legacyKeyDir, 'inbox-key');
392
- writeFileSync(legacyKeyFile, 'M-i\n');
393
- const result = installTmuxBindings(resolveKeybindings());
394
- assert.equal(result.ok, true, JSON.stringify(result.diagnostics));
395
- // Cleanup ran despite the existing manifest: M-i is crouter's tracked inbox
396
- // toggle, no occupied/foreign diagnostic, and the key file is gone.
397
- assert.ok(!result.diagnostics.some((d) => d.bindingId === 'crtr.tmux.inbox.toggle'), JSON.stringify(result.diagnostics));
398
- assert.match(tmuxBinding(socket, 'root', 'M-i') ?? '', /crtr human inbox toggle/);
399
- assert.ok(result.installed.some((pair) => pair.table === 'root' && pair.key === 'M-i'));
400
- assert.equal(existsSync(legacyKeyFile), false, 'legacy inbox-key file should be removed');
401
- }
402
- finally {
403
- if (priorTmux === undefined)
404
- delete process.env['TMUX'];
405
- else
406
- process.env['TMUX'] = priorTmux;
407
- if (priorState === undefined)
408
- delete process.env['XDG_STATE_HOME'];
409
- else
410
- process.env['XDG_STATE_HOME'] = priorState;
411
- isolatedTmux(socket, ['kill-server']);
412
- }
413
- });
414
- test('tmux installer removes a legacy custom inbox key recorded in the state file', (t) => {
415
- if (spawnSync('tmux', ['-V']).status !== 0) {
416
- t.skip('tmux is unavailable');
417
- return;
418
- }
419
- const name = `crtr-inbox-custom-${process.pid}-${Date.now()}`;
420
- const boot = spawnSync('tmux', ['-L', name, '-f', '/dev/null', 'new-session', '-d', '-s', 'test'], { encoding: 'utf8' });
421
- assert.equal(boot.status, 0, boot.stderr);
422
- const socket = spawnSync('tmux', ['-L', name, 'display-message', '-p', '#{socket_path}'], { encoding: 'utf8' }).stdout.trim();
423
- assert.notEqual(socket, '');
424
- const priorTmux = process.env['TMUX'];
425
- const priorState = process.env['XDG_STATE_HOME'];
426
- const stateHome = mkdtempSync(join(tmpdir(), 'crtr-inbox-state-'));
427
- process.env['TMUX'] = `${socket},1,0`;
428
- process.env['XDG_STATE_HOME'] = stateHome;
429
- try {
430
- // Contract: an hl-owned binding at a non-default key named by the state
431
- // file must be located via that file and unbound (its value is never
432
- // imported as a crouter gesture), leaving crouter's configured M-i the only
433
- // installed inbox key even when a crouter manifest already exists.
434
- isolatedTmux(socket, ['set-option', '-s', '@crtr_keybindings_manifest', '[]']);
435
- isolatedTmux(socket, ['bind-key', '-T', 'root', 'M-z', 'run-shell', '-b', 'hl inbox toggle --quiet --tmux-socket "#{socket_path}"']);
436
- const legacyKeyDir = join(stateHome, 'humanloop');
437
- mkdirSync(legacyKeyDir, { recursive: true });
438
- const legacyKeyFile = join(legacyKeyDir, 'inbox-key');
439
- writeFileSync(legacyKeyFile, 'M-z\n');
440
- const result = installTmuxBindings(resolveKeybindings());
441
- assert.equal(result.ok, true, JSON.stringify(result.diagnostics));
442
- // The orphaned custom-key binding is gone — not left as an untracked live
443
- // shortcut — and was not imported into crouter's config (M-z stays unbound).
444
- assert.equal(tmuxBinding(socket, 'root', 'M-z'), null, 'legacy custom key must be unbound');
445
- assert.match(tmuxBinding(socket, 'root', 'M-i') ?? '', /crtr human inbox toggle/);
446
- assert.equal(existsSync(legacyKeyFile), false, 'legacy inbox-key file should be removed');
447
- }
448
- finally {
449
- if (priorTmux === undefined)
450
- delete process.env['TMUX'];
451
- else
452
- process.env['TMUX'] = priorTmux;
453
- if (priorState === undefined)
454
- delete process.env['XDG_STATE_HOME'];
455
- else
456
- process.env['XDG_STATE_HOME'] = priorState;
457
- isolatedTmux(socket, ['kill-server']);
458
- }
459
- });
460
- test('legacyInboxKeyFile resolves under the OS home when HOME and XDG_STATE_HOME are unset', () => {
461
- const priorHome = process.env['HOME'];
462
- const priorState = process.env['XDG_STATE_HOME'];
463
- delete process.env['HOME'];
464
- delete process.env['XDG_STATE_HOME'];
465
- try {
466
- const resolved = legacyInboxKeyFile();
467
- // Must be an absolute OS-home path (via os.homedir()), never cwd-relative —
468
- // otherwise cleanup would miss the real file and could delete an unrelated
469
- // file under the current directory.
470
- assert.ok(resolved.startsWith('/'), `expected an absolute path, got ${resolved}`);
471
- assert.ok(resolved.endsWith(join('.local', 'state', 'humanloop', 'inbox-key')), resolved);
472
- assert.ok(!resolved.startsWith(join(process.cwd(), '.local')), `must not resolve relative to cwd: ${resolved}`);
473
- }
474
- finally {
475
- if (priorHome === undefined)
476
- delete process.env['HOME'];
477
- else
478
- process.env['HOME'] = priorHome;
479
- if (priorState === undefined)
480
- delete process.env['XDG_STATE_HOME'];
481
- else
482
- process.env['XDG_STATE_HOME'] = priorState;
483
- }
484
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,102 +0,0 @@
1
- // Run with: node --import tsx/esm --test src/core/__tests__/wake-bearings.test.ts
2
- //
3
- // Cron-birth self-knowledge (the <crtr-wake> provenance block). These checks
4
- // cover one-shot and recurring birth prose, including a reaped armer, plus the
5
- // absence of cron provenance on an ordinary revive.
6
- import { test, before, after, beforeEach } from 'node:test';
7
- import assert from 'node:assert/strict';
8
- import { mkdtempSync, rmSync } from 'node:fs';
9
- import { tmpdir } from 'node:os';
10
- import { join } from 'node:path';
11
- import { createNode } from '../canvas/canvas.js';
12
- import { closeDb } from '../canvas/db.js';
13
- import { buildWakeBearings } from '../runtime/bearings.js';
14
- import { buildReviveKickoff, drainBearings } from '../runtime/kickoff.js';
15
- let home;
16
- function node(id) {
17
- return {
18
- node_id: id,
19
- name: id,
20
- created: new Date().toISOString(),
21
- cwd: '/tmp/work',
22
- kind: 'general',
23
- mode: 'base',
24
- lifecycle: 'terminal',
25
- status: 'active',
26
- };
27
- }
28
- const ARMED = '2026-06-08T13:30:00.000Z';
29
- before(() => {
30
- home = mkdtempSync(join(tmpdir(), 'crtr-wake-bearings-'));
31
- process.env['CRTR_HOME'] = home;
32
- });
33
- beforeEach(() => {
34
- closeDb();
35
- rmSync(home, { recursive: true, force: true });
36
- });
37
- after(() => {
38
- closeDb();
39
- rmSync(home, { recursive: true, force: true });
40
- delete process.env['CRTR_HOME'];
41
- });
42
- // --- buildWakeBearings: one per kind / cadence variant ----------------------
43
- test('node_birth one-shot: names a deferred birth + the armer, and says it does not recur', () => {
44
- const o = {
45
- kind: 'node_birth',
46
- ownerId: 'arm-1',
47
- ownerName: 'release-orch',
48
- armedAt: ARMED,
49
- recur: null,
50
- };
51
- const b = buildWakeBearings(o);
52
- assert.ok(b.startsWith('<crtr-wake>') && b.endsWith('</crtr-wake>'));
53
- assert.match(b, /BORN by a scheduled wake/);
54
- assert.match(b, /deferred birth/);
55
- // Armer named ROLE-explicitly so the newborn never reads the id as its own.
56
- assert.match(b, /armed by node arm-1 \("release-orch"\)/);
57
- assert.match(b, /only run, not a recurring job/);
58
- assert.match(b, /Your task follows\./);
59
- });
60
- test('node_birth cron: surfaces the cadence + frames it as one run of a standing job', () => {
61
- const o = {
62
- kind: 'node_birth',
63
- ownerId: 'arm-1',
64
- ownerName: 'nightly',
65
- armedAt: ARMED,
66
- recur: JSON.stringify({ cron: '0 9 * * *', tz: 'America/New_York' }),
67
- };
68
- const b = buildWakeBearings(o);
69
- assert.match(b, /recurring spawn-cron armed by node arm-1 \("nightly"\)/);
70
- // The cadence renders via the shared cadenceDisplay (matches `wake list`).
71
- assert.match(b, /firing cron `0 9 \* \* \*` \(America\/New_York\)/);
72
- assert.match(b, /one run of a standing job, not a one-off/);
73
- assert.match(b, /inherit nothing from prior runs but this task/);
74
- });
75
- test('node_birth interval cron: renders the every-N cadence', () => {
76
- const o = {
77
- kind: 'node_birth',
78
- ownerId: 'arm-1',
79
- ownerName: 'poller',
80
- armedAt: ARMED,
81
- recur: JSON.stringify({ every: '6h' }),
82
- };
83
- assert.match(buildWakeBearings(o), /firing every 6h/);
84
- });
85
- test('node_birth with a reaped armer: renders the bare id, no name, never crashes', () => {
86
- const o = {
87
- kind: 'node_birth',
88
- ownerId: 'gone-9',
89
- ownerName: undefined, // armer no longer exists → no resolved name
90
- armedAt: ARMED,
91
- recur: JSON.stringify({ every: '12h' }),
92
- };
93
- const b = buildWakeBearings(o);
94
- assert.match(b, /armed by node gone-9 \(now gone\)/); // bare id, flagged reaped
95
- assert.doesNotMatch(b, /\("/); // never an empty/dangling name
96
- });
97
- test('an ordinary fresh revive (no wakeReason) carries NO wake block', () => {
98
- const id = 'b2';
99
- const meta = createNode(node(id));
100
- const msg = buildReviveKickoff(meta, drainBearings(meta));
101
- assert.doesNotMatch(msg, /<crtr-wake>/);
102
- });