@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
@@ -50,20 +50,22 @@ import { execFile } from 'node:child_process';
50
50
  import { randomBytes } from 'node:crypto';
51
51
  import { promisify } from 'node:util';
52
52
  import { crtrHome, nodeDir, jobDir, isSafeNodeId } from '../core/canvas/paths.js';
53
- import { listNodes, getRow, getNode, migrateLegacyPidIdentities, listFocuses, closeFocusRow, pruneToLimit, subscribersOf, reconcileFollowUpWork, reconcileVisualWork, } from '../core/canvas/index.js';
53
+ import { listNodes, getRow, getNode, migrateLegacyPidIdentities, listFocuses, closeFocusRow, pruneToLimit, subscribersOf, } from '../core/canvas/index.js';
54
54
  import { fullName } from '../core/canvas/labels.js';
55
55
  import { transition } from '../core/runtime/lifecycle.js';
56
56
  import { isBusy, busySince } from '../core/runtime/busy.js';
57
57
  import { FAULT_QUIET_MS, readFault, recordFault } from '../core/runtime/fault.js';
58
58
  import { fanDoctrineWake } from '../core/runtime/close.js';
59
59
  import { createApiServer } from './api/server.js';
60
+ import { reconcileUndeliveredTickets } from './human/sweep.js';
61
+ import { sweepReviews } from './review/sweep.js';
60
62
  // Lean pidfile/liveness helpers now live in `pidfile.ts` (db-free, so the CLI
61
63
  // daemon front door can import them without reaching openDb). Imported here for
62
64
  // internal use and re-exported below to preserve the historical crtrd.ts
63
65
  // surface (tests, `commands/sys/daemon.ts`).
64
66
  import { pidfilePath } from './pidfile.js';
65
67
  export { readPidfile, isDaemonRunning } from './pidfile.js';
66
- import { globalHumanloopWarning } from '../core/runtime/package-health.js';
68
+ import { rendererWarning } from '../core/runtime/package-health.js';
67
69
  import { DEFAULT_INTERVAL_MS } from './supervise-cadence.js';
68
70
  import { readConfig } from '../core/config.js';
69
71
  export { FAULT_QUIET_MS };
@@ -80,7 +82,7 @@ import { reviveNode } from '../core/runtime/revive.js';
80
82
  import { prewarmRecentRecipes, reapStaleSpares } from '../core/runtime/warm-pool.js';
81
83
  import { headlessBrokerHost } from '../core/runtime/host.js';
82
84
  import { reloadAuthLive } from '../core/runtime/auth-reload.js';
83
- import { DaemonFleet, reconcileFollowUpWorkOnCrash, retryResumeMode } from './fleet.js';
85
+ import { DaemonFleet, retryResumeMode } from './fleet.js';
84
86
  export { retryResumeMode };
85
87
  import { appendControllerDeathNotice, readInboxSince, readCursor, } from '../core/feed/inbox.js';
86
88
  import { migrateLegacyInboxIdentities } from '../core/feed/inbox-migrate.js';
@@ -99,9 +101,6 @@ import { recoverStaleCronLeases, runDueCrons } from './cron-run.js';
99
101
  // `encoding`/`timeout`, same decisions made from stdout) — only the blocking
100
102
  // behavior changes.
101
103
  const execFileAsync = promisify(execFile);
102
- // surfaceBootFailure + reconcileFollowUpWorkOnCrash moved to ./fleet.js — the
103
- // fleet's exit-policy paths are their primary consumers; the surviving crtrd
104
- // passes import them back from there.
105
104
  // Count-based auto-prune of the canvas (pruneToLimit). The canvas grows
106
105
  // unbounded — the TTL `crtr canvas prune` is manual, so without this a long-lived
107
106
  // daemon's canvas accumulates thousands of terminal nodes, making every scan +
@@ -359,7 +358,7 @@ export async function runStartupRecoverySweep(fleet) {
359
358
  const thresholds = brokerThresholdsForDaemon();
360
359
  for (const row of rows) {
361
360
  if (row.kind === 'human')
362
- continue; // humanloop bridge rows — never broker-hosted
361
+ continue; // human bridge rows — never broker-hosted
363
362
  if (fleet.size() >= thresholds.automaticReviveCap) {
364
363
  emitEvent({
365
364
  level: 'warn',
@@ -915,7 +914,6 @@ function handleFatalFault(id, now) {
915
914
  if (terminalOverflow) {
916
915
  try {
917
916
  transition(id, 'crash');
918
- reconcileFollowUpWorkOnCrash(id);
919
917
  headlessBrokerHost.teardown(id);
920
918
  }
921
919
  catch {
@@ -1275,10 +1273,9 @@ export async function superviseTick(now = Date.now(), lifecycle = directTickLife
1275
1273
  return;
1276
1274
  }
1277
1275
  // kind:'human' rows are NOT broker-hosted agent nodes — they are bookkeeping
1278
- // rows for the `crtr human` bridge. Their lifecycle is driven entirely by
1279
- // humanloop's registered `_deliver` handler — which pushFinals the answer when
1280
- // the human responds from the humanloop inbox — or by `human cancel`. They
1281
- // never launch a broker or record a `pi_session_id`, so the dead-node policy
1276
+ // rows for the `crtr human` bridge. crtrd delivers their terminal ticket result
1277
+ // with pushFinal when the person responds from crouter's inbox, or when `human cancel`
1278
+ // publishes a cancellation. They never launch a broker or record a `pi_session_id`, so the dead-node policy
1282
1279
  // table would read every one as a never-booted broker (row 8) and crash it
1283
1280
  // with surfaceBootFailure — exactly the regression where a headless
1284
1281
  // orchestrator's `human ask` nodes all died at boot. The daemon must never
@@ -1433,7 +1430,6 @@ export async function superviseTick(now = Date.now(), lifecycle = directTickLife
1433
1430
  },
1434
1431
  });
1435
1432
  transition(id, 'crash');
1436
- reconcileFollowUpWorkOnCrash(id);
1437
1433
  if (meta !== null) {
1438
1434
  try {
1439
1435
  fanDoctrineWake(id, subscribersOf(id), `Child crashed — ${fullName(meta)} (${id}) failed to relaunch after ${attempts} attempts while trying to ` +
@@ -1845,13 +1841,12 @@ export async function runDaemon(opts = {}) {
1845
1841
  operationIdContext.fresh(() => {
1846
1842
  emitEvent({ level: 'info', event: 'daemon.install_id.resolved', fields: { install_id: installId } });
1847
1843
  });
1848
- // The tmux inbox binding resolves a PATH-global `hl`, while crouter imports
1849
- // its bundled humanloop library. The health probe is advisory; setup repairs
1850
- // a stale executable without blocking supervision.
1844
+ // The pinned termrender renderer is an advisory dependency; setup repairs
1845
+ // an unprovisioned venv without blocking supervision.
1851
1846
  operationIdContext.fresh(() => {
1852
1847
  let warning;
1853
1848
  try {
1854
- warning = globalHumanloopWarning();
1849
+ warning = rendererWarning();
1855
1850
  }
1856
1851
  catch {
1857
1852
  return;
@@ -1860,25 +1855,14 @@ export async function runDaemon(opts = {}) {
1860
1855
  emitEvent({
1861
1856
  level: 'warn',
1862
1857
  event: 'daemon.startup.warning',
1863
- fields: { stage: 'global_humanloop', warning: warning.slice(0, 2_048) },
1858
+ fields: { stage: 'termrender', warning: warning.slice(0, 2_048) },
1864
1859
  });
1865
1860
  }
1866
1861
  });
1867
- // Consult-outbox reconciliation is the startup crash-safety pass for
1868
- // pending delivery and armed forks that terminated before reporting.
1869
- operationIdContext.fresh(() => {
1870
- try {
1871
- reconcileFollowUpWork();
1872
- reconcileVisualWork();
1873
- }
1874
- catch (error) {
1875
- emitEvent({
1876
- level: 'error',
1877
- event: 'consult.outbox.reconcile_failed',
1878
- error,
1879
- fields: { phase: 'startup' },
1880
- });
1881
- }
1862
+ // Complete ticket delivery before API traffic can observe terminal answers.
1863
+ await operationIdContext.fresh(async () => {
1864
+ await sweepReviews();
1865
+ await reconcileUndeliveredTickets();
1882
1866
  });
1883
1867
  // Boot reconciliation clears stale process identities before any tick can
1884
1868
  // inspect them, then migrates legacy identities only with proven same-boot
@@ -9,13 +9,6 @@ import type { HostHandle } from '../core/runtime/host.js';
9
9
  * urgent push so the parent learns the child failed to launch instead of just
10
10
  * seeing a silent `dead`. */
11
11
  export declare function surfaceBootFailure(meta: NodeMeta): Promise<void>;
12
- /** Event-driven follow-up human-work settlement at daemon-detected node death
13
- * (design-followup-consult-v2.md §B.4 step 4). Re-runs the consult-outbox
14
- * reconcile scan right where the daemon first observes a death, so an `armed`
15
- * row whose fork just died with no final report becomes the ticket's error
16
- * result immediately. A no-op for every crash that isn't a consult/visual
17
- * fork. Best-effort, mirrors the startup call's error handling. */
18
- export declare function reconcileFollowUpWorkOnCrash(id: string): void;
19
12
  /** Whether a dead relaunch should resume the saved session strictly, or retry
20
13
  * as a fresh cycle instead. A cycling attempt (cycle_pending) that dies
21
14
  * before session_start must retry AS a cycle — a strict reopen only restores
@@ -26,7 +19,7 @@ export declare function retryResumeMode(meta: Pick<NodeMeta, 'cycle_pending'> |
26
19
  export type DeadNodeAction = 'forget' | 'respawn-fresh' | 'dormant' | 'respawn-cycle' | 'respawn-resume' | 'boot-failure';
27
20
  /** The narrow durable state the policy table reads. Structural (a Pick, not
28
21
  * NodeMeta itself) so tests fabricate table rows directly. */
29
- export type DeadNodeRow = Pick<NodeMeta, 'status' | 'intent' | 'pi_session_id' | 'cycle_pending' | 'private_fork_phase'>;
22
+ export type DeadNodeRow = Pick<NodeMeta, 'status' | 'intent' | 'pi_session_id' | 'cycle_pending' | 'fork_from'>;
30
23
  /** One pure function producing the action for a node known-dead. Used at
31
24
  * exactly two call sites — an exit-policy job and the startup recovery sweep
32
25
  * (design D-12) — so exit recovery and startup recovery can never diverge.
@@ -13,7 +13,7 @@
13
13
  // before every deliberate exit, and that durable state is robust to every kill
14
14
  // path. Codes/signals are logged for diagnostics only. The single timing
15
15
  // input is uptime, used only by the throttle.
16
- import { getNode, subscribersOf, reconcileFollowUpWork, reconcileVisualWork } from '../core/canvas/index.js';
16
+ import { getNode, subscribersOf } from '../core/canvas/index.js';
17
17
  import { fullName } from '../core/canvas/labels.js';
18
18
  import { isSafeNodeId } from '../core/canvas/paths.js';
19
19
  import { transition } from '../core/runtime/lifecycle.js';
@@ -50,30 +50,6 @@ async function surfaceRecoveryFailure(meta, error) {
50
50
  `The node is now dead. Fix the recorded launch configuration, then revive it if the work still needs doing.`;
51
51
  await pushUrgent(meta.node_id, body, { from: meta.node_id });
52
52
  }
53
- /** Event-driven follow-up human-work settlement at daemon-detected node death
54
- * (design-followup-consult-v2.md §B.4 step 4). Re-runs the consult-outbox
55
- * reconcile scan right where the daemon first observes a death, so an `armed`
56
- * row whose fork just died with no final report becomes the ticket's error
57
- * result immediately. A no-op for every crash that isn't a consult/visual
58
- * fork. Best-effort, mirrors the startup call's error handling. */
59
- export function reconcileFollowUpWorkOnCrash(id) {
60
- try {
61
- reconcileFollowUpWork();
62
- reconcileVisualWork();
63
- }
64
- catch (err) {
65
- emitEvent({
66
- level: 'error',
67
- event: 'consult.outbox.reconcile_failed',
68
- ...(isSafeNodeId(id) ? { node_id: id } : {}),
69
- error: err,
70
- fields: {
71
- phase: 'crash',
72
- ...(isSafeNodeId(id) ? {} : { affected_node_id: id }),
73
- },
74
- });
75
- }
76
- }
77
53
  /** Whether a dead relaunch should resume the saved session strictly, or retry
78
54
  * as a fresh cycle instead. A cycling attempt (cycle_pending) that dies
79
55
  * before session_start must retry AS a cycle — a strict reopen only restores
@@ -104,8 +80,8 @@ export function classifyDeadNode(row, busy, cleanAbort = false) {
104
80
  return 'respawn-cycle'; // row 6: dirty interrupted turn
105
81
  if (row.pi_session_id != null)
106
82
  return retryResumeMode(row, false) ? 'respawn-resume' : 'respawn-cycle'; // row 7
107
- if (row.private_fork_phase === 'fork_pending')
108
- return 'respawn-fresh'; // row 8: bounded fork-birth retry
83
+ if (row.fork_from != null && row.pi_session_id == null)
84
+ return 'respawn-fresh'; // row 8: bounded ordinary fork-birth retry
109
85
  return 'boot-failure'; // row 9
110
86
  }
111
87
  // ---------------------------------------------------------------------------
@@ -377,8 +353,7 @@ export class DaemonFleet {
377
353
  }
378
354
  }
379
355
  /** Terminal outcome shared by table row 8 and throttle exhaustion:
380
- * transition('crash') + consult-outbox reconcile + surfaceBootFailure +
381
- * doctrine wake, counter cleared. */
356
+ * transition('crash') + surfaceBootFailure + doctrine wake, counter cleared. */
382
357
  async #terminalize(nodeId, meta, opts) {
383
358
  this.#clearThrottle(nodeId);
384
359
  emitEvent({
@@ -387,7 +362,6 @@ export class DaemonFleet {
387
362
  ...(isSafeNodeId(nodeId) ? { node_id: nodeId } : { fields: { affected_node_id: nodeId } }),
388
363
  });
389
364
  transition(nodeId, 'crash');
390
- reconcileFollowUpWorkOnCrash(nodeId);
391
365
  try {
392
366
  await (opts.surface ?? (() => surfaceBootFailure(meta)))();
393
367
  }
@@ -0,0 +1,14 @@
1
+ import type { InteractionResponse, TicketResult } from '../../core/human/types.js';
2
+ /** Resolve a deck ticket under the store-owned claim-takeover lock boundary. */
3
+ export declare function resolveDeckTicket(nodeId: string, responses: InteractionResponse[]): Promise<TicketResult>;
4
+ /** Cancel a ticket with the store's first-writer-wins publication. */
5
+ export declare function cancelHumanTicket(nodeId: string, opts: {
6
+ reason?: string;
7
+ actor?: string;
8
+ }): Promise<TicketResult>;
9
+ /**
10
+ * Deliver a terminal ticket result to its bridge. The canonical response is the
11
+ * receipt: every action below is replay-safe, so lost delivery can be retried
12
+ * by a later resolve/cancel attempt or the daemon-start sweep.
13
+ */
14
+ export declare function deliverTerminalResult(nodeId: string): Promise<boolean>;
@@ -0,0 +1,115 @@
1
+ import { join } from 'node:path';
2
+ import { ApiError } from '../../api/index.js';
3
+ import { getNode, subscribersOf } from '../../core/canvas/canvas.js';
4
+ import { ticketDir } from '../../core/human/root.js';
5
+ import { cancelTicket, projectReviewOutput, readTicketResult, takeoverAndCompleteDeck, } from '../../core/human/tickets.js';
6
+ import { readJson, responsePath } from '../../core/human/convention.js';
7
+ import { appendInbox } from '../../core/feed/inbox.js';
8
+ import { FinalDeliveryError, pushFinal } from '../../core/feed/feed.js';
9
+ import { transition } from '../../core/runtime/lifecycle.js';
10
+ function envelopeFromDeckResult(responses, summary, completedAt, resultPath) {
11
+ return { summary, responsePath: resultPath, schema: 'humanloop.response/v2', responses, completedAt };
12
+ }
13
+ function renderDeckAnswer(env) {
14
+ const summary = env.summary.trim();
15
+ const body = summary === '' ? '(the human submitted no answer text)' : summary;
16
+ return `${body}\n\nResponse metadata (question ids, selected options, timestamp): ${env.responsePath}`;
17
+ }
18
+ function deliveryFailed(error) {
19
+ // A canonical final is committed inside its own write boundary and can never
20
+ // be replayed (`already_finalized`), so a subscriber that missed the fanout
21
+ // stays missed. Say that rather than promising a retry that cannot happen.
22
+ if (error instanceof FinalDeliveryError) {
23
+ return new ApiError(500, 'delivery_failed', `The answer is recorded and the bridge node is finalized; its report is at ${error.reportPath}. Notifying ${error.failedTo.join(', ')} failed and will not be retried.`);
24
+ }
25
+ const detail = error instanceof Error ? error.message : String(error);
26
+ return new ApiError(500, 'delivery_failed', `The answer is recorded and delivery will be retried: ${detail}`);
27
+ }
28
+ async function deliverOrConflict(nodeId) {
29
+ try {
30
+ await deliverTerminalResult(nodeId);
31
+ }
32
+ catch (error) {
33
+ throw deliveryFailed(error);
34
+ }
35
+ throw new ApiError(409, 'ticket_already_resolved', 'ticket already resolved');
36
+ }
37
+ /** Resolve a deck ticket under the store-owned claim-takeover lock boundary. */
38
+ export async function resolveDeckTicket(nodeId, responses) {
39
+ const completed = takeoverAndCompleteDeck(ticketDir(nodeId), responses, { host: 'crtrd', pid: process.pid });
40
+ if (!completed.won)
41
+ return deliverOrConflict(nodeId);
42
+ try {
43
+ await deliverTerminalResult(nodeId);
44
+ }
45
+ catch (error) {
46
+ throw deliveryFailed(error);
47
+ }
48
+ return completed.result;
49
+ }
50
+ /** Cancel a ticket with the store's first-writer-wins publication. */
51
+ export async function cancelHumanTicket(nodeId, opts) {
52
+ const canceled = cancelTicket(ticketDir(nodeId), opts);
53
+ if (canceled.status === 'already_resolved')
54
+ return deliverOrConflict(nodeId);
55
+ try {
56
+ await deliverTerminalResult(nodeId);
57
+ }
58
+ catch (error) {
59
+ throw deliveryFailed(error);
60
+ }
61
+ return canceled.result;
62
+ }
63
+ /**
64
+ * Deliver a terminal ticket result to its bridge. The canonical response is the
65
+ * receipt: every action below is replay-safe, so lost delivery can be retried
66
+ * by a later resolve/cancel attempt or the daemon-start sweep.
67
+ */
68
+ export async function deliverTerminalResult(nodeId) {
69
+ const dir = ticketDir(nodeId);
70
+ const run = readJson(join(dir, 'run.json'));
71
+ if (run?.mode === 'notify')
72
+ return false;
73
+ const result = readTicketResult(dir);
74
+ if (result === null)
75
+ return false;
76
+ projectReviewOutput(dir);
77
+ const node = getNode(nodeId);
78
+ if (node === null || node.status === 'dead' || node.status === 'canceled' || (node.status === 'done' && node.final_report !== null)) {
79
+ return true;
80
+ }
81
+ if (result.kind === 'canceled') {
82
+ const note = result.reason !== undefined && result.reason !== '' ? ` — ${result.reason}` : '';
83
+ // One failing subscriber must not silence the rest, and the bridge stays
84
+ // live until every notice lands: a partial fanout leaves the ticket for the
85
+ // next resolve/cancel attempt or the daemon-start sweep to replay. A
86
+ // subscriber notified twice reads the same idempotent "no answer is coming";
87
+ // a subscriber never notified waits forever.
88
+ const failedTo = [];
89
+ for (const subscriber of subscribersOf(nodeId)) {
90
+ if (result.actor !== undefined && subscriber.node_id === result.actor)
91
+ continue;
92
+ try {
93
+ appendInbox(subscriber.node_id, {
94
+ from: nodeId,
95
+ tier: 'deferred',
96
+ kind: 'message',
97
+ label: `human interaction ${nodeId} canceled — no answer is coming${note}`,
98
+ data: { body: `The human interaction ${nodeId} was canceled${note}. No response will arrive.` },
99
+ });
100
+ }
101
+ catch {
102
+ failedTo.push(subscriber.node_id);
103
+ }
104
+ }
105
+ if (failedTo.length > 0)
106
+ throw new Error(`cancellation notice failed for ${failedTo.join(', ')}`);
107
+ transition(nodeId, 'finish');
108
+ return true;
109
+ }
110
+ if (result.kind !== 'deck')
111
+ return true;
112
+ const envelope = envelopeFromDeckResult(result.responses, result.summary, result.completedAt, responsePath(dir));
113
+ await pushFinal(nodeId, renderDeckAnswer(envelope));
114
+ return true;
115
+ }
@@ -0,0 +1,6 @@
1
+ /** Deliver terminal ticket results left behind before their bridge could finish. */
2
+ export declare function reconcileUndeliveredTickets(): Promise<{
3
+ scanned: number;
4
+ delivered: number;
5
+ failed: number;
6
+ }>;
@@ -0,0 +1,49 @@
1
+ import { readdirSync, statSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
+ import { getNode } from '../../core/canvas/canvas.js';
4
+ import { getReviewByBridge } from '../../core/review/store.js';
5
+ import { emitEvent } from '../../core/events/emit.js';
6
+ import { ticketsRoot } from '../../core/human/root.js';
7
+ import { readTicketResult } from '../../core/human/tickets.js';
8
+ import { deliverTerminalResult } from './finish.js';
9
+ function isTerminalBridge(status) {
10
+ return status === 'done' || status === 'dead' || status === 'canceled';
11
+ }
12
+ /** Deliver terminal ticket results left behind before their bridge could finish. */
13
+ export async function reconcileUndeliveredTickets() {
14
+ let scanned = 0;
15
+ let delivered = 0;
16
+ let failed = 0;
17
+ const root = ticketsRoot();
18
+ for (const entry of readdirSync(root)) {
19
+ try {
20
+ const dir = join(root, entry);
21
+ if (!statSync(dir).isDirectory())
22
+ continue;
23
+ scanned += 1;
24
+ if (readTicketResult(dir) === null)
25
+ continue;
26
+ // Canonical reviews own terminal delivery and bridge retirement. Their
27
+ // finisher retries only when its winning operation is explicitly repeated.
28
+ if (getReviewByBridge(entry) !== null)
29
+ continue;
30
+ const bridge = getNode(entry);
31
+ if (bridge === null || isTerminalBridge(bridge.status))
32
+ continue;
33
+ if (await deliverTerminalResult(entry))
34
+ delivered += 1;
35
+ }
36
+ catch (error) {
37
+ failed += 1;
38
+ emitEvent({
39
+ level: 'error',
40
+ event: 'human.delivery.reconcile_failed',
41
+ node_id: entry,
42
+ error,
43
+ });
44
+ }
45
+ }
46
+ const result = { scanned, delivered, failed };
47
+ emitEvent({ level: 'info', event: 'human.delivery.reconciled', fields: result });
48
+ return result;
49
+ }
@@ -0,0 +1,18 @@
1
+ export type NodeMessageMode = 'interactive' | 'wake' | 'quiet';
2
+ export interface NodeMessageDelivery {
3
+ entry_id: string | null;
4
+ via: 'engine' | 'inbox';
5
+ revived: boolean;
6
+ }
7
+ /**
8
+ * Deliver one daemon-originated node message. Interactive messages use the live
9
+ * broker when available; every other successful path is a durable inbox entry.
10
+ */
11
+ export declare function deliverNodeMessage(args: {
12
+ node_id: string;
13
+ body: string;
14
+ label: string;
15
+ from?: string | null;
16
+ mode: NodeMessageMode;
17
+ data?: Record<string, unknown>;
18
+ }): Promise<NodeMessageDelivery>;
@@ -0,0 +1,70 @@
1
+ import { getNode } from '../../core/canvas/canvas.js';
2
+ import { withFreshTerminalGuard } from '../../core/canvas/canvas.js';
3
+ import { appendInbox } from '../../core/feed/inbox.js';
4
+ import { BrokerUnreachableError } from '../../core/runtime/broker-request.js';
5
+ import { deliverLive } from '../../core/runtime/interactive-deliver.js';
6
+ import { isBrokerLive } from '../../core/runtime/model-swap.js';
7
+ import { reviveNode } from '../../core/runtime/revive.js';
8
+ import { hasNoNaturalCycle } from '../../core/runtime/revive-all.js';
9
+ import { ReviewOperationError } from '../../core/review/types.js';
10
+ function deliveryUnroutable(nodeId, reason) {
11
+ throw new ReviewOperationError('delivery_unroutable', reason === 'origin_missing' ? 'message target was not found' : 'message target has no natural delivery cycle', { node_id: nodeId, reason });
12
+ }
13
+ /** Run a fresh terminal guard before any delivery path, including live engine sends. */
14
+ function guardRoutable(nodeId, body) {
15
+ const outcome = withFreshTerminalGuard(nodeId, hasNoNaturalCycle, body);
16
+ if (outcome.kind === 'missing')
17
+ deliveryUnroutable(nodeId, 'origin_missing');
18
+ if (outcome.kind === 'terminal')
19
+ deliveryUnroutable(nodeId, 'no_natural_cycle');
20
+ return outcome.result;
21
+ }
22
+ /**
23
+ * Deliver one daemon-originated node message. Interactive messages use the live
24
+ * broker when available; every other successful path is a durable inbox entry.
25
+ */
26
+ export async function deliverNodeMessage(args) {
27
+ // A live interactive delivery has no durable append to guard, so establish
28
+ // routability first. The durable fallback below takes the guard again to
29
+ // close the race before its append.
30
+ guardRoutable(args.node_id, () => undefined);
31
+ let target = getNode(args.node_id);
32
+ if (target === null)
33
+ deliveryUnroutable(args.node_id, 'origin_missing');
34
+ if (args.mode === 'interactive' && isBrokerLive(target)) {
35
+ try {
36
+ await deliverLive(args.node_id, args.body);
37
+ // The broker acknowledgement is asynchronous to the SQLite guard. Recheck
38
+ // before reporting an engine receipt so a final that committed during the
39
+ // request is not represented as a routable delivery.
40
+ guardRoutable(args.node_id, () => undefined);
41
+ return { entry_id: null, via: 'engine', revived: false };
42
+ }
43
+ catch (error) {
44
+ if (!(error instanceof BrokerUnreachableError))
45
+ throw error;
46
+ }
47
+ }
48
+ const entry = guardRoutable(args.node_id, () => appendInbox(args.node_id, {
49
+ from: args.from ?? null,
50
+ tier: args.mode === 'quiet' ? 'deferred' : 'normal',
51
+ kind: 'message',
52
+ label: args.label,
53
+ data: { ...args.data, body: args.body },
54
+ }));
55
+ let revived = false;
56
+ if (args.mode !== 'quiet') {
57
+ target = getNode(args.node_id);
58
+ if (target === null)
59
+ deliveryUnroutable(args.node_id, 'origin_missing');
60
+ if (!isBrokerLive(target)) {
61
+ try {
62
+ revived = reviveNode(args.node_id, { resume: true }).launch !== undefined;
63
+ }
64
+ catch {
65
+ // The durable entry remains authoritative; one wake attempt is enough.
66
+ }
67
+ }
68
+ }
69
+ return { entry_id: entry.entry_id, via: 'inbox', revived };
70
+ }
@@ -0,0 +1,26 @@
1
+ import type { ReviewComment, ReviewRecord } from '../../core/review/types.js';
2
+ export type DeliverMode = 'wake' | 'quiet';
3
+ type CommentVerb = 'create' | 'edit' | 'resolve' | 'reopen' | 'delete';
4
+ export interface CommentDelivery {
5
+ attempted: boolean;
6
+ target_node_id?: string;
7
+ status: 'delivered' | 'skipped' | 'failed';
8
+ via?: 'engine' | 'inbox';
9
+ woke: boolean;
10
+ error?: string;
11
+ }
12
+ /** Render the one bounded, durable comment notice delivered to a review companion. */
13
+ export declare function renderCommentNotice(review: ReviewRecord, comment: ReviewComment, verb: CommentVerb): string;
14
+ /**
15
+ * Best-effort post-commit notice for one review-comment mutation. Delivery and
16
+ * its audit are deliberately outside the comment's state transaction.
17
+ */
18
+ export declare function notifyComment(args: {
19
+ review: ReviewRecord;
20
+ comment: ReviewComment;
21
+ verb: CommentVerb;
22
+ actor_node_id: string | null;
23
+ deliver: DeliverMode | undefined;
24
+ operation_id: string;
25
+ }): Promise<CommentDelivery>;
26
+ export {};
@@ -0,0 +1,107 @@
1
+ import { appendDeliveryEvent } from '../../core/review/comments.js';
2
+ import { deliverNodeMessage } from '../messaging/node-message.js';
3
+ function defaultDeliverMode(verb) {
4
+ switch (verb) {
5
+ case 'create':
6
+ case 'edit':
7
+ case 'reopen':
8
+ return 'wake';
9
+ case 'resolve':
10
+ case 'delete':
11
+ return 'quiet';
12
+ }
13
+ }
14
+ function range(comment) {
15
+ return comment.anchor.end_line > comment.anchor.line
16
+ ? `L${comment.anchor.line}-${comment.anchor.end_line}`
17
+ : `L${comment.anchor.line}`;
18
+ }
19
+ function quotedSource(comment) {
20
+ const quote = comment.anchor.quote;
21
+ return quote === undefined || quote === '' ? comment.anchor_line_text : quote;
22
+ }
23
+ function verbPastTense(verb) {
24
+ switch (verb) {
25
+ case 'create': return 'created';
26
+ case 'edit': return 'edited';
27
+ case 'resolve': return 'resolved';
28
+ case 'reopen': return 'reopened';
29
+ case 'delete': return 'deleted';
30
+ }
31
+ }
32
+ /** Render the one bounded, durable comment notice delivered to a review companion. */
33
+ export function renderCommentNotice(review, comment, verb) {
34
+ return [
35
+ `Review comment ${comment.comment_id} was ${verbPastTense(verb)} in review ${review.review_id}.`,
36
+ '',
37
+ `File: ${review.file}`,
38
+ `Range: ${range(comment)}`,
39
+ 'Quoted source:',
40
+ quotedSource(comment),
41
+ '',
42
+ 'Comment:',
43
+ comment.text,
44
+ ].join('\n');
45
+ }
46
+ function errorMessage(error) {
47
+ return error instanceof Error ? error.message : String(error);
48
+ }
49
+ /**
50
+ * Best-effort post-commit notice for one review-comment mutation. Delivery and
51
+ * its audit are deliberately outside the comment's state transaction.
52
+ */
53
+ export async function notifyComment(args) {
54
+ if (args.actor_node_id === args.review.companion_node_id && args.deliver === undefined) {
55
+ return { attempted: false, status: 'skipped', woke: false };
56
+ }
57
+ const target_node_id = args.review.companion_node_id;
58
+ const mode = args.deliver ?? defaultDeliverMode(args.verb);
59
+ const body = renderCommentNotice(args.review, args.comment, args.verb);
60
+ let delivery;
61
+ try {
62
+ delivery = await deliverNodeMessage({
63
+ node_id: target_node_id,
64
+ body,
65
+ label: 'review comment',
66
+ from: 'crtrd',
67
+ mode: mode === 'wake' ? 'interactive' : 'quiet',
68
+ data: {
69
+ review_id: args.review.review_id,
70
+ comment_id: args.comment.comment_id,
71
+ verb: args.verb,
72
+ },
73
+ });
74
+ }
75
+ catch (error) {
76
+ const projection = {
77
+ attempted: true,
78
+ target_node_id,
79
+ status: 'failed',
80
+ woke: false,
81
+ error: errorMessage(error),
82
+ };
83
+ appendDeliveryEvent({
84
+ review_id: args.review.review_id,
85
+ comment_id: args.comment.comment_id,
86
+ kind: 'notify_failed',
87
+ payload: projection,
88
+ operation_id: args.operation_id,
89
+ });
90
+ return projection;
91
+ }
92
+ const projection = {
93
+ attempted: true,
94
+ target_node_id,
95
+ status: 'delivered',
96
+ via: delivery.via,
97
+ woke: delivery.revived,
98
+ };
99
+ appendDeliveryEvent({
100
+ review_id: args.review.review_id,
101
+ comment_id: args.comment.comment_id,
102
+ kind: 'notified',
103
+ payload: projection,
104
+ operation_id: args.operation_id,
105
+ });
106
+ return projection;
107
+ }
@@ -0,0 +1,7 @@
1
+ import type { ReviewRecord } from '../../core/review/types.js';
2
+ /** Render the immutable approval fact without replaying comment text. */
3
+ export declare function renderApprovalMessage(review: ReviewRecord, resultPath: string): string;
4
+ /** Deliver an approval through its origin-specific canonical route. */
5
+ export declare function deliverApproval(review: ReviewRecord, resultPath: string): Promise<{
6
+ receipt: string | null;
7
+ }>;