@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
@@ -0,0 +1,287 @@
1
+ // Canonical daemon-owned review lifecycle routes. Handlers validate the full
2
+ // wire request, delegate lifecycle work to review services, and project only
3
+ // committed daemon state.
4
+ import { existsSync } from 'node:fs';
5
+ import { ApiError } from '../../../api/index.js';
6
+ import { isSafeNodeId, reviewResultPath } from '../../../core/canvas/paths.js';
7
+ import { responsePath, reviewPath } from '../../../core/human/convention.js';
8
+ import { ticketDir } from '../../../core/human/root.js';
9
+ import { createReview } from '../../../core/review/birth.js';
10
+ import { openExistingReview } from '../../../core/review/realize.js';
11
+ import { readAnchorBase, getReview, getReviewByBridge, listReviews } from '../../../core/review/store.js';
12
+ import { ReviewOperationError } from '../../../core/review/types.js';
13
+ import { cancelReview, submitReviewApproval } from '../../review/finish.js';
14
+ import { toFeedbackResultDTO, toReviewDTO } from '../map.js';
15
+ const REVIEW_STATES = new Set(['open', 'approved', 'canceled']);
16
+ const CREATE_FIELDS = ['origin_kind', 'origin_node_id', 'file', 'idempotency_key', 'subtitle', 'output_path'];
17
+ const CANCEL_FIELDS = ['reason', 'actor'];
18
+ function invalidRequest(violations) {
19
+ throw new ApiError(400, 'invalid_request', 'review request is invalid', { violations });
20
+ }
21
+ function isRecord(value) {
22
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
23
+ }
24
+ function objectBody(body, allowed, violations) {
25
+ if (!isRecord(body)) {
26
+ violations.push({ field: 'body', problem: 'must be an object', received: body });
27
+ return {};
28
+ }
29
+ for (const key of Object.keys(body)) {
30
+ if (!allowed.includes(key))
31
+ violations.push({ field: key, problem: 'is not allowed', received: body[key] });
32
+ }
33
+ return body;
34
+ }
35
+ function requiredString(body, field, violations) {
36
+ const value = body[field];
37
+ if (typeof value !== 'string' || value === '') {
38
+ violations.push({ field, problem: 'must be a non-empty string', ...(value === undefined ? {} : { received: value }) });
39
+ return undefined;
40
+ }
41
+ return value;
42
+ }
43
+ function optionalString(body, field, violations) {
44
+ const value = body[field];
45
+ if (value === undefined)
46
+ return undefined;
47
+ if (typeof value !== 'string' || value === '') {
48
+ violations.push({ field, problem: 'must be a non-empty string', received: value });
49
+ return undefined;
50
+ }
51
+ return value;
52
+ }
53
+ function requireReviewId(ctx, violations) {
54
+ const reviewId = ctx.params['review_id'];
55
+ if (reviewId === undefined || !isSafeNodeId(reviewId)) {
56
+ violations.push({ field: 'review_id', problem: 'must be a safe review id', ...(reviewId === undefined ? {} : { received: reviewId }) });
57
+ return undefined;
58
+ }
59
+ return reviewId;
60
+ }
61
+ function requireBridgeNodeId(ctx, violations) {
62
+ const bridgeNodeId = ctx.params['bridge_node_id'];
63
+ if (bridgeNodeId === undefined || !isSafeNodeId(bridgeNodeId)) {
64
+ violations.push({ field: 'bridge_node_id', problem: 'must be a safe node id', ...(bridgeNodeId === undefined ? {} : { received: bridgeNodeId }) });
65
+ return undefined;
66
+ }
67
+ return bridgeNodeId;
68
+ }
69
+ function requireVisibleReview(reviewId) {
70
+ const review = getReview(reviewId);
71
+ if (review === null || review.state === 'binding') {
72
+ throw new ReviewOperationError('unknown_review', 'review was not found', { received: reviewId });
73
+ }
74
+ return review;
75
+ }
76
+ function approvedResultPath(review) {
77
+ if (review.origin_kind === 'inline')
78
+ return reviewResultPath(review.review_id);
79
+ if (review.bridge_node_id === null)
80
+ throw new Error(`approved ticket review lacks its bridge node: ${review.review_id}`);
81
+ return responsePath(ticketDir(review.bridge_node_id));
82
+ }
83
+ function toReviewResponseDTO(review) {
84
+ return review.state === 'approved'
85
+ ? toReviewDTO(review, { result_path: approvedResultPath(review) })
86
+ : toReviewDTO(review);
87
+ }
88
+ function parseCreate(ctx) {
89
+ const violations = [];
90
+ const body = objectBody(ctx.body, CREATE_FIELDS, violations);
91
+ const originKind = body['origin_kind'];
92
+ const origin_kind = originKind === 'ticket' || originKind === 'inline'
93
+ ? originKind
94
+ : undefined;
95
+ if (origin_kind === undefined) {
96
+ violations.push({ field: 'origin_kind', problem: 'must be ticket or inline', ...(originKind === undefined ? {} : { received: originKind }) });
97
+ }
98
+ const origin_node_id = requiredString(body, 'origin_node_id', violations);
99
+ if (origin_node_id !== undefined && !isSafeNodeId(origin_node_id)) {
100
+ violations.push({ field: 'origin_node_id', problem: 'must be a safe node id', received: origin_node_id });
101
+ }
102
+ const file = requiredString(body, 'file', violations);
103
+ const idempotency_key = requiredString(body, 'idempotency_key', violations);
104
+ if (idempotency_key !== undefined && idempotency_key.length > 128) {
105
+ violations.push({ field: 'idempotency_key', problem: 'must be at most 128 characters', received: idempotency_key });
106
+ }
107
+ const subtitle = optionalString(body, 'subtitle', violations);
108
+ const output_path = optionalString(body, 'output_path', violations);
109
+ if (origin_kind === 'ticket' && subtitle === undefined && body['subtitle'] === undefined) {
110
+ violations.push({ field: 'subtitle', problem: 'is required for ticket reviews' });
111
+ }
112
+ if (origin_kind === 'inline' && body['subtitle'] !== undefined) {
113
+ violations.push({ field: 'subtitle', problem: 'is only allowed for ticket reviews', received: body['subtitle'] });
114
+ }
115
+ if (origin_kind === 'inline' && body['output_path'] !== undefined) {
116
+ violations.push({ field: 'output_path', problem: 'is only allowed for ticket reviews', received: body['output_path'] });
117
+ }
118
+ if (violations.length > 0
119
+ || origin_kind === undefined
120
+ || origin_node_id === undefined
121
+ || !isSafeNodeId(origin_node_id)
122
+ || file === undefined
123
+ || idempotency_key === undefined
124
+ || idempotency_key.length > 128)
125
+ invalidRequest(violations);
126
+ return {
127
+ origin_kind,
128
+ origin_node_id,
129
+ file,
130
+ idempotency_key,
131
+ ...(subtitle === undefined ? {} : { subtitle }),
132
+ ...(output_path === undefined ? {} : { output_path }),
133
+ };
134
+ }
135
+ function parseList(ctx) {
136
+ const violations = [];
137
+ const parsed = {};
138
+ const allowed = new Set(['state', 'origin_node_id', 'file']);
139
+ for (const [field, value] of ctx.query.entries()) {
140
+ if (!allowed.has(field))
141
+ violations.push({ field, problem: 'is not allowed', received: value });
142
+ }
143
+ for (const field of allowed) {
144
+ const values = ctx.query.getAll(field);
145
+ if (values.length > 1) {
146
+ violations.push({ field, problem: 'must appear at most once', received: values });
147
+ continue;
148
+ }
149
+ const value = values[0];
150
+ if (value === undefined)
151
+ continue;
152
+ if (field === 'state') {
153
+ if (!REVIEW_STATES.has(value)) {
154
+ violations.push({ field, problem: 'must be open, approved, or canceled', received: value });
155
+ }
156
+ else {
157
+ parsed.state = value;
158
+ }
159
+ }
160
+ else if (field === 'origin_node_id') {
161
+ if (!isSafeNodeId(value)) {
162
+ violations.push({ field, problem: 'must be a safe node id', received: value });
163
+ }
164
+ else {
165
+ parsed.origin_node_id = value;
166
+ }
167
+ }
168
+ else if (value === '') {
169
+ violations.push({ field, problem: 'must be a non-empty string', received: value });
170
+ }
171
+ else {
172
+ parsed.file = value;
173
+ }
174
+ }
175
+ if (violations.length > 0)
176
+ invalidRequest(violations);
177
+ return parsed;
178
+ }
179
+ function parseCancel(ctx, violations) {
180
+ const body = ctx.body === undefined ? {} : objectBody(ctx.body, CANCEL_FIELDS, violations);
181
+ const reason = optionalString(body, 'reason', violations);
182
+ const actor = optionalString(body, 'actor', violations);
183
+ return { ...(reason === undefined ? {} : { reason }), ...(actor === undefined ? {} : { actor }) };
184
+ }
185
+ function requireEmptyBody(ctx, violations) {
186
+ objectBody(ctx.body, [], violations);
187
+ }
188
+ async function handleCreate(ctx) {
189
+ const review = await createReview(parseCreate(ctx));
190
+ return { status: 200, body: toReviewResponseDTO(review) };
191
+ }
192
+ function handleList(ctx) {
193
+ const query = parseList(ctx);
194
+ const body = { reviews: listReviews(query).map(toReviewResponseDTO) };
195
+ return { status: 200, body };
196
+ }
197
+ function handleRead(ctx) {
198
+ const violations = [];
199
+ const reviewId = requireReviewId(ctx, violations);
200
+ if (violations.length > 0 || reviewId === undefined)
201
+ invalidRequest(violations);
202
+ return { status: 200, body: toReviewResponseDTO(requireVisibleReview(reviewId)) };
203
+ }
204
+ function handleByBridge(ctx) {
205
+ const violations = [];
206
+ const bridgeNodeId = requireBridgeNodeId(ctx, violations);
207
+ if (violations.length > 0 || bridgeNodeId === undefined)
208
+ invalidRequest(violations);
209
+ const review = getReviewByBridge(bridgeNodeId);
210
+ if (review !== null)
211
+ return { status: 200, body: toReviewResponseDTO(review) };
212
+ if (existsSync(reviewPath(ticketDir(bridgeNodeId)))) {
213
+ throw new ApiError(409, 'review_predates_system', 'this review predates canonical review records; cancel it and re-file the review', { bridge_node_id: bridgeNodeId });
214
+ }
215
+ throw new ReviewOperationError('unknown_review', 'review was not found', { received: bridgeNodeId });
216
+ }
217
+ async function handleOpen(ctx) {
218
+ const violations = [];
219
+ const reviewId = requireReviewId(ctx, violations);
220
+ requireEmptyBody(ctx, violations);
221
+ if (violations.length > 0 || reviewId === undefined)
222
+ invalidRequest(violations);
223
+ const opened = await openExistingReview(reviewId);
224
+ const body = opened.disposition === 'terminal'
225
+ ? { review: toReviewResponseDTO(opened.review), disposition: 'terminal' }
226
+ : {
227
+ review: toReviewResponseDTO(opened.review),
228
+ companion_node_id: opened.review.companion_node_id,
229
+ companion_status: opened.companion_status,
230
+ disposition: 'open',
231
+ };
232
+ return { status: 200, body };
233
+ }
234
+ async function handleSubmit(ctx) {
235
+ const violations = [];
236
+ const reviewId = requireReviewId(ctx, violations);
237
+ requireEmptyBody(ctx, violations);
238
+ if (violations.length > 0 || reviewId === undefined)
239
+ invalidRequest(violations);
240
+ const finished = await submitReviewApproval(reviewId);
241
+ const body = {
242
+ review: toReviewResponseDTO(finished.record),
243
+ result: toFeedbackResultDTO(finished.result),
244
+ outcome: finished.outcome,
245
+ };
246
+ return { status: 200, body };
247
+ }
248
+ async function handleCancel(ctx) {
249
+ const violations = [];
250
+ const reviewId = requireReviewId(ctx, violations);
251
+ const request = parseCancel(ctx, violations);
252
+ if (violations.length > 0 || reviewId === undefined)
253
+ invalidRequest(violations);
254
+ const finished = await cancelReview(reviewId, request);
255
+ const body = {
256
+ review: toReviewResponseDTO(finished.record),
257
+ outcome: finished.outcome,
258
+ };
259
+ return { status: 200, body };
260
+ }
261
+ function handleDocument(ctx) {
262
+ const violations = [];
263
+ const reviewId = requireReviewId(ctx, violations);
264
+ if (violations.length > 0 || reviewId === undefined)
265
+ invalidRequest(violations);
266
+ const review = requireVisibleReview(reviewId);
267
+ const anchor = readAnchorBase(review.review_id);
268
+ if (anchor === null)
269
+ throw new Error(`review anchor base is missing: ${review.review_id}`);
270
+ const body = {
271
+ review_id: review.review_id,
272
+ anchor_base_sha256: anchor.sha256,
273
+ anchor_base_text: new TextDecoder('utf-8', { fatal: true }).decode(anchor.bytes),
274
+ file: review.file,
275
+ };
276
+ return { status: 200, body };
277
+ }
278
+ export const reviewRoutes = [
279
+ { method: 'POST', pattern: '/v1/human/reviews', handler: handleCreate },
280
+ { method: 'GET', pattern: '/v1/human/reviews', handler: handleList },
281
+ { method: 'GET', pattern: '/v1/human/reviews/by-bridge/:bridge_node_id', handler: handleByBridge },
282
+ { method: 'GET', pattern: '/v1/human/reviews/:review_id', handler: handleRead },
283
+ { method: 'POST', pattern: '/v1/human/reviews/:review_id/open', handler: handleOpen },
284
+ { method: 'POST', pattern: '/v1/human/reviews/:review_id/submit', handler: handleSubmit },
285
+ { method: 'POST', pattern: '/v1/human/reviews/:review_id/cancel', handler: handleCancel },
286
+ { method: 'GET', pattern: '/v1/human/reviews/:review_id/document', handler: handleDocument },
287
+ ];
@@ -1,11 +1,11 @@
1
1
  import type { ManagedWorktree, NodeMeta, NodeRow, SubscriptionRef } from '../../core/canvas/types.js';
2
- import type { HumanWorkRow } from '../../core/canvas/human-work-outbox.js';
2
+ import type { ReviewComment, ReviewCommentEvent, ReviewErrorCode, ReviewRecord, ReviewResult } from '../../core/review/types.js';
3
3
  import type { Cron, CronRunRecord } from '../../core/canvas/crons.js';
4
4
  import type { ProfileEntry } from '../../core/profiles/manifest.js';
5
5
  import type { ReviveResult } from '../../core/runtime/revive.js';
6
6
  import type { CloseNodeResult } from '../../core/runtime/close.js';
7
7
  import { type PushResult } from '../../core/feed/feed.js';
8
- import type { CloseResultDTO, ConsultOutboxEntryDTO, CronDTO, CronRunDTO, ErrorBody, NodeEdgesDTO, NodePathsDTO, NodeStatusDTO, NodeSummaryDTO, NodeDetailDTO, NodeWorktreeDTO, ProfileDTO, PushReportResultDTO, ReviveResultDTO, SubscriptionDTO } from '../../api/index.js';
8
+ import type { CloseResultDTO, CronDTO, CronRunDTO, ErrorBody, NodeEdgesDTO, NodePathsDTO, NodeStatusDTO, NodeSummaryDTO, NodeDetailDTO, NodeWorktreeDTO, ProfileDTO, ReviewCommentDTO, ReviewCommentEventDTO, ReviewDTO, FeedbackResultDTO, PushReportResultDTO, ReviveResultDTO, SubscriptionDTO } from '../../api/index.js';
9
9
  /** Project the queryable row (what `listNodes` yields) into a summary DTO. */
10
10
  export declare function toNodeSummaryDTO(row: NodeRow): NodeSummaryDTO;
11
11
  /** The subscription/child edges a detail projection needs. The handler gathers
@@ -61,11 +61,26 @@ export declare function toCronRunDTO(r: CronRunRecord): CronRunDTO;
61
61
  * entry, so it is left null here — a caller that needs it resolves it
62
62
  * separately. */
63
63
  export declare function toProfileDTO(entry: ProfileEntry): ProfileDTO;
64
- /** Project a `consult_outbox` (human-work) row into a consult-outbox entry DTO
65
- * (the canvas half of a human consult/visual request). `work_kind` is the same
66
- * `'follow_up' | 'visual'` union as `ConsultKindDTO`; `created` carries the
67
- * row's last-touch timestamp (the table has no separate creation column). */
68
- export declare function toConsultOutboxEntryDTO(row: HumanWorkRow): ConsultOutboxEntryDTO;
64
+ /** Extra daemon-derived review fields whose source is outside the canonical row. */
65
+ export interface ReviewDTOExtras {
66
+ /** Deterministic destination of an approved review's immutable result. */
67
+ result_path?: string;
68
+ }
69
+ /** Project the canonical review row without exposing fork/session/store coordinates. */
70
+ export declare function toReviewDTO(row: ReviewRecord, extras?: ReviewDTOExtras): ReviewDTO;
71
+ /** Project one daemon-owned comment, omitting absent node identities on human actions. */
72
+ export declare function toReviewCommentDTO(comment: ReviewComment): ReviewCommentDTO;
73
+ /** Project one immutable review-comment audit event. */
74
+ export declare function toReviewCommentEventDTO(event: ReviewCommentEvent): ReviewCommentEventDTO;
75
+ /** Project the immutable snake_case review result to the existing camelCase feedback wire shape. */
76
+ export declare function toFeedbackResultDTO(result: ReviewResult): FeedbackResultDTO;
77
+ /** The only internal review-error to public HTTP projection. Every internal
78
+ * review failure is listed explicitly so handlers never need to invent a status
79
+ * or public code. */
80
+ export declare const REVIEW_ERROR_MAP: Readonly<Record<ReviewErrorCode, {
81
+ status: number;
82
+ code: string;
83
+ }>>;
69
84
  /** The single error-mapping function (spec §8). Projects any thrown value into
70
85
  * `{ status, code }`:
71
86
  * - a CrtrError → status by its `exitCode` class, `code` its machine code;
@@ -9,6 +9,7 @@
9
9
  // constructors. The DTO field sets these project into were pinned by A-1 as
10
10
  // reasonable projections; this module is what makes them concrete, so any DTO
11
11
  // field that projection proves wrong is corrected here at the source.
12
+ import { ReviewOperationError as ReviewOperationErrorClass } from '../../core/review/types.js';
12
13
  import { contextDir, inboxPath, nodeDir, nodeMetaPath, reportsDir, transcriptPath, viewSocketPath, } from '../../core/canvas/paths.js';
13
14
  import { FinalizationError } from '../../core/feed/feed.js';
14
15
  import { NodeIdConflictError } from '../../core/runtime/nodes.js';
@@ -116,6 +117,16 @@ export function toNodeDetailDTO(meta, edges) {
116
117
  dto.model_override = meta.model_override ?? null;
117
118
  if (meta.pi_session_file !== undefined)
118
119
  dto.pi_session_file = meta.pi_session_file ?? null;
120
+ if (meta.review_binding !== undefined) {
121
+ dto.review_binding = meta.review_binding === null
122
+ ? null
123
+ : {
124
+ review_id: meta.review_binding.review_id,
125
+ origin_node_id: meta.review_binding.origin_node_id,
126
+ branch_file: meta.review_binding.branch_file,
127
+ target_file: meta.review_binding.target_file,
128
+ };
129
+ }
119
130
  if (meta.managed_worktree != null)
120
131
  dto.worktree = toNodeWorktreeDTO(meta.managed_worktree);
121
132
  return dto;
@@ -242,24 +253,142 @@ export function toProfileDTO(entry) {
242
253
  default_dir: null,
243
254
  };
244
255
  }
245
- /** Project a `consult_outbox` (human-work) row into a consult-outbox entry DTO
246
- * (the canvas half of a human consult/visual request). `work_kind` is the same
247
- * `'follow_up' | 'visual'` union as `ConsultKindDTO`; `created` carries the
248
- * row's last-touch timestamp (the table has no separate creation column). */
249
- export function toConsultOutboxEntryDTO(row) {
256
+ /** Project the canonical review row without exposing fork/session/store coordinates. */
257
+ export function toReviewDTO(row, extras = {}) {
258
+ const dto = {
259
+ review_id: row.review_id,
260
+ origin_kind: row.origin_kind,
261
+ origin_node_id: row.origin_node_id,
262
+ bridge_node_id: row.bridge_node_id,
263
+ companion_node_id: row.companion_node_id,
264
+ file: row.file,
265
+ state: row.state,
266
+ created: row.created,
267
+ source_missing: row.source_missing,
268
+ anchor_base_sha256: row.anchor_base_sha256,
269
+ };
270
+ if (row.opened_at !== null)
271
+ dto.opened_at = row.opened_at;
272
+ if (row.approved_at !== null)
273
+ dto.approved_at = row.approved_at;
274
+ if (row.changed !== null)
275
+ dto.changed = row.changed;
276
+ if (row.comments_total !== null)
277
+ dto.comments_total = row.comments_total;
278
+ if (row.comments_unresolved !== null)
279
+ dto.comments_unresolved = row.comments_unresolved;
280
+ if (row.canceled_at !== null)
281
+ dto.canceled_at = row.canceled_at;
282
+ if (row.cancel_reason !== null)
283
+ dto.cancel_reason = row.cancel_reason;
284
+ if (row.cancel_actor !== null)
285
+ dto.cancel_actor = row.cancel_actor;
286
+ if (extras.result_path !== undefined)
287
+ dto.result_path = extras.result_path;
288
+ if (row.delivery_error !== null)
289
+ dto.delivery_error = row.delivery_error;
290
+ if (row.projection_error !== null)
291
+ dto.projection_error = row.projection_error;
292
+ return dto;
293
+ }
294
+ /** Project one daemon-owned comment, omitting absent node identities on human actions. */
295
+ export function toReviewCommentDTO(comment) {
250
296
  return {
251
- request_id: row.request_id,
252
- node_id: row.node_id,
253
- kind: row.work_kind,
254
- dir: row.dir,
255
- created: row.updated_at,
297
+ comment_id: comment.comment_id,
298
+ review_id: comment.review_id,
299
+ status: comment.status,
300
+ revision: comment.revision,
301
+ text: comment.text,
302
+ anchor: { ...comment.anchor },
303
+ anchor_state: comment.anchor_state,
304
+ anchor_line_text: comment.anchor_line_text,
305
+ anchor_doc_hash: comment.anchor_doc_hash,
306
+ author: {
307
+ kind: comment.author.kind,
308
+ ...(comment.author.node_id === null ? {} : { node_id: comment.author.node_id }),
309
+ },
310
+ updated_by: {
311
+ kind: comment.updated_by.kind,
312
+ ...(comment.updated_by.node_id === null ? {} : { node_id: comment.updated_by.node_id }),
313
+ },
314
+ created_at: comment.created_at,
315
+ updated_at: comment.updated_at,
316
+ ...(comment.resolved_at === null ? {} : { resolved_at: comment.resolved_at }),
317
+ ...(comment.deleted_at === null ? {} : { deleted_at: comment.deleted_at }),
318
+ created_seq: comment.created_seq,
256
319
  };
257
320
  }
321
+ /** Project one immutable review-comment audit event. */
322
+ export function toReviewCommentEventDTO(event) {
323
+ return {
324
+ seq: event.seq,
325
+ review_id: event.review_id,
326
+ comment_id: event.comment_id,
327
+ kind: event.kind,
328
+ state_change: event.state_change === 1,
329
+ revision_after: event.revision_after,
330
+ actor: {
331
+ kind: event.actor.kind,
332
+ ...(event.actor.node_id === null ? {} : { node_id: event.actor.node_id }),
333
+ },
334
+ at: event.at,
335
+ operation_id: event.operation_id,
336
+ ...(event.payload === undefined ? {} : { payload: event.payload }),
337
+ };
338
+ }
339
+ /** Project the immutable snake_case review result to the existing camelCase feedback wire shape. */
340
+ export function toFeedbackResultDTO(result) {
341
+ const dto = {
342
+ file: result.file,
343
+ submitted: result.submitted,
344
+ approved: result.approved,
345
+ comments: result.comments.map((comment) => ({ ...comment })),
346
+ submittedAt: result.submittedAt,
347
+ savedAt: result.savedAt,
348
+ reviewId: result.review_id,
349
+ changed: result.changed,
350
+ baselineSha256: result.baseline_sha256,
351
+ approvedSha256: result.approved_sha256,
352
+ companionNodeId: result.companion_node_id,
353
+ commentsTotal: result.comments_total,
354
+ commentsUnresolved: result.comments_unresolved,
355
+ };
356
+ return dto;
357
+ }
258
358
  const _exitIntentParity = true;
259
359
  void _exitIntentParity;
260
360
  // ---------------------------------------------------------------------------
261
361
  // Error → HTTP status mapping (spec §8)
262
362
  // ---------------------------------------------------------------------------
363
+ /** The only internal review-error to public HTTP projection. Every internal
364
+ * review failure is listed explicitly so handlers never need to invent a status
365
+ * or public code. */
366
+ export const REVIEW_ERROR_MAP = Object.freeze({
367
+ review_origin_missing: { status: 400, code: 'review_origin_unavailable' },
368
+ review_origin_unforkable: { status: 400, code: 'review_origin_unavailable' },
369
+ review_origin_unstable: { status: 409, code: 'review_origin_unstable' },
370
+ review_branch_unavailable: { status: 409, code: 'review_branch_unavailable' },
371
+ branch_lost: { status: 409, code: 'review_branch_unavailable' },
372
+ review_companion_unbound: { status: 409, code: 'review_companion_unbound' },
373
+ review_bridge_unsubscribed: { status: 409, code: 'review_bridge_unavailable' },
374
+ review_target_unreviewable: { status: 400, code: 'review_file_unreadable' },
375
+ source_unreadable: { status: 409, code: 'review_source_unreadable' },
376
+ delivery_unroutable: { status: 409, code: 'review_delivery_unroutable' },
377
+ unknown_review: { status: 404, code: 'unknown_review' },
378
+ review_not_open: { status: 409, code: 'review_not_open' },
379
+ review_terminal: { status: 409, code: 'review_terminal_conflict' },
380
+ review_required: { status: 400, code: 'review_required' },
381
+ stale_document: { status: 409, code: 'stale_document' },
382
+ unknown_comment: { status: 404, code: 'unknown_comment' },
383
+ comment_deleted: { status: 409, code: 'comment_deleted' },
384
+ invalid_anchor: { status: 400, code: 'invalid_anchor' },
385
+ anchor_out_of_range: { status: 400, code: 'anchor_out_of_range' },
386
+ text_too_long: { status: 400, code: 'text_too_long' },
387
+ comment_limit_reached: { status: 409, code: 'comment_limit_reached' },
388
+ stale_comment: { status: 409, code: 'stale_comment' },
389
+ range_batch_incomplete: { status: 409, code: 'range_batch_incomplete' },
390
+ range_batch_stale: { status: 409, code: 'range_batch_stale' },
391
+ });
263
392
  /** The single error-mapping function (spec §8). Projects any thrown value into
264
393
  * `{ status, code }`:
265
394
  * - a CrtrError → status by its `exitCode` class, `code` its machine code;
@@ -298,6 +427,9 @@ export function errorToStatus(err) {
298
427
  if (err instanceof NodeIdConflictError) {
299
428
  return { status: 409, code: 'node_id_exists' };
300
429
  }
430
+ if (err instanceof ReviewOperationErrorClass) {
431
+ return REVIEW_ERROR_MAP[err.code];
432
+ }
301
433
  if (err instanceof CrtrError) {
302
434
  return { status: statusForExitCode(err.exitCode), code: err.code };
303
435
  }
@@ -313,6 +445,18 @@ export function errorToStatus(err) {
313
445
  }
314
446
  return { status: 500, code: 'internal' };
315
447
  }
448
+ /** Remove the store row from a terminal-conflict detail before it reaches the wire.
449
+ * Only the approved `ReviewDTO` fields cross this boundary; all other review
450
+ * errors retain their explicitly specified internal detail object. */
451
+ function reviewErrorDetails(err) {
452
+ if (err.code !== 'review_terminal')
453
+ return err.detail;
454
+ const { review, ...detail } = err.detail;
455
+ return {
456
+ ...detail,
457
+ review: toReviewDTO(review),
458
+ };
459
+ }
316
460
  function statusForExitCode(exitCode) {
317
461
  switch (exitCode) {
318
462
  case ExitCode.NOT_FOUND:
@@ -354,7 +498,11 @@ export function toErrorBody(err) {
354
498
  return { status, body: { error: { code, message: boundedCause(err) } } };
355
499
  }
356
500
  const message = err instanceof Error ? err.message : String(err);
357
- const details = err instanceof CrtrError && err.details !== undefined ? err.details : undefined;
501
+ const details = err instanceof ReviewOperationErrorClass
502
+ ? reviewErrorDetails(err)
503
+ : err instanceof CrtrError && err.details !== undefined
504
+ ? err.details
505
+ : undefined;
358
506
  const body = { error: { code, message } };
359
507
  if (details !== undefined)
360
508
  body.error.details = details;
@@ -35,6 +35,8 @@ import { modelAuthRoutes } from './handlers/modelauth.js';
35
35
  import { nodeRoutes } from './handlers/nodes.js';
36
36
  import { profileRoutes } from './handlers/profiles.js';
37
37
  import { reportRoutes } from './handlers/reports.js';
38
+ import { reviewCommentRoutes } from './handlers/review-comments.js';
39
+ import { reviewRoutes } from './handlers/reviews.js';
38
40
  import { subscriptionRoutes } from './handlers/subscriptions.js';
39
41
  import { cronRoutes } from './handlers/crons.js';
40
42
  import { worktreeRoutes } from './handlers/worktree.js';
@@ -58,6 +60,8 @@ function buildRouter() {
58
60
  .registerAll(profileRoutes)
59
61
  .registerAll(modelAuthRoutes)
60
62
  .registerAll(humanRoutes)
63
+ .registerAll(reviewRoutes)
64
+ .registerAll(reviewCommentRoutes)
61
65
  .registerAll(inboxRoutes);
62
66
  }
63
67
  /** Is this request an attach upgrade — `GET /v1/nodes/{id}/attach` — and if so,
@@ -30,14 +30,14 @@
30
30
  // promises for graceful-teardown drain but never blocks on a slow run.
31
31
  import { spawn } from 'node:child_process';
32
32
  import { createHash, randomBytes, randomUUID } from 'node:crypto';
33
- import { mkdirSync } from 'node:fs';
34
33
  import { join } from 'node:path';
35
34
  import { setTimeout as delay } from 'node:timers/promises';
36
- import { notifyDeck, submitDeck } from '@crouton-kit/humanloop';
35
+ import { notifyDeck } from '../core/human/deck-factories.js';
36
+ import { ticketDir } from '../core/human/root.js';
37
+ import { submitDeck } from '../core/human/tickets.js';
37
38
  import { dueClockCrons, dueOverlapCrons, expiredIdleCrons, runningCrons, acquireCronRunLease, releaseCronRunLease, recordCronRun, listCronRuns, advanceCron, consumeCron, cancelCron, killLeasedCronRun, verifyLeasedCronRun, getCron, setCronState, setCronLastOutputHash, } from '../core/canvas/crons.js';
38
39
  import { getNode } from '../core/canvas/canvas.js';
39
40
  import { fullName } from '../core/canvas/labels.js';
40
- import { nodeDir } from '../core/canvas/paths.js';
41
41
  import { killProcessGroup } from '../core/canvas/pid.js';
42
42
  import { appendInbox } from '../core/feed/inbox.js';
43
43
  import { atomicWriteJson } from '../core/fs-utils.js';
@@ -50,7 +50,6 @@ import { nextSlotAfter, cadenceDisplay } from '../core/wake.js';
50
50
  import { buildOperationalEnvBase } from '../core/runtime/spawn-env.js';
51
51
  import { parseSink } from './cron-sink.js';
52
52
  import { readProfileEnvVars } from '../core/profiles/env-store.js';
53
- import { registerCrouterRoot } from '../commands/human/shared.js';
54
53
  /** Output head caps for the run log (spec: "capped, e.g. 4KB"). */
55
54
  export const CRON_OUTPUT_HEAD_BYTES = 4 * 1024;
56
55
  /** A byte-capped capture of one output stream's head. Bytes are buffered and
@@ -187,21 +186,19 @@ async function deliverSpawnSink(c, kind, stdout) {
187
186
  });
188
187
  return res.node.node_id;
189
188
  }
190
- /** Deliver stdout through humanloop as a durable notify deck (fire-and-forget
189
+ /** Deliver stdout through crouter as a durable notify deck (fire-and-forget
191
190
  * inbox state — jobs whose output is a person's call). Mirrors `crtr human
192
191
  * notify` minus the CLI-env source stamp: the deck names the cron instead. */
193
192
  function deliverHumanSink(c, stdout) {
194
193
  const id = `nfy-${randomBytes(4).toString('hex')}`;
195
- const idir = nodeDir(id);
196
- mkdirSync(idir, { recursive: true });
197
194
  const rc = { mode: 'notify' };
198
- atomicWriteJson(join(idir, 'run.json'), rc);
195
+ atomicWriteJson(join(ticketDir(id), 'run.json'), rc);
199
196
  let deck = notifyDeck(`⏰ cron ${c.name}`, {
200
197
  subtitle: `Scheduled cron "${c.name}" delivered output for your attention.`,
201
198
  body: stdout,
202
199
  });
203
200
  deck = { ...deck, source: { sessionName: `cron ${c.name} (${c.cron_id})` } };
204
- submitDeck({ root: registerCrouterRoot(), id, deck });
201
+ submitDeck({ dir: ticketDir(id), deck });
205
202
  }
206
203
  /** Route stdout to the cron's armed sink. Returns the delivered string on
207
204
  * success; throws on an undeliverable sink (the caller's failure path). */