@crouton-kit/crouter 0.3.28 → 0.3.30

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 (324) hide show
  1. package/dist/build-root.d.ts +15 -7
  2. package/dist/build-root.js +48 -34
  3. package/dist/builtin-memory/crouter-development/marketplaces.md +7 -6
  4. package/dist/builtin-memory/crouter-development/personas/base-prompt.md +1 -1
  5. package/dist/builtin-memory/crouter-development/personas/orchestrator-prompt.md +1 -1
  6. package/dist/builtin-memory/crouter-development/personas.md +1 -1
  7. package/dist/builtin-memory/crouter-development/plugins.md +20 -18
  8. package/dist/builtin-memory/design.md +1 -1
  9. package/dist/builtin-memory/development.md +1 -1
  10. package/dist/builtin-memory/internal/INDEX.md +1 -1
  11. package/dist/builtin-memory/internal/examples/INDEX.md +1 -1
  12. package/dist/builtin-memory/internal/examples/imessage-assistant.md +2 -2
  13. package/dist/builtin-memory/internal/nodes-and-canvas.md +1 -1
  14. package/dist/builtin-memory/internal/storage-tiers.md +1 -1
  15. package/dist/builtin-memory/planning.md +1 -1
  16. package/dist/builtin-memory/spec.md +6 -4
  17. package/dist/builtin-personas/orchestration-kernel.md +4 -5
  18. package/dist/builtin-personas/runtime-base.md +5 -4
  19. package/dist/builtin-personas/spec/PERSONA.md +8 -4
  20. package/dist/builtin-personas/spec/orchestrator.md +5 -3
  21. package/dist/builtin-personas/spec/requirements/PERSONA.md +10 -0
  22. package/dist/builtin-views/canvas/core.mjs +586 -0
  23. package/dist/builtin-views/canvas/text.mjs +58 -0
  24. package/dist/builtin-views/canvas/tui.mjs +165 -0
  25. package/dist/builtin-views/canvas/web.jsx +120 -0
  26. package/dist/builtin-views/git-pr/core.mjs +673 -0
  27. package/dist/builtin-views/git-pr/text.mjs +84 -0
  28. package/dist/builtin-views/git-pr/tui.mjs +302 -0
  29. package/dist/builtin-views/git-pr/web.jsx +216 -0
  30. package/dist/builtin-views/inbox/_lib/render.mjs +1 -3
  31. package/dist/builtin-views/inbox/core.mjs +1273 -0
  32. package/dist/builtin-views/inbox/text.mjs +73 -0
  33. package/dist/builtin-views/inbox/tui.mjs +312 -0
  34. package/dist/builtin-views/inbox/web.jsx +188 -0
  35. package/dist/builtin-views/linkedin/core.mjs +906 -0
  36. package/dist/builtin-views/linkedin/text.mjs +69 -0
  37. package/dist/builtin-views/linkedin/tui.mjs +427 -0
  38. package/dist/builtin-views/linkedin/web.jsx +206 -0
  39. package/dist/builtin-views/workspace-sidebar/core.mjs +621 -0
  40. package/dist/builtin-views/workspace-sidebar/text.mjs +53 -0
  41. package/dist/builtin-views/workspace-sidebar/tui.mjs +142 -0
  42. package/dist/builtin-views/workspace-sidebar/web.jsx +109 -0
  43. package/dist/cli.js +22 -17
  44. package/dist/clients/attach/__tests__/action-parity.test.js +48 -0
  45. package/dist/clients/attach/__tests__/clipboard-image.test.js +76 -0
  46. package/dist/clients/attach/__tests__/editor-newline.test.js +57 -0
  47. package/dist/clients/attach/__tests__/git-info.test.js +31 -0
  48. package/dist/clients/attach/__tests__/onrequest-wired.test.js +20 -0
  49. package/dist/clients/attach/__tests__/slash-quit-copy.test.js +42 -0
  50. package/dist/clients/attach/__tests__/titled-editor.test.js +39 -0
  51. package/dist/clients/attach/attach-cmd.js +282 -46
  52. package/dist/clients/attach/auth-pickers.d.ts +9 -0
  53. package/dist/clients/attach/auth-pickers.js +194 -0
  54. package/dist/clients/attach/canvas-panels.d.ts +4 -2
  55. package/dist/clients/attach/canvas-panels.js +45 -17
  56. package/dist/clients/attach/chat-view.d.ts +27 -2
  57. package/dist/clients/attach/chat-view.js +98 -9
  58. package/dist/clients/attach/clipboard-image.d.ts +47 -8
  59. package/dist/clients/attach/clipboard-image.js +150 -26
  60. package/dist/clients/attach/clipboard-text.d.ts +3 -0
  61. package/dist/clients/attach/clipboard-text.js +39 -0
  62. package/dist/clients/attach/config-load.d.ts +54 -7
  63. package/dist/clients/attach/config-load.js +99 -3
  64. package/dist/clients/attach/context-message.d.ts +12 -0
  65. package/dist/clients/attach/context-message.js +72 -0
  66. package/dist/clients/attach/git-info.d.ts +20 -0
  67. package/dist/clients/attach/git-info.js +44 -0
  68. package/dist/clients/attach/graph-overlay.d.ts +13 -4
  69. package/dist/clients/attach/graph-overlay.js +59 -19
  70. package/dist/clients/attach/input-controller.d.ts +75 -13
  71. package/dist/clients/attach/input-controller.js +305 -67
  72. package/dist/clients/attach/pickers.d.ts +58 -0
  73. package/dist/clients/attach/pickers.js +171 -0
  74. package/dist/clients/attach/slash-commands.d.ts +22 -0
  75. package/dist/clients/attach/slash-commands.js +91 -25
  76. package/dist/clients/attach/titled-editor.d.ts +33 -0
  77. package/dist/clients/attach/titled-editor.js +84 -0
  78. package/dist/clients/attach/view-socket.d.ts +18 -1
  79. package/dist/clients/attach/view-socket.js +70 -1
  80. package/dist/clients/web/dev-server.d.ts +7 -0
  81. package/dist/clients/web/dev-server.js +59 -0
  82. package/dist/clients/web/events.d.ts +14 -0
  83. package/dist/clients/web/events.js +151 -0
  84. package/dist/clients/web/server.d.ts +18 -0
  85. package/dist/clients/web/server.js +450 -0
  86. package/dist/clients/web/web-cmd.d.ts +2 -0
  87. package/dist/clients/web/web-cmd.js +120 -0
  88. package/dist/commands/canvas.js +1 -2
  89. package/dist/commands/chord.js +4 -25
  90. package/dist/commands/dashboard.js +5 -1
  91. package/dist/commands/memory/__tests__/lint-schema.test.js +6 -6
  92. package/dist/commands/memory/lint.js +14 -2
  93. package/dist/commands/memory/read.js +2 -2
  94. package/dist/commands/memory/shared.d.ts +7 -1
  95. package/dist/commands/memory/shared.js +18 -3
  96. package/dist/commands/memory/write.js +8 -4
  97. package/dist/commands/memory.js +4 -4
  98. package/dist/commands/node.d.ts +1 -1
  99. package/dist/commands/node.js +64 -65
  100. package/dist/commands/pkg.js +1 -2
  101. package/dist/commands/revive.js +11 -3
  102. package/dist/commands/sys/sync.d.ts +1 -0
  103. package/dist/commands/sys/sync.js +187 -0
  104. package/dist/commands/sys.js +3 -2
  105. package/dist/commands/view-cycle.js +2 -2
  106. package/dist/commands/view-list.js +8 -8
  107. package/dist/commands/view-new.js +21 -17
  108. package/dist/commands/view-pick.js +1 -1
  109. package/dist/commands/view-run.js +35 -14
  110. package/dist/commands/view.js +8 -6
  111. package/dist/commands/workspace.d.ts +2 -0
  112. package/dist/commands/workspace.js +161 -0
  113. package/dist/core/__tests__/broker-double-spawn.test.d.ts +1 -0
  114. package/dist/core/__tests__/broker-double-spawn.test.js +143 -0
  115. package/dist/core/__tests__/broker-fork-seam.test.d.ts +1 -0
  116. package/dist/core/__tests__/broker-fork-seam.test.js +102 -0
  117. package/dist/core/__tests__/broker-sdk-wiring.test.js +2 -0
  118. package/dist/core/__tests__/child-death-wake.test.js +56 -111
  119. package/dist/core/__tests__/close.test.js +14 -20
  120. package/dist/core/__tests__/context-intro.test.js +19 -19
  121. package/dist/core/__tests__/daemon-boot.test.js +30 -23
  122. package/dist/core/__tests__/draw-style.test.js +1 -1
  123. package/dist/core/__tests__/error-stall-recycle.test.d.ts +1 -0
  124. package/dist/core/__tests__/error-stall-recycle.test.js +141 -0
  125. package/dist/core/__tests__/fixtures/fake-engine.d.ts +17 -1
  126. package/dist/core/__tests__/fixtures/fake-engine.js +22 -2
  127. package/dist/core/__tests__/fixtures/fake-pi-host.js +2 -2
  128. package/dist/core/__tests__/focuses.test.js +25 -13
  129. package/dist/core/__tests__/fork.test.js +22 -5
  130. package/dist/core/__tests__/full/broker-control-preempt.test.d.ts +1 -0
  131. package/dist/core/__tests__/full/broker-control-preempt.test.js +61 -0
  132. package/dist/core/__tests__/full/broker-model-changed-broadcast.test.d.ts +1 -0
  133. package/dist/core/__tests__/full/broker-model-changed-broadcast.test.js +57 -0
  134. package/dist/core/__tests__/full/broker-navigate-tree-rewelcome.test.d.ts +1 -0
  135. package/dist/core/__tests__/full/broker-navigate-tree-rewelcome.test.js +80 -0
  136. package/dist/core/__tests__/full/broker-pane-resolution.test.js +90 -0
  137. package/dist/core/__tests__/full/cascade-close.test.js +22 -8
  138. package/dist/core/__tests__/full/detach-focus.test.js +66 -169
  139. package/dist/core/__tests__/helpers/harness.d.ts +6 -9
  140. package/dist/core/__tests__/helpers/harness.js +19 -36
  141. package/dist/core/__tests__/human-node-not-supervised.test.d.ts +1 -0
  142. package/dist/core/__tests__/human-node-not-supervised.test.js +83 -0
  143. package/dist/core/__tests__/lifecycle.test.js +1 -19
  144. package/dist/core/__tests__/listing-completeness.test.js +2 -2
  145. package/dist/core/__tests__/live-mutation-verbs.test.js +5 -5
  146. package/dist/core/__tests__/memory-resolver.test.js +1 -1
  147. package/dist/core/__tests__/on-read-dedup-resume.test.js +2 -2
  148. package/dist/core/__tests__/refresh-stall-recycle.test.d.ts +1 -0
  149. package/dist/core/__tests__/refresh-stall-recycle.test.js +88 -0
  150. package/dist/core/__tests__/relaunch-root.test.d.ts +1 -0
  151. package/dist/core/__tests__/relaunch-root.test.js +114 -0
  152. package/dist/core/__tests__/reset.test.js +19 -79
  153. package/dist/core/__tests__/steer-note.test.js +9 -7
  154. package/dist/core/__tests__/tmux-surface.test.js +13 -7
  155. package/dist/core/bootstrap.d.ts +0 -3
  156. package/dist/core/bootstrap.js +1 -143
  157. package/dist/core/canvas/browse/__tests__/model.test.js +86 -1
  158. package/dist/core/canvas/browse/__tests__/render.test.js +2 -1
  159. package/dist/core/canvas/browse/app.js +131 -8
  160. package/dist/core/canvas/browse/model.d.ts +23 -5
  161. package/dist/core/canvas/browse/model.js +68 -13
  162. package/dist/core/canvas/browse/render.d.ts +7 -1
  163. package/dist/core/canvas/browse/render.js +178 -47
  164. package/dist/core/canvas/canvas.js +1 -1
  165. package/dist/core/canvas/focuses.d.ts +4 -4
  166. package/dist/core/canvas/focuses.js +7 -7
  167. package/dist/core/canvas/nav-model.js +8 -7
  168. package/dist/core/canvas/render.d.ts +68 -9
  169. package/dist/core/canvas/render.js +195 -61
  170. package/dist/core/canvas/types.d.ts +16 -23
  171. package/dist/core/config.js +1 -4
  172. package/dist/core/memory-resolver.js +43 -5
  173. package/dist/core/runtime/bearings.d.ts +1 -1
  174. package/dist/core/runtime/bearings.js +8 -8
  175. package/dist/core/runtime/branded-host.d.ts +16 -0
  176. package/dist/core/runtime/branded-host.js +127 -0
  177. package/dist/core/runtime/broker-protocol.d.ts +212 -6
  178. package/dist/core/runtime/broker.d.ts +4 -1
  179. package/dist/core/runtime/broker.js +494 -58
  180. package/dist/core/runtime/close.d.ts +12 -2
  181. package/dist/core/runtime/close.js +37 -16
  182. package/dist/core/runtime/front-door.js +6 -14
  183. package/dist/core/runtime/host.d.ts +14 -34
  184. package/dist/core/runtime/host.js +14 -50
  185. package/dist/core/runtime/launch.d.ts +12 -9
  186. package/dist/core/runtime/launch.js +27 -15
  187. package/dist/core/runtime/lifecycle.d.ts +1 -1
  188. package/dist/core/runtime/lifecycle.js +15 -19
  189. package/dist/core/runtime/nodes.d.ts +0 -55
  190. package/dist/core/runtime/nodes.js +6 -74
  191. package/dist/core/runtime/placement.d.ts +91 -335
  192. package/dist/core/runtime/placement.js +291 -858
  193. package/dist/core/runtime/promote.d.ts +2 -0
  194. package/dist/core/runtime/promote.js +24 -6
  195. package/dist/core/runtime/recap.d.ts +8 -0
  196. package/dist/core/runtime/recap.js +107 -0
  197. package/dist/core/runtime/recycle.js +25 -61
  198. package/dist/core/runtime/reset.d.ts +43 -37
  199. package/dist/core/runtime/reset.js +131 -218
  200. package/dist/core/runtime/revive.d.ts +9 -29
  201. package/dist/core/runtime/revive.js +40 -139
  202. package/dist/core/runtime/spawn.d.ts +15 -16
  203. package/dist/core/runtime/spawn.js +165 -194
  204. package/dist/core/runtime/surface-bg.d.ts +11 -0
  205. package/dist/core/runtime/surface-bg.js +68 -0
  206. package/dist/core/runtime/tmux.d.ts +15 -52
  207. package/dist/core/runtime/tmux.js +35 -99
  208. package/dist/core/scope.d.ts +1 -2
  209. package/dist/core/scope.js +1 -5
  210. package/dist/core/skill-sync/__tests__/dry-run-wrote-count.test.d.ts +1 -0
  211. package/dist/core/skill-sync/__tests__/dry-run-wrote-count.test.js +57 -0
  212. package/dist/core/skill-sync/builtins.d.ts +42 -0
  213. package/dist/core/skill-sync/builtins.js +112 -0
  214. package/dist/core/skill-sync/claude-plugins.d.ts +23 -0
  215. package/dist/core/skill-sync/claude-plugins.js +71 -0
  216. package/dist/core/skill-sync/engine.d.ts +42 -0
  217. package/dist/core/skill-sync/engine.js +633 -0
  218. package/dist/core/skill-sync/export.d.ts +23 -0
  219. package/dist/core/skill-sync/export.js +86 -0
  220. package/dist/core/skill-sync/manifest.d.ts +64 -0
  221. package/dist/core/skill-sync/manifest.js +181 -0
  222. package/dist/core/skill-sync/profile.d.ts +76 -0
  223. package/dist/core/skill-sync/profile.js +173 -0
  224. package/dist/core/skill-sync/snapshot.d.ts +57 -0
  225. package/dist/core/skill-sync/snapshot.js +120 -0
  226. package/dist/core/substrate/index.d.ts +1 -1
  227. package/dist/core/substrate/index.js +1 -1
  228. package/dist/core/substrate/injected-store.js +3 -3
  229. package/dist/core/substrate/on-read.js +68 -6
  230. package/dist/core/substrate/render.d.ts +8 -11
  231. package/dist/core/substrate/render.js +29 -43
  232. package/dist/core/substrate/schema.d.ts +10 -3
  233. package/dist/core/substrate/schema.js +6 -3
  234. package/dist/core/tui/host.d.ts +12 -4
  235. package/dist/core/tui/host.js +280 -149
  236. package/dist/core/view/bridge.d.ts +10 -0
  237. package/dist/core/view/bridge.js +31 -0
  238. package/dist/core/view/chrome.d.ts +9 -0
  239. package/dist/core/view/chrome.js +22 -0
  240. package/dist/core/view/contract.d.ts +171 -0
  241. package/dist/core/view/contract.js +23 -0
  242. package/dist/core/view/loader.d.ts +31 -0
  243. package/dist/core/view/loader.js +188 -0
  244. package/dist/core/view/transport-local.d.ts +7 -0
  245. package/dist/core/view/transport-local.js +70 -0
  246. package/dist/core/view/transport.d.ts +4 -0
  247. package/dist/core/view/transport.js +15 -0
  248. package/dist/daemon/crtrd.d.ts +38 -27
  249. package/dist/daemon/crtrd.js +303 -376
  250. package/dist/daemon/manage.js +6 -1
  251. package/dist/index.js +1 -1
  252. package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +28 -20
  253. package/dist/pi-extensions/canvas-context-intro.js +4 -4
  254. package/dist/pi-extensions/canvas-doc-substrate.js +16 -16
  255. package/dist/pi-extensions/canvas-nav.js +5 -0
  256. package/dist/pi-extensions/canvas-recap.d.ts +37 -0
  257. package/dist/pi-extensions/canvas-recap.js +236 -0
  258. package/dist/pi-extensions/canvas-resume.js +2 -1
  259. package/dist/pi-extensions/canvas-stophook.d.ts +14 -12
  260. package/dist/pi-extensions/canvas-stophook.js +87 -101
  261. package/dist/pi-extensions/canvas-view.js +2 -1
  262. package/dist/pi-extensions/widget-order-bus.d.ts +6 -0
  263. package/dist/pi-extensions/widget-order-bus.js +34 -0
  264. package/dist/prompts/view.d.ts +2 -2
  265. package/dist/prompts/view.js +145 -73
  266. package/dist/types.d.ts +1 -6
  267. package/dist/types.js +1 -3
  268. package/dist/web/ViewChrome.d.ts +7 -0
  269. package/dist/web/ViewChrome.js +28 -0
  270. package/dist/web/ViewPane.d.ts +39 -0
  271. package/dist/web/ViewPane.js +48 -0
  272. package/dist/web/index.d.ts +6 -0
  273. package/dist/web/index.js +16 -0
  274. package/dist/web/runtime.d.ts +39 -0
  275. package/dist/web/runtime.js +133 -0
  276. package/dist/web/states.d.ts +24 -0
  277. package/dist/web/states.js +24 -0
  278. package/dist/web/transport-http.d.ts +5 -0
  279. package/dist/web/transport-http.js +28 -0
  280. package/dist/web-client/assets/index-BUvQb4hR.css +2 -0
  281. package/dist/web-client/assets/index-ClLQXYAE.js +10 -0
  282. package/dist/web-client/index.html +13 -0
  283. package/package.json +20 -6
  284. package/dist/builtin-views/canvas/client.mjs +0 -303
  285. package/dist/builtin-views/canvas/view.mjs +0 -576
  286. package/dist/builtin-views/git-pr/client.mjs +0 -440
  287. package/dist/builtin-views/git-pr/view.mjs +0 -675
  288. package/dist/builtin-views/inbox/sources/gmail.mjs +0 -965
  289. package/dist/builtin-views/inbox/sources/linkedin.mjs +0 -427
  290. package/dist/builtin-views/inbox/view.mjs +0 -889
  291. package/dist/builtin-views/linkedin/client.mjs +0 -610
  292. package/dist/builtin-views/linkedin/view.mjs +0 -1171
  293. package/dist/commands/pkg/bridge.d.ts +0 -1
  294. package/dist/commands/pkg/bridge.js +0 -137
  295. package/dist/commands/skill/author.d.ts +0 -3
  296. package/dist/commands/skill/author.js +0 -140
  297. package/dist/commands/skill/shared.d.ts +0 -3
  298. package/dist/commands/skill/shared.js +0 -19
  299. package/dist/commands/skill.d.ts +0 -2
  300. package/dist/commands/skill.js +0 -21
  301. package/dist/commands/tmux-spread.d.ts +0 -2
  302. package/dist/commands/tmux-spread.js +0 -144
  303. package/dist/core/__tests__/full/daemon-liveness-pane.full.test.js +0 -292
  304. package/dist/core/__tests__/full/placement-focus.test.js +0 -309
  305. package/dist/core/__tests__/full/placement-reconcile.test.js +0 -212
  306. package/dist/core/__tests__/full/placement-revive.test.js +0 -238
  307. package/dist/core/__tests__/full/placement-teardown.test.js +0 -297
  308. package/dist/core/__tests__/home-session.test.js +0 -186
  309. package/dist/core/__tests__/relaunch.test.js +0 -335
  310. package/dist/core/bridge-map.d.ts +0 -19
  311. package/dist/core/bridge-map.js +0 -73
  312. package/dist/core/tui/contract.d.ts +0 -83
  313. package/dist/core/tui/contract.js +0 -8
  314. package/dist/core/tui/loader.d.ts +0 -16
  315. package/dist/core/tui/loader.js +0 -94
  316. package/dist/prompts/skill.d.ts +0 -2
  317. package/dist/prompts/skill.js +0 -650
  318. /package/dist/{core/__tests__/full/daemon-liveness-pane.full.test.d.ts → clients/attach/__tests__/action-parity.test.d.ts} +0 -0
  319. /package/dist/{core/__tests__/full/placement-focus.test.d.ts → clients/attach/__tests__/clipboard-image.test.d.ts} +0 -0
  320. /package/dist/{core/__tests__/full/placement-reconcile.test.d.ts → clients/attach/__tests__/editor-newline.test.d.ts} +0 -0
  321. /package/dist/{core/__tests__/full/placement-revive.test.d.ts → clients/attach/__tests__/git-info.test.d.ts} +0 -0
  322. /package/dist/{core/__tests__/full/placement-teardown.test.d.ts → clients/attach/__tests__/onrequest-wired.test.d.ts} +0 -0
  323. /package/dist/{core/__tests__/home-session.test.d.ts → clients/attach/__tests__/slash-quit-copy.test.d.ts} +0 -0
  324. /package/dist/{core/__tests__/relaunch.test.d.ts → clients/attach/__tests__/titled-editor.test.d.ts} +0 -0
@@ -1,27 +1,25 @@
1
- // The revive primitive — restores a node to active status under a fresh tmux
2
- // window. Used by both the supervisor daemon (on crash/refresh detection) and
3
- // the explicit `crtr canvas revive` command.
1
+ // The revive primitive — restores a node to active status by relaunching its
2
+ // broker engine. Used by both the supervisor daemon (on crash/refresh
3
+ // detection) and the explicit `crtr canvas revive` command.
4
4
  //
5
5
  // A revive replays the node's persisted LaunchSpec + cwd (the canonical recipe)
6
- // and routes PLACEMENT through reviveIntoPlacement (§1.4): a non-focused node
7
- // opens a fresh background window in its home_session (the backstage `crtr` for
8
- // a child NEVER a user session); a node that occupies a LIVE focus resumes IN
9
- // PLACE in that focus pane (respawn-pane -k, no new window). reviveNode never
10
- // targets meta.tmux_session, so a background revive can no longer open an
11
- // unbidden window in the user's session.
6
+ // and launches the headless broker host (the only host after the
7
+ // broker-is-the-host cut). It opens NO viewer it relaunches the engine only;
8
+ // existing viewer panes reconnect to the fresh broker on their own (attach
9
+ // auto-reconnect), and a node with no viewer is brought on screen by the next
10
+ // `focus`.
12
11
  //
13
12
  // resume=true → `pi --session <path|id>` — wakes the saved conversation,
14
13
  // preferring the absolute session-file path (cwd-immune) over
15
14
  // the bare session id.
16
15
  // resume=false → fresh pi invocation — the node re-reads its roadmap/context dir.
17
- import { getNode, updateNode, setPresence, clearPid, fullName, cancelDeadlinesFor, } from '../canvas/index.js';
16
+ //
17
+ // reviveNode remains the ONLY sanctioned launcher of the node engine.
18
+ import { getNode, updateNode, clearPid, fullName, cancelDeadlinesFor, } from '../canvas/index.js';
18
19
  import { transition } from './lifecycle.js';
19
20
  import { buildPiArgv } from './launch.js';
20
21
  import { buildReviveKickoff, drainBearings } from './kickoff.js';
21
- import { FRONT_DOOR_ENV } from './front-door.js';
22
- import { reconcile, piCommand, respawnPane, } from './placement.js';
23
- import { hostFor } from './host.js';
24
- import { nodeSession, childBackstageOf, rootOfSpine } from './nodes.js';
22
+ import { headlessBrokerHost } from './host.js';
25
23
  import { isPidAlive } from '../canvas/pid.js';
26
24
  import { clearInjectedDocs } from '../substrate/injected-store.js';
27
25
  // ---------------------------------------------------------------------------
@@ -44,29 +42,33 @@ export function resumeArgs(meta, resume) {
44
42
  // ---------------------------------------------------------------------------
45
43
  // reviveNode
46
44
  // ---------------------------------------------------------------------------
47
- /** Open a fresh background tmux window for `nodeId` and update canvas meta.
45
+ /** Relaunch `nodeId`'s broker engine from its persisted recipe and update canvas
46
+ * meta. Opens no viewer (engine-only).
48
47
  *
49
- * Throws if the node does not exist. All other failures (e.g. tmux not
50
- * available) propagate as-is — callers (daemon, command) decide how to handle.
48
+ * Throws if the node does not exist. All other failures propagate as-is
49
+ * callers (daemon, command) decide how to handle.
51
50
  */
52
51
  export function reviveNode(nodeId, opts) {
53
52
  const meta = getNode(nodeId);
54
53
  if (meta === null) {
55
54
  throw new Error(`reviveNode: unknown node ${nodeId}`);
56
55
  }
57
- // Double-revive guard (pane-keyed, §2.4): reconcile FIRST so a user-moved pane
58
- // isn't misread as "not yet revived", then probe pane-existence. A node whose
59
- // pane is alive AND whose pi is still RUNNING was already revived by another
60
- // path; re-launching would put a SECOND pi on the same session file — no-op.
61
- // A FROZEN focus pane (remain-on-exit, F3) is pane-alive but pi-DEAD: that is
62
- // the resume-into-focus case and MUST proceed (respawn-pane -k back into the
63
- // frozen pane), so the guard gates on pi liveness too, not pane-existence alone.
64
- reconcile(nodeId);
56
+ // Lazy host_kind coerce C): a pre-cut row carries host_kind null or 'tmux'.
57
+ // Every launcher now uses the broker host regardless, loading the same
58
+ // host-agnostic session.jsonl; persist 'broker' so inspect/history read honest
59
+ // values and the daemon never branches it back. Mutate the in-memory meta too.
60
+ if (meta.host_kind !== 'broker') {
61
+ updateNode(nodeId, { host_kind: 'broker' });
62
+ meta.host_kind = 'broker';
63
+ }
64
+ // Double-revive guard: the broker's isAlive IS isPidAlive(pi_pid), so a node
65
+ // whose broker pid is still running was already revived by another path —
66
+ // re-launching would put a SECOND broker on the same session file. No-op.
65
67
  const live = getNode(nodeId) ?? meta;
66
- if (hostFor(live).isAlive(nodeId) && isPidAlive(live.pi_pid)) {
68
+ if (isPidAlive(live.pi_pid)) {
67
69
  return {
68
- window: live.window ?? null,
69
- session: live.tmux_session ?? nodeSession(),
70
+ window: null,
71
+ session: live.tmux_session ?? null,
70
72
  resumed: false,
71
73
  };
72
74
  }
@@ -99,125 +101,24 @@ export function reviveNode(nodeId, opts) {
99
101
  // would instead KEEP the persisted set, continuing the same transcript).
100
102
  clearInjectedDocs(nodeId);
101
103
  }
102
- // Placement owns WHERE this revive lands (§1.4): resume into a live focus pane
103
- // if the node occupies one, else a fresh window in its home_session (the
104
- // backstage `crtr` for a child NEVER a user session). reviveIntoPlacement
105
- // performs the one atomic setPresence; reviveNode keeps transition+clearPid
106
- // around it (the crash-safety ordering, unchanged). THIS is the bug-kill: a
107
- // non-focused background revive can no longer new-window into a user session.
104
+ // The broker host launches the detached engine. reviveNode keeps
105
+ // transition+clearPid around it (the crash-safety ordering, unchanged). It
106
+ // opens NO viewer engine-only; existing viewers reconnect, and a viewer-less
107
+ // node is brought on screen by the next `focus`.
108
108
  transition(nodeId, 'revive');
109
109
  // Cancel-on-wake (design §6.4, AC-E1): every revive-for-any-reason (an inbox
110
110
  // event, a different wake, a manual focus) drops this node's pending deadline,
111
111
  // so the deadline always belongs to the dormancy being left. Writes only the
112
- // wakeups table, after the atomic transition above. (reviveInPlace's
113
- // transition('boot') needs NO hook — a refresh is the same node continuing,
114
- // not leaving a dormancy.)
112
+ // wakeups table, after the atomic transition above.
115
113
  cancelDeadlinesFor(nodeId);
116
- const placed = hostFor(meta).launch(nodeId, inv, {
114
+ headlessBrokerHost.launch(nodeId, inv, {
117
115
  cwd: meta.cwd,
118
116
  name: fullName(meta),
119
117
  resuming,
120
118
  });
121
- // Window-backed launch: clear the stale pid so the daemon won't re-fire on
122
- // it during the new pi's boot. The fresh pi re-records its pid on
123
- // session_start; if it never boots, this window closes and the window-gone
124
- // pass reaps it.
119
+ // Clear the stale pid so the daemon won't re-fire on it during the new
120
+ // broker's boot. The fresh broker re-records its pid during extension bind; if
121
+ // it never boots, the daemon's boot-grace + surfaceBootFailure own that case.
125
122
  clearPid(nodeId);
126
- return { window: placed.window, session: placed.session, resumed: resuming };
127
- }
128
- // ---------------------------------------------------------------------------
129
- // reviveInPlace — refresh-yield without churning the window
130
- // ---------------------------------------------------------------------------
131
- /** Re-exec a node's pi FRESH in its EXISTING tmux pane (the refresh-yield
132
- * path). Unlike `reviveNode`, this opens no new window: the pane's current pi
133
- * is replaced in place via `respawn-pane -k`, so a foreground/interactive
134
- * session keeps its terminal and a background node keeps its window. Always
135
- * fresh (no resume) — the node re-reads its roadmap/context dir.
136
- *
137
- * `pane` is the target pane id (the yielding node reads it from $TMUX_PANE).
138
- * Throws on unknown node or when the respawn could not be dispatched, so the
139
- * caller can fall back to a plain shutdown (daemon revives in a new window). */
140
- export function reviveInPlace(nodeId, pane, respawn = respawnPane) {
141
- const meta = getNode(nodeId);
142
- if (meta === null) {
143
- throw new Error(`reviveInPlace: unknown node ${nodeId}`);
144
- }
145
- // A refresh-yield is a cycle too — advance the label's trailing N.
146
- meta.cycles = (meta.cycles ?? 0) + 1;
147
- updateNode(nodeId, { cycles: meta.cycles });
148
- // Fresh re-exec → new transcript: reset the on-read doc dedup.
149
- clearInjectedDocs(nodeId);
150
- // The node's LOCATION — the session its pane physically lives in. The re-exec
151
- // is IN PLACE (the pane never moves), so this is preserved unchanged below.
152
- const session = meta.tmux_session ?? nodeSession();
153
- // Fresh re-exec: same recipe as a no-resume reviveNode, with the kickoff so
154
- // the node rebuilds its bearings from disk. Drain the one-shot bearings first,
155
- // then build purely.
156
- const bearings = drainBearings(meta);
157
- const inv = buildPiArgv(meta, { prompt: buildReviveKickoff(meta, bearings) });
158
- // CRTR_ROOT_SESSION is the backstage this node's CHILDREN spawn into — NOT the
159
- // pane's live `session`. A FOCUSED child's pane is in a USER session (focus
160
- // taints meta.tmux_session), so sourcing it from `session` would land any
161
- // child it spawns in the user's session, re-tainting that child's
162
- // home_session (A-MAJOR-1). childBackstageOf is the taint-immune backstage:
163
- // home_session for a managed child, but `nodeSession()` for a ROOT (whose
164
- // home_session may itself be a user session it adopted via the inline front
165
- // door — sourcing children from it would re-point the root's whole subtree
166
- // into the user's session on every refresh-yield).
167
- const env = { ...inv.env, CRTR_ROOT_SESSION: childBackstageOf(nodeId), CRTR_SUBTREE: rootOfSpine(nodeId) };
168
- const ok = respawn({ pane, cwd: meta.cwd, env, command: piCommand(inv.argv) });
169
- if (!ok) {
170
- throw new Error(`reviveInPlace: respawn-pane dispatch failed for ${nodeId}`);
171
- }
172
- // Deliberately DO NOT clear intent here, and DO NOT touch pi_pid. The detached
173
- // respawn-pane can't confirm it actually replaced the pi (it kills this very
174
- // process mid-flight), so clearing intent optimistically is how a failed
175
- // refresh became a silent death: the fresh pi never boots, yet meta says the
176
- // refresh completed. Instead we leave intent='refresh' (the fresh pi clears it
177
- // on boot — the only proof the respawn worked) and leave pi_pid as the OLD
178
- // pid. If the respawn succeeds, the old pi dies and the fresh one overwrites
179
- // pid+intent within the daemon's grace window; if it fails, the old pid stays
180
- // dead and the daemon's pi-liveness pass revives the node.
181
- transition(nodeId, 'boot');
182
- // tmux_session may have resolved to the shared session; window is unchanged
183
- // (we re-execed in place), so preserve it explicitly.
184
- setPresence(nodeId, { tmux_session: session, window: meta.window ?? null });
185
- // Window is unchanged (we re-execed in place); report the existing one.
186
- return { window: meta.window ?? null, session, resumed: false };
187
- }
188
- // ---------------------------------------------------------------------------
189
- // relaunchRootInPane — boot a CLEAN fresh root in the current pane (option C)
190
- // ---------------------------------------------------------------------------
191
- /** Re-exec a FRESH pi for `nodeId` in EXISTING `pane` (respawn-pane -k), with
192
- * NO prompt and NO resume — a clean root conversation (goal-capture /
193
- * context-intro handle the first message + bearings, exactly like bare
194
- * `crtr`). Unlike reviveInPlace: no buildReviveKickoff prompt, no cycles bump,
195
- * and it sets CRTR_FRONT_DOOR=1 (REQUIRED — src/core/runtime/CLAUDE.md: any
196
- * path that boots a pi must guard against a removed/renamed subcommand
197
- * fork-bombing). Throws if the respawn could not be dispatched.
198
- *
199
- * Used by relaunchRoot (reset.ts) for the `/new`-in-a-root relaunch. Kept
200
- * SEPARATE from reviveInPlace so the refresh-yield path's exact semantics
201
- * (kickoff + cycle bump) are untouched. */
202
- export function relaunchRootInPane(nodeId, pane) {
203
- const meta = getNode(nodeId);
204
- if (meta === null) {
205
- throw new Error(`relaunchRootInPane: unknown node ${nodeId}`);
206
- }
207
- // No prompt, no resume → a brand-new root conversation at cycle 0.
208
- // Brand-new transcript: reset the on-read doc dedup.
209
- clearInjectedDocs(nodeId);
210
- const inv = buildPiArgv(meta, {});
211
- // Source CRTR_ROOT_SESSION from childBackstageOf, the same backstage rule as
212
- // reviveInPlace. relaunchRootInPane runs only on a root, whose children must
213
- // flow to the shared backstage `nodeSession()` — never the root's own adopted
214
- // user session — so both in-pane revive paths stay sourced identically.
215
- const env = { ...inv.env, CRTR_ROOT_SESSION: childBackstageOf(nodeId), CRTR_SUBTREE: rootOfSpine(nodeId), [FRONT_DOOR_ENV]: '1' };
216
- const ok = respawnPane({ pane, cwd: meta.cwd, env, command: piCommand(inv.argv) });
217
- if (!ok) {
218
- throw new Error(`relaunchRootInPane: respawn-pane dispatch failed for ${nodeId}`);
219
- }
220
- // Do NOT clear intent/pi_pid here — the fresh pi clears intent='refresh' on
221
- // its session_start boot (the only proof the respawn worked), same dance as
222
- // reviveInPlace.
123
+ return { window: null, session: meta.tmux_session ?? null, resumed: resuming };
223
124
  }
@@ -6,14 +6,11 @@ export interface BootRootOpts {
6
6
  name?: string;
7
7
  /** Optional starter prompt (bare `crtr` requires none). */
8
8
  prompt?: string;
9
- /** Tri-state host selection: `true`/`false` from an explicit
10
- * `--headless`/`--no-headless`, `undefined` to defer to the `headless`
11
- * config default. When it resolves to broker, the front door boots a
12
- * DETACHED broker root and auto-attaches a viewer inline in this pane. */
13
- headless?: boolean;
14
9
  }
15
- /** Create a root node and bring up its pi. Returns the node; for 'inline' this
16
- * only returns after pi exits (it took over the terminal). */
10
+ /** Create the front-door root: launch its broker engine, then exec `crtr attach`
11
+ * inline so THIS terminal becomes the broker's controller-viewer. Does not
12
+ * return — it process.exit()s when the inline attach exits (detach leaves the
13
+ * resident broker running, to be reconnected later). */
17
14
  export declare function bootRoot(opts: BootRootOpts): NodeMeta;
18
15
  export interface SpawnChildOpts {
19
16
  kind: string;
@@ -40,24 +37,26 @@ export interface SpawnChildOpts {
40
37
  * a <crtr-wake> block is prepended to the kickoff so the newborn knows a clock
41
38
  * birthed it. */
42
39
  wakeOrigin?: WakeOrigin;
43
- /** Which HOST launches + supervises this node: a tmux pane (default) or the
44
- * headless broker. Persisted as `host_kind` at birth (resolved from
45
- * `--headless` / the `headless` config default by the caller). */
46
- hostKind?: 'tmux' | 'broker';
47
40
  /** Pin the node to a model TIER (ultra/strong/medium/light), overriding the
48
41
  * persona's declared default. Persisted to `meta.model_override` so it
49
42
  * survives polymorphs. Omit to use the persona default. */
50
43
  model?: string;
51
44
  }
52
- /** Resolve a `--fork-from` value to the source pi gets as `--fork <path|id>`.
53
- * A live node id resolves to its captured session FILE (absolute, cwd-immune),
54
- * falling back to its bare session id; a path or partial uuid passes straight
55
- * through to pi. Throws when a known node has no session to fork yet. */
45
+ /** Resolve a `--fork-from` value to an ABSOLUTE `.jsonl` source path for the
46
+ * broker fork (`SessionManager.forkFrom`, which loads a file never a bare id).
47
+ * A live node id resolves to its captured session FILE (absolute, cwd-immune); a
48
+ * relative path is made absolute; a bare/partial uuid is resolved against pi's
49
+ * sessions store. Throws when a known node has no captured session file, or when
50
+ * a uuid resolves to zero or multiple sessions. */
56
51
  export declare function resolveForkSource(value: string): string;
57
52
  export interface SpawnChildResult {
58
53
  node: NodeMeta;
54
+ /** The viewer window opened for a --root in tmux; null otherwise (a managed
55
+ * child opens no viewer, and a --root spawned outside tmux opens none). */
59
56
  window: string | null;
60
- session: string;
57
+ /** The session the --root's viewer opened into (the caller's current session);
58
+ * null when no viewer was opened. */
59
+ session: string | null;
61
60
  }
62
61
  /** Resolve who a spawn is attributed to. A managed child needs a spine parent
63
62
  * (explicit `--parent` or the calling node's CRTR_NODE_ID). A --root spawn