@north-light/crouter 0.3.170 → 0.3.172

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 (670) hide show
  1. package/dist/api/client.d.ts +37 -11
  2. package/dist/api/client.js +84 -15
  3. package/dist/api/dto/human.d.ts +53 -39
  4. package/dist/api/dto/human.js +2 -3
  5. package/dist/api/dto/inbox.d.ts +0 -1
  6. package/dist/api/dto/nodes.d.ts +12 -0
  7. package/dist/api/dto/review-comments.d.ts +137 -0
  8. package/dist/api/dto/review-comments.js +5 -0
  9. package/dist/api/dto/reviews.d.ts +109 -0
  10. package/dist/api/dto/reviews.js +5 -0
  11. package/dist/api/index.d.ts +2 -0
  12. package/dist/api/index.js +2 -0
  13. package/dist/api/routes.d.ts +17 -4
  14. package/dist/api/routes.js +21 -5
  15. package/dist/build-root.d.ts +1 -16
  16. package/dist/build-root.js +1 -25
  17. package/dist/builtin-memory/00-runtime-base.md +7 -5
  18. package/dist/builtin-memory/04-base-worker.md +1 -1
  19. package/dist/builtin-memory/04-orchestration-kernel.md +7 -7
  20. package/dist/builtin-memory/05-kinds/design/00-base.md +1 -1
  21. package/dist/builtin-memory/05-kinds/design/01-orchestrator.md +1 -1
  22. package/dist/builtin-memory/05-kinds/developer/00-base.md +1 -1
  23. package/dist/builtin-memory/05-kinds/explore/00-base.md +1 -1
  24. package/dist/builtin-memory/05-kinds/plan/00-base.md +1 -1
  25. package/dist/builtin-memory/05-kinds/plan/01-orchestrator.md +1 -1
  26. package/dist/builtin-memory/05-kinds/review/00-base.md +1 -1
  27. package/dist/builtin-memory/05-kinds/review/companion/00-base.md +20 -0
  28. package/dist/builtin-memory/05-kinds/spec/00-base.md +3 -7
  29. package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +3 -3
  30. package/dist/builtin-memory/05-kinds/spec/requirements.md +3 -3
  31. package/dist/builtin-memory/design.md +2 -2
  32. package/dist/builtin-memory/insights/capture.md +50 -0
  33. package/dist/builtin-memory/insights/init.md +45 -0
  34. package/dist/builtin-memory/insights/listen.md +9 -0
  35. package/dist/builtin-memory/internal/agent-shaping.md +2 -2
  36. package/dist/builtin-memory/internal/nodes-and-canvas.md +1 -1
  37. package/dist/builtin-memory/internal/plugins.md +12 -11
  38. package/dist/builtin-memory/internal/storage-tiers.md +2 -2
  39. package/dist/builtin-memory/{planning.md → plan/roadmap.md} +3 -3
  40. package/dist/builtin-memory/plan.md +19 -0
  41. package/dist/builtin-memory/spec/guide.md +38 -0
  42. package/dist/builtin-memory/spec/requirements.md +31 -0
  43. package/dist/builtin-memory/spec/roadmap.md +35 -0
  44. package/dist/builtin-memory/spec.md +10 -86
  45. package/dist/builtin-pi-packages/pi-crtr-extensions/README.md +3 -4
  46. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/provider-rotation.test.ts +49 -5
  47. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.d.ts +56 -0
  48. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.js +920 -0
  49. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/provider-rotation.ts +221 -156
  50. package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/statusline.ts +4 -5
  51. package/dist/cli.js +2 -6
  52. package/dist/clients/attach/__tests__/attach-chrome-remote.test.js +7 -35
  53. package/dist/clients/attach/__tests__/attach-keybindings.test.js +32 -16
  54. package/dist/clients/attach/__tests__/context-message.test.js +142 -6
  55. package/dist/clients/attach/__tests__/crtr-output.test.js +29 -45
  56. package/dist/clients/attach/__tests__/diagram.test.js +1 -1
  57. package/dist/clients/attach/__tests__/file-review-focus.test.js +48 -0
  58. package/dist/clients/attach/__tests__/group-activity.test.js +266 -0
  59. package/dist/clients/attach/__tests__/input-controller-extension-command.test.js +32 -0
  60. package/dist/clients/attach/__tests__/session-identity-refresh.test.js +32 -0
  61. package/dist/clients/attach/__tests__/titled-editor-preview.test.js +1 -2
  62. package/dist/clients/attach/chrome/header.d.ts +10 -0
  63. package/dist/clients/attach/chrome/header.js +30 -0
  64. package/dist/clients/attach/chrome/recap.d.ts +7 -0
  65. package/dist/clients/attach/chrome/recap.js +19 -0
  66. package/dist/clients/attach/chrome/status-line.d.ts +3 -0
  67. package/dist/clients/attach/chrome/status-line.js +5 -0
  68. package/dist/clients/attach/chrome/widgets.js +11 -21
  69. package/dist/clients/attach/command.js +11 -7
  70. package/dist/clients/attach/config.d.ts +4 -0
  71. package/dist/clients/attach/config.js +3 -0
  72. package/dist/clients/attach/input/controller.d.ts +19 -0
  73. package/dist/clients/attach/input/controller.js +62 -28
  74. package/dist/clients/attach/input/titled-editor.d.ts +0 -4
  75. package/dist/clients/attach/input/titled-editor.js +2 -10
  76. package/dist/clients/attach/overlays/file-review.d.ts +9 -5
  77. package/dist/clients/attach/overlays/file-review.js +9 -70
  78. package/dist/clients/attach/overlays/help.d.ts +33 -0
  79. package/dist/clients/attach/overlays/help.js +204 -0
  80. package/dist/clients/attach/render/activity-slot.d.ts +4 -0
  81. package/dist/clients/attach/render/activity-slot.js +13 -0
  82. package/dist/clients/attach/render/chat-view.d.ts +117 -12
  83. package/dist/clients/attach/render/chat-view.js +604 -135
  84. package/dist/clients/attach/render/context-message.d.ts +2 -1
  85. package/dist/clients/attach/render/context-message.js +17 -13
  86. package/dist/clients/attach/render/crtr-output.js +1 -3
  87. package/dist/clients/attach/render/diagram.js +2 -2
  88. package/dist/clients/attach/render/edit-diff.d.ts +4 -1
  89. package/dist/clients/attach/render/edit-diff.js +7 -11
  90. package/dist/clients/attach/render/group-activity.d.ts +32 -0
  91. package/dist/clients/attach/render/group-activity.js +206 -0
  92. package/dist/clients/attach/render/group-recap.d.ts +10 -0
  93. package/dist/clients/attach/render/group-recap.js +93 -0
  94. package/dist/clients/attach/render/html-markdown.d.ts +17 -0
  95. package/dist/clients/attach/render/html-markdown.js +228 -0
  96. package/dist/clients/attach/render/measured-container.d.ts +96 -0
  97. package/dist/clients/attach/render/measured-container.js +322 -0
  98. package/dist/clients/attach/render/scroll-animation.d.ts +8 -0
  99. package/dist/clients/attach/render/scroll-animation.js +80 -0
  100. package/dist/clients/attach/render/tool-calls.js +6 -6
  101. package/dist/clients/attach/render/transcript-copy.d.ts +9 -0
  102. package/dist/clients/attach/render/transcript-copy.js +81 -0
  103. package/dist/clients/attach/render/viewport.d.ts +29 -0
  104. package/dist/clients/attach/render/viewport.js +159 -0
  105. package/dist/clients/attach/session/bindings.d.ts +10 -7
  106. package/dist/clients/attach/session/bindings.js +23 -8
  107. package/dist/clients/attach/session/connection.js +4 -5
  108. package/dist/clients/attach/session/context.d.ts +6 -4
  109. package/dist/clients/attach/session/frame.d.ts +34 -0
  110. package/dist/clients/attach/session/frame.js +176 -0
  111. package/dist/clients/attach/session/frames.d.ts +4 -1
  112. package/dist/clients/attach/session/frames.js +14 -1
  113. package/dist/clients/attach/session/identity.js +4 -3
  114. package/dist/clients/attach/session/input-wiring.d.ts +14 -4
  115. package/dist/clients/attach/session/input-wiring.js +15 -13
  116. package/dist/clients/attach/session/invariant.d.ts +9 -0
  117. package/dist/clients/attach/session/invariant.js +15 -0
  118. package/dist/clients/attach/session/keys.d.ts +10 -2
  119. package/dist/clients/attach/session/keys.js +13 -5
  120. package/dist/clients/attach/session/layout.d.ts +10 -8
  121. package/dist/clients/attach/session/layout.js +33 -34
  122. package/dist/clients/attach/session/mouse.d.ts +18 -0
  123. package/dist/clients/attach/session/mouse.js +64 -0
  124. package/dist/clients/attach/session/pane-tag.d.ts +3 -0
  125. package/dist/clients/attach/session/pane-tag.js +51 -8
  126. package/dist/clients/attach/session/reconnect.d.ts +3 -0
  127. package/dist/clients/attach/session/reconnect.js +42 -5
  128. package/dist/clients/attach/session/surface-frame.d.ts +20 -0
  129. package/dist/clients/attach/session/surface-frame.js +73 -0
  130. package/dist/clients/attach/session/surface-host.d.ts +64 -0
  131. package/dist/clients/attach/session/surface-host.js +255 -0
  132. package/dist/clients/attach/session/whip.d.ts +17 -0
  133. package/dist/clients/attach/session/whip.js +334 -0
  134. package/dist/clients/attach/slash/dispatch.d.ts +13 -1
  135. package/dist/clients/attach/slash/dispatch.js +51 -29
  136. package/dist/clients/attach/viewer.js +907 -819
  137. package/dist/clients/conversation/conversation.d.ts +65 -0
  138. package/dist/clients/conversation/conversation.js +318 -0
  139. package/dist/clients/conversation/frames.d.ts +30 -0
  140. package/dist/clients/conversation/frames.js +52 -0
  141. package/dist/clients/conversation/region.d.ts +51 -0
  142. package/dist/clients/conversation/region.js +265 -0
  143. package/dist/clients/conversation/submit.d.ts +38 -0
  144. package/dist/clients/conversation/submit.js +51 -0
  145. package/dist/clients/inbox/__tests__/inbox-controller.test.js +247 -0
  146. package/dist/clients/inbox/__tests__/mount-panel.test.js +776 -0
  147. package/dist/clients/inbox/controller.d.ts +79 -0
  148. package/dist/clients/inbox/controller.js +448 -0
  149. package/dist/clients/inbox/deck-adapter.d.ts +29 -0
  150. package/dist/clients/inbox/deck-adapter.js +62 -0
  151. package/dist/clients/inbox/layout.d.ts +8 -0
  152. package/dist/clients/inbox/layout.js +9 -0
  153. package/dist/clients/inbox/resolve.d.ts +10 -0
  154. package/dist/clients/inbox/resolve.js +34 -0
  155. package/dist/clients/inbox/review/__tests__/editor-roundtrip.test.js +29 -0
  156. package/dist/clients/inbox/review/__tests__/remap.test.js +196 -0
  157. package/dist/clients/inbox/review/__tests__/review-core.test.js +341 -0
  158. package/dist/clients/inbox/review/anchors.d.ts +41 -0
  159. package/dist/clients/inbox/review/anchors.js +89 -0
  160. package/dist/clients/inbox/review/columns.d.ts +22 -0
  161. package/dist/clients/inbox/review/columns.js +40 -0
  162. package/dist/clients/inbox/review/comments-client.d.ts +66 -0
  163. package/dist/clients/inbox/review/comments-client.js +98 -0
  164. package/dist/clients/inbox/review/composition.d.ts +60 -0
  165. package/dist/clients/inbox/review/composition.js +278 -0
  166. package/dist/clients/inbox/review/document-region.d.ts +120 -0
  167. package/dist/clients/inbox/review/document-region.js +902 -0
  168. package/dist/clients/inbox/review/frame.d.ts +45 -0
  169. package/dist/clients/inbox/review/frame.js +215 -0
  170. package/dist/clients/inbox/review/keys.d.ts +67 -0
  171. package/dist/clients/inbox/review/keys.js +130 -0
  172. package/dist/clients/inbox/review/launch.d.ts +10 -0
  173. package/dist/clients/inbox/review/launch.js +129 -0
  174. package/dist/clients/inbox/review/live-source.d.ts +24 -0
  175. package/dist/clients/inbox/review/live-source.js +160 -0
  176. package/dist/clients/inbox/review/nvim.d.ts +13 -0
  177. package/dist/clients/inbox/review/nvim.js +42 -0
  178. package/dist/clients/inbox/review/remap.d.ts +51 -0
  179. package/dist/clients/inbox/review/remap.js +157 -0
  180. package/dist/clients/inbox/review/review-client.d.ts +30 -0
  181. package/dist/clients/inbox/review/review-client.js +107 -0
  182. package/dist/clients/inbox/review/roundtrip.d.ts +5 -0
  183. package/dist/clients/inbox/review/roundtrip.js +36 -0
  184. package/dist/clients/inbox/review/state.d.ts +143 -0
  185. package/dist/clients/inbox/review/state.js +282 -0
  186. package/dist/clients/inbox/review-adapter.d.ts +29 -0
  187. package/dist/clients/inbox/review-adapter.js +92 -0
  188. package/dist/clients/inbox/review-visibility.d.ts +5 -0
  189. package/dist/clients/inbox/review-visibility.js +19 -0
  190. package/dist/clients/inbox/surface.d.ts +19 -0
  191. package/dist/clients/inbox/surface.js +128 -0
  192. package/dist/clients/inbox/tui/ansi.d.ts +66 -0
  193. package/dist/clients/inbox/tui/ansi.js +317 -0
  194. package/dist/clients/inbox/tui/clipboard.d.ts +2 -0
  195. package/dist/clients/inbox/tui/clipboard.js +26 -0
  196. package/dist/clients/inbox/tui/input.d.ts +7 -0
  197. package/dist/clients/inbox/tui/input.js +653 -0
  198. package/dist/clients/inbox/tui/keys.d.ts +28 -0
  199. package/dist/clients/inbox/tui/keys.js +111 -0
  200. package/dist/clients/inbox/tui/panel.d.ts +2 -0
  201. package/dist/clients/inbox/tui/panel.js +217 -0
  202. package/dist/clients/inbox/tui/render.d.ts +37 -0
  203. package/dist/clients/inbox/tui/render.js +476 -0
  204. package/dist/clients/inbox/tui/types.d.ts +57 -0
  205. package/dist/clients/inbox/tui/types.js +1 -0
  206. package/dist/clients/inbox/tui.d.ts +6 -0
  207. package/dist/clients/inbox/tui.js +74 -0
  208. package/dist/clients/surfaces/host.d.ts +66 -0
  209. package/dist/clients/surfaces/host.js +1 -0
  210. package/dist/clients/surfaces/region.d.ts +16 -0
  211. package/dist/clients/surfaces/region.js +1 -0
  212. package/dist/clients/web/__tests__/push-engine.test.js +14 -158
  213. package/dist/clients/web/dev-server.d.ts +3 -3
  214. package/dist/clients/web/dev-server.js +9 -23
  215. package/dist/clients/web/events.js +4 -6
  216. package/dist/clients/web/push-engine.d.ts +2 -66
  217. package/dist/clients/web/push-engine.js +30 -161
  218. package/dist/clients/web/push-registry.d.ts +0 -4
  219. package/dist/clients/web/push-registry.js +2 -7
  220. package/dist/clients/web/server.js +3 -35
  221. package/dist/clients/web/web-client/shared/protocol.d.ts +0 -108
  222. package/dist/clients/web/web-cmd.js +2 -2
  223. package/dist/commands/__tests__/human.test.js +27 -15
  224. package/dist/commands/api-client.js +3 -3
  225. package/dist/commands/canvas-browse.js +1 -1
  226. package/dist/commands/canvas-issue.js +1 -1
  227. package/dist/commands/canvas-use.js +1 -1
  228. package/dist/commands/human/doc.d.ts +2 -0
  229. package/dist/commands/human/doc.js +98 -0
  230. package/dist/commands/human/inbox.d.ts +2 -0
  231. package/dist/commands/human/inbox.js +101 -0
  232. package/dist/commands/human/prompts.d.ts +2 -3
  233. package/dist/commands/human/prompts.js +27 -180
  234. package/dist/commands/human/queue.d.ts +1 -5
  235. package/dist/commands/human/queue.js +54 -216
  236. package/dist/commands/human/review.d.ts +2 -0
  237. package/dist/commands/human/review.js +298 -0
  238. package/dist/commands/human/shared.d.ts +2 -69
  239. package/dist/commands/human/shared.js +1 -181
  240. package/dist/commands/human.js +15 -20
  241. package/dist/commands/memory/__tests__/lint.test.d.ts +1 -0
  242. package/dist/commands/memory/__tests__/lint.test.js +15 -0
  243. package/dist/commands/memory/delete.js +2 -2
  244. package/dist/commands/memory/lint.d.ts +1 -0
  245. package/dist/commands/memory/lint.js +21 -3
  246. package/dist/commands/memory/read.js +4 -4
  247. package/dist/commands/node.js +8 -7
  248. package/dist/commands/pkg/plugin-manage.js +143 -68
  249. package/dist/commands/surface-inspect.js +2 -2
  250. package/dist/commands/surface.js +6 -12
  251. package/dist/commands/sys/__tests__/setup-core.test.js +9 -5
  252. package/dist/commands/sys/__tests__/setup-front-door.test.js +7 -42
  253. package/dist/commands/sys/config.js +29 -3
  254. package/dist/commands/sys/feedback.js +1 -1
  255. package/dist/commands/sys/setup-core.d.ts +12 -11
  256. package/dist/commands/sys/setup-core.js +55 -46
  257. package/dist/commands/sys/setup-wizard.d.ts +4 -1
  258. package/dist/commands/sys/setup-wizard.js +50 -9
  259. package/dist/commands/sys/sync-deps.js +1 -1
  260. package/dist/commands/sys.js +4 -6
  261. package/dist/core/__tests__/broker-sdk-wiring.test.js +6 -1
  262. package/dist/core/__tests__/broker-snapshot-history.test.js +9 -1
  263. package/dist/core/__tests__/dead-node-policy-table.test.js +3 -4
  264. package/dist/core/__tests__/fixtures/fake-engine.d.ts +8 -5
  265. package/dist/core/__tests__/fixtures/fake-engine.js +28 -2
  266. package/dist/core/__tests__/full/broker-provider-retry.test.js +87 -2
  267. package/dist/core/__tests__/full/broker-whip-interrupt.test.d.ts +1 -0
  268. package/dist/core/__tests__/full/broker-whip-interrupt.test.js +39 -0
  269. package/dist/core/__tests__/full/detach-focus.test.js +1 -1
  270. package/dist/core/__tests__/human-deliver-e2e.test.js +64 -64
  271. package/dist/core/__tests__/human-deliver.test.js +71 -345
  272. package/dist/core/__tests__/inline-memory-refs.test.js +2 -12
  273. package/dist/core/__tests__/memory-resolver-precedence.test.js +12 -15
  274. package/dist/core/__tests__/migration.test.js +10 -0
  275. package/dist/core/__tests__/model-pin-durability.test.js +14 -0
  276. package/dist/core/__tests__/phase4-review-migration.test.d.ts +1 -0
  277. package/dist/core/__tests__/phase4-review-migration.test.js +100 -0
  278. package/dist/core/__tests__/phase4-review-store.test.d.ts +1 -0
  279. package/dist/core/__tests__/phase4-review-store.test.js +143 -0
  280. package/dist/core/__tests__/remote-canvas-target.test.js +2 -2
  281. package/dist/core/__tests__/revive.test.js +22 -53
  282. package/dist/core/__tests__/session-cycles.test.js +48 -18
  283. package/dist/core/__tests__/spawn-no-kickoff.test.js +8 -12
  284. package/dist/core/__tests__/stop-guard.test.js +16 -1
  285. package/dist/core/__tests__/tmux-surface.test.js +21 -25
  286. package/dist/core/asset-root.d.ts +7 -0
  287. package/dist/core/asset-root.js +18 -0
  288. package/dist/core/broker-client/client.d.ts +0 -7
  289. package/dist/core/broker-client/client.js +4 -10
  290. package/dist/core/broker-client/transport-relay.d.ts +3 -4
  291. package/dist/core/broker-client/transport-relay.js +3 -4
  292. package/dist/core/canvas/__tests__/attention.test.js +1 -1
  293. package/dist/core/canvas/__tests__/remote-canvas-source.test.js +1 -1
  294. package/dist/core/canvas/__tests__/remote-transport.test.d.ts +1 -0
  295. package/dist/core/{view/__tests__/transport-remote.test.js → canvas/__tests__/remote-transport.test.js} +2 -2
  296. package/dist/core/canvas/__tests__/render-remote.test.js +1 -1
  297. package/dist/core/canvas/attention.js +4 -4
  298. package/dist/core/canvas/canvas.d.ts +6 -11
  299. package/dist/core/canvas/canvas.js +11 -33
  300. package/dist/core/canvas/db.js +207 -38
  301. package/dist/core/canvas/extensions.d.ts +1 -1
  302. package/dist/core/canvas/extensions.js +8 -1
  303. package/dist/core/canvas/index.d.ts +0 -1
  304. package/dist/core/canvas/index.js +0 -1
  305. package/dist/core/canvas/nav-model.d.ts +1 -1
  306. package/dist/core/canvas/nav-model.js +1 -1
  307. package/dist/core/canvas/paths.d.ts +5 -0
  308. package/dist/core/canvas/paths.js +16 -0
  309. package/dist/core/canvas/remote-canvas-source.js +2 -2
  310. package/dist/core/canvas/remote-transport.d.ts +7 -0
  311. package/dist/core/{view/transport-remote.js → canvas/remote-transport.js} +3 -4
  312. package/dist/core/canvas/source.js +1 -1
  313. package/dist/core/canvas/status-glyph.js +4 -12
  314. package/dist/core/canvas/types.d.ts +10 -35
  315. package/dist/core/clipboard-text.d.ts +8 -0
  316. package/dist/core/clipboard-text.js +18 -0
  317. package/dist/core/command-manifests/registry.d.ts +1 -3
  318. package/dist/core/command-plugins/bundle.d.ts +29 -0
  319. package/dist/core/command-plugins/bundle.js +198 -0
  320. package/dist/core/command-plugins/discovery.d.ts +0 -8
  321. package/dist/core/command-plugins/discovery.js +2 -39
  322. package/dist/core/command-plugins/transport/http-fetch.d.ts +4 -30
  323. package/dist/core/command-plugins/transport/http-fetch.js +17 -95
  324. package/dist/core/command.d.ts +1 -13
  325. package/dist/core/command.js +1 -16
  326. package/dist/core/config.d.ts +4 -0
  327. package/dist/core/config.js +28 -3
  328. package/dist/core/document-lines.d.ts +4 -0
  329. package/dist/core/document-lines.js +6 -0
  330. package/dist/core/feed/feed.d.ts +2 -0
  331. package/dist/core/feed/feed.js +11 -7
  332. package/dist/core/human/__tests__/inbox-cancel-worker.d.ts +1 -0
  333. package/dist/core/human/__tests__/inbox-cancel-worker.js +7 -0
  334. package/dist/core/human/__tests__/inbox-claim-worker.d.ts +1 -0
  335. package/dist/core/human/__tests__/inbox-claim-worker.js +17 -0
  336. package/dist/core/human/__tests__/inbox-core.test.d.ts +1 -0
  337. package/dist/core/human/__tests__/inbox-core.test.js +144 -0
  338. package/dist/core/human/__tests__/inbox-stale-claim-worker.d.ts +1 -0
  339. package/dist/core/human/__tests__/inbox-stale-claim-worker.js +8 -0
  340. package/dist/core/human/__tests__/visible-paths.test.d.ts +1 -0
  341. package/dist/{clients/attach → core/human}/__tests__/visible-paths.test.js +9 -0
  342. package/dist/core/human/claim.d.ts +23 -0
  343. package/dist/core/human/claim.js +67 -0
  344. package/dist/core/human/convention.d.ts +30 -0
  345. package/dist/core/human/convention.js +202 -0
  346. package/dist/core/human/deck-factories.d.ts +8 -0
  347. package/dist/core/human/deck-factories.js +15 -0
  348. package/dist/core/human/deck-schema.d.ts +70 -0
  349. package/dist/core/human/deck-schema.js +92 -0
  350. package/dist/core/human/root.d.ts +7 -0
  351. package/dist/core/human/root.js +37 -0
  352. package/dist/core/human/scan.d.ts +3 -0
  353. package/dist/core/human/scan.js +76 -0
  354. package/dist/core/human/summary.d.ts +8 -0
  355. package/dist/core/human/summary.js +44 -0
  356. package/dist/core/human/tickets.d.ts +49 -0
  357. package/dist/core/human/tickets.js +190 -0
  358. package/dist/core/human/types.d.ts +136 -0
  359. package/dist/core/human/types.js +5 -0
  360. package/dist/{clients/attach → core/human}/visible-paths.d.ts +1 -1
  361. package/dist/{clients/attach → core/human}/visible-paths.js +3 -2
  362. package/dist/core/inspector/chrome.d.ts +6 -0
  363. package/dist/core/inspector/chrome.js +14 -0
  364. package/dist/core/inspector/contract.d.ts +105 -0
  365. package/dist/core/inspector/contract.js +1 -0
  366. package/dist/core/inspector/core.d.ts +4 -5
  367. package/dist/core/inspector/core.js +3 -5
  368. package/dist/core/inspector/host.d.ts +46 -0
  369. package/dist/core/{tui → inspector}/host.js +42 -208
  370. package/dist/core/inspector/text.d.ts +2 -2
  371. package/dist/core/inspector/transport.d.ts +6 -0
  372. package/dist/core/inspector/transport.js +36 -0
  373. package/dist/core/inspector/tui.d.ts +2 -2
  374. package/dist/core/inspector/tui.js +15 -15
  375. package/dist/core/keybindings/__tests__/inbox-affordance.test.js +11 -11
  376. package/dist/core/keybindings/__tests__/resolve.test.js +10 -19
  377. package/dist/core/keybindings/attach-control.d.ts +9 -3
  378. package/dist/core/keybindings/attach-control.js +3 -1
  379. package/dist/core/keybindings/catalog.d.ts +6 -5
  380. package/dist/core/keybindings/catalog.js +61 -133
  381. package/dist/core/keybindings/inbox.d.ts +5 -6
  382. package/dist/core/keybindings/inbox.js +9 -10
  383. package/dist/core/keybindings/index.d.ts +3 -3
  384. package/dist/core/keybindings/index.js +3 -3
  385. package/dist/core/keybindings/persistence.d.ts +5 -1
  386. package/dist/core/keybindings/persistence.js +24 -6
  387. package/dist/core/keybindings/resolve.d.ts +6 -0
  388. package/dist/core/keybindings/resolve.js +10 -3
  389. package/dist/core/memory/inline-ref-grammar.js +2 -3
  390. package/dist/core/memory-resolver.d.ts +27 -29
  391. package/dist/core/memory-resolver.js +45 -39
  392. package/dist/core/model-routes.d.ts +33 -0
  393. package/dist/core/model-routes.js +42 -3
  394. package/dist/core/preview-registry.js +17 -55
  395. package/dist/core/profiles/select.js +3 -3
  396. package/dist/core/{view/remote-canvas-target.d.ts → remote-canvas-target.d.ts} +2 -2
  397. package/dist/core/{view/remote-canvas-target.js → remote-canvas-target.js} +4 -4
  398. package/dist/core/review/__tests__/capture-origin.test.d.ts +1 -0
  399. package/dist/core/review/__tests__/capture-origin.test.js +139 -0
  400. package/dist/core/review/__tests__/comments.test.d.ts +1 -0
  401. package/dist/core/review/__tests__/comments.test.js +98 -0
  402. package/dist/core/review/__tests__/project.test.d.ts +1 -0
  403. package/dist/core/review/__tests__/project.test.js +71 -0
  404. package/dist/core/review/__tests__/remap.test.d.ts +1 -0
  405. package/dist/core/review/__tests__/remap.test.js +159 -0
  406. package/dist/core/review/__tests__/stage-identity.test.d.ts +1 -0
  407. package/dist/core/review/__tests__/stage-identity.test.js +140 -0
  408. package/dist/core/review/birth.d.ts +7 -0
  409. package/dist/core/review/birth.js +23 -0
  410. package/dist/core/review/comments.d.ts +69 -0
  411. package/dist/core/review/comments.js +295 -0
  412. package/dist/core/review/companion.d.ts +35 -0
  413. package/dist/core/review/companion.js +205 -0
  414. package/dist/core/review/document.d.ts +27 -0
  415. package/dist/core/review/document.js +138 -0
  416. package/dist/core/review/project.d.ts +13 -0
  417. package/dist/core/review/project.js +58 -0
  418. package/dist/core/review/realize.d.ts +19 -0
  419. package/dist/core/review/realize.js +217 -0
  420. package/dist/core/review/remap.d.ts +24 -0
  421. package/dist/core/review/remap.js +156 -0
  422. package/dist/core/review/signal.d.ts +5 -0
  423. package/dist/core/review/signal.js +31 -0
  424. package/dist/core/review/stage.d.ts +26 -0
  425. package/dist/core/review/stage.js +184 -0
  426. package/dist/core/review/store.d.ts +46 -0
  427. package/dist/core/review/store.js +163 -0
  428. package/dist/core/review/ticket-filter.d.ts +17 -0
  429. package/dist/core/review/ticket-filter.js +32 -0
  430. package/dist/core/review/types.d.ts +130 -0
  431. package/dist/core/review/types.js +23 -0
  432. package/dist/core/runtime/__tests__/session-visibility.test.d.ts +1 -0
  433. package/dist/core/runtime/__tests__/session-visibility.test.js +119 -0
  434. package/dist/core/runtime/bearings.d.ts +5 -17
  435. package/dist/core/runtime/bearings.js +88 -71
  436. package/dist/core/runtime/broker-protocol.d.ts +31 -8
  437. package/dist/core/runtime/broker.d.ts +15 -1
  438. package/dist/core/runtime/broker.js +573 -141
  439. package/dist/core/runtime/canvas-extensions.d.ts +4 -5
  440. package/dist/core/runtime/canvas-extensions.js +5 -5
  441. package/dist/core/runtime/front-door.js +4 -4
  442. package/dist/core/runtime/headless-pi.d.ts +24 -0
  443. package/dist/core/runtime/headless-pi.js +152 -0
  444. package/dist/core/runtime/kickoff.d.ts +1 -5
  445. package/dist/core/runtime/kickoff.js +1 -5
  446. package/dist/core/runtime/model-registry.d.ts +3 -0
  447. package/dist/core/runtime/model-registry.js +13 -0
  448. package/dist/core/runtime/naming-persist.d.ts +4 -0
  449. package/dist/core/runtime/naming-persist.js +27 -1
  450. package/dist/core/runtime/naming.d.ts +17 -12
  451. package/dist/core/runtime/naming.js +91 -140
  452. package/dist/core/runtime/node-read.js +19 -10
  453. package/dist/core/runtime/nodes.d.ts +9 -14
  454. package/dist/core/runtime/nodes.js +3 -53
  455. package/dist/core/runtime/package-health.d.ts +6 -21
  456. package/dist/core/runtime/package-health.js +12 -123
  457. package/dist/core/runtime/placement-tmux.d.ts +2 -1
  458. package/dist/core/runtime/placement-tmux.js +6 -4
  459. package/dist/core/runtime/placement.d.ts +1 -0
  460. package/dist/core/runtime/placement.js +4 -8
  461. package/dist/core/runtime/promote.js +3 -0
  462. package/dist/core/runtime/recap.d.ts +2 -7
  463. package/dist/core/runtime/recap.js +35 -69
  464. package/dist/core/runtime/revive.js +34 -77
  465. package/dist/core/runtime/session-cycles.d.ts +4 -0
  466. package/dist/core/runtime/session-cycles.js +14 -1
  467. package/dist/core/runtime/session-visibility.d.ts +37 -0
  468. package/dist/core/runtime/session-visibility.js +83 -0
  469. package/dist/core/runtime/spawn.js +10 -22
  470. package/dist/core/runtime/stop-guard.d.ts +1 -1
  471. package/dist/core/runtime/stop-guard.js +18 -13
  472. package/dist/core/runtime/surface-bg.js +1 -1
  473. package/dist/core/runtime/tmux-chrome.d.ts +1 -1
  474. package/dist/core/runtime/tmux-chrome.js +1 -1
  475. package/dist/core/runtime/tmux.d.ts +35 -7
  476. package/dist/core/runtime/tmux.js +439 -62
  477. package/dist/core/runtime/tool-group-summary.d.ts +19 -0
  478. package/dist/core/runtime/tool-group-summary.js +88 -0
  479. package/dist/core/scope.d.ts +2 -7
  480. package/dist/core/scope.js +9 -35
  481. package/dist/core/substrate/schema.d.ts +2 -2
  482. package/dist/core/termrender/code-doc.d.ts +12 -0
  483. package/dist/core/termrender/code-doc.js +92 -0
  484. package/dist/core/termrender/display.d.ts +12 -0
  485. package/dist/core/termrender/display.js +19 -0
  486. package/dist/core/termrender/termrender.d.ts +73 -0
  487. package/dist/core/termrender/termrender.js +795 -0
  488. package/dist/core/termrender/version.d.ts +1 -0
  489. package/dist/core/termrender/version.js +1 -0
  490. package/dist/core/tui/terminal.js +1 -2
  491. package/dist/core/user-settings.d.ts +71 -3
  492. package/dist/core/user-settings.js +83 -1
  493. package/dist/daemon/api/__tests__/inbox.test.js +44 -133
  494. package/dist/daemon/api/handlers/human.d.ts +0 -10
  495. package/dist/daemon/api/handlers/human.js +104 -702
  496. package/dist/daemon/api/handlers/inbox.js +113 -142
  497. package/dist/daemon/api/handlers/review-comments.d.ts +2 -0
  498. package/dist/daemon/api/handlers/review-comments.js +500 -0
  499. package/dist/daemon/api/handlers/reviews.d.ts +2 -0
  500. package/dist/daemon/api/handlers/reviews.js +287 -0
  501. package/dist/daemon/api/map.d.ts +22 -7
  502. package/dist/daemon/api/map.js +159 -11
  503. package/dist/daemon/api/server.js +4 -0
  504. package/dist/daemon/cron-run.js +6 -9
  505. package/dist/daemon/crtrd.js +17 -33
  506. package/dist/daemon/fleet.d.ts +1 -8
  507. package/dist/daemon/fleet.js +4 -30
  508. package/dist/daemon/human/finish.d.ts +14 -0
  509. package/dist/daemon/human/finish.js +115 -0
  510. package/dist/daemon/human/sweep.d.ts +6 -0
  511. package/dist/daemon/human/sweep.js +49 -0
  512. package/dist/daemon/messaging/node-message.d.ts +18 -0
  513. package/dist/daemon/messaging/node-message.js +70 -0
  514. package/dist/daemon/review/comment-notify.d.ts +26 -0
  515. package/dist/daemon/review/comment-notify.js +107 -0
  516. package/dist/daemon/review/deliver.d.ts +7 -0
  517. package/dist/daemon/review/deliver.js +56 -0
  518. package/dist/daemon/review/finish.d.ts +22 -0
  519. package/dist/daemon/review/finish.js +254 -0
  520. package/dist/daemon/review/sweep.d.ts +11 -0
  521. package/dist/daemon/review/sweep.js +120 -0
  522. package/dist/index.d.ts +2 -0
  523. package/dist/index.js +2 -2
  524. package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +42 -64
  525. package/dist/pi-extensions/__tests__/canvas-recap.test.d.ts +1 -0
  526. package/dist/pi-extensions/__tests__/canvas-recap.test.js +159 -0
  527. package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +16 -38
  528. package/dist/pi-extensions/__tests__/canvas-structured-output.test.d.ts +1 -0
  529. package/dist/pi-extensions/__tests__/canvas-structured-output.test.js +63 -0
  530. package/dist/pi-extensions/canvas-context-intro.d.ts +8 -11
  531. package/dist/pi-extensions/canvas-context-intro.js +50 -104
  532. package/dist/pi-extensions/canvas-recap.d.ts +15 -2
  533. package/dist/pi-extensions/canvas-recap.js +192 -69
  534. package/dist/pi-extensions/canvas-review-boundary.d.ts +59 -0
  535. package/dist/pi-extensions/canvas-review-boundary.js +81 -0
  536. package/dist/pi-extensions/canvas-stophook.d.ts +3 -3
  537. package/dist/pi-extensions/canvas-stophook.js +78 -128
  538. package/dist/pi-extensions/canvas-structured-output.js +52 -8
  539. package/dist/shared/generated-context.d.ts +29 -4
  540. package/dist/shared/generated-context.js +122 -7
  541. package/dist/shared/tool-groups.d.ts +23 -0
  542. package/dist/shared/tool-groups.js +60 -0
  543. package/dist/shared/working-activity.d.ts +8 -0
  544. package/dist/shared/working-activity.js +26 -0
  545. package/dist/types.d.ts +36 -2
  546. package/dist/types.js +51 -0
  547. package/dist/web-client/assets/index-CCPaLeW7.css +2 -0
  548. package/dist/web-client/assets/index-kyOWsnZK.js +86 -0
  549. package/dist/web-client/index.html +2 -2
  550. package/dist/web-client/sw.js +1 -1
  551. package/docs/compat/hearth-crtr-v4.md +2 -2
  552. package/docs/compat/hearth-crtr-v5.md +4 -2
  553. package/docs/public-api.md +3 -3
  554. package/package.json +21 -14
  555. package/runtime.lock.json +4661 -1453
  556. package/scripts/postinstall.mjs +15 -2
  557. package/dist/builtin-pi-packages/pi-mode-switch/README.md +0 -36
  558. package/dist/builtin-pi-packages/pi-mode-switch/bin/mode +0 -36
  559. package/dist/builtin-pi-packages/pi-mode-switch/extensions/index.ts +0 -449
  560. package/dist/builtin-pi-packages/pi-mode-switch/package.json +0 -14
  561. package/dist/builtin-pi-packages/pi-mode-switch/tsconfig.json +0 -9
  562. package/dist/builtin-views/_lib/states.mjs +0 -161
  563. package/dist/builtin-views/canvas/core.mjs +0 -657
  564. package/dist/builtin-views/canvas/text.mjs +0 -58
  565. package/dist/builtin-views/canvas/tui.mjs +0 -168
  566. package/dist/builtin-views/canvas/web.jsx +0 -121
  567. package/dist/builtin-views/chat/core.mjs +0 -684
  568. package/dist/builtin-views/chat/text.mjs +0 -101
  569. package/dist/builtin-views/chat/tui.mjs +0 -360
  570. package/dist/builtin-views/chat/web.jsx +0 -362
  571. package/dist/builtin-views/git-pr/core.mjs +0 -673
  572. package/dist/builtin-views/git-pr/text.mjs +0 -84
  573. package/dist/builtin-views/git-pr/tui.mjs +0 -301
  574. package/dist/builtin-views/git-pr/web.jsx +0 -216
  575. package/dist/builtin-views/inbox/_lib/render.mjs +0 -175
  576. package/dist/builtin-views/inbox/core.mjs +0 -1273
  577. package/dist/builtin-views/inbox/text.mjs +0 -73
  578. package/dist/builtin-views/inbox/tui.mjs +0 -314
  579. package/dist/builtin-views/inbox/web.jsx +0 -188
  580. package/dist/builtin-views/linkedin/core.mjs +0 -906
  581. package/dist/builtin-views/linkedin/text.mjs +0 -69
  582. package/dist/builtin-views/linkedin/tui.mjs +0 -413
  583. package/dist/builtin-views/linkedin/web.jsx +0 -206
  584. package/dist/builtin-views/prompt-review/core.mjs +0 -735
  585. package/dist/builtin-views/prompt-review/text.mjs +0 -15
  586. package/dist/builtin-views/prompt-review/tui.mjs +0 -196
  587. package/dist/builtin-views/prompt-review/web.jsx +0 -484
  588. package/dist/builtin-views/workspace-sidebar/__tests__/core.test.js +0 -50
  589. package/dist/builtin-views/workspace-sidebar/__tests__/core.test.ts +0 -53
  590. package/dist/builtin-views/workspace-sidebar/core.mjs +0 -670
  591. package/dist/builtin-views/workspace-sidebar/text.mjs +0 -53
  592. package/dist/builtin-views/workspace-sidebar/tui.mjs +0 -141
  593. package/dist/builtin-views/workspace-sidebar/web.jsx +0 -109
  594. package/dist/clients/attach/session/mode.d.ts +0 -25
  595. package/dist/clients/attach/session/mode.js +0 -97
  596. package/dist/commands/sys/promptstudio.d.ts +0 -2
  597. package/dist/commands/sys/promptstudio.js +0 -65
  598. package/dist/commands/view-cycle.d.ts +0 -2
  599. package/dist/commands/view-cycle.js +0 -130
  600. package/dist/commands/view-list.d.ts +0 -2
  601. package/dist/commands/view-list.js +0 -66
  602. package/dist/commands/view-new.d.ts +0 -2
  603. package/dist/commands/view-new.js +0 -74
  604. package/dist/commands/view-pick.d.ts +0 -6
  605. package/dist/commands/view-pick.js +0 -129
  606. package/dist/commands/view-run.d.ts +0 -2
  607. package/dist/commands/view-run.js +0 -214
  608. package/dist/commands/view.d.ts +0 -2
  609. package/dist/commands/view.js +0 -31
  610. package/dist/commands/workspace.d.ts +0 -2
  611. package/dist/commands/workspace.js +0 -165
  612. package/dist/core/__tests__/chat-view-reconnect.test.js +0 -105
  613. package/dist/core/__tests__/full/consult-startup-failure.test.js +0 -124
  614. package/dist/core/canvas/__tests__/human-work-outbox.test.js +0 -123
  615. package/dist/core/canvas/human-work-outbox.d.ts +0 -73
  616. package/dist/core/canvas/human-work-outbox.js +0 -261
  617. package/dist/core/command-plugins/store.d.ts +0 -16
  618. package/dist/core/command-plugins/store.js +0 -64
  619. package/dist/core/keybindings/__tests__/bespoke-consumers.test.js +0 -40
  620. package/dist/core/runtime/fault-recovery-nudge.d.ts +0 -3
  621. package/dist/core/runtime/fault-recovery-nudge.js +0 -3
  622. package/dist/core/tui/__tests__/host-keybindings.test.js +0 -113
  623. package/dist/core/tui/host.d.ts +0 -66
  624. package/dist/core/view/__tests__/transport-cache.test.js +0 -62
  625. package/dist/core/view/bridge.d.ts +0 -10
  626. package/dist/core/view/bridge.js +0 -31
  627. package/dist/core/view/chrome.d.ts +0 -9
  628. package/dist/core/view/chrome.js +0 -22
  629. package/dist/core/view/contract.d.ts +0 -205
  630. package/dist/core/view/contract.js +0 -23
  631. package/dist/core/view/loader.d.ts +0 -31
  632. package/dist/core/view/loader.js +0 -188
  633. package/dist/core/view/stream-local.d.ts +0 -3
  634. package/dist/core/view/stream-local.js +0 -231
  635. package/dist/core/view/transport-cache.d.ts +0 -8
  636. package/dist/core/view/transport-cache.js +0 -38
  637. package/dist/core/view/transport-local.d.ts +0 -7
  638. package/dist/core/view/transport-local.js +0 -83
  639. package/dist/core/view/transport-remote.d.ts +0 -2
  640. package/dist/core/view/transport.d.ts +0 -10
  641. package/dist/core/view/transport.js +0 -15
  642. package/dist/pi-extensions/naming-tool.d.ts +0 -24
  643. package/dist/pi-extensions/naming-tool.js +0 -67
  644. package/dist/prompts/view.d.ts +0 -7
  645. package/dist/prompts/view.js +0 -172
  646. package/dist/web/ViewChrome.d.ts +0 -7
  647. package/dist/web/ViewChrome.js +0 -28
  648. package/dist/web/ViewPane.d.ts +0 -39
  649. package/dist/web/ViewPane.js +0 -48
  650. package/dist/web/index.d.ts +0 -8
  651. package/dist/web/index.js +0 -22
  652. package/dist/web/runtime.d.ts +0 -39
  653. package/dist/web/runtime.js +0 -232
  654. package/dist/web/states.d.ts +0 -24
  655. package/dist/web/states.js +0 -24
  656. package/dist/web/transport-http.d.ts +0 -5
  657. package/dist/web/transport-http.js +0 -34
  658. package/dist/web/transport-stream.d.ts +0 -3
  659. package/dist/web/transport-stream.js +0 -204
  660. package/dist/web-client/assets/index-U_NZ66VE.js +0 -79
  661. package/dist/web-client/assets/index-aaeu4adv.css +0 -2
  662. /package/dist/{builtin-views/workspace-sidebar/__tests__/core.test.d.ts → clients/attach/__tests__/file-review-focus.test.d.ts} +0 -0
  663. /package/dist/clients/attach/__tests__/{visible-paths.test.d.ts → group-activity.test.d.ts} +0 -0
  664. /package/dist/{core/__tests__/chat-view-reconnect.test.d.ts → clients/attach/__tests__/input-controller-extension-command.test.d.ts} +0 -0
  665. /package/dist/{core/__tests__/full/consult-startup-failure.test.d.ts → clients/attach/__tests__/session-identity-refresh.test.d.ts} +0 -0
  666. /package/dist/{core/canvas/__tests__/human-work-outbox.test.d.ts → clients/inbox/__tests__/inbox-controller.test.d.ts} +0 -0
  667. /package/dist/{core/keybindings/__tests__/bespoke-consumers.test.d.ts → clients/inbox/__tests__/mount-panel.test.d.ts} +0 -0
  668. /package/dist/{core/tui/__tests__/host-keybindings.test.d.ts → clients/inbox/review/__tests__/editor-roundtrip.test.d.ts} +0 -0
  669. /package/dist/{core/view/__tests__/transport-cache.test.d.ts → clients/inbox/review/__tests__/remap.test.d.ts} +0 -0
  670. /package/dist/{core/view/__tests__/transport-remote.test.d.ts → clients/inbox/review/__tests__/review-core.test.d.ts} +0 -0
@@ -10,131 +10,20 @@
10
10
  // vanishes with no diagnostic. This turns that silent failure into a loud,
11
11
  // actionable warning. The fix it points at is `crtr sys setup`, which re-resolves
12
12
  // package paths to the repo's current location.
13
- import { accessSync, constants, existsSync, readFileSync, realpathSync } from 'node:fs';
14
- import { fileURLToPath } from 'node:url';
13
+ import { existsSync, readFileSync } from 'node:fs';
15
14
  import { homedir } from 'node:os';
16
- import { delimiter, dirname, join, resolve } from 'node:path';
17
- const GLOBAL_HUMANLOOP_INSTALL_COMMAND = 'npm i -g @crouton-kit/humanloop@latest';
18
- /** Read the installed library's version rather than coupling this check to the
19
- * dependency range in crouter's package.json. The bundled copy is the floor
20
- * required by crouter's generated `hl inbox toggle` binding. */
21
- export function bundledHumanloopVersion() {
22
- try {
23
- // package.json is deliberately not an exported subpath. Resolve the public
24
- // ESM entry, then walk from dist/index.js to the package root.
25
- const entryPath = fileURLToPath(import.meta.resolve('@crouton-kit/humanloop'));
26
- const packageJsonPath = join(dirname(entryPath), '..', 'package.json');
27
- const value = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
28
- return typeof value.version === 'string'
29
- ? value.version
30
- : null;
31
- }
32
- catch {
33
- return null;
34
- }
35
- }
36
- /** Compare ordinary npm semvers without loading a semver dependency on the
37
- * foreground/daemon startup path. Unparseable versions deliberately fail the
38
- * health check: setup can repair them and boot only warns. */
39
- function compareVersions(left, right) {
40
- const parse = (version) => {
41
- const match = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(version);
42
- if (match === null)
43
- return null;
44
- return { core: [Number(match[1]), Number(match[2]), Number(match[3])], prerelease: match[4]?.split('.') ?? [] };
45
- };
46
- const a = parse(left);
47
- const b = parse(right);
48
- if (a === null || b === null)
15
+ import { join, resolve } from 'node:path';
16
+ import { isRendererReady } from '../termrender/termrender.js';
17
+ /** A non-fatal, action-oriented diagnostic for an unprovisioned managed
18
+ * renderer — the one remaining out-of-tree dependency. Deliberately calls
19
+ * `isRendererReady()`, NOT `ensureRenderer()`: this runs on the front-door boot
20
+ * path and at crtrd startup, where a `uv pip install` (up to 180s) must never
21
+ * happen. Readiness is a handful of fs stats, no subprocess. */
22
+ export function rendererWarning() {
23
+ if (isRendererReady())
49
24
  return null;
50
- for (let index = 0; index < a.core.length; index++) {
51
- const difference = a.core[index] - b.core[index];
52
- if (difference !== 0)
53
- return difference;
54
- }
55
- if (a.prerelease.length === 0 || b.prerelease.length === 0) {
56
- return a.prerelease.length === b.prerelease.length ? 0 : a.prerelease.length === 0 ? 1 : -1;
57
- }
58
- for (let index = 0; index < Math.max(a.prerelease.length, b.prerelease.length); index++) {
59
- const aPart = a.prerelease[index];
60
- const bPart = b.prerelease[index];
61
- if (aPart === undefined || bPart === undefined)
62
- return aPart === bPart ? 0 : aPart === undefined ? -1 : 1;
63
- if (aPart === bPart)
64
- continue;
65
- const aNumber = /^\d+$/.test(aPart);
66
- const bNumber = /^\d+$/.test(bPart);
67
- if (aNumber && bNumber)
68
- return Number(aPart) - Number(bPart);
69
- if (aNumber !== bNumber)
70
- return aNumber ? -1 : 1;
71
- return aPart < bPart ? -1 : 1;
72
- }
73
- return 0;
74
- }
75
- /** Read the PATH-visible `hl` package directly. Spawning `npm ls -g` here
76
- * makes every front-door boot pay for npm's global dependency-tree scan; a
77
- * linked development install can make that scan take many seconds. The real
78
- * executable points into the package for both ordinary and npm-linked installs,
79
- * so walking upward to its package.json is authoritative for the CLI crtr will
80
- * actually invoke. */
81
- export function globalHumanloopVersion() {
82
- const executable = (process.env['PATH'] ?? '')
83
- .split(delimiter)
84
- .filter(Boolean)
85
- .map((entry) => join(entry, 'hl'))
86
- .find((candidate) => {
87
- try {
88
- accessSync(candidate, constants.X_OK);
89
- return true;
90
- }
91
- catch {
92
- return false;
93
- }
94
- });
95
- if (executable === undefined)
96
- return null;
97
- try {
98
- let cursor = dirname(realpathSync(executable));
99
- for (;;) {
100
- const packageJsonPath = join(cursor, 'package.json');
101
- if (existsSync(packageJsonPath)) {
102
- const value = JSON.parse(readFileSync(packageJsonPath, 'utf8'));
103
- const manifest = value;
104
- if (manifest.name === '@crouton-kit/humanloop')
105
- return typeof manifest.version === 'string' ? manifest.version : null;
106
- }
107
- const parent = dirname(cursor);
108
- if (parent === cursor)
109
- return null;
110
- cursor = parent;
111
- }
112
- }
113
- catch {
114
- return null;
115
- }
116
- }
117
- export function globalHumanloopHealth() {
118
- const bundledVersion = bundledHumanloopVersion();
119
- const globalVersion = globalHumanloopVersion();
120
- const comparison = bundledVersion !== null && globalVersion !== null
121
- ? compareVersions(globalVersion, bundledVersion)
122
- : null;
123
- return { bundledVersion, globalVersion, current: comparison !== null && comparison >= 0 };
124
- }
125
- /** A non-fatal action-oriented diagnostic for a missing, unreadable, or stale
126
- * global `hl` executable. */
127
- export function globalHumanloopWarning() {
128
- const { bundledVersion, globalVersion, current } = globalHumanloopHealth();
129
- if (current)
130
- return null;
131
- const floor = bundledVersion ?? 'the bundled version';
132
- const found = globalVersion === null ? 'missing or unprobeable' : globalVersion;
133
- return `crtr: global \`hl\` CLI is ${found}; crouter requires at least bundled humanloop ${floor} for its inbox toggle.\n` +
134
- ` Fix: run \`${GLOBAL_HUMANLOOP_INSTALL_COMMAND}\`.`;
135
- }
136
- export function globalHumanloopInstallCommand() {
137
- return GLOBAL_HUMANLOOP_INSTALL_COMMAND;
25
+ return 'crtr: the pinned termrender renderer is not provisioned — decks, reviews, and inline diagrams render as plaintext.\n' +
26
+ ' Fix: run `crtr sys setup` (requires `uv`: curl -LsSf https://astral.sh/uv/install.sh | sh).';
138
27
  }
139
28
  /** Expand a leading `~` against `homeDir` (pi's own convention). */
140
29
  function expandTilde(pathValue, homeDir) {
@@ -1,4 +1,4 @@
1
- export { paneExists, paneLocation, paneOfNode, paneCurrentPath, ensureSession, openNodeWindow, splitWindow, closePane, currentTmux, switchClient, selectWindow, selectLayout, selectPane, getPaneOption, setPaneOption, breakPane, inTmux, piCommand, shellQuote, installTmuxBindings, renameWindow, displayPopup, windowOfPane, respawnPaneSync, respawnPaneInPlace, paneStartCommand, panePid, windowAlive, listLivePanes, } from './tmux.js';
1
+ export { paneExists, paneLocation, paneOfNode, paneCurrentPath, ensureSession, openNodeWindow, splitWindow, closePane, currentTmux, switchClient, selectWindow, selectLayout, selectPane, getPaneOption, setPaneOption, breakPane, inTmux, piCommand, shellQuote, installTmuxBindings, renameWindow, displayPopup, windowOfPane, respawnPaneSync, respawnPaneInPlace, paneStartCommand, panePid, windowAlive, listLivePanes, VIEWER_STAMP_OPTION, stampViewerPaneAsync, liveViewerPanes, sendAttachControl, displayClientMessage, } from './tmux.js';
2
2
  /** The shared cold-start deadline (ms) a freshly-opened viewer waits for its
3
3
  * broker's view.sock — one source of truth for the CRTR_ATTACH_WAIT_MS a viewer
4
4
  * pane is handed. */
@@ -39,4 +39,5 @@ export declare function openViewerPane(nodeId: string, session: string, opts?: {
39
39
  cwd?: string;
40
40
  besidePane?: string;
41
41
  waitForBroker?: boolean;
42
+ initialWhip?: boolean;
42
43
  }): ViewerPane | null;
@@ -21,7 +21,7 @@ import { viewSocketPath } from '../canvas/paths.js';
21
21
  // Re-export the pure tmux driver verbs the CLI/viewer consumers need, so the
22
22
  // §5.1 lint's "only placement / tmux-chrome import tmux.ts" holds while these
23
23
  // modules never reach the canvas focuses table.
24
- export { paneExists, paneLocation, paneOfNode, paneCurrentPath, ensureSession, openNodeWindow, splitWindow, closePane, currentTmux, switchClient, selectWindow, selectLayout, selectPane, getPaneOption, setPaneOption, breakPane, inTmux, piCommand, shellQuote, installTmuxBindings, renameWindow, displayPopup, windowOfPane, respawnPaneSync, respawnPaneInPlace, paneStartCommand, panePid, windowAlive, listLivePanes, } from './tmux.js';
24
+ export { paneExists, paneLocation, paneOfNode, paneCurrentPath, ensureSession, openNodeWindow, splitWindow, closePane, currentTmux, switchClient, selectWindow, selectLayout, selectPane, getPaneOption, setPaneOption, breakPane, inTmux, piCommand, shellQuote, installTmuxBindings, renameWindow, displayPopup, windowOfPane, respawnPaneSync, respawnPaneInPlace, paneStartCommand, panePid, windowAlive, listLivePanes, VIEWER_STAMP_OPTION, stampViewerPaneAsync, liveViewerPanes, sendAttachControl, displayClientMessage, } from './tmux.js';
25
25
  // ---------------------------------------------------------------------------
26
26
  // view.sock readiness — the one shared broker-cold-start primitive
27
27
  // ---------------------------------------------------------------------------
@@ -124,9 +124,11 @@ export function openViewerPane(nodeId, session, opts = {}) {
124
124
  // the pane instantly — the same self-polling bootRoot/resume rely on. The
125
125
  // deadline is the shared BROKER_VIEW_SOCKET_WAIT_MS (one source of truth), not
126
126
  // a literal duplicated at the call site.
127
- const env = opts.waitForBroker === true
128
- ? { ...viewerSplitEnv(), CRTR_ATTACH_WAIT_MS: String(BROKER_FOCUS_SOCKET_WAIT_MS) }
129
- : viewerSplitEnv();
127
+ const env = {
128
+ ...viewerSplitEnv(),
129
+ ...(opts.waitForBroker === true ? { CRTR_ATTACH_WAIT_MS: String(BROKER_FOCUS_SOCKET_WAIT_MS) } : {}),
130
+ ...(opts.initialWhip === true ? { CRTR_ATTACH_INITIAL_WHIP: '1' } : {}),
131
+ };
130
132
  const cwd = opts.cwd ?? process.cwd();
131
133
  if (opts.besidePane !== undefined) {
132
134
  const pane = splitWindow(opts.besidePane, { cwd, env, command });
@@ -55,6 +55,7 @@ export declare function openViewerWindow(nodeId: string, session: string, opts?:
55
55
  cwd?: string;
56
56
  besidePane?: string;
57
57
  waitForBroker?: boolean;
58
+ initialWhip?: boolean;
58
59
  }): FocusRow | null;
59
60
  export declare function focus(nodeId: string, opts: {
60
61
  pane?: string;
@@ -44,14 +44,10 @@ import { isPidAlive } from '../canvas/pid.js';
44
44
  // `selectLayout` are FRESH minimal viewer-chrome helpers (not the deleted
45
45
  // engine-in-pane `breakPaneToSession`): `surface tmux-spread` breaks the caller's
46
46
  // viewer pane into its own window and tiles sibling viewers beside it.
47
- // `piCommand` + `paneCurrentPath` are KEPT: the sessionless surface-view system
48
- // (view-cycle.ts / view-run.ts) builds its pane commands with them, and the §5.1
49
- // import-lint forbids those commands importing tmux.ts directly — they must reach
50
- // the driver through placement. (They are NOT engine-in-pane; the design's
51
- // "nothing keeps" classification missed the view consumers.) `shellQuote` is
52
- // re-exported for the same reason — callers building the seam's expected
53
- // bundled-pi command string (e.g. the M1 seam test) need the identical quoting
54
- // piCommand uses internally, without importing tmux.ts directly.
47
+ // `piCommand`, `paneCurrentPath`, and `shellQuote` remain available to command
48
+ // modules that need to build or inspect tmux pane commands without importing
49
+ // tmux.ts directly; the §5.1 lint keeps the raw driver behind this placement
50
+ // boundary.
55
51
  export { splitWindow, breakPane, selectLayout, selectPane, focusWindow, selectWindow, switchClient, openNodeWindow, ensureSession, paneLocation, paneExists, paneRunning, paneCurrentPath, currentTmux, inTmux, paneOfNode, installTmuxBindings,
56
52
  // Compile seam for viewer.ts, which still calls installMenuBinding();
57
53
  // deleted when the attach unit imports installTmuxBindings directly.
@@ -60,6 +60,9 @@ function reshapeNode(nodeId, opts = {}, beforePersist) {
60
60
  // choice — so carry the node's existing pin verbatim instead.
61
61
  modelProviderPinned: opts.model === undefined ? node.launch?.modelProviderPinned : undefined,
62
62
  modelIntent: opts.model === undefined ? node.launch?.modelIntent : undefined,
63
+ // Exact-model human-work forks must stay fail-closed after a polymorph.
64
+ // Dropping this bit produces a recipe reviveNode refuses to relaunch.
65
+ modelExact: opts.model === undefined ? node.launch?.modelExact : undefined,
63
66
  // Resolve kind/ladder config against the NODE's own cwd + profile, not
64
67
  // this process's ambient scope.
65
68
  cwd: node.cwd,
@@ -1,8 +1,3 @@
1
- /** Ask pi headlessly for a concise briefing of `conversation`, async. Invokes
2
- * `onRecap` with the parsed string on success, or never (silent) on any
3
- * failure — non-zero exit, timeout, empty/garbled output. Owns the subprocess
4
- * mechanics — crucially it hands pi an immediate stdin EOF: `pi -p` reads stdin,
5
- * and execFile's default stdin is an OPEN pipe that never closes, so without
6
- * this pi blocks waiting for EOF and the call exits non-zero (the same gotcha
7
- * naming.ts documents). */
1
+ /** Ask Pi for a concise briefing of `conversation`. Invokes `onRecap` with
2
+ * the parsed string on success, or never on timeout, empty, or garbled output. */
8
3
  export declare function generateRecap(conversation: string, onRecap: (briefing: string) => void, liveModel?: string, roadmap?: string): void;
@@ -1,22 +1,16 @@
1
1
  // Inactivity recap — turn a dormant node's conversation into one concise
2
2
  // returning-developer briefing for the recap widget.
3
3
  //
4
- // One entry point: generateRecap — async (execFile, non-blocking), mirroring
5
- // naming.ts's headless-`pi -p` pattern exactly. It runs the live conversation's
6
- // working model over the literal back-and-forth (the caller concatenates user and
7
- // assistant text, plus the node's roadmap when one exists) with a stripped-
8
- // down pi invocation (no tools/session/context/extensions/skills), so it's fast
9
- // and side-effect free and can never recurse into another spawn.
4
+ // One entry point: generateRecap — async and non-blocking. It runs the live
5
+ // conversation's working model over the literal back-and-forth (the caller
6
+ // concatenates user and assistant text, plus the node's roadmap when one exists)
7
+ // in an isolated one-shot with no tools or canvas resources.
10
8
  //
11
- // Best-effort and silent on failure: a non-zero exit, timeout, empty or garbled
12
- // output resolves to NO recap (the caller shows nothing). The recap is throwaway
13
- // idle chrome — there is no local fallback, unlike naming, because a wrong or
14
- // stale recap is worse than none.
15
- //
16
- // Plain TS-with-types — no imports from @earendil-works/* so it compiles inside
17
- // crouter's own tsc build without a dep on the pi packages.
18
- import { execFile } from 'node:child_process';
19
- import { bundledPiSubprocessEnv, resolveBundledPiCliPath } from './pi-cli.js';
9
+ // Best-effort and silent on failure: timeout, empty, or garbled output resolves
10
+ // to NO recap (the caller shows nothing). The recap is throwaway idle chrome —
11
+ // there is no local fallback, unlike naming, because a wrong recap is worse than
12
+ // none.
13
+ import { headlessText } from './headless-pi.js';
20
14
  /** Wall-clock budget for the headless pi call before we give up (no recap). */
21
15
  const RECAP_TIMEOUT_MS = 25_000;
22
16
  /** Fallback model when the live session has not resolved one yet. Ordinarily the
@@ -62,37 +56,15 @@ function recapUserPrompt(conversation, roadmap) {
62
56
  : '';
63
57
  return `${rm}<conversation>\n${conversation}\n</conversation>\n\nWrite the two-line Goal:/State: briefing for the conversation above. Output JUST the two lines.`;
64
58
  }
65
- /** The pi argv for a headless recap request. Stripped down (no tools, session,
66
- * context files, extensions, skills, templates, themes) so it's fast and
67
- * side-effect free. Thinking stays off; model precedence is explicit env
68
- * override → the conversation's live working model → the small fallback. */
69
- function recapArgs(conversation, liveModel, roadmap) {
59
+ /** Model precedence is explicit env override → the conversation's live
60
+ * working model → the small fallback. */
61
+ function recapModel(liveModel) {
70
62
  const override = process.env['CRTR_RECAP_MODEL'];
71
- // An explicit operator override wins. Otherwise prefer the live conversation's
72
- // current model: it just completed a successful turn, while a hard-pinned
73
- // provider (the old Haiku-only path) may be rate-limited and silently produce
74
- // no brief. The small default remains for sessions with no resolved model yet.
75
- const model = override !== undefined && override.trim() !== ''
76
- ? override.trim()
77
- : liveModel !== undefined && liveModel.trim() !== ''
78
- ? liveModel.trim()
79
- : DEFAULT_RECAP_MODEL;
80
- const argv = [
81
- '-p',
82
- '--no-session',
83
- '--no-context-files',
84
- '--no-extensions',
85
- '--no-skills',
86
- '--no-prompt-templates',
87
- '--no-themes',
88
- '--no-tools',
89
- '--mode', 'text',
90
- '--thinking', 'off',
91
- '--model', model,
92
- '--system-prompt', RECAP_SYSTEM_PROMPT,
93
- recapUserPrompt(conversation, roadmap),
94
- ];
95
- return argv;
63
+ if (override !== undefined && override.trim() !== '')
64
+ return override.trim();
65
+ if (liveModel !== undefined && liveModel.trim() !== '')
66
+ return liveModel.trim();
67
+ return DEFAULT_RECAP_MODEL;
96
68
  }
97
69
  /** Normalize model stdout to the two-line `Goal:`/`State:` briefing. Collapses
98
70
  * intra-line whitespace and drops blank lines; the viewer paints each line
@@ -105,32 +77,26 @@ function parseRecap(stdout) {
105
77
  .filter((l) => l !== '')
106
78
  .join('\n');
107
79
  }
108
- /** Ask pi headlessly for a concise briefing of `conversation`, async. Invokes
109
- * `onRecap` with the parsed string on success, or never (silent) on any
110
- * failure — non-zero exit, timeout, empty/garbled output. Owns the subprocess
111
- * mechanics — crucially it hands pi an immediate stdin EOF: `pi -p` reads stdin,
112
- * and execFile's default stdin is an OPEN pipe that never closes, so without
113
- * this pi blocks waiting for EOF and the call exits non-zero (the same gotcha
114
- * naming.ts documents). */
80
+ /** Ask Pi for a concise briefing of `conversation`. Invokes `onRecap` with
81
+ * the parsed string on success, or never on timeout, empty, or garbled output. */
115
82
  export function generateRecap(conversation, onRecap, liveModel, roadmap) {
116
83
  const body = (conversation ?? '').trim();
117
84
  if (body === '')
118
85
  return;
119
- try {
120
- const child = execFile(process.execPath, [resolveBundledPiCliPath(), ...recapArgs(body, liveModel, roadmap)], { encoding: 'utf8', timeout: RECAP_TIMEOUT_MS, env: bundledPiSubprocessEnv() }, (err, stdout) => {
121
- if (err || typeof stdout !== 'string')
122
- return; // silent — no recap
123
- const briefing = parseRecap(stdout);
124
- if (briefing === '')
125
- return;
126
- try {
127
- onRecap(briefing);
128
- }
129
- catch { /* best-effort */ }
130
- });
131
- child.stdin?.end(); // immediate EOF — see the doc above
132
- }
133
- catch {
134
- // best-effort: no recap
135
- }
86
+ void headlessText({
87
+ systemPrompt: RECAP_SYSTEM_PROMPT,
88
+ userPrompt: recapUserPrompt(body, roadmap),
89
+ modelSpec: recapModel(liveModel),
90
+ timeoutMs: RECAP_TIMEOUT_MS,
91
+ })
92
+ .then((reply) => {
93
+ const briefing = parseRecap(reply);
94
+ if (briefing === '')
95
+ return;
96
+ try {
97
+ onRecap(briefing);
98
+ }
99
+ catch { /* best-effort */ }
100
+ })
101
+ .catch(() => undefined);
136
102
  }
@@ -22,7 +22,7 @@
22
22
  // reviveNode remains the ONLY sanctioned launcher of the node engine.
23
23
  import { existsSync } from 'node:fs';
24
24
  import { isAbsolute } from 'node:path';
25
- import { getNode, updateNode, clearPid, recordPid, fullName, subscribersOf, getHumanWorkRow, } from '../canvas/index.js';
25
+ import { getNode, updateNode, clearPid, recordPid, fullName, subscribersOf, } from '../canvas/index.js';
26
26
  import { cancelCronsOnWake } from '../canvas/crons.js';
27
27
  import { transition } from './lifecycle.js';
28
28
  import { fanDoctrineWake } from './close.js';
@@ -35,6 +35,7 @@ import { boundFleet } from './fleet.js';
35
35
  import { clearFault, beginBootFaultAttempt } from './fault.js';
36
36
  import { clearInjectedDocs } from '../substrate/injected-store.js';
37
37
  import { rootOfSpine } from './nodes.js';
38
+ import { isReviewCompanionBound } from '../review/companion.js';
38
39
  // ---------------------------------------------------------------------------
39
40
  // resumeArgs — which session source a revive resumes from
40
41
  // ---------------------------------------------------------------------------
@@ -63,15 +64,6 @@ export function resumeArgs(meta, resume) {
63
64
  // ---------------------------------------------------------------------------
64
65
  // Return type
65
66
  // ---------------------------------------------------------------------------
66
- function isHumanWorkTarget(value) {
67
- if (value === null || typeof value !== 'object')
68
- return false;
69
- const target = value;
70
- return ((target.work_kind === 'follow_up' || target.work_kind === 'visual') &&
71
- typeof target.dir === 'string' && target.dir !== '' &&
72
- typeof target.request_id === 'string' && target.request_id !== '' &&
73
- typeof target.root === 'string' && target.root !== '');
74
- }
75
67
  /** A relaunch that has NO transcript to resume or branch from, and no durable
76
68
  * work state on disk (no roadmap, no yield note), is not a revive at all — the
77
69
  * node never got a conversation off the ground, so there is no "previous
@@ -106,11 +98,7 @@ export function reviveNode(nodeId, opts) {
106
98
  if (meta === null) {
107
99
  throw new Error(`reviveNode: unknown node ${nodeId}`);
108
100
  }
109
- // Fresh durable snapshot immediately before the guard. A private fork's
110
- // session_start hook may have atomically changed fork_pending →
111
- // session_started since the caller's read; launching from a stale phase
112
- // would fork provenance a second time instead of resuming the
113
- // now-authoritative child session.
101
+ // Fresh durable snapshot immediately before the lifecycle guard.
114
102
  meta = getNode(nodeId) ?? meta;
115
103
  // #339/#340: refuse to revive a LATCHED node — the reopen gate at every
116
104
  // legitimate caller (node message send, node lifecycle revive) already checked this
@@ -153,70 +141,41 @@ export function reviveNode(nodeId, opts) {
153
141
  updateNode(nodeId, { host_kind: 'broker' });
154
142
  meta.host_kind = 'broker';
155
143
  }
156
- // Private human-work forks have one explicit two-phase recipe. Before a
157
- // child session is bound, every attempt MUST replay the same immutable
158
- // `--fork` birth + kickoff regardless of the caller's requested resume mode.
159
- // After bind, provenance is never a launch source again: recovery goes only
160
- // through the recorded writable child session. The target + exact-model
161
- // assertions make malformed partial claims fail closed rather than silently
162
- // becoming an ordinary fresh node.
163
- const privateForkPending = meta.private_fork_phase === 'fork_pending';
164
- const privateForkStarted = meta.private_fork_phase === 'session_started';
165
- const hasPrivateClaim = meta.human_work_target != null || meta.private_fork_phase != null || meta.private_fork_recipe != null;
166
- if (hasPrivateClaim && !privateForkPending && !privateForkStarted) {
167
- throw new Error(`reviveNode: private fork ${nodeId} has no recognized phase`);
168
- }
169
- if (privateForkPending || privateForkStarted) {
170
- if (!isHumanWorkTarget(meta.human_work_target)) {
171
- throw new Error(`reviveNode: private fork ${nodeId} has no recognized human_work_target`);
172
- }
173
- if (meta.private_fork_recipe == null || meta.private_fork_recipe.kickoff.trim() === '') {
174
- throw new Error(`reviveNode: private fork ${nodeId} has no persisted kickoff recipe`);
175
- }
176
- if (meta.launch?.modelExact !== true || typeof meta.launch.model !== 'string' || meta.launch.model.trim() === '') {
177
- throw new Error(`reviveNode: private fork ${nodeId} has no exact persisted model`);
178
- }
179
- }
180
- if (privateForkPending) {
181
- // A Visual child is deliberately born inert. Its start handler rechecks
182
- // Humanloop after persisting the node, then this locked gate consumes the
183
- // still-armed claim immediately before launch. A cancel changes the claim
184
- // to visual_retired before it can acknowledge, so it can never wake a
185
- // canceled fork after the fact.
186
- const work = getHumanWorkRow(nodeId);
187
- const expectedStatus = meta.human_work_target.work_kind === 'visual' ? 'visual_armed' : 'armed';
188
- if (work === null || work.work_kind !== meta.human_work_target.work_kind || work.status !== expectedStatus) {
189
- throw new Error(`reviveNode: private fork ${nodeId} is no longer launchable`);
190
- }
191
- if (typeof meta.fork_from !== 'string' || !isAbsolute(meta.fork_from)) {
192
- throw new Error(`reviveNode: pending private fork ${nodeId} requires an absolute fork_from provenance file`);
193
- }
194
- if (meta.pi_session_id != null || meta.pi_session_file != null) {
195
- throw new Error(`reviveNode: pending private fork ${nodeId} cannot already have a bound child session`);
196
- }
144
+ // A review companion's session coordinates are valid only after its durable
145
+ // visible boundary. Detach any markerless child so this launch replays the
146
+ // immutable fork instead of resuming an inherited transcript.
147
+ const reviewCompanionUnbound = meta.review_binding != null && !isReviewCompanionBound(nodeId);
148
+ if (reviewCompanionUnbound && (meta.pi_session_id != null || meta.pi_session_file != null)) {
149
+ updateNode(nodeId, { pi_session_id: null, pi_session_file: null });
150
+ meta.pi_session_id = null;
151
+ meta.pi_session_file = null;
197
152
  }
198
- if (privateForkStarted) {
199
- if (typeof meta.pi_session_id !== 'string' || meta.pi_session_id === '' ||
200
- typeof meta.pi_session_file !== 'string' || meta.pi_session_file === '' ||
201
- !existsSync(meta.pi_session_file)) {
202
- throw new Error(`reviveNode: bound private fork ${nodeId} requires its recorded child session file`);
203
- }
153
+ // An ordinary fork remains a birth until session_start records the child
154
+ // session. Replaying the immutable branch on every pre-bind retry prevents a
155
+ // crash from silently turning it into a fresh conversation.
156
+ const forkBirthPending = typeof meta.fork_from === 'string' &&
157
+ isAbsolute(meta.fork_from) &&
158
+ meta.pi_session_id == null;
159
+ if (forkBirthPending && !existsSync(meta.fork_from)) {
160
+ throw new InputError({
161
+ error: 'fork_from_missing',
162
+ message: `${nodeId} cannot be revived — its fork source no longer exists: ${meta.fork_from}`,
163
+ next: `Restore ${meta.fork_from}, or update the node's fork source, then retry \`crtr node lifecycle revive ${nodeId}\`.`,
164
+ });
204
165
  }
205
166
  // Every (re)launch is a new cycle — bump the counter so CRTR_CYCLES and the
206
167
  // footer stay in sync. Mutate the in-memory meta too so buildPiArgv below
207
168
  // launches with the incremented count.
208
169
  meta.cycles = (meta.cycles ?? 0) + 1;
209
170
  updateNode(nodeId, { cycles: meta.cycles });
210
- // Ordinary nodes choose resume/cycle/fresh from their recorded session. A
211
- // pending private fork deliberately has no child session yet and takes the
212
- // dedicated immutable birth branch below instead. Persisted pending-refresh
213
- // state (durable across a pre-session_start crash-retry) outranks a caller's
214
- // strict-resume request; a bound private fork's forced resume outranks both.
215
- // resumeArgs then selects only an existing absolute session path: strict
171
+ // Ordinary nodes choose resume/cycle/fresh from their recorded session.
172
+ // Persisted pending-refresh state (durable across a pre-session_start
173
+ // crash-retry) outranks a caller's strict-resume request. resumeArgs then
174
+ // selects only an existing absolute session path: strict
216
175
  // resume continues its leaf, while fresh/cycle mode roots a new one.
217
176
  const refreshPending = meta.intent === 'refresh' || meta.cycle_pending === true;
218
- const effectiveResume = privateForkStarted ? true : (refreshPending ? false : opts.resume);
219
- const resume = privateForkPending ? {} : resumeArgs(meta, effectiveResume);
177
+ const effectiveResume = refreshPending ? false : opts.resume;
178
+ const resume = forkBirthPending ? {} : resumeArgs(meta, effectiveResume);
220
179
  // hasSessionPath: there is a real `.jsonl` to hand pi via `--session`, whether
221
180
  // as a true resume OR a cycling refresh-yield (resumeArgs sets `newCycle` in
222
181
  // the latter case). cycling and resuming are mutually exclusive; `resuming`
@@ -231,7 +190,7 @@ export function reviveNode(nodeId, opts) {
231
190
  const cyclePending = meta.cycle_pending === true || cycling;
232
191
  updateNode(nodeId, { cycle_pending: cyclePending });
233
192
  meta.cycle_pending = cyclePending;
234
- // A truly fresh ordinary launch — no `.jsonl` to resume OR cycle from —
193
+ // A truly fresh launch — no `.jsonl` to resume OR cycle from —
235
194
  // starts a NEW pi session, so the old session identity is dead. Clear it from meta NOW,
236
195
  // before launch, so the recorded state matches what we're about to do. This
237
196
  // is load-bearing for exit-policy classification (classifyDeadNode row 8):
@@ -243,7 +202,7 @@ export function reviveNode(nodeId, opts) {
243
202
  // are exactly what's being reused — so a cycling broker that dies
244
203
  // pre-session_start classifies as a retryable respawn, same class as a
245
204
  // resume revive.
246
- if (!privateForkPending && !hasSessionPath && (meta.pi_session_id != null || meta.pi_session_file != null)) {
205
+ if (!forkBirthPending && !hasSessionPath && (meta.pi_session_id != null || meta.pi_session_file != null)) {
247
206
  updateNode(nodeId, { pi_session_id: null, pi_session_file: null });
248
207
  meta.pi_session_id = null;
249
208
  meta.pi_session_file = null;
@@ -256,14 +215,12 @@ export function reviveNode(nodeId, opts) {
256
215
  // unchanged (empty for true-fresh, both set for cycling) so buildPiArgv emits
257
216
  // the right argv either way.
258
217
  let inv;
259
- if (privateForkPending) {
218
+ if (forkBirthPending) {
219
+ const goal = readGoal(nodeId);
260
220
  inv = buildPiArgv(meta, {
261
- prompt: meta.private_fork_recipe.kickoff,
262
221
  forkFrom: meta.fork_from,
222
+ ...(goal != null && goal !== '' ? { prompt: goal } : {}),
263
223
  });
264
- // A fork birth creates a new LLM context just like an ordinary fresh
265
- // launch; retries before bind must not inherit an injected-doc cache from
266
- // a failed process.
267
224
  clearInjectedDocs(nodeId);
268
225
  }
269
226
  else if (resuming) {
@@ -20,6 +20,10 @@ export interface CycleSessionManagerLike {
20
20
  * path root-first. */
21
21
  getBranch?(fromId?: string): SessionEntry[];
22
22
  }
23
+ /** A refresh-yield deliberately aborts its own turn before the next cycle is
24
+ * rooted. Preserve that assistant message (including tool calls and prose), but
25
+ * omit the failure annotation: the cycle divider is the truthful visible seam. */
26
+ export declare function withoutYieldAbort(message: SnapshotMessage): SnapshotMessage;
23
27
  /** The full multi-cycle message history for display: prior cycles (oldest
24
28
  * first, each closed by a divider), then the live cycle's context. Falls back
25
29
  * to plain `buildSessionContext()` when the session has no cycle markers, when
@@ -32,6 +32,19 @@ function cycleDivider(cycle, timestamp) {
32
32
  timestamp: new Date(timestamp).getTime(),
33
33
  };
34
34
  }
35
+ /** A refresh-yield deliberately aborts its own turn before the next cycle is
36
+ * rooted. Preserve that assistant message (including tool calls and prose), but
37
+ * omit the failure annotation: the cycle divider is the truthful visible seam. */
38
+ export function withoutYieldAbort(message) {
39
+ if (message.role !== 'assistant' || message.stopReason !== 'aborted')
40
+ return message;
41
+ const { stopReason: _stopReason, errorMessage: _errorMessage, ...visible } = message;
42
+ return visible;
43
+ }
44
+ function priorCycleMessages(messages) {
45
+ const last = messages.at(-1);
46
+ return last === undefined ? messages : [...messages.slice(0, -1), withoutYieldAbort(last)];
47
+ }
35
48
  /** The full multi-cycle message history for display: prior cycles (oldest
36
49
  * first, each closed by a divider), then the live cycle's context. Falls back
37
50
  * to plain `buildSessionContext()` when the session has no cycle markers, when
@@ -68,7 +81,7 @@ export function cycleAwareMessages(sm) {
68
81
  // builder — preserving compaction semantics (one compactionSummary +
69
82
  // kept + post-compaction messages only) exactly like the live cycle
70
83
  // below.
71
- out.push(...buildSessionContext(entries, fromLeaf, byId).messages);
84
+ out.push(...priorCycleMessages(buildSessionContext(entries, fromLeaf, byId).messages));
72
85
  }
73
86
  out.push(cycleDivider(marker.data?.cycle, marker.timestamp));
74
87
  }
@@ -0,0 +1,37 @@
1
+ import type { BrokerSnapshot, WireSessionTreeNode } from './broker-protocol.js';
2
+ /** customType of the crtr-authored boundary marker that opens a review
3
+ * companion's visible transcript. Data payload: `{ reviewId, originNodeId,
4
+ * targetFile }` — per-review facts that complement the inheritance prefix.
5
+ *
6
+ * The marker itself is a crtr-rendered divider shown to the person; everything
7
+ * above it in the inherited session is context they cannot see.
8
+ */
9
+ export declare const REVIEW_BOUNDARY_CUSTOM_TYPE = "crtr-review-boundary";
10
+ /** True when an entry is a durable review boundary, optionally for one review. */
11
+ export declare function isReviewBoundary(entry: unknown, reviewId?: string): boolean;
12
+ /**
13
+ * Project snapshot messages to the visible window for a review companion.
14
+ *
15
+ * Contract (in evaluation order):
16
+ * 1. Marker present → slice from the **first** occurrence (marker included) to
17
+ * the end. Everything before the marker is inherited context, hidden from
18
+ * the person.
19
+ * 2. Not a review companion → return input unchanged (same reference). Ordinary
20
+ * nodes are not filtered.
21
+ * 3. No marker and review companion → a leading compaction summary is replaced
22
+ * with a synthetic boundary while its retained tail remains visible. Every
23
+ * other markerless shape fails closed with the synthetic boundary alone.
24
+ */
25
+ export declare function visibleMessages(messages: BrokerSnapshot['messages'], opts: {
26
+ reviewCompanion: boolean;
27
+ }): BrokerSnapshot['messages'];
28
+ /**
29
+ * Project a session tree to the review companion's visible transcript boundary.
30
+ *
31
+ * Pre-boundary ancestors are omitted rather than retained as empty structural
32
+ * shells, making each durable boundary a root in the returned forest. Once a
33
+ * boundary is crossed, its complete descendant subtree remains navigable. An
34
+ * absent boundary produces an empty tree, so picker previews never disclose an
35
+ * inherited entry before a mutation guard can reject its selection.
36
+ */
37
+ export declare function boundaryRootedTree(tree: readonly WireSessionTreeNode[]): WireSessionTreeNode[];