@north-light/crouter 0.3.173 → 0.3.175

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (674) hide show
  1. package/bin/runtime-selector.mjs +8 -1
  2. package/dist/api/__tests__/{client.test.js → serial/client.test.js} +2 -135
  3. package/dist/api/client.d.ts +12 -21
  4. package/dist/api/client.js +22 -31
  5. package/dist/api/dto/broker-ops.d.ts +158 -0
  6. package/dist/api/dto/broker-ops.js +6 -0
  7. package/dist/api/dto/crons.d.ts +6 -0
  8. package/dist/api/dto/human.d.ts +7 -1
  9. package/dist/api/dto/inbox.d.ts +1 -71
  10. package/dist/api/dto/inbox.js +1 -9
  11. package/dist/api/dto/nodes.d.ts +6 -7
  12. package/dist/api/dto/reviews.d.ts +1 -11
  13. package/dist/api/routes.d.ts +7 -4
  14. package/dist/api/routes.js +8 -5
  15. package/dist/build-root.js +3 -3
  16. package/dist/builtin-memory/04-base-worker.md +1 -4
  17. package/dist/builtin-memory/05-kinds/advisor/00-base.md +1 -5
  18. package/dist/builtin-memory/05-kinds/advisor/01-orchestrator.md +2 -7
  19. package/dist/builtin-memory/05-kinds/design/00-base.md +1 -6
  20. package/dist/builtin-memory/05-kinds/developer/00-base.md +1 -6
  21. package/dist/builtin-memory/05-kinds/explore/00-base.md +1 -4
  22. package/dist/builtin-memory/05-kinds/explore/01-orchestrator.md +1 -2
  23. package/dist/builtin-memory/05-kinds/general/00-base.md +1 -3
  24. package/dist/builtin-memory/05-kinds/plan/00-base.md +1 -6
  25. package/dist/builtin-memory/05-kinds/plan/reviewers/00-base.md +1 -2
  26. package/dist/builtin-memory/05-kinds/plan/reviewers/architecture-fit.md +1 -3
  27. package/dist/builtin-memory/05-kinds/plan/reviewers/code-smells.md +1 -3
  28. package/dist/builtin-memory/05-kinds/plan/reviewers/pattern-consistency.md +1 -3
  29. package/dist/builtin-memory/05-kinds/plan/reviewers/requirements-coverage.md +1 -3
  30. package/dist/builtin-memory/05-kinds/plan/reviewers/security.md +1 -4
  31. package/dist/builtin-memory/05-kinds/review/companion/00-base.md +2 -3
  32. package/dist/builtin-memory/05-kinds/spec/00-base.md +1 -2
  33. package/dist/builtin-memory/advisor/council.md +1 -6
  34. package/dist/builtin-memory/design.md +2 -7
  35. package/dist/builtin-memory/development.md +9 -14
  36. package/dist/builtin-memory/internal/marketplaces.md +2 -6
  37. package/dist/builtin-memory/internal/nodes-and-canvas.md +1 -1
  38. package/dist/builtin-memory/internal/plugins.md +2 -8
  39. package/dist/builtin-memory/internal/storage-tiers.md +1 -2
  40. package/dist/builtin-memory/testing.md +41 -0
  41. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/{provider-rotation.test.ts → serial/provider-rotation.test.ts} +27 -179
  42. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/claude-plugin-commands.ts +5 -15
  43. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/frontmatter-rules/index.ts +1 -28
  44. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/memory-slash-commands.ts +43 -88
  45. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +7 -1
  46. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +9 -1
  47. package/dist/cli.js +2 -2
  48. package/dist/clients/attach/__tests__/attach-remote-readonly.test.js +37 -131
  49. package/dist/clients/attach/__tests__/chat-view-snapshot-ordering.test.js +71 -152
  50. package/dist/clients/attach/__tests__/context-message.test.js +16 -174
  51. package/dist/clients/attach/__tests__/crtr-output.test.js +36 -2069
  52. package/dist/clients/attach/__tests__/diagram.test.js +2 -2
  53. package/dist/clients/attach/__tests__/edit-diff.test.js +0 -4
  54. package/dist/clients/attach/__tests__/file-review-focus.test.js +2 -1
  55. package/dist/clients/attach/__tests__/group-activity.test.js +40 -229
  56. package/dist/clients/attach/__tests__/oauth-dialog-lifecycle.test.js +26 -76
  57. package/dist/clients/attach/__tests__/prompt-preview.test.js +4 -70
  58. package/dist/clients/attach/__tests__/ref-autocomplete.test.js +11 -125
  59. package/dist/clients/attach/__tests__/titled-editor-preview.test.js +14 -205
  60. package/dist/clients/attach/command.d.ts +2 -1
  61. package/dist/clients/attach/command.js +81 -76
  62. package/dist/clients/attach/input/capabilities.d.ts +27 -0
  63. package/dist/clients/attach/input/capabilities.js +96 -0
  64. package/dist/clients/attach/input/controller.d.ts +20 -182
  65. package/dist/clients/attach/input/controller.js +128 -537
  66. package/dist/clients/attach/input/overlay-owner.d.ts +41 -0
  67. package/dist/clients/attach/input/overlay-owner.js +199 -0
  68. package/dist/clients/attach/overlays/file-review.d.ts +0 -4
  69. package/dist/clients/attach/overlays/file-review.js +13 -5
  70. package/dist/clients/attach/overlays/graph.js +2 -10
  71. package/dist/clients/attach/render/chat-view.d.ts +4 -3
  72. package/dist/clients/attach/render/chat-view.js +39 -33
  73. package/dist/clients/attach/render/group-activity.d.ts +1 -0
  74. package/dist/clients/attach/render/group-activity.js +20 -13
  75. package/dist/clients/attach/render/group-recap.js +12 -3
  76. package/dist/clients/attach/session/connection.js +9 -15
  77. package/dist/clients/attach/session/editor-inventory.d.ts +6 -5
  78. package/dist/clients/attach/session/editor-inventory.js +7 -8
  79. package/dist/clients/attach/session/file-links.d.ts +13 -0
  80. package/dist/clients/attach/session/file-links.js +107 -0
  81. package/dist/clients/attach/session/frame.d.ts +3 -0
  82. package/dist/clients/attach/session/frame.js +10 -1
  83. package/dist/clients/attach/session/frames.js +2 -3
  84. package/dist/clients/attach/session/input-wiring.d.ts +4 -1
  85. package/dist/clients/attach/session/input-wiring.js +15 -14
  86. package/dist/clients/attach/session/mouse.d.ts +6 -1
  87. package/dist/clients/attach/session/mouse.js +8 -5
  88. package/dist/clients/attach/session/profile-files.js +18 -12
  89. package/dist/clients/attach/session/reconnect.js +1 -1
  90. package/dist/clients/attach/session/state-sync.js +1 -2
  91. package/dist/clients/attach/session/surface-host.d.ts +3 -2
  92. package/dist/clients/attach/session/surface-host.js +4 -4
  93. package/dist/clients/attach/slash/dispatch.d.ts +8 -31
  94. package/dist/clients/attach/slash/dispatch.js +34 -81
  95. package/dist/clients/attach/viewer.js +820 -860
  96. package/dist/clients/conversation/projection.d.ts +79 -0
  97. package/dist/clients/conversation/projection.js +341 -0
  98. package/dist/clients/inbox/__tests__/serial/inbox-controller.test.js +159 -0
  99. package/dist/clients/inbox/__tests__/serial/mount-panel.test.js +151 -0
  100. package/dist/clients/inbox/controller.d.ts +0 -4
  101. package/dist/clients/inbox/controller.js +0 -2
  102. package/dist/clients/inbox/review/__tests__/review-core.test.js +4 -293
  103. package/dist/clients/inbox/review/__tests__/teardown-notice.test.js +100 -0
  104. package/dist/clients/inbox/review/comments-client.d.ts +3 -2
  105. package/dist/clients/inbox/review/comments-client.js +12 -12
  106. package/dist/clients/inbox/review/companion-pane.d.ts +30 -0
  107. package/dist/clients/inbox/review/companion-pane.js +86 -0
  108. package/dist/clients/inbox/review/document-surface.d.ts +182 -0
  109. package/dist/clients/inbox/review/{document-region.js → document-surface.js} +252 -48
  110. package/dist/clients/inbox/review/frame.js +5 -4
  111. package/dist/clients/inbox/review/launch.d.ts +8 -8
  112. package/dist/clients/inbox/review/launch.js +52 -92
  113. package/dist/clients/inbox/review/nvim.d.ts +2 -0
  114. package/dist/clients/inbox/review/nvim.js +14 -12
  115. package/dist/clients/inbox/review/review-client.d.ts +12 -8
  116. package/dist/clients/inbox/review/review-client.js +46 -35
  117. package/dist/clients/inbox/review-adapter.d.ts +3 -10
  118. package/dist/clients/inbox/review-adapter.js +27 -19
  119. package/dist/clients/inbox/surface.d.ts +0 -4
  120. package/dist/clients/inbox/surface.js +0 -2
  121. package/dist/clients/surfaces/host.d.ts +11 -3
  122. package/dist/commands/__tests__/api-client-cold-start-diagnostic.test.js +7 -34
  123. package/dist/commands/__tests__/human.test.js +11 -322
  124. package/dist/commands/api-client.d.ts +5 -5
  125. package/dist/commands/api-client.js +6 -85
  126. package/dist/commands/canvas-browse.js +3 -29
  127. package/dist/commands/canvas-config.js +1 -1
  128. package/dist/commands/canvas-use.js +3 -3
  129. package/dist/commands/canvas.js +1 -1
  130. package/dist/commands/cron.js +5 -1
  131. package/dist/commands/human/queue.d.ts +0 -4
  132. package/dist/commands/human/queue.js +7 -40
  133. package/dist/commands/memory/list.d.ts +14 -0
  134. package/dist/commands/memory/list.js +35 -31
  135. package/dist/commands/memory/read.d.ts +7 -0
  136. package/dist/commands/memory/read.js +14 -8
  137. package/dist/commands/memory/write.js +13 -12
  138. package/dist/commands/node/bash.d.ts +1 -0
  139. package/dist/commands/node/bash.js +198 -0
  140. package/dist/commands/node/create.d.ts +23 -0
  141. package/dist/commands/node/create.js +207 -0
  142. package/dist/commands/node/inspect.d.ts +2 -0
  143. package/dist/commands/node/inspect.js +302 -0
  144. package/dist/commands/node/lifecycle.d.ts +4 -0
  145. package/dist/commands/node/lifecycle.js +415 -0
  146. package/dist/commands/node/message.d.ts +1 -0
  147. package/dist/commands/node/message.js +164 -0
  148. package/dist/commands/node/pyramid.d.ts +2 -0
  149. package/dist/commands/node/pyramid.js +79 -0
  150. package/dist/commands/node/subscription.d.ts +1 -0
  151. package/dist/commands/node/subscription.js +82 -0
  152. package/dist/commands/node/wait.d.ts +1 -0
  153. package/dist/commands/node/wait.js +159 -0
  154. package/dist/commands/node-lifecycle-revive.js +10 -57
  155. package/dist/commands/node.d.ts +0 -42
  156. package/dist/commands/node.js +11 -2065
  157. package/dist/commands/search.js +1 -1
  158. package/dist/commands/surface/node/cycle.d.ts +1 -0
  159. package/dist/commands/surface/node/cycle.js +83 -0
  160. package/dist/commands/surface/node/focus.d.ts +1 -0
  161. package/dist/commands/surface/node/focus.js +67 -0
  162. package/dist/commands/surface/node/id.d.ts +1 -0
  163. package/dist/commands/surface/node/id.js +38 -0
  164. package/dist/commands/surface/node/pin.d.ts +1 -0
  165. package/dist/commands/surface/node/pin.js +42 -0
  166. package/dist/commands/surface/node/placement.d.ts +46 -0
  167. package/dist/commands/surface/node/placement.js +124 -0
  168. package/dist/commands/surface-node.js +4 -1
  169. package/dist/commands/surface-reload.js +1 -2
  170. package/dist/commands/surface-tmux-spread.js +1 -1
  171. package/dist/commands/surface.js +5 -20
  172. package/dist/commands/sys/__tests__/setup-core.test.js +18 -271
  173. package/dist/commands/sys/config.js +6 -6
  174. package/dist/commands/sys/logs.js +1 -1
  175. package/dist/commands/sys/panels/broker-limits-panel.d.ts +17 -0
  176. package/dist/commands/sys/panels/broker-limits-panel.js +104 -0
  177. package/dist/commands/sys/panels/dependencies-panel.d.ts +14 -0
  178. package/dist/commands/sys/panels/dependencies-panel.js +80 -0
  179. package/dist/commands/sys/panels/keybindings-panel.d.ts +56 -0
  180. package/dist/commands/sys/panels/keybindings-panel.js +703 -0
  181. package/dist/commands/sys/panels/keys-panel.d.ts +16 -0
  182. package/dist/commands/sys/panels/keys-panel.js +60 -0
  183. package/dist/commands/sys/panels/models-panel.d.ts +77 -0
  184. package/dist/commands/sys/panels/models-panel.js +647 -0
  185. package/dist/commands/sys/panels/panel.d.ts +45 -0
  186. package/dist/commands/sys/panels/panel.js +137 -0
  187. package/dist/commands/sys/panels/plugins-panel.d.ts +16 -0
  188. package/dist/commands/sys/panels/plugins-panel.js +80 -0
  189. package/dist/commands/sys/panels/prefs-panel.d.ts +21 -0
  190. package/dist/commands/sys/panels/prefs-panel.js +85 -0
  191. package/dist/commands/sys/panels/provider-panel.d.ts +62 -0
  192. package/dist/commands/sys/panels/provider-panel.js +538 -0
  193. package/dist/commands/sys/settings-shell.d.ts +55 -0
  194. package/dist/commands/sys/settings-shell.js +400 -0
  195. package/dist/commands/sys/settings.d.ts +2 -0
  196. package/dist/commands/sys/settings.js +31 -0
  197. package/dist/commands/sys/setup-core.d.ts +3 -33
  198. package/dist/commands/sys/setup-core.js +27 -78
  199. package/dist/commands/sys/setup-settings-runner.d.ts +24 -0
  200. package/dist/commands/sys/setup-settings-runner.js +63 -0
  201. package/dist/commands/sys/setup-wizard.d.ts +26 -125
  202. package/dist/commands/sys/setup-wizard.js +209 -2473
  203. package/dist/commands/sys/setup.js +5 -7
  204. package/dist/commands/sys.js +3 -2
  205. package/dist/core/__tests__/broker-extension-canvas-db-boundary.test.js +50 -0
  206. package/dist/core/__tests__/broker-launch-candidates.test.js +20 -9
  207. package/dist/core/__tests__/broker-preflight.test.js +1 -1
  208. package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +108 -27
  209. package/dist/core/__tests__/canvas-inbox-watcher.test.js +14 -0
  210. package/dist/core/__tests__/canvas.test.js +2 -36
  211. package/dist/core/__tests__/close.test.js +14 -3
  212. package/dist/core/__tests__/context-intro.test.js +32 -143
  213. package/dist/core/__tests__/cron-broker-capacity.test.js +22 -3
  214. package/dist/core/__tests__/daemon-boot.test.js +2 -20
  215. package/dist/core/__tests__/daemon-wedge.test.js +1 -1
  216. package/dist/core/__tests__/dead-node-policy-table.test.js +1 -18
  217. package/dist/core/__tests__/fixtures/fake-engine.d.ts +1 -1
  218. package/dist/core/__tests__/fixtures/fake-engine.js +2 -2
  219. package/dist/core/__tests__/fixtures/fake-pi-host.js +2 -2
  220. package/dist/core/__tests__/focuses.test.js +4 -98
  221. package/dist/core/__tests__/helpers/broker-clients.d.ts +0 -3
  222. package/dist/core/__tests__/helpers/broker-clients.js +0 -14
  223. package/dist/core/__tests__/helpers/harness.d.ts +0 -8
  224. package/dist/core/__tests__/helpers/harness.js +7 -87
  225. package/dist/core/__tests__/helpers/viewer-panes.js +1 -1
  226. package/dist/core/__tests__/inline-memory-refs.test.js +5 -134
  227. package/dist/core/__tests__/kickoff.test.js +1 -1
  228. package/dist/core/__tests__/memory-resolver-precedence.test.js +29 -1
  229. package/dist/core/__tests__/migration.test.js +35 -48
  230. package/dist/core/__tests__/on-read-dedup-resume.test.js +22 -12
  231. package/dist/core/__tests__/passive-subscription.test.js +26 -49
  232. package/dist/core/__tests__/preview-registry-sync.test.js +1 -2
  233. package/dist/core/__tests__/prune.test.js +94 -1
  234. package/dist/core/__tests__/review-model-floor.test.js +0 -32
  235. package/dist/core/__tests__/seam/broker-attach-multiclient.test.js +255 -0
  236. package/dist/core/__tests__/{full → seam}/broker-attach-stream.test.js +39 -7
  237. package/dist/core/__tests__/{full → seam}/broker-crash-teardown.test.js +30 -29
  238. package/dist/core/__tests__/{full → seam}/broker-pane-resolution.test.js +54 -5
  239. package/dist/core/__tests__/{full → seam}/broker-provider-retry.test.js +134 -82
  240. package/dist/core/__tests__/{full → seam}/broker-whip-interrupt.test.js +15 -4
  241. package/dist/core/__tests__/{full/idle-release-settlement.test.js → seam/dormancy-release.test.js} +69 -17
  242. package/dist/core/__tests__/{full/yield-message-transaction.test.js → seam/yield-refresh-transaction.test.js} +31 -9
  243. package/dist/core/__tests__/secrets.test.js +1 -7
  244. package/dist/core/__tests__/{broker-fork-seam.test.js → serial/broker-fork-seam.test.js} +58 -7
  245. package/dist/core/__tests__/{broker-sdk-wiring.test.js → serial/broker-sdk-wiring.test.js} +18 -162
  246. package/dist/core/__tests__/{broker-snapshot-history.test.js → serial/broker-snapshot-history.test.js} +9 -9
  247. package/dist/core/__tests__/{command-plugins.test.js → serial/command-plugins.test.js} +105 -15
  248. package/dist/core/__tests__/{deferred-no-wake.test.js → serial/deferred-no-wake.test.js} +23 -20
  249. package/dist/core/__tests__/{flagship-lifecycle.test.js → serial/flagship-lifecycle.test.js} +7 -7
  250. package/dist/core/__tests__/{host-teardown-process-group.test.js → serial/host-teardown-process-group.test.js} +6 -6
  251. package/dist/core/__tests__/{human-deliver-e2e.test.js → serial/human-deliver-e2e.test.js} +12 -12
  252. package/dist/core/__tests__/{live-mutation.test.js → serial/live-mutation.test.js} +5 -5
  253. package/dist/core/__tests__/{refresh-stall-recycle.test.js → serial/refresh-stall-recycle.test.js} +5 -14
  254. package/dist/core/__tests__/{revive.test.js → serial/revive.test.js} +15 -100
  255. package/dist/core/__tests__/{spawn-root.test.js → serial/spawn-root.test.js} +32 -15
  256. package/dist/core/__tests__/serial/subscription-delivery.test.js +126 -0
  257. package/dist/core/__tests__/serial/tmux-surface.test.js +256 -0
  258. package/dist/core/__tests__/{worktree.test.js → serial/worktree.test.js} +15 -15
  259. package/dist/core/__tests__/session-model.test.js +0 -18
  260. package/dist/core/__tests__/spawn-worktree-id-conflict.test.js +9 -0
  261. package/dist/core/__tests__/watchdog-abort-arms-retry.test.js +50 -0
  262. package/dist/core/broker-client/__tests__/transport-relay.test.js +15 -16
  263. package/dist/core/broker-client/__tests__/transport-socket.test.js +28 -0
  264. package/dist/core/broker-client/client.d.ts +2 -2
  265. package/dist/core/broker-client/client.js +4 -7
  266. package/dist/core/broker-client/transport-relay.d.ts +13 -19
  267. package/dist/core/broker-client/transport-relay.js +19 -34
  268. package/dist/core/broker-client/transport-socket.d.ts +2 -2
  269. package/dist/core/broker-client/transport-socket.js +9 -2
  270. package/dist/core/broker-client/transport.d.ts +7 -3
  271. package/dist/core/broker-client/transport.js +4 -4
  272. package/dist/core/canvas/__tests__/attention.test.js +1 -18
  273. package/dist/core/canvas/__tests__/remote-canvas-source.test.js +7 -64
  274. package/dist/core/canvas/__tests__/remote-transport.test.js +2 -3
  275. package/dist/core/canvas/__tests__/render-remote.test.js +7 -52
  276. package/dist/core/canvas/browse/app.d.ts +2 -17
  277. package/dist/core/canvas/browse/app.js +16 -88
  278. package/dist/core/canvas/browse/model.d.ts +0 -4
  279. package/dist/core/canvas/browse/model.js +1 -12
  280. package/dist/core/canvas/browse/render.js +6 -3
  281. package/dist/core/canvas/crons.d.ts +8 -5
  282. package/dist/core/canvas/crons.js +7 -6
  283. package/dist/core/canvas/extensions.d.ts +7 -3
  284. package/dist/core/canvas/extensions.js +16 -4
  285. package/dist/core/canvas/nav-model.d.ts +0 -4
  286. package/dist/core/canvas/nav-model.js +2 -14
  287. package/dist/core/canvas/node-order.d.ts +3 -0
  288. package/dist/core/canvas/node-order.js +12 -0
  289. package/dist/core/canvas/remote-canvas-source.d.ts +3 -6
  290. package/dist/core/canvas/remote-canvas-source.js +8 -15
  291. package/dist/core/command.js +11 -4
  292. package/dist/core/config.js +3 -1
  293. package/dist/core/events/envelope.js +1 -1
  294. package/dist/core/events/read.js +7 -21
  295. package/dist/core/events/source.d.ts +0 -2
  296. package/dist/core/events/source.js +0 -16
  297. package/dist/core/events/types.d.ts +1 -1
  298. package/dist/core/fault-classifier.d.ts +1 -1
  299. package/dist/core/feed/passive.d.ts +0 -11
  300. package/dist/core/feed/passive.js +1 -62
  301. package/dist/core/human/__tests__/{inbox-core.test.js → serial/inbox-core.test.js} +6 -6
  302. package/dist/core/keybindings/__tests__/resolve.test.js +1 -96
  303. package/dist/core/keybindings/background-bash.js +3 -4
  304. package/dist/core/keybindings/catalog.js +1 -1
  305. package/dist/core/memory/inline-ref-grammar.js +3 -3
  306. package/dist/core/memory-resolver.d.ts +11 -25
  307. package/dist/core/memory-resolver.js +51 -33
  308. package/dist/core/model-routes.d.ts +15 -0
  309. package/dist/core/model-routes.js +12 -0
  310. package/dist/core/pool-credential-store.js +1 -1
  311. package/dist/core/preview-registry.js +8 -9
  312. package/dist/core/profiles/__tests__/root-profile.test.js +4 -14
  313. package/dist/core/review/realize.d.ts +0 -13
  314. package/dist/core/review/realize.js +0 -40
  315. package/dist/core/review/types.d.ts +1 -1
  316. package/dist/core/runtime/__tests__/engine-route.test.js +2 -2
  317. package/dist/core/runtime/bearings.js +1 -11
  318. package/dist/core/runtime/broker/client-registry.d.ts +33 -0
  319. package/dist/core/runtime/broker/client-registry.js +164 -0
  320. package/dist/core/runtime/broker/daemon-ops.d.ts +19 -0
  321. package/dist/core/runtime/broker/daemon-ops.js +49 -0
  322. package/dist/core/runtime/broker/event-projection.d.ts +42 -0
  323. package/dist/core/runtime/broker/event-projection.js +178 -0
  324. package/dist/core/runtime/broker/fault-retry.d.ts +39 -0
  325. package/dist/core/runtime/broker/fault-retry.js +277 -0
  326. package/dist/core/runtime/broker/frame-dispatch.d.ts +238 -0
  327. package/dist/core/runtime/broker/frame-dispatch.js +1537 -0
  328. package/dist/core/runtime/broker/inbox.d.ts +22 -0
  329. package/dist/core/runtime/broker/inbox.js +167 -0
  330. package/dist/core/runtime/broker/passive.d.ts +16 -0
  331. package/dist/core/runtime/broker/passive.js +44 -0
  332. package/dist/core/runtime/broker/read-ops.d.ts +23 -0
  333. package/dist/core/runtime/broker/read-ops.js +150 -0
  334. package/dist/core/runtime/broker/rebind.d.ts +74 -0
  335. package/dist/core/runtime/broker/rebind.js +211 -0
  336. package/dist/core/runtime/broker/tool-groups.d.ts +39 -0
  337. package/dist/core/runtime/broker/tool-groups.js +244 -0
  338. package/dist/core/runtime/broker-extension-render.d.ts +11 -0
  339. package/dist/core/runtime/broker-extension-render.js +181 -0
  340. package/dist/core/runtime/broker-persona-guidance.d.ts +13 -0
  341. package/dist/core/runtime/broker-persona-guidance.js +58 -0
  342. package/dist/core/runtime/broker-protocol.d.ts +1 -1
  343. package/dist/core/runtime/broker-protocol.js +1 -1
  344. package/dist/core/runtime/broker.d.ts +5 -196
  345. package/dist/core/runtime/broker.js +276 -3059
  346. package/dist/core/runtime/canvas-extensions.js +11 -2
  347. package/dist/core/runtime/fault.js +1 -1
  348. package/dist/core/runtime/model-selection.d.ts +9 -0
  349. package/dist/core/runtime/model-selection.js +12 -0
  350. package/dist/core/runtime/model-swap.d.ts +3 -3
  351. package/dist/core/runtime/model-swap.js +33 -25
  352. package/dist/core/runtime/placement-tmux.d.ts +3 -14
  353. package/dist/core/runtime/placement-tmux.js +11 -80
  354. package/dist/core/runtime/placement.d.ts +4 -2
  355. package/dist/core/runtime/placement.js +7 -12
  356. package/dist/core/runtime/promote.d.ts +14 -1
  357. package/dist/core/runtime/promote.js +1 -1
  358. package/dist/core/runtime/reset.d.ts +1 -1
  359. package/dist/core/runtime/roadmap.js +1 -1
  360. package/dist/core/runtime/spawn.d.ts +8 -0
  361. package/dist/core/runtime/spawn.js +36 -6
  362. package/dist/core/runtime/stop-guard.d.ts +4 -3
  363. package/dist/core/runtime/stop-guard.js +36 -18
  364. package/dist/core/runtime/stop-signals.d.ts +4 -1
  365. package/dist/core/runtime/stream-watchdog.js +4 -5
  366. package/dist/core/runtime/structured-output.d.ts +15 -2
  367. package/dist/core/runtime/structured-output.js +35 -12
  368. package/dist/core/runtime/tmux-bindings.d.ts +25 -0
  369. package/dist/core/runtime/tmux-bindings.js +682 -0
  370. package/dist/core/runtime/tmux-chrome.d.ts +2 -1
  371. package/dist/core/runtime/tmux-chrome.js +3 -2
  372. package/dist/core/runtime/{tmux.d.ts → tmux-driver.d.ts} +18 -26
  373. package/dist/core/runtime/tmux-driver.js +598 -0
  374. package/dist/core/runtime/view-socket.d.ts +14 -0
  375. package/dist/core/runtime/view-socket.js +83 -0
  376. package/dist/core/session-model/session-state.d.ts +1 -2
  377. package/dist/core/session-model/session-state.js +5 -8
  378. package/dist/core/spawn.d.ts +1 -1
  379. package/dist/core/spawn.js +2 -2
  380. package/dist/core/substrate/gate.d.ts +1 -1
  381. package/dist/core/substrate/on-read-pure.d.ts +7 -0
  382. package/dist/core/substrate/on-read-pure.js +272 -0
  383. package/dist/core/termrender/termrender.js +32 -2
  384. package/dist/core/user-settings.d.ts +23 -1
  385. package/dist/core/user-settings.js +18 -1
  386. package/dist/daemon/api/__tests__/node-model-validation.test.js +134 -0
  387. package/dist/daemon/api/__tests__/review-terminal-conflict.test.js +98 -0
  388. package/dist/daemon/api/__tests__/{full → seam}/api-server.test.js +6 -48
  389. package/dist/daemon/api/__tests__/{full → seam}/b10-attach-modelauth.test.js +17 -44
  390. package/dist/daemon/api/__tests__/{full/push-parity.test.js → seam/leaf-api-parity.test.js} +61 -42
  391. package/dist/daemon/api/bridge.js +40 -81
  392. package/dist/daemon/api/handlers/broker-ops.d.ts +2 -0
  393. package/dist/daemon/api/handlers/broker-ops.js +383 -0
  394. package/dist/daemon/api/handlers/crons.js +9 -4
  395. package/dist/daemon/api/handlers/files.js +6 -7
  396. package/dist/daemon/api/handlers/inbox.js +2 -340
  397. package/dist/daemon/api/handlers/nodes.d.ts +10 -1
  398. package/dist/daemon/api/handlers/nodes.js +74 -39
  399. package/dist/daemon/api/handlers/review-comments.js +5 -1
  400. package/dist/daemon/api/handlers/reviews.js +0 -19
  401. package/dist/daemon/api/map.js +25 -4
  402. package/dist/daemon/api/router.js +2 -3
  403. package/dist/daemon/api/server.js +5 -7
  404. package/dist/daemon/cron-run.d.ts +4 -0
  405. package/dist/daemon/cron-run.js +30 -13
  406. package/dist/daemon/crtrd.d.ts +3 -58
  407. package/dist/daemon/crtrd.js +28 -1244
  408. package/dist/daemon/manage.js +0 -1
  409. package/dist/daemon/reconcilers/broker-supervision.d.ts +50 -0
  410. package/dist/daemon/reconcilers/broker-supervision.js +549 -0
  411. package/dist/daemon/reconcilers/cron-lane.d.ts +10 -0
  412. package/dist/daemon/reconcilers/cron-lane.js +32 -0
  413. package/dist/daemon/reconcilers/dormant-inbox.d.ts +18 -0
  414. package/dist/daemon/reconcilers/dormant-inbox.js +143 -0
  415. package/dist/daemon/reconcilers/storage-maintenance.d.ts +22 -0
  416. package/dist/daemon/reconcilers/storage-maintenance.js +213 -0
  417. package/dist/daemon/review/finish.js +2 -5
  418. package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +34 -53
  419. package/dist/pi-extensions/__tests__/canvas-recap.test.js +16 -113
  420. package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +72 -99
  421. package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.js +29 -12
  422. package/dist/pi-extensions/broker-local.d.ts +20 -0
  423. package/dist/pi-extensions/broker-local.js +89 -0
  424. package/dist/pi-extensions/canvas-context-intro.d.ts +3 -3
  425. package/dist/pi-extensions/canvas-context-intro.js +22 -11
  426. package/dist/pi-extensions/canvas-doc-substrate.js +17 -34
  427. package/dist/pi-extensions/canvas-goal-capture.js +7 -12
  428. package/dist/pi-extensions/canvas-inbox-watcher.js +124 -139
  429. package/dist/pi-extensions/canvas-passive-context.d.ts +3 -3
  430. package/dist/pi-extensions/canvas-passive-context.js +22 -18
  431. package/dist/pi-extensions/canvas-recap.d.ts +2 -2
  432. package/dist/pi-extensions/canvas-recap.js +48 -21
  433. package/dist/pi-extensions/canvas-review-boundary.js +10 -4
  434. package/dist/pi-extensions/canvas-stophook.d.ts +0 -5
  435. package/dist/pi-extensions/canvas-stophook.js +149 -431
  436. package/dist/pi-extensions/canvas-structured-output.js +52 -30
  437. package/dist/pi-extensions/envelope-merge.d.ts +13 -0
  438. package/dist/pi-extensions/envelope-merge.js +29 -0
  439. package/dist/shared/working-activity.d.ts +3 -2
  440. package/dist/shared/working-activity.js +3 -2
  441. package/dist/types.d.ts +6 -5
  442. package/dist/types.js +2 -2
  443. package/docs/compat/hearth-crtr-v1.md +4 -12
  444. package/docs/compat/hearth-crtr-v2.md +3 -11
  445. package/docs/compat/hearth-crtr-v3.md +4 -12
  446. package/docs/compat/hearth-crtr-v4.md +3 -11
  447. package/docs/compat/hearth-crtr-v5.md +3 -11
  448. package/docs/public-api.md +3 -7
  449. package/package.json +7 -49
  450. package/runtime.lock.json +2766 -14533
  451. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/claude-plugin-commands.test.ts +0 -49
  452. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/memory-slash-commands.test.ts +0 -194
  453. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/statusline.test.ts +0 -68
  454. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/frontmatter-rules/test.ts +0 -119
  455. package/dist/clients/attach/__tests__/attach-chrome-remote.test.js +0 -439
  456. package/dist/clients/attach/__tests__/attach-keybindings.test.js +0 -170
  457. package/dist/clients/attach/__tests__/crtr-output-coverage.test.js +0 -57
  458. package/dist/clients/attach/__tests__/editor-frame-title.test.js +0 -19
  459. package/dist/clients/attach/__tests__/input-controller-extension-command.test.js +0 -32
  460. package/dist/clients/attach/__tests__/markdown-headings.test.js +0 -35
  461. package/dist/clients/attach/__tests__/session-identity-refresh.test.js +0 -32
  462. package/dist/clients/conversation/conversation.d.ts +0 -65
  463. package/dist/clients/conversation/conversation.js +0 -318
  464. package/dist/clients/conversation/frames.d.ts +0 -30
  465. package/dist/clients/conversation/frames.js +0 -52
  466. package/dist/clients/conversation/region.d.ts +0 -51
  467. package/dist/clients/conversation/region.js +0 -265
  468. package/dist/clients/inbox/__tests__/inbox-controller.test.js +0 -247
  469. package/dist/clients/inbox/__tests__/mount-panel.test.js +0 -776
  470. package/dist/clients/inbox/review/__tests__/remap.test.js +0 -196
  471. package/dist/clients/inbox/review/columns.d.ts +0 -22
  472. package/dist/clients/inbox/review/columns.js +0 -40
  473. package/dist/clients/inbox/review/composition.d.ts +0 -60
  474. package/dist/clients/inbox/review/composition.js +0 -278
  475. package/dist/clients/inbox/review/document-region.d.ts +0 -120
  476. package/dist/clients/surfaces/region.d.ts +0 -16
  477. package/dist/clients/web/__tests__/push-engine.test.js +0 -158
  478. package/dist/clients/web/__tests__/push-registry.test.d.ts +0 -1
  479. package/dist/clients/web/__tests__/push-registry.test.js +0 -177
  480. package/dist/clients/web/dev-server.d.ts +0 -7
  481. package/dist/clients/web/dev-server.js +0 -46
  482. package/dist/clients/web/events.d.ts +0 -19
  483. package/dist/clients/web/events.js +0 -163
  484. package/dist/clients/web/push-engine.d.ts +0 -44
  485. package/dist/clients/web/push-engine.js +0 -125
  486. package/dist/clients/web/push-registry.d.ts +0 -85
  487. package/dist/clients/web/push-registry.js +0 -373
  488. package/dist/clients/web/server.d.ts +0 -19
  489. package/dist/clients/web/server.js +0 -661
  490. package/dist/clients/web/web-client/shared/protocol.d.ts +0 -214
  491. package/dist/clients/web/web-client/shared/protocol.js +0 -8
  492. package/dist/clients/web/web-cmd.d.ts +0 -2
  493. package/dist/clients/web/web-cmd.js +0 -141
  494. package/dist/commands/__tests__/api-canvas-source.test.d.ts +0 -1
  495. package/dist/commands/__tests__/api-canvas-source.test.js +0 -37
  496. package/dist/commands/__tests__/canvas-config.test.d.ts +0 -1
  497. package/dist/commands/__tests__/canvas-config.test.js +0 -107
  498. package/dist/commands/__tests__/node-no-kickoff-flag.test.d.ts +0 -1
  499. package/dist/commands/__tests__/node-no-kickoff-flag.test.js +0 -73
  500. package/dist/commands/__tests__/node-worktree-flag.test.d.ts +0 -1
  501. package/dist/commands/__tests__/node-worktree-flag.test.js +0 -49
  502. package/dist/commands/__tests__/search-contents.test.d.ts +0 -1
  503. package/dist/commands/__tests__/search-contents.test.js +0 -52
  504. package/dist/commands/memory/__tests__/lint.test.d.ts +0 -1
  505. package/dist/commands/memory/__tests__/lint.test.js +0 -15
  506. package/dist/commands/sys/__tests__/config-broker-thresholds.test.d.ts +0 -1
  507. package/dist/commands/sys/__tests__/config-broker-thresholds.test.js +0 -95
  508. package/dist/commands/sys/__tests__/config-keybindings.test.d.ts +0 -1
  509. package/dist/commands/sys/__tests__/config-keybindings.test.js +0 -55
  510. package/dist/commands/sys/__tests__/helpers/setup-runtime.d.ts +0 -5
  511. package/dist/commands/sys/__tests__/helpers/setup-runtime.js +0 -19
  512. package/dist/commands/sys/__tests__/setup-front-door.test.d.ts +0 -1
  513. package/dist/commands/sys/__tests__/setup-front-door.test.js +0 -102
  514. package/dist/commands/sys/__tests__/setup-models.test.d.ts +0 -1
  515. package/dist/commands/sys/__tests__/setup-models.test.js +0 -205
  516. package/dist/commands/sys/__tests__/setup-providers-viewport.test.d.ts +0 -1
  517. package/dist/commands/sys/__tests__/setup-providers-viewport.test.js +0 -155
  518. package/dist/commands/sys/__tests__/sync-deps.test.d.ts +0 -1
  519. package/dist/commands/sys/__tests__/sync-deps.test.js +0 -179
  520. package/dist/commands/sys/__tests__/sync-import.test.d.ts +0 -1
  521. package/dist/commands/sys/__tests__/sync-import.test.js +0 -315
  522. package/dist/core/__tests__/base-worker-prompt.test.d.ts +0 -1
  523. package/dist/core/__tests__/base-worker-prompt.test.js +0 -57
  524. package/dist/core/__tests__/command-plugins-surfaces.test.d.ts +0 -1
  525. package/dist/core/__tests__/command-plugins-surfaces.test.js +0 -359
  526. package/dist/core/__tests__/connection-reconnect-resume.test.d.ts +0 -1
  527. package/dist/core/__tests__/connection-reconnect-resume.test.js +0 -36
  528. package/dist/core/__tests__/finalization-migration.test.d.ts +0 -1
  529. package/dist/core/__tests__/finalization-migration.test.js +0 -38
  530. package/dist/core/__tests__/fixtures/extra-extension.d.ts +0 -1
  531. package/dist/core/__tests__/fixtures/extra-extension.js +0 -3
  532. package/dist/core/__tests__/fixtures/spawn-proof-target.test.d.ts +0 -1
  533. package/dist/core/__tests__/fixtures/spawn-proof-target.test.js +0 -15
  534. package/dist/core/__tests__/fork.test.d.ts +0 -1
  535. package/dist/core/__tests__/fork.test.js +0 -108
  536. package/dist/core/__tests__/full/broker-attach-limits.test.d.ts +0 -1
  537. package/dist/core/__tests__/full/broker-attach-limits.test.js +0 -147
  538. package/dist/core/__tests__/full/broker-deliver-ack.test.d.ts +0 -1
  539. package/dist/core/__tests__/full/broker-deliver-ack.test.js +0 -73
  540. package/dist/core/__tests__/full/broker-dialogs.test.d.ts +0 -1
  541. package/dist/core/__tests__/full/broker-dialogs.test.js +0 -180
  542. package/dist/core/__tests__/full/broker-display-snapshot.test.d.ts +0 -1
  543. package/dist/core/__tests__/full/broker-display-snapshot.test.js +0 -75
  544. package/dist/core/__tests__/full/broker-dormant-wake.test.d.ts +0 -1
  545. package/dist/core/__tests__/full/broker-dormant-wake.test.js +0 -130
  546. package/dist/core/__tests__/full/broker-model-changed-broadcast.test.d.ts +0 -1
  547. package/dist/core/__tests__/full/broker-model-changed-broadcast.test.js +0 -57
  548. package/dist/core/__tests__/full/broker-navigate-tree-rewelcome.test.d.ts +0 -1
  549. package/dist/core/__tests__/full/broker-navigate-tree-rewelcome.test.js +0 -80
  550. package/dist/core/__tests__/full/cascade-close.test.d.ts +0 -1
  551. package/dist/core/__tests__/full/cascade-close.test.js +0 -240
  552. package/dist/core/__tests__/full/detach-focus.test.d.ts +0 -1
  553. package/dist/core/__tests__/full/detach-focus.test.js +0 -126
  554. package/dist/core/__tests__/full/idle-release-settlement.test.d.ts +0 -1
  555. package/dist/core/__tests__/full/issue-146-yield-spawn-focus.test.d.ts +0 -1
  556. package/dist/core/__tests__/full/issue-146-yield-spawn-focus.test.js +0 -107
  557. package/dist/core/__tests__/full/park-clock-release.test.d.ts +0 -1
  558. package/dist/core/__tests__/full/park-clock-release.test.js +0 -56
  559. package/dist/core/__tests__/full/yield-message-transaction.test.d.ts +0 -1
  560. package/dist/core/__tests__/memory-index-render.test.d.ts +0 -1
  561. package/dist/core/__tests__/memory-index-render.test.js +0 -60
  562. package/dist/core/__tests__/model-routes.test.d.ts +0 -1
  563. package/dist/core/__tests__/model-routes.test.js +0 -41
  564. package/dist/core/__tests__/on-read-identity.test.d.ts +0 -1
  565. package/dist/core/__tests__/on-read-identity.test.js +0 -61
  566. package/dist/core/__tests__/phase4-review-migration.test.d.ts +0 -1
  567. package/dist/core/__tests__/phase4-review-migration.test.js +0 -100
  568. package/dist/core/__tests__/prune-to-limit.test.d.ts +0 -1
  569. package/dist/core/__tests__/prune-to-limit.test.js +0 -126
  570. package/dist/core/__tests__/reset.test.d.ts +0 -1
  571. package/dist/core/__tests__/reset.test.js +0 -69
  572. package/dist/core/__tests__/spawn-no-kickoff.test.d.ts +0 -1
  573. package/dist/core/__tests__/spawn-no-kickoff.test.js +0 -115
  574. package/dist/core/__tests__/steer-note.test.d.ts +0 -1
  575. package/dist/core/__tests__/steer-note.test.js +0 -41
  576. package/dist/core/__tests__/subcommand-tier.test.d.ts +0 -1
  577. package/dist/core/__tests__/subcommand-tier.test.js +0 -99
  578. package/dist/core/__tests__/subscription-delivery.test.js +0 -211
  579. package/dist/core/__tests__/test-runner-cheap-sharding.test.d.ts +0 -1
  580. package/dist/core/__tests__/test-runner-cheap-sharding.test.js +0 -97
  581. package/dist/core/__tests__/tmux-surface.test.js +0 -484
  582. package/dist/core/__tests__/wake-bearings.test.d.ts +0 -1
  583. package/dist/core/__tests__/wake-bearings.test.js +0 -102
  584. package/dist/core/canvas/__tests__/remote-event-stream.test.d.ts +0 -1
  585. package/dist/core/canvas/__tests__/remote-event-stream.test.js +0 -146
  586. package/dist/core/canvas/__tests__/source-resolve.test.d.ts +0 -1
  587. package/dist/core/canvas/__tests__/source-resolve.test.js +0 -77
  588. package/dist/core/canvas/browse/__tests__/model.test.d.ts +0 -1
  589. package/dist/core/canvas/browse/__tests__/model.test.js +0 -290
  590. package/dist/core/canvas/browse/__tests__/rebuild-coalescer.test.d.ts +0 -1
  591. package/dist/core/canvas/browse/__tests__/rebuild-coalescer.test.js +0 -134
  592. package/dist/core/canvas/browse/__tests__/render.test.d.ts +0 -1
  593. package/dist/core/canvas/browse/__tests__/render.test.js +0 -111
  594. package/dist/core/canvas/browse/rebuild-coalescer.d.ts +0 -7
  595. package/dist/core/canvas/browse/rebuild-coalescer.js +0 -61
  596. package/dist/core/canvas/remote-event-stream.d.ts +0 -24
  597. package/dist/core/canvas/remote-event-stream.js +0 -94
  598. package/dist/core/feed/__tests__/coalesce-human.test.d.ts +0 -1
  599. package/dist/core/feed/__tests__/coalesce-human.test.js +0 -36
  600. package/dist/core/feed/__tests__/empty-node-guard.test.d.ts +0 -1
  601. package/dist/core/feed/__tests__/empty-node-guard.test.js +0 -45
  602. package/dist/core/host-exports/__tests__/export-prunes-boot-skill.test.d.ts +0 -1
  603. package/dist/core/host-exports/__tests__/export-prunes-boot-skill.test.js +0 -84
  604. package/dist/core/human/__tests__/visible-paths.test.d.ts +0 -1
  605. package/dist/core/human/__tests__/visible-paths.test.js +0 -28
  606. package/dist/core/keybindings/__tests__/inbox-affordance.test.d.ts +0 -1
  607. package/dist/core/keybindings/__tests__/inbox-affordance.test.js +0 -38
  608. package/dist/core/review/__tests__/project.test.d.ts +0 -1
  609. package/dist/core/review/__tests__/project.test.js +0 -71
  610. package/dist/core/runtime/__tests__/command-expansion.test.d.ts +0 -1
  611. package/dist/core/runtime/__tests__/command-expansion.test.js +0 -25
  612. package/dist/core/runtime/__tests__/session-visibility.test.d.ts +0 -1
  613. package/dist/core/runtime/__tests__/session-visibility.test.js +0 -119
  614. package/dist/core/runtime/__tests__/spawn-at-given-id.test.d.ts +0 -1
  615. package/dist/core/runtime/__tests__/spawn-at-given-id.test.js +0 -34
  616. package/dist/core/runtime/tmux.js +0 -1314
  617. package/dist/daemon/api/__tests__/full/push-parity.test.d.ts +0 -1
  618. package/dist/daemon/api/__tests__/full/worktree-parity.test.d.ts +0 -1
  619. package/dist/daemon/api/__tests__/full/worktree-parity.test.js +0 -160
  620. package/dist/daemon/api/__tests__/inbox.test.d.ts +0 -1
  621. package/dist/daemon/api/__tests__/inbox.test.js +0 -489
  622. package/dist/web-client/apple-touch-icon.png +0 -0
  623. package/dist/web-client/assets/fragment-mono-latin-400-normal-BYwT3kSJ.woff +0 -0
  624. package/dist/web-client/assets/fragment-mono-latin-400-normal-yxdJ5AmL.woff2 +0 -0
  625. package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-BbKYyvR9.woff2 +0 -0
  626. package/dist/web-client/assets/fragment-mono-latin-ext-400-normal-CT4YFKeK.woff +0 -0
  627. package/dist/web-client/assets/index-CCPaLeW7.css +0 -2
  628. package/dist/web-client/assets/index-kyOWsnZK.js +0 -86
  629. package/dist/web-client/assets/martian-mono-cyrillic-wght-normal-B84CD5C_.woff2 +0 -0
  630. package/dist/web-client/assets/martian-mono-latin-ext-wght-normal-DlL6xMw5.woff2 +0 -0
  631. package/dist/web-client/assets/martian-mono-latin-wght-normal-5W32yIyr.woff2 +0 -0
  632. package/dist/web-client/assets/workbox-window.prod.es5-Bd17z0YL.js +0 -2
  633. package/dist/web-client/icon-192.png +0 -0
  634. package/dist/web-client/icon-512.png +0 -0
  635. package/dist/web-client/icon-maskable-512.png +0 -0
  636. package/dist/web-client/index.html +0 -17
  637. package/dist/web-client/manifest.webmanifest +0 -1
  638. package/dist/web-client/sw.js +0 -1
  639. /package/dist/api/__tests__/{client.test.d.ts → serial/client.test.d.ts} +0 -0
  640. /package/dist/clients/inbox/__tests__/{inbox-controller.test.d.ts → serial/inbox-controller.test.d.ts} +0 -0
  641. /package/dist/clients/inbox/__tests__/{mount-panel.test.d.ts → serial/mount-panel.test.d.ts} +0 -0
  642. /package/dist/clients/{attach/__tests__/attach-chrome-remote.test.d.ts → inbox/review/__tests__/teardown-notice.test.d.ts} +0 -0
  643. /package/dist/{clients/attach/__tests__/attach-keybindings.test.d.ts → core/__tests__/broker-extension-canvas-db-boundary.test.d.ts} +0 -0
  644. /package/dist/{clients/attach/__tests__/crtr-output-coverage.test.d.ts → core/__tests__/seam/broker-attach-multiclient.test.d.ts} +0 -0
  645. /package/dist/core/__tests__/{full → seam}/broker-attach-stream.test.d.ts +0 -0
  646. /package/dist/core/__tests__/{full → seam}/broker-crash-teardown.test.d.ts +0 -0
  647. /package/dist/core/__tests__/{full → seam}/broker-pane-resolution.test.d.ts +0 -0
  648. /package/dist/core/__tests__/{full → seam}/broker-provider-retry.test.d.ts +0 -0
  649. /package/dist/core/__tests__/{full → seam}/broker-whip-interrupt.test.d.ts +0 -0
  650. /package/dist/{clients/attach/__tests__/editor-frame-title.test.d.ts → core/__tests__/seam/dormancy-release.test.d.ts} +0 -0
  651. /package/dist/{clients/attach/__tests__/input-controller-extension-command.test.d.ts → core/__tests__/seam/yield-refresh-transaction.test.d.ts} +0 -0
  652. /package/dist/core/__tests__/{broker-fork-seam.test.d.ts → serial/broker-fork-seam.test.d.ts} +0 -0
  653. /package/dist/core/__tests__/{broker-sdk-wiring.test.d.ts → serial/broker-sdk-wiring.test.d.ts} +0 -0
  654. /package/dist/core/__tests__/{broker-snapshot-history.test.d.ts → serial/broker-snapshot-history.test.d.ts} +0 -0
  655. /package/dist/core/__tests__/{command-plugins.test.d.ts → serial/command-plugins.test.d.ts} +0 -0
  656. /package/dist/core/__tests__/{deferred-no-wake.test.d.ts → serial/deferred-no-wake.test.d.ts} +0 -0
  657. /package/dist/core/__tests__/{flagship-lifecycle.test.d.ts → serial/flagship-lifecycle.test.d.ts} +0 -0
  658. /package/dist/core/__tests__/{host-teardown-process-group.test.d.ts → serial/host-teardown-process-group.test.d.ts} +0 -0
  659. /package/dist/core/__tests__/{human-deliver-e2e.test.d.ts → serial/human-deliver-e2e.test.d.ts} +0 -0
  660. /package/dist/core/__tests__/{live-mutation.test.d.ts → serial/live-mutation.test.d.ts} +0 -0
  661. /package/dist/core/__tests__/{refresh-stall-recycle.test.d.ts → serial/refresh-stall-recycle.test.d.ts} +0 -0
  662. /package/dist/core/__tests__/{revive.test.d.ts → serial/revive.test.d.ts} +0 -0
  663. /package/dist/core/__tests__/{spawn-root.test.d.ts → serial/spawn-root.test.d.ts} +0 -0
  664. /package/dist/core/__tests__/{subscription-delivery.test.d.ts → serial/subscription-delivery.test.d.ts} +0 -0
  665. /package/dist/core/__tests__/{tmux-surface.test.d.ts → serial/tmux-surface.test.d.ts} +0 -0
  666. /package/dist/core/__tests__/{worktree.test.d.ts → serial/worktree.test.d.ts} +0 -0
  667. /package/dist/{clients/attach/__tests__/markdown-headings.test.d.ts → core/__tests__/watchdog-abort-arms-retry.test.d.ts} +0 -0
  668. /package/dist/{clients/attach/__tests__/session-identity-refresh.test.d.ts → core/broker-client/__tests__/transport-socket.test.d.ts} +0 -0
  669. /package/dist/core/human/__tests__/{inbox-core.test.d.ts → serial/inbox-core.test.d.ts} +0 -0
  670. /package/dist/{clients/inbox/review/__tests__/remap.test.d.ts → daemon/api/__tests__/node-model-validation.test.d.ts} +0 -0
  671. /package/dist/{clients/surfaces/region.js → daemon/api/__tests__/review-terminal-conflict.test.d.ts} +0 -0
  672. /package/dist/daemon/api/__tests__/{full → seam}/api-server.test.d.ts +0 -0
  673. /package/dist/daemon/api/__tests__/{full → seam}/b10-attach-modelauth.test.d.ts +0 -0
  674. /package/dist/{clients/web/__tests__/push-engine.test.d.ts → daemon/api/__tests__/seam/leaf-api-parity.test.d.ts} +0 -0
@@ -0,0 +1,126 @@
1
+ // Run with: npm run test:serial
2
+ //
3
+ // THE DAEMON WAKE HALF of delivery-vs-wake, on a graph >=2 levels deep. Routing
4
+ // itself (active → inbox.jsonl, passive → passive.jsonl) is owned by
5
+ // passive-subscription.test.ts; what this file owns is the decision ONE real
6
+ // `superviseTick` makes on that routing: the ACTIVE subscriber of a finished
7
+ // target is revived, the PASSIVE subscriber on the same target is not.
8
+ //
9
+ // HEADLESS / FABRICATED DRIVE (foundation-spec §C.15 + §E). All nodes are
10
+ // broker-hosted (paneless), so the topology and dormant states are fabricated
11
+ // directly rather than booted — a released broker's dormancy is an EXITED
12
+ // process (status=idle, intent=idle-release, pi_pid dead). A daemon revive is
13
+ // observed via getNode().cycles, which reviveNode bumps together with
14
+ // transition('revive') BEFORE it spawns, so the model effect is instant.
15
+ //
16
+ // HOW IT FAILS IF THE SPLIT REGRESSES: after T's pushFinal, one h.tick() must
17
+ // revive the ACTIVE subscriber B (cycles bumps, status→active) while the PASSIVE
18
+ // subscriber P stays idle with cycles==0. If routing breaks, either B's entry
19
+ // never reaches its inbox (the 2nd-pass gate finds nothing → B not revived) or P
20
+ // gets an inbox entry and IS woken — both go red here.
21
+ //
22
+ // Graph (T is two hops under A):
23
+ // A (resident root — the user's virtual front door)
24
+ // └── B (terminal) A→B active seed ── ACTIVE subscriber of T
25
+ // ├── T (terminal) B→T active seed ── THE TARGET (level 2)
26
+ // ├── K (terminal) B→K active seed ── keepalive (stays active)
27
+ // └── P (terminal) B→P active seed ── PASSIVE subscriber of T
28
+ // P→T passive (wired via subscribe(P,T,false))
29
+ // P→K active (the tie that legitimizes P's own release)
30
+ import { test } from 'node:test';
31
+ import assert from 'node:assert/strict';
32
+ import { spawnSync } from 'node:child_process';
33
+ import { existsSync, readFileSync } from 'node:fs';
34
+ import { createHarness } from '../helpers/harness.js';
35
+ import { closeDb } from '../../canvas/db.js';
36
+ import { subscribe } from '../../canvas/canvas.js';
37
+ import { pushFinal } from '../../feed/feed.js';
38
+ import { passivePath } from '../../canvas/paths.js';
39
+ // A pid reaped (dead) by the time spawnSync returns — a released broker's exited
40
+ // process (the headless analog of a closed pane).
41
+ function deadPid() {
42
+ const r = spawnSync('true', [], { stdio: 'ignore' });
43
+ return r.pid ?? 0x7ffffffe;
44
+ }
45
+ // LOCAL helper: read a node's PASSIVE accumulator (passive.jsonl) straight off
46
+ // the data layer, mirroring the harness's own `inbox()` reader. The harness
47
+ // exposes inbox() but NOT passive() — this fills that gap.
48
+ function passive(nodeId) {
49
+ closeDb();
50
+ const path = passivePath(nodeId);
51
+ if (!existsSync(path))
52
+ return [];
53
+ return readFileSync(path, 'utf8').split('\n').filter(Boolean).map((line) => JSON.parse(line));
54
+ }
55
+ // `{node_id, active}` arrays → a stable comparable set of `id:active|passive`.
56
+ function edgeSet(arr) {
57
+ return new Set(arr.map((e) => `${e.node_id}:${e.active ? 'active' : 'passive'}`));
58
+ }
59
+ test('one daemon tick revives the active subscriber of a finished target and leaves the passive one dormant', { timeout: 30_000 }, async () => {
60
+ const h = await createHarness({ headless: true, sessionPrefix: 'crtr-subdeliv' });
61
+ try {
62
+ // ===================================================================
63
+ // Build the graph by FABRICATION (no boots). A is a resident root
64
+ // (inline, daemon-untouched); B/T/K/P are broker nodes whose liveness
65
+ // fields are set directly. Each parent→child spine edge is wired ACTIVE.
66
+ // ===================================================================
67
+ const A = h.spawnRoot('front door'); // resident root, active, no placement
68
+ // T (the target) and K (keepalive) are LIVE-active workers; B and P start
69
+ // already DORMANT (idle-released, broker exited = dead pid) — exactly the
70
+ // post-stop state the delivery split is judged against.
71
+ const T = h.fabricateBrokerNode({ status: 'active', pi_pid: deadPid(), pi_session_id: 'sess-T' });
72
+ const K = h.fabricateBrokerNode({ status: 'active', pi_pid: deadPid(), pi_session_id: 'sess-K' });
73
+ const B = h.fabricateBrokerNode({ status: 'idle', intent: 'idle-release', pi_pid: deadPid(), pi_session_id: 'sess-B' });
74
+ const P = h.fabricateBrokerNode({ status: 'idle', intent: 'idle-release', pi_pid: deadPid(), pi_session_id: 'sess-P' });
75
+ // Spine seeds: A→B, B→T, B→K, B→P all ACTIVE (subscriber, publisher).
76
+ subscribe(A, B, true);
77
+ subscribe(B, T, true);
78
+ subscribe(B, K, true);
79
+ subscribe(B, P, true);
80
+ // PASSIVE axis under test: P passively subscribes to T; P actively to K
81
+ // (the only tie that legitimizes P's own idle-release).
82
+ subscribe(P, T, false);
83
+ subscribe(P, K, true);
84
+ assert.deepEqual(edgeSet(h.subscribers(T)), new Set([`${B}:active`, `${P}:passive`]), 'T has B(active) + P(passive) as subscribers — the same-target split');
85
+ // Pre-push baseline: keepalive up, nothing delivered, nothing revived.
86
+ assert.equal(h.status(K), 'active', 'K active (keepalive holds P legitimately dormant)');
87
+ assert.equal(h.inbox(B).length, 0, 'B inbox empty before the push');
88
+ assert.equal(passive(P).length, 0, 'P passive accumulator empty before the push');
89
+ assert.equal(h.node(B).cycles ?? 0, 0, 'B not yet revived');
90
+ assert.equal(h.node(P).cycles ?? 0, 0, 'P not yet revived');
91
+ // ===================================================================
92
+ // T FINISHES via the model layer — the precondition the daemon decides on:
93
+ // B's pointer lands in inbox.jsonl (the wake channel), P's in passive.jsonl.
94
+ // ===================================================================
95
+ await pushFinal(T, 'TARGET-FINAL-BODY: the worker completed');
96
+ closeDb();
97
+ assert.ok(h.inbox(B).find((e) => e.from === T && e.kind === 'final'), 'ACTIVE subscriber B: T-final pointer delivered to inbox.jsonl');
98
+ assert.equal(h.inbox(P).length, 0, 'PASSIVE subscriber P: inbox.jsonl stays empty (no wake channel)');
99
+ assert.equal(passive(P).length, 1, 'PASSIVE subscriber P: exactly one passive entry');
100
+ // ===================================================================
101
+ // The DAEMON decision pass. Its 2nd pass revives an idle-released node
102
+ // ONLY on an unseen INBOX entry. B has one (active) → REVIVED. P has none
103
+ // (its entry went to passive.jsonl) → stays idle. Decided in ONE tick.
104
+ // ===================================================================
105
+ await h.tick();
106
+ // ACTIVE subscriber: WOKEN — reviveNode bumped cycles + transition(revive).
107
+ {
108
+ const b = h.node(B);
109
+ assert.equal(b.cycles ?? 0, 1, 'ACTIVE subscriber B: daemon pass-2 REVIVED (cycles bumped to 1)');
110
+ assert.equal(b.status, 'active', 'B revive → active');
111
+ assert.equal(b.intent ?? null, null, 'B intent cleared by revive');
112
+ }
113
+ // PASSIVE subscriber: NOT WOKEN — the same tick did NOT revive P.
114
+ {
115
+ const p = h.node(P);
116
+ assert.equal(p.cycles ?? 0, 0, 'PASSIVE subscriber P: NOT revived (cycles still 0)');
117
+ assert.equal(p.status, 'idle', 'P STILL idle — daemon did NOT wake it');
118
+ assert.equal(p.intent, 'idle-release', 'P still intent=idle-release (untouched)');
119
+ }
120
+ assert.equal(passive(P).length, 1, "P's passive entry is still pending (drained only on its next message)");
121
+ assert.equal(h.inbox(P).length, 0, "P's inbox still empty");
122
+ }
123
+ finally {
124
+ await h.dispose();
125
+ }
126
+ });
@@ -0,0 +1,256 @@
1
+ // Run with: npm run test:serial
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 driver-import lint guard (ENFORCED as of Step 8): every other
15
+ // module reaches the driver through placement's re-exports or the
16
+ // tmux-chrome seam, so the only direct importers are placement.ts,
17
+ // placement-tmux.ts, tmux-chrome.ts, and tmux-bindings.ts.
18
+ import { test } from 'node:test';
19
+ import assert from 'node:assert/strict';
20
+ import { readFileSync, readdirSync, statSync } from 'node:fs';
21
+ import { spawnSync } from 'node:child_process';
22
+ import { fileURLToPath } from 'node:url';
23
+ import { dirname, join, basename } from 'node:path';
24
+ import { ensureSession } from '../../runtime/placement.js';
25
+ import { installTmuxBindings } from '../../runtime/tmux-chrome.js';
26
+ import { resolveKeybindings } from '../../keybindings/index.js';
27
+ const __dirname = dirname(fileURLToPath(import.meta.url));
28
+ const SRC_ROOT = join(__dirname, '..', '..', '..'); // .../src
29
+ const TMUX_DRIVER_TS = join(SRC_ROOT, 'core', 'runtime', 'tmux-driver.ts');
30
+ /** The placement verbs the §2.2 invariant governs. (swap-pane/break-pane/
31
+ * join-pane/move-pane were deleted with the engine-in-pane host in the broker
32
+ * cut; kept in the match set so a regression that re-introduces an untargeted
33
+ * one is still caught.) */
34
+ const PLACEMENT_VERBS = [
35
+ 'new-window',
36
+ 'split-window',
37
+ 'swap-pane',
38
+ 'break-pane',
39
+ 'join-pane',
40
+ 'move-pane',
41
+ 'respawn-pane',
42
+ ];
43
+ /** The smallest `[ … ]` array literal that encloses `matchIdx`: scan back to the
44
+ * nearest `[` (the array open — the verb is always its first element), then
45
+ * forward with bracket-depth counting to the matching `]` (handles nested
46
+ * arrays like splitWindow's `? [] : ['-h']`). Returns the array source slice. */
47
+ function enclosingArray(src, matchIdx) {
48
+ let open = matchIdx;
49
+ while (open >= 0 && src[open] !== '[')
50
+ open--;
51
+ assert.ok(open >= 0, `no enclosing [ for the verb at index ${matchIdx}`);
52
+ let depth = 0;
53
+ for (let i = open; i < src.length; i++) {
54
+ if (src[i] === '[')
55
+ depth++;
56
+ else if (src[i] === ']') {
57
+ depth--;
58
+ if (depth === 0)
59
+ return src.slice(open, i + 1);
60
+ }
61
+ }
62
+ throw new Error('unbalanced [ ] while bracket-matching the verb array');
63
+ }
64
+ test('§2.2 driver invariant: every placement verb in tmux-driver.ts passes an explicit -t target', () => {
65
+ const src = readFileSync(TMUX_DRIVER_TS, 'utf8');
66
+ // Match only the QUOTED JS string forms (`'new-window'`, …) — these are real
67
+ // args-array elements; the jsdoc prose mentions the verbs unquoted / in
68
+ // backticks, so this never trips on a comment.
69
+ const re = new RegExp(`'(${PLACEMENT_VERBS.join('|')})'`, 'g');
70
+ let found = 0;
71
+ for (let m = re.exec(src); m !== null; m = re.exec(src)) {
72
+ found++;
73
+ const verb = m[1];
74
+ const arr = enclosingArray(src, m.index);
75
+ // The invariant is "name a specific tmux object, never fall back to the
76
+ // GLOBAL current one". `-t` targets a destination; `break-pane` (and the
77
+ // deleted swap/join/move-pane) instead name their SOURCE with `-s` — which
78
+ // satisfies the invariant identically. Accept either explicit target flag.
79
+ assert.ok(arr.includes(`'-t'`) || arr.includes(`'-s'`), `tmux verb '${verb}' is invoked WITHOUT an explicit -t/-s target — a latent ` +
80
+ `instance of the unbidden-window bug (§2.2). Offending args array:\n${arr}`);
81
+ }
82
+ // Sanity: the driver really does contain placement verbs (so a refactor that
83
+ // renames them can't make this assertion vacuously pass). The broker cut left
84
+ // three (new-window / split-window / respawn-pane).
85
+ assert.ok(found >= 3, `expected to scan ≥3 placement verbs, saw ${found}`);
86
+ });
87
+ // ---------------------------------------------------------------------------
88
+ // Lint guard — §5.1, ENFORCED. The driver (tmux-driver.ts) is imported only by
89
+ // placement.ts, placement-tmux.ts, tmux-chrome.ts, and tmux-bindings.ts. Every
90
+ // other module — runtime, daemon, commands, stophook, and tests — must route
91
+ // through those sanctioned seams.
92
+ // ---------------------------------------------------------------------------
93
+ /** Every `.ts` file under `src` (recursively), excluding nothing. */
94
+ function allTsFiles(dir) {
95
+ const out = [];
96
+ for (const entry of readdirSync(dir)) {
97
+ const p = join(dir, entry);
98
+ if (statSync(p).isDirectory())
99
+ out.push(...allTsFiles(p));
100
+ else if (entry.endsWith('.ts'))
101
+ out.push(p);
102
+ }
103
+ return out;
104
+ }
105
+ /** Files (basename) sanctioned to import the driver, per §2.1. */
106
+ const ALLOWED_IMPORTERS = new Set(['placement.ts', 'placement-tmux.ts', 'tmux-chrome.ts', 'tmux-bindings.ts']);
107
+ function importsDriver(file) {
108
+ const src = readFileSync(file, 'utf8');
109
+ // A specifier whose basename is exactly `tmux-driver.js` (so
110
+ // `tmux-bindings.js` is not matched). Covers `from '...'` and `import('...')`.
111
+ return [...src.matchAll(/(?:from|import\s*\()\s*'([^']+)'/g)].some((m) => basename(m[1]) === 'tmux-driver.js');
112
+ }
113
+ test('§5.1 lint: only sanctioned seams import the tmux driver', () => {
114
+ const offenders = allTsFiles(SRC_ROOT)
115
+ .filter((f) => !ALLOWED_IMPORTERS.has(basename(f)))
116
+ .filter(importsDriver)
117
+ .map((f) => f.slice(SRC_ROOT.length + 1));
118
+ assert.deepEqual(offenders, [], `modules importing tmux-driver.ts directly: ${offenders.join(', ')}`);
119
+ });
120
+ function isolatedTmux(socket, args) {
121
+ const result = spawnSync('tmux', ['-S', socket, ...args], { encoding: 'utf8' });
122
+ return { status: result.status, stdout: result.stdout ?? '', stderr: result.stderr ?? '' };
123
+ }
124
+ function tmuxBinding(socket, table, key) {
125
+ const result = isolatedTmux(socket, ['list-keys', '-T', table]);
126
+ if (result.status !== 0)
127
+ return null;
128
+ return result.stdout.split('\n').find((line) => {
129
+ const match = line.match(/^bind-key\s+(?:-r\s+)?-T\s+\S+\s+(\S+)\s+/);
130
+ return match?.[1] === key;
131
+ }) ?? null;
132
+ }
133
+ test('tmux repairs corrupt bracketed-paste caps without replacing user overrides', (t) => {
134
+ if (spawnSync('tmux', ['-V']).status !== 0) {
135
+ t.skip('tmux is unavailable');
136
+ return;
137
+ }
138
+ const name = `crtr-bracketed-paste-${process.pid}-${Date.now()}`;
139
+ // `-f /dev/null`: boot a config-less isolated server so these binding tests are
140
+ // hermetic. Without it the server sources the developer's ~/.tmux.conf, whose
141
+ // own root-table bindings (e.g. M-j) pre-occupy keys these tests rebind onto —
142
+ // the installer then correctly refuses to clobber the foreign binding and the
143
+ // assertion fails on the dev's machine but not on a config-less CI runner.
144
+ const boot = spawnSync('tmux', ['-L', name, '-f', '/dev/null', 'new-session', '-d', '-s', 'test'], { encoding: 'utf8' });
145
+ assert.equal(boot.status, 0, boot.stderr);
146
+ const socket = spawnSync('tmux', ['-L', name, 'display-message', '-p', '#{socket_path}'], { encoding: 'utf8' }).stdout.trim();
147
+ assert.notEqual(socket, '');
148
+ const priorTmux = process.env['TMUX'];
149
+ process.env['TMUX'] = `${socket},1,0`;
150
+ try {
151
+ assert.equal(isolatedTmux(socket, ['set-option', '-s', 'terminal-overrides', 'xterm*:Tc']).status, 0);
152
+ assert.equal(isolatedTmux(socket, ['set-option', '-sga', 'terminal-overrides', '*:Enbp=E[?2004h:Dsbp=E[?2004l']).status, 0);
153
+ ensureSession('test', process.cwd());
154
+ const repaired = isolatedTmux(socket, ['show-options', '-s', 'terminal-overrides']);
155
+ assert.equal(repaired.status, 0, repaired.stderr);
156
+ assert.match(repaired.stdout, /xterm\*:Tc/, 'unrelated user override must remain');
157
+ assert.match(repaired.stdout, /Enbp=\\+E\[\?2004h/, 'a valid Enbp override must be appended');
158
+ ensureSession('test', process.cwd());
159
+ assert.equal(isolatedTmux(socket, ['show-options', '-s', 'terminal-overrides']).stdout, repaired.stdout, 'valid Enbp must make the repair idempotent');
160
+ }
161
+ finally {
162
+ if (priorTmux === undefined)
163
+ delete process.env['TMUX'];
164
+ else
165
+ process.env['TMUX'] = priorTmux;
166
+ isolatedTmux(socket, ['kill-server']);
167
+ }
168
+ });
169
+ test('tmux installer remaps owned pairs and preserves occupied user bindings', (t) => {
170
+ if (spawnSync('tmux', ['-V']).status !== 0) {
171
+ t.skip('tmux is unavailable');
172
+ return;
173
+ }
174
+ const name = `crtr-keybindings-${process.pid}-${Date.now()}`;
175
+ const boot = spawnSync('tmux', ['-L', name, '-f', '/dev/null', 'new-session', '-d', '-s', 'test'], { encoding: 'utf8' });
176
+ assert.equal(boot.status, 0, boot.stderr);
177
+ const socketResult = spawnSync('tmux', ['-L', name, 'display-message', '-p', '#{socket_path}'], { encoding: 'utf8' });
178
+ const socket = socketResult.stdout.trim();
179
+ assert.notEqual(socket, '');
180
+ const priorTmux = process.env['TMUX'];
181
+ process.env['TMUX'] = `${socket},1,0`;
182
+ try {
183
+ const first = installTmuxBindings(resolveKeybindings());
184
+ assert.equal(first.ok, true, JSON.stringify(first.diagnostics));
185
+ assert.ok(first.installed.some((pair) => pair.table === 'root' && pair.key === 'M-]'));
186
+ const defaultMenu = tmuxBinding(socket, 'root', 'M-c') ?? '';
187
+ assert.match(defaultMenu, /display-menu/);
188
+ // The inbox toggle installs at its default key (alt+i → M-i) in the same sweep.
189
+ assert.match(tmuxBinding(socket, 'root', 'M-i') ?? '', /crtr human inbox toggle/);
190
+ const remapped = installTmuxBindings(resolveKeybindings({
191
+ 'crtr.tmux.menu.open': ['alt+shift+z'],
192
+ 'crtr.tmux.menu.graph': ['shift+z'],
193
+ 'crtr.tmux.menu-global.fold-tools': ['alt+shift+f'],
194
+ 'crtr.tmux.node.next': [],
195
+ }));
196
+ assert.equal(remapped.ok, true, JSON.stringify(remapped.diagnostics));
197
+ assert.equal(tmuxBinding(socket, 'root', 'M-c'), null);
198
+ assert.equal(tmuxBinding(socket, 'root', 'M-]'), null);
199
+ assert.equal(tmuxBinding(socket, 'root', 'M-F'), null);
200
+ assert.equal(tmuxBinding(socket, 'root', 'M-S-f'), null);
201
+ const foldTools = tmuxBinding(socket, 'root', 'M-S-F') ?? '';
202
+ assert.match(foldTools, /fold-tools/);
203
+ assert.doesNotMatch(foldTools, /#\{pane_id\}/);
204
+ const menu = tmuxBinding(socket, 'root', 'M-S-Z') ?? '';
205
+ assert.match(menu, /canvas graph/);
206
+ assert.match(menu, /Z/);
207
+ assert.match(menu, /"Alt\+Shift\+Z to close" M-S-Z refresh-client/);
208
+ const again = installTmuxBindings(resolveKeybindings({
209
+ 'crtr.tmux.menu.open': ['alt+shift+y'],
210
+ 'crtr.tmux.node.next': [],
211
+ }));
212
+ assert.equal(again.ok, true, JSON.stringify(again.diagnostics));
213
+ isolatedTmux(socket, ['bind-key', '-T', 'root', 'M-S-Z', 'display-message', 'user-owned']);
214
+ const occupied = installTmuxBindings(resolveKeybindings({ 'crtr.tmux.menu.open': ['alt+shift+z'] }));
215
+ assert.equal(occupied.ok, true);
216
+ assert.ok(occupied.diagnostics.some((diagnostic) => diagnostic.code === 'occupied' && diagnostic.bindingId === 'crtr.tmux.menu.open'));
217
+ assert.match(tmuxBinding(socket, 'root', 'M-S-Z') ?? '', /user-owned/);
218
+ }
219
+ finally {
220
+ if (priorTmux === undefined)
221
+ delete process.env['TMUX'];
222
+ else
223
+ process.env['TMUX'] = priorTmux;
224
+ isolatedTmux(socket, ['kill-server']);
225
+ }
226
+ });
227
+ test('tmux installer reads pair-array manifests and replaces owned pairs', (t) => {
228
+ if (spawnSync('tmux', ['-V']).status !== 0) {
229
+ t.skip('tmux is unavailable');
230
+ return;
231
+ }
232
+ const name = `crtr-pair-manifest-${process.pid}-${Date.now()}`;
233
+ const boot = spawnSync('tmux', ['-L', name, '-f', '/dev/null', 'new-session', '-d', '-s', 'test'], { encoding: 'utf8' });
234
+ assert.equal(boot.status, 0, boot.stderr);
235
+ const socket = spawnSync('tmux', ['-L', name, 'display-message', '-p', '#{socket_path}'], { encoding: 'utf8' }).stdout.trim();
236
+ assert.notEqual(socket, '');
237
+ const priorTmux = process.env['TMUX'];
238
+ process.env['TMUX'] = `${socket},1,0`;
239
+ try {
240
+ // Current-scope releases wrote the pair array before wrappers were added.
241
+ isolatedTmux(socket, ['set-option', '-s', '@crtr_keybindings_manifest', JSON.stringify([{ table: 'root', key: 'M-i' }])]);
242
+ isolatedTmux(socket, ['bind-key', '-T', 'root', 'M-i', 'run-shell', '-b', 'crtr human inbox toggle --quiet']);
243
+ const result = installTmuxBindings(resolveKeybindings());
244
+ assert.equal(result.ok, true, JSON.stringify(result.diagnostics));
245
+ assert.ok(!result.diagnostics.some((d) => d.bindingId === 'crtr.tmux.inbox.toggle'), JSON.stringify(result.diagnostics));
246
+ assert.match(tmuxBinding(socket, 'root', 'M-i') ?? '', /crtr human inbox toggle/);
247
+ assert.match(tmuxBinding(socket, 'root', 'M-c') ?? '', /background running bash/);
248
+ }
249
+ finally {
250
+ if (priorTmux === undefined)
251
+ delete process.env['TMUX'];
252
+ else
253
+ process.env['TMUX'] = priorTmux;
254
+ isolatedTmux(socket, ['kill-server']);
255
+ }
256
+ });
@@ -4,11 +4,11 @@ import { mkdtempSync, mkdirSync, rmSync, existsSync, readdirSync, statSync, writ
4
4
  import { spawn } from 'node:child_process';
5
5
  import { tmpdir } from 'node:os';
6
6
  import { join } from 'node:path';
7
- import { gitSync } from '../git.js';
8
- import { push } from '../feed/feed.js';
9
- import { createManagedWorktree, closeManagedWorktree, managedWorktreePath, rollbackManagedWorktree, setWorktreeCleanupRunnerForTest } from '../worktree.js';
10
- import { createNode, getNode } from '../canvas/canvas.js';
11
- import { closeDb } from '../canvas/db.js';
7
+ import { gitSync } from '../../git.js';
8
+ import { push } from '../../feed/feed.js';
9
+ import { createManagedWorktree, closeManagedWorktree, managedWorktreePath, rollbackManagedWorktree, setWorktreeCleanupRunnerForTest } from '../../worktree.js';
10
+ import { createNode, getNode } from '../../canvas/canvas.js';
11
+ import { closeDb } from '../../canvas/db.js';
12
12
  let home;
13
13
  let remoteDir;
14
14
  let sourceDir;
@@ -93,7 +93,7 @@ test('closeManagedWorktree recreates the worktree path as a tombstone dir so the
93
93
  assert.equal(meta?.cwd, wt.repo_root, 'closed node cwd must repoint to the repo root, not the removed worktree path');
94
94
  });
95
95
  test('two concurrent creates from linked worktrees serialize on their shared repository', async () => {
96
- const worktreeModule = new URL('../worktree.ts', import.meta.url).href;
96
+ const worktreeModule = new URL('../../worktree.ts', import.meta.url).href;
97
97
  const createFrom = (cwd, nodeId) => new Promise((resolve, reject) => {
98
98
  const script = `import { createManagedWorktree } from ${JSON.stringify(worktreeModule)}; createManagedWorktree(${JSON.stringify(cwd)}, ${JSON.stringify(nodeId)});`;
99
99
  const child = spawn(process.execPath, ['--import', 'tsx/esm', '--input-type=module', '--eval', script], { env: { ...process.env, CRTR_HOME: home }, stdio: 'pipe' });
@@ -410,7 +410,7 @@ test('close still blocks on real .crouter/memory/ work — a tracked-file edit a
410
410
  // (autoDropCleanManagedWorktree) must close it without requiring an explicit
411
411
  // `node worktree close`.
412
412
  test('autoDropCleanManagedWorktree drops a clean, zero-commit worktree', async () => {
413
- const { autoDropCleanManagedWorktree } = await import('../worktree.js');
413
+ const { autoDropCleanManagedWorktree } = await import('../../worktree.js');
414
414
  const nodeId = 'wt-auto-drop-empty';
415
415
  const wt = createManagedWorktree(sourceDir, nodeId);
416
416
  createNode(node(nodeId, { cwd: wt.path, managed_worktree: wt }));
@@ -435,7 +435,7 @@ test('autoDropCleanManagedWorktree drops a clean, zero-commit worktree', async (
435
435
  // The same real-commit case close already protects: a worktree with actual
436
436
  // unlanded work must NEVER be auto-dropped by push-final.
437
437
  test('autoDropCleanManagedWorktree refuses a worktree with a real commit ahead of base', async () => {
438
- const { autoDropCleanManagedWorktree } = await import('../worktree.js');
438
+ const { autoDropCleanManagedWorktree } = await import('../../worktree.js');
439
439
  const nodeId = 'wt-auto-drop-real-work';
440
440
  const wt = createManagedWorktree(sourceDir, nodeId);
441
441
  createNode(node(nodeId, { cwd: wt.path, managed_worktree: wt }));
@@ -450,7 +450,7 @@ test('autoDropCleanManagedWorktree refuses a worktree with a real commit ahead o
450
450
  // Real uncommitted (non-crtr-bookkeeping) changes must also refuse auto-drop,
451
451
  // even with zero commits.
452
452
  test('autoDropCleanManagedWorktree refuses a worktree with real uncommitted changes', async () => {
453
- const { autoDropCleanManagedWorktree } = await import('../worktree.js');
453
+ const { autoDropCleanManagedWorktree } = await import('../../worktree.js');
454
454
  const nodeId = 'wt-auto-drop-dirty';
455
455
  const wt = createManagedWorktree(sourceDir, nodeId);
456
456
  createNode(node(nodeId, { cwd: wt.path, managed_worktree: wt }));
@@ -465,7 +465,7 @@ test('autoDropCleanManagedWorktree refuses a worktree with real uncommitted chan
465
465
  // ever going through crtr's own close path). This must auto-drop and, above
466
466
  // all, must never lose the work — it stays reachable from the moved base.
467
467
  test('autoDropCleanManagedWorktree drops a branch with real commits already contained in a moved base (#327)', async () => {
468
- const { autoDropCleanManagedWorktree } = await import('../worktree.js');
468
+ const { autoDropCleanManagedWorktree } = await import('../../worktree.js');
469
469
  const repo = mkdtempSync(join(tmpdir(), 'crtr-worktree-327-'));
470
470
  run(['init', '-b', 'main'], repo);
471
471
  run(['config', 'user.email', 'test@example.com'], repo);
@@ -498,7 +498,7 @@ test('autoDropCleanManagedWorktree drops a branch with real commits already cont
498
498
  // auto-drop rather than guess — the SAME guard `resolveLandableBase` already
499
499
  // gives the explicit close path.
500
500
  test('autoDropCleanManagedWorktree refuses when the recorded base branch no longer resolves', async () => {
501
- const { autoDropCleanManagedWorktree } = await import('../worktree.js');
501
+ const { autoDropCleanManagedWorktree } = await import('../../worktree.js');
502
502
  const repo = mkdtempSync(join(tmpdir(), 'crtr-worktree-missingbase-'));
503
503
  run(['init', '-b', 'main'], repo);
504
504
  run(['config', 'user.email', 'test@example.com'], repo);
@@ -531,7 +531,7 @@ test('autoDropCleanManagedWorktree refuses when the recorded base branch no long
531
531
  // compare-and-delete must refuse, leaving the branch (and the new commit)
532
532
  // fully intact.
533
533
  test('the atomic delete refuses when a commit lands on the branch between the predicate and cleanup', async () => {
534
- const { proveCleanEmptyManagedWorktree, autoDropCleanManagedWorktreeLocked } = await import('../worktree.js');
534
+ const { proveCleanEmptyManagedWorktree, autoDropCleanManagedWorktreeLocked } = await import('../../worktree.js');
535
535
  const nodeId = 'wt-race-branch-commit';
536
536
  const wt = createManagedWorktree(sourceDir, nodeId);
537
537
  createNode(node(nodeId, { cwd: wt.path, managed_worktree: wt }));
@@ -561,7 +561,7 @@ test('the atomic delete refuses when a commit lands on the branch between the pr
561
561
  // before the delete must catch this even though the branch itself never
562
562
  // moved.
563
563
  test('the re-verified base containment refuses when the base is rewritten between the predicate and cleanup', async () => {
564
- const { proveCleanEmptyManagedWorktree, autoDropCleanManagedWorktreeLocked } = await import('../worktree.js');
564
+ const { proveCleanEmptyManagedWorktree, autoDropCleanManagedWorktreeLocked } = await import('../../worktree.js');
565
565
  const repo = mkdtempSync(join(tmpdir(), 'crtr-worktree-race-base-'));
566
566
  run(['init', '-b', 'main'], repo);
567
567
  run(['config', 'user.email', 'test@example.com'], repo);
@@ -605,7 +605,7 @@ test('the re-verified base containment refuses when the base is rewritten betwee
605
605
  // to reproduce this exact Critical against `6de1c8d`.
606
606
  // ---------------------------------------------------------------------------
607
607
  test('auto-drop atomic delete refuses when the base is force-reset between the live ancestry check and the ref transaction', async () => {
608
- const { proveCleanEmptyManagedWorktree, autoDropCleanManagedWorktreeLocked } = await import('../worktree.js');
608
+ const { proveCleanEmptyManagedWorktree, autoDropCleanManagedWorktreeLocked } = await import('../../worktree.js');
609
609
  const repo = mkdtempSync(join(tmpdir(), 'crtr-worktree-auto-drop-base-window-'));
610
610
  run(['init', '-b', 'main'], repo);
611
611
  run(['config', 'user.email', 'test@example.com'], repo);
@@ -717,7 +717,7 @@ PATH="$CRTR_TEST_REAL_PATH" exec git "$@"
717
717
  // transaction, which bypasses Git's own checked-out-branch protection.
718
718
  // ---------------------------------------------------------------------------
719
719
  test('auto-drop refuses and preserves the branch and checkout when checkout removal is refused after the clean predicate', async () => {
720
- const { proveCleanEmptyManagedWorktree, autoDropCleanManagedWorktreeLocked } = await import('../worktree.js');
720
+ const { proveCleanEmptyManagedWorktree, autoDropCleanManagedWorktreeLocked } = await import('../../worktree.js');
721
721
  const nodeId = 'wt-auto-drop-removal-refused';
722
722
  const wt = createManagedWorktree(sourceDir, nodeId);
723
723
  createNode(node(nodeId, { cwd: wt.path, managed_worktree: wt }));
@@ -94,24 +94,6 @@ test('a notify is never a dialog, and never disturbs one that is pending', () =>
94
94
  assert.equal(reduce(asked, { type: 'extension_ui_dismiss', id: 'other' }), asked);
95
95
  assert.equal(reduce(asked, { type: 'extension_ui_dismiss', id: 'ask-1' }).dialog, null);
96
96
  });
97
- test('frames that carry no session state return the SAME state reference', () => {
98
- const s0 = reduce(initialSessionState(), welcome());
99
- const inert = [
100
- { type: 'error', code: 'read_only', message: 'read-only' },
101
- { type: 'ack', for: 'get_commands', ok: true, detail: '[]' },
102
- { type: 'bash_start', command: 'ls' },
103
- { type: 'bash_output', chunk: 'a\n' },
104
- { type: 'bash_end', exitCode: 0, cancelled: false, truncated: false },
105
- ];
106
- for (const f of inert) {
107
- assert.equal(reduce(s0, f), s0, `${f.type} must not allocate a new state`);
108
- }
109
- // Slice identity is what viewers repaint off: an engine-only change must leave
110
- // the display slice untouched by reference.
111
- const started = reduce(s0, { type: 'agent_start' });
112
- assert.notEqual(started, s0);
113
- assert.equal(started.display, s0.display, 'an engine change must not dirty the display slice');
114
- });
115
97
  test('a welcome is a COMPLETE catch-up: a re-welcome drops a dead broker s levels and queue', () => {
116
98
  const s0 = fold(initialSessionState(), [
117
99
  welcome(),
@@ -57,3 +57,12 @@ test('a --worktree spawn at an already-existing node id throws and leaves NO wor
57
57
  assert.equal(getNode(nodeId).kind, 'general');
58
58
  assert.equal(getNode(nodeId).managed_worktree, undefined);
59
59
  });
60
+ test('spawnNode({ nodeId }): a hyphen-less opaque id spawns at the exact given id', () => {
61
+ // Regression for the reviewed opaque-id-contract violation: the old validator
62
+ // required >=2 hyphen segments and rejected a hyphen-less id outright,
63
+ // contradicting the design's "opaque, never parsed for structure" ID scheme
64
+ // that remote and cloud spawns depend on.
65
+ const meta = spawnNode({ kind: 'general', cwd: '/tmp/work', nodeId: 'remote42' });
66
+ assert.equal(meta.node_id, 'remote42');
67
+ assert.notEqual(getNode('remote42'), null);
68
+ });
@@ -0,0 +1,50 @@
1
+ import { after, before, test } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { mkdtempSync, rmSync } from 'node:fs';
4
+ import { tmpdir } from 'node:os';
5
+ import { join } from 'node:path';
6
+ import { FaultRetry } from '../runtime/broker/fault-retry.js';
7
+ import { readFault } from '../runtime/fault.js';
8
+ let home;
9
+ before(() => {
10
+ home = mkdtempSync(join(tmpdir(), 'crtr-watchdog-abort-retry-'));
11
+ process.env['CRTR_HOME'] = home;
12
+ });
13
+ after(() => {
14
+ rmSync(home, { recursive: true, force: true });
15
+ });
16
+ test('only a watchdog-stamped aborted settlement records an automatic connection fault', () => {
17
+ const settleAbort = (nodeId, stagedWatchdogAbort) => {
18
+ const session = {
19
+ sessionManager: { getLeafId: () => 'leaf-entry' },
20
+ model: undefined,
21
+ };
22
+ const generation = {
23
+ id: 1,
24
+ session,
25
+ fallback: { blocked: false },
26
+ stagedProviderAgentEnd: {
27
+ messages: [{ role: 'assistant', stopReason: 'aborted', errorMessage: 'Request was aborted' }],
28
+ },
29
+ stagedWatchdogAbort,
30
+ stagedOverflowFailure: null,
31
+ executingTools: new Set(),
32
+ };
33
+ const retry = new FaultRetry({
34
+ nodeId,
35
+ currentSession: () => session,
36
+ installedGeneration: () => generation,
37
+ });
38
+ retry.publishSettledProviderFault(generation);
39
+ return { retry, generation };
40
+ };
41
+ const watchdog = settleAbort('watchdog-node', true);
42
+ const fault = readFault('watchdog-node');
43
+ assert.equal(fault?.link, 'pi→provider');
44
+ assert.equal(fault?.kind, 'connection');
45
+ assert.deepEqual(fault?.retry, { disposition: 'auto', by: 'daemon' });
46
+ assert.equal(watchdog.retry.isActiveAutoFault(fault), true);
47
+ assert.equal(watchdog.generation.stagedWatchdogAbort, false, 'settlement consumes the one-shot provenance');
48
+ settleAbort('human-node', false);
49
+ assert.equal(readFault('human-node'), null, 'an otherwise-identical human abort must not arm recovery');
50
+ });