@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,70 @@
1
+ import { z } from 'zod';
2
+ import type { Deck, ReviewDescriptor } from './types.js';
3
+ export declare const interactionOptionSchema: z.ZodObject<{
4
+ id: z.ZodString;
5
+ label: z.ZodString;
6
+ description: z.ZodOptional<z.ZodString>;
7
+ }, z.core.$strip>;
8
+ export declare const preAnswerSchema: z.ZodObject<{
9
+ selectedOptionId: z.ZodOptional<z.ZodString>;
10
+ selectedOptionIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
11
+ freetext: z.ZodOptional<z.ZodString>;
12
+ label: z.ZodOptional<z.ZodString>;
13
+ }, z.core.$strip>;
14
+ export declare const deckSchema: z.ZodObject<{
15
+ title: z.ZodString;
16
+ source: z.ZodOptional<z.ZodObject<{
17
+ sessionName: z.ZodOptional<z.ZodString>;
18
+ askedBy: z.ZodOptional<z.ZodString>;
19
+ blockedSince: z.ZodOptional<z.ZodString>;
20
+ nodeId: z.ZodOptional<z.ZodString>;
21
+ }, z.core.$strip>>;
22
+ interactions: z.ZodArray<z.ZodObject<{
23
+ id: z.ZodString;
24
+ title: z.ZodString;
25
+ subtitle: z.ZodString;
26
+ body: z.ZodOptional<z.ZodString>;
27
+ bodyPath: z.ZodOptional<z.ZodString>;
28
+ options: z.ZodArray<z.ZodObject<{
29
+ id: z.ZodString;
30
+ label: z.ZodString;
31
+ description: z.ZodOptional<z.ZodString>;
32
+ }, z.core.$strip>>;
33
+ multiSelect: z.ZodOptional<z.ZodBoolean>;
34
+ allowFreetext: z.ZodOptional<z.ZodBoolean>;
35
+ freetextLabel: z.ZodOptional<z.ZodString>;
36
+ kind: z.ZodOptional<z.ZodEnum<{
37
+ error: "error";
38
+ context: "context";
39
+ notify: "notify";
40
+ review: "review";
41
+ decision: "decision";
42
+ }>>;
43
+ preAnswered: z.ZodOptional<z.ZodObject<{
44
+ selectedOptionId: z.ZodOptional<z.ZodString>;
45
+ selectedOptionIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
46
+ freetext: z.ZodOptional<z.ZodString>;
47
+ label: z.ZodOptional<z.ZodString>;
48
+ }, z.core.$strip>>;
49
+ }, z.core.$strip>>;
50
+ }, z.core.$strip>;
51
+ export declare const reviewDescriptorSchema: z.ZodObject<{
52
+ schema: z.ZodLiteral<"humanloop.review/v1">;
53
+ file: z.ZodString;
54
+ output: z.ZodString;
55
+ title: z.ZodString;
56
+ subtitle: z.ZodString;
57
+ source: z.ZodObject<{
58
+ sessionName: z.ZodOptional<z.ZodString>;
59
+ askedBy: z.ZodOptional<z.ZodString>;
60
+ blockedSince: z.ZodOptional<z.ZodString>;
61
+ nodeId: z.ZodOptional<z.ZodString>;
62
+ }, z.core.$strip>;
63
+ blockedSince: z.ZodString;
64
+ }, z.core.$strict>;
65
+ export declare function resolveDeckBodyPaths(deck: Deck, dir: string): Deck;
66
+ export declare function parseDeck(path: string): Deck;
67
+ export declare function validateDeck(parsed: unknown): Deck;
68
+ export declare function validateReviewDescriptor(parsed: unknown): ReviewDescriptor;
69
+ /** Canonicalize and authorize the one review projection boundary before every write. */
70
+ export declare function validateReviewProjection(dir: string, parsed: unknown): ReviewDescriptor;
@@ -0,0 +1,92 @@
1
+ import { existsSync, lstatSync, readFileSync, realpathSync } from 'node:fs';
2
+ import { basename, dirname, isAbsolute, resolve, sep } from 'node:path';
3
+ import { claimPath, deckPath, progressPath, responsePath, reviewPath } from './convention.js';
4
+ import { z } from 'zod';
5
+ import { INTERACTION_KINDS } from './types.js';
6
+ import { checkMarkdown } from '../termrender/termrender.js';
7
+ import { checkReviewableFile } from './visible-paths.js';
8
+ export const interactionOptionSchema = z.object({ id: z.string().min(1), label: z.string().min(1), description: z.string().optional() });
9
+ export const preAnswerSchema = z.object({ selectedOptionId: z.string().optional(), selectedOptionIds: z.array(z.string()).optional(), freetext: z.string().optional(), label: z.string().optional() });
10
+ const interactionSchema = z.object({
11
+ id: z.string().regex(/^[A-Za-z0-9_-]+$/, { error: 'interaction id must match /^[A-Za-z0-9_-]+$/' }).min(1).max(64),
12
+ title: z.string().trim().min(1), subtitle: z.string().trim().min(1), body: z.string().optional(), bodyPath: z.string().optional(),
13
+ options: z.array(interactionOptionSchema), multiSelect: z.boolean().optional(), allowFreetext: z.boolean().optional(), freetextLabel: z.string().optional(), kind: z.enum(INTERACTION_KINDS).optional(), preAnswered: preAnswerSchema.optional(),
14
+ });
15
+ const deckSourceSchema = z.object({ sessionName: z.string().optional(), askedBy: z.string().optional(), blockedSince: z.string().optional(), nodeId: z.string().optional() });
16
+ export const deckSchema = z.object({ title: z.string().trim().min(1), source: deckSourceSchema.optional(), interactions: z.array(interactionSchema).min(1) }).superRefine((input, ctx) => {
17
+ const seen = new Set();
18
+ input.interactions.forEach((interaction, index) => {
19
+ if (interaction.body !== undefined && interaction.bodyPath !== undefined)
20
+ ctx.addIssue({ code: 'custom', message: 'body and bodyPath are mutually exclusive', path: ['interactions', index] });
21
+ if (seen.has(interaction.id))
22
+ ctx.addIssue({ code: 'custom', message: `duplicate interaction id "${interaction.id}"`, path: ['interactions', index, 'id'] });
23
+ seen.add(interaction.id);
24
+ });
25
+ });
26
+ const reviewSourceSchema = deckSourceSchema;
27
+ export const reviewDescriptorSchema = z.object({
28
+ schema: z.literal('humanloop.review/v1'),
29
+ file: z.string().min(1).refine(isAbsolute, 'file must be absolute'),
30
+ output: z.string().min(1).refine(isAbsolute, 'output must be absolute'),
31
+ title: z.string().trim().min(1),
32
+ subtitle: z.string().trim().min(1),
33
+ source: reviewSourceSchema,
34
+ blockedSince: z.string().datetime({ offset: true }),
35
+ }).strict();
36
+ function readBodyPathFile(dir, bodyPath) {
37
+ const joined = resolve(dir, bodyPath);
38
+ if (!existsSync(joined))
39
+ throw new Error(`bodyPath does not exist: '${bodyPath}'`);
40
+ if (!lstatSync(joined).isFile())
41
+ throw new Error(`bodyPath must be a regular file: ${bodyPath}`);
42
+ const realResolved = realpathSync(joined);
43
+ const realDeckDir = realpathSync(dir);
44
+ if (!realResolved.startsWith(realDeckDir + sep))
45
+ throw new Error(`bodyPath '${bodyPath}' escapes the deck directory`);
46
+ return readFileSync(joined, 'utf8');
47
+ }
48
+ export function resolveDeckBodyPaths(deck, dir) {
49
+ return { ...deck, interactions: deck.interactions.map((interaction) => {
50
+ if (interaction.bodyPath === undefined)
51
+ return interaction;
52
+ const { bodyPath: _bodyPath, ...rest } = interaction;
53
+ return { ...rest, body: readBodyPathFile(dir, interaction.bodyPath) };
54
+ }) };
55
+ }
56
+ export function parseDeck(path) {
57
+ let raw;
58
+ try {
59
+ raw = JSON.parse(readFileSync(path, 'utf8'));
60
+ }
61
+ catch {
62
+ throw new Error('deck is not valid JSON');
63
+ }
64
+ const deck = resolveDeckBodyPaths(deckSchema.parse(raw), dirname(path));
65
+ for (const interaction of deck.interactions)
66
+ if (interaction.body !== undefined) {
67
+ const check = checkMarkdown(interaction.body);
68
+ if (!check.ok)
69
+ throw new Error(check.error);
70
+ }
71
+ return deck;
72
+ }
73
+ export function validateDeck(parsed) { return deckSchema.parse(parsed); }
74
+ export function validateReviewDescriptor(parsed) { return reviewDescriptorSchema.parse(parsed); }
75
+ /** Canonicalize and authorize the one review projection boundary before every write. */
76
+ export function validateReviewProjection(dir, parsed) {
77
+ const descriptor = validateReviewDescriptor(parsed);
78
+ // Any reviewable UTF-8 text file: a .md artifact renders as a document, a
79
+ // source file as a syntax-highlighted code panel.
80
+ if (!existsSync(descriptor.file))
81
+ throw new Error('review file must be an existing absolute path');
82
+ const reviewable = checkReviewableFile(descriptor.file);
83
+ if (!reviewable.ok)
84
+ throw new Error(`review file is not reviewable: ${reviewable.reason}`);
85
+ const file = realpathSync(descriptor.file);
86
+ const output = resolve(realpathSync(dirname(descriptor.output)), basename(descriptor.output));
87
+ const reserved = new Set(['deck.json', 'review.json', 'response.json', 'progress.json', 'claim.json']);
88
+ const ownProtocolPaths = new Set([deckPath(dir), reviewPath(dir), responsePath(dir), progressPath(dir), claimPath(dir)]);
89
+ if (output === file || reserved.has(basename(output)) || ownProtocolPaths.has(output))
90
+ throw new Error('review output must not alias the source or ticket protocol files');
91
+ return { ...descriptor, file, output };
92
+ }
@@ -0,0 +1,7 @@
1
+ export declare function ticketsRoot(): string;
2
+ /** A ticket directory is the bridge node's canvas directory, the same path by construction. */
3
+ export declare function ticketDir(nodeId: string): string;
4
+ export declare function inboxActivityPath(): string;
5
+ /** Signal one durable ticket mutation to every open inbox without watching every ticket directory. */
6
+ export declare function signalInboxActivity(): void;
7
+ export declare function watchInboxActivity(onChange: () => void): () => void;
@@ -0,0 +1,37 @@
1
+ import { mkdirSync, watch, writeFileSync } from 'node:fs';
2
+ import { basename, dirname, join } from 'node:path';
3
+ import { crtrHome, nodeDir, nodesRoot } from '../canvas/paths.js';
4
+ export function ticketsRoot() {
5
+ return nodesRoot();
6
+ }
7
+ /** A ticket directory is the bridge node's canvas directory, the same path by construction. */
8
+ export function ticketDir(nodeId) {
9
+ return nodeDir(nodeId);
10
+ }
11
+ export function inboxActivityPath() {
12
+ return join(crtrHome(), 'signals', 'inbox-activity');
13
+ }
14
+ /** Signal one durable ticket mutation to every open inbox without watching every ticket directory. */
15
+ export function signalInboxActivity() {
16
+ try {
17
+ mkdirSync(dirname(inboxActivityPath()), { recursive: true, mode: 0o700 });
18
+ writeFileSync(inboxActivityPath(), `${Date.now()}\n`, { mode: 0o600 });
19
+ }
20
+ catch {
21
+ // A later inbox scan is still authoritative.
22
+ }
23
+ }
24
+ export function watchInboxActivity(onChange) {
25
+ const activityPath = inboxActivityPath();
26
+ try {
27
+ mkdirSync(dirname(activityPath), { recursive: true, mode: 0o700 });
28
+ const watcher = watch(dirname(activityPath), (_event, filename) => {
29
+ if (String(filename) === basename(activityPath))
30
+ onChange();
31
+ });
32
+ return () => watcher.close();
33
+ }
34
+ catch {
35
+ return () => { };
36
+ }
37
+ }
@@ -0,0 +1,3 @@
1
+ import type { TicketSummary } from './types.js';
2
+ /** Read all unresolved deck/review tickets, newest first. Progress never affects visibility. */
3
+ export declare function scanInbox(): TicketSummary[];
@@ -0,0 +1,76 @@
1
+ import { readdirSync, statSync } from 'node:fs';
2
+ import { basename, join } from 'node:path';
3
+ import { claimPath, deckPath, isResolved, readJson, reviewPath } from './convention.js';
4
+ import { validateDeck, validateReviewDescriptor } from './deck-schema.js';
5
+ import { ticketsRoot } from './root.js';
6
+ function claimSummary(dir) {
7
+ const claim = readJson(claimPath(dir));
8
+ if (claim === null || typeof claim.host !== 'string' || typeof claim.claimedAt !== 'string' || typeof claim.heartbeatAt !== 'string')
9
+ return undefined;
10
+ return { owner: claim.host, claimedAt: claim.claimedAt, heartbeatAt: claim.heartbeatAt };
11
+ }
12
+ function deckSummary(dir, id) {
13
+ const raw = readJson(deckPath(dir));
14
+ if (raw === null)
15
+ return null;
16
+ let deck;
17
+ try {
18
+ deck = validateDeck(raw);
19
+ }
20
+ catch {
21
+ return null;
22
+ }
23
+ const first = deck.interactions[0];
24
+ if (first === undefined)
25
+ return null;
26
+ let blockedSince = deck.source?.blockedSince;
27
+ if (blockedSince === undefined) {
28
+ try {
29
+ blockedSince = statSync(deckPath(dir)).mtime.toISOString();
30
+ }
31
+ catch {
32
+ return null;
33
+ }
34
+ }
35
+ return { dir, id, kind: 'deck', title: deck.title, subtitle: first.subtitle, interactionKind: first.kind, interactionCount: deck.interactions.length, source: deck.source ?? {}, blockedSince, claim: claimSummary(dir) };
36
+ }
37
+ function reviewSummary(dir, id) {
38
+ const raw = readJson(reviewPath(dir));
39
+ if (raw === null)
40
+ return null;
41
+ let review;
42
+ try {
43
+ review = validateReviewDescriptor(raw);
44
+ }
45
+ catch {
46
+ return null;
47
+ }
48
+ return { dir, id, kind: 'review', title: review.title, subtitle: review.subtitle, file: review.file, output: review.output, source: review.source, blockedSince: review.blockedSince, claim: claimSummary(dir) };
49
+ }
50
+ /** Read all unresolved deck/review tickets, newest first. Progress never affects visibility. */
51
+ export function scanInbox() {
52
+ let entries;
53
+ try {
54
+ entries = readdirSync(ticketsRoot());
55
+ }
56
+ catch {
57
+ return [];
58
+ }
59
+ const items = [];
60
+ for (const entry of entries) {
61
+ const dir = join(ticketsRoot(), entry);
62
+ try {
63
+ if (!statSync(dir).isDirectory())
64
+ continue;
65
+ }
66
+ catch {
67
+ continue;
68
+ }
69
+ if (isResolved(dir))
70
+ continue;
71
+ const item = deckSummary(dir, basename(dir)) ?? reviewSummary(dir, basename(dir));
72
+ if (item !== null)
73
+ items.push(item);
74
+ }
75
+ return items.sort((a, b) => b.blockedSince.localeCompare(a.blockedSince) || a.id.localeCompare(b.id));
76
+ }
@@ -0,0 +1,8 @@
1
+ import type { Deck, InteractionResponse } from './types.js';
2
+ /**
3
+ * Deterministic, no-LLM resolution summary — one line per answered
4
+ * interaction: `"<title>: <option label>[ — <freetext>]"`. Shared by `ask()`
5
+ * (envelope summary) and `writeResponse` (persisted into response.json at write
6
+ * time).
7
+ */
8
+ export declare function buildSummary(deck: Deck, responses: InteractionResponse[]): string;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Deterministic, no-LLM resolution summary — one line per answered
3
+ * interaction: `"<title>: <option label>[ — <freetext>]"`. Shared by `ask()`
4
+ * (envelope summary) and `writeResponse` (persisted into response.json at write
5
+ * time).
6
+ */
7
+ export function buildSummary(deck, responses) {
8
+ const byId = new Map(responses.map((r) => [r.id, r]));
9
+ const lines = [];
10
+ for (const it of deck.interactions) {
11
+ const r = byId.get(it.id);
12
+ if (r === undefined)
13
+ continue;
14
+ const ft = r.freetext !== undefined && r.freetext !== '' ? r.freetext : undefined;
15
+ let picked;
16
+ if (r.selectedOptionIds !== undefined) {
17
+ const oc = r.optionComments;
18
+ const parts = r.selectedOptionIds
19
+ .map((id) => it.options.find((o) => o.id === id))
20
+ .filter((o) => o !== undefined)
21
+ .map((o) => {
22
+ const note = oc !== undefined ? oc[o.id] : undefined;
23
+ return typeof note === 'string' && note.length > 0
24
+ ? `${o.label} ("${note}")`
25
+ : o.label;
26
+ });
27
+ picked = parts.length > 0 ? parts.join(', ') : undefined;
28
+ }
29
+ else if (r.selectedOptionId !== undefined) {
30
+ picked = it.options.find((o) => o.id === r.selectedOptionId)?.label;
31
+ }
32
+ let val;
33
+ if (picked !== undefined && ft !== undefined)
34
+ val = `${picked} — ${ft}`;
35
+ else if (picked !== undefined)
36
+ val = picked;
37
+ else if (ft !== undefined)
38
+ val = ft;
39
+ else
40
+ val = '(skipped)';
41
+ lines.push(`${it.title}: ${val}`);
42
+ }
43
+ return lines.join('\n');
44
+ }
@@ -0,0 +1,49 @@
1
+ import type { Deck, DeckTicketResult, ReviewDescriptor, TicketResult } from './types.js';
2
+ /** Strict decoder for the only canonical final marker. */
3
+ export declare function readTicketResult(dir: string): TicketResult | null;
4
+ export interface SubmitDeckOptions {
5
+ dir: string;
6
+ deck: Deck;
7
+ }
8
+ export declare function submitDeck(opts: SubmitDeckOptions): {
9
+ id: string;
10
+ dir: string;
11
+ kind: 'deck';
12
+ };
13
+ export interface SubmitReviewOptions {
14
+ dir: string;
15
+ review: Omit<ReviewDescriptor, 'schema' | 'file' | 'output' | 'blockedSince'> & {
16
+ file: string;
17
+ output?: string;
18
+ blockedSince?: string;
19
+ };
20
+ }
21
+ export declare function submitReview(opts: SubmitReviewOptions): {
22
+ id: string;
23
+ dir: string;
24
+ kind: 'review';
25
+ };
26
+ /** Validate a deck resolution against its canonical ticket before claim takeover. */
27
+ export declare function validateDeckTicketResponses(dir: string, responses: unknown): DeckTicketResult['responses'];
28
+ export declare function completeDeck(dir: string, responses: DeckTicketResult['responses'], claimToken: string, completedAt?: string): {
29
+ won: boolean;
30
+ result: TicketResult;
31
+ };
32
+ /** Atomically take a ticket's claim over, complete it, and release the takeover claim. */
33
+ export declare function takeoverAndCompleteDeck(dir: string, responses: DeckTicketResult['responses'], owner: {
34
+ host: string;
35
+ pid: number;
36
+ }): {
37
+ won: boolean;
38
+ result: TicketResult;
39
+ };
40
+ /** Cancellation races finalization but never requires or removes another claim. */
41
+ export declare function cancelTicket(dir: string, opts?: {
42
+ reason?: string;
43
+ actor?: string;
44
+ }): {
45
+ status: 'canceled' | 'already_resolved';
46
+ result: TicketResult;
47
+ };
48
+ /** Write the validated review output once its review result is published. */
49
+ export declare function projectReviewOutput(dir: string): 'projected' | 'not_a_review' | 'no_result';
@@ -0,0 +1,190 @@
1
+ import { existsSync, mkdirSync, readFileSync, realpathSync, unlinkSync, writeFileSync } from 'node:fs';
2
+ import { basename, isAbsolute, resolve } from 'node:path';
3
+ import { randomUUID } from 'node:crypto';
4
+ import { z } from 'zod';
5
+ import { buildSummary } from './summary.js';
6
+ import { atomicWriteJson, clearProgress, claimPath, deckPath, progressPath, publishJsonExclusive, requireTicket, responsePath, reviewPath } from './convention.js';
7
+ import { validateDeck, validateReviewDescriptor, validateReviewProjection, resolveDeckBodyPaths } from './deck-schema.js';
8
+ import { signalInboxActivity } from './root.js';
9
+ import { readTicketClaim, releaseClaimLocked, withTicketLock } from './claim.js';
10
+ import { checkReviewableFile } from './visible-paths.js';
11
+ const responseSchema = z.object({ id: z.string().min(1), selectedOptionId: z.string().optional(), selectedOptionIds: z.array(z.string()).optional(), freetext: z.string().optional(), optionComments: z.record(z.string(), z.string()).optional() }).strict();
12
+ const feedbackCommentSchema = z.object({ id: z.string().min(1), line: z.number().int().positive(), endLine: z.number().int().positive(), quote: z.string().optional(), colStart: z.number().int().nonnegative().optional(), colEnd: z.number().int().nonnegative().optional(), lineText: z.string(), comment: z.string().min(1), createdAt: z.string().min(1) }).strict();
13
+ const iso = z.string().datetime({ offset: true });
14
+ const feedbackSchema = z.object({ file: z.string().min(1).refine(isAbsolute, 'file must be absolute').refine((file) => resolve(file) === file, 'file must be canonical'), submitted: z.literal(true), approved: z.boolean(), comments: z.array(feedbackCommentSchema), submittedAt: iso, savedAt: iso, reviewId: z.string().optional(), changed: z.boolean().optional(), baselineSha256: z.string().optional(), approvedSha256: z.string().optional(), companionNodeId: z.string().optional(), commentsTotal: z.number().int().nonnegative().optional(), commentsUnresolved: z.number().int().nonnegative().optional() }).strict().superRefine((result, ctx) => {
15
+ result.comments.forEach((comment, index) => {
16
+ if (comment.endLine < comment.line)
17
+ ctx.addIssue({ code: 'custom', message: 'endLine must be >= line', path: ['comments', index, 'endLine'] });
18
+ if ((comment.colStart === undefined) !== (comment.colEnd === undefined))
19
+ ctx.addIssue({ code: 'custom', message: 'columns must be supplied together', path: ['comments', index] });
20
+ if (comment.line === comment.endLine && comment.colStart !== undefined && comment.colEnd !== undefined && comment.colEnd <= comment.colStart)
21
+ ctx.addIssue({ code: 'custom', message: 'colEnd must exceed colStart', path: ['comments', index, 'colEnd'] });
22
+ });
23
+ });
24
+ const deckResultSchema = z.object({ schema: z.literal('humanloop.response/v2'), kind: z.literal('deck'), responses: z.array(responseSchema), summary: z.string(), completedAt: iso }).strict();
25
+ const reviewResultSchema = z.object({ schema: z.literal('humanloop.review-response/v1'), kind: z.literal('review'), result: feedbackSchema, completedAt: iso }).strict();
26
+ const canceledResultSchema = z.object({ schema: z.literal('humanloop.cancel/v1'), kind: z.literal('canceled'), canceledAt: iso, reason: z.string().optional(), actor: z.string().optional() }).strict();
27
+ /** Strict decoder for the only canonical final marker. */
28
+ export function readTicketResult(dir) {
29
+ let raw;
30
+ try {
31
+ raw = JSON.parse(readFileSync(responsePath(dir), 'utf8'));
32
+ }
33
+ catch {
34
+ return null;
35
+ }
36
+ const parsed = deckResultSchema.safeParse(raw);
37
+ if (parsed.success)
38
+ return parsed.data;
39
+ const review = reviewResultSchema.safeParse(raw);
40
+ if (review.success)
41
+ return review.data;
42
+ const canceled = canceledResultSchema.safeParse(raw);
43
+ return canceled.success ? canceled.data : null;
44
+ }
45
+ function hasTicketProtocolState(dir) {
46
+ return [deckPath(dir), reviewPath(dir), responsePath(dir), progressPath(dir), claimPath(dir)].some(existsSync);
47
+ }
48
+ function publishRequest(path, value) {
49
+ if (!publishJsonExclusive(path, value))
50
+ throw new Error(`ticket request already exists: ${path}`);
51
+ }
52
+ export function submitDeck(opts) {
53
+ // Validate shape before mutating the bridge node's canvas directory.
54
+ validateDeck(opts.deck);
55
+ mkdirSync(opts.dir, { recursive: true, mode: 0o700 });
56
+ const dir = realpathSync(opts.dir);
57
+ if (hasTicketProtocolState(dir))
58
+ throw new Error(`ticket protocol state already exists: ${dir}`);
59
+ const deck = validateDeck(resolveDeckBodyPaths(opts.deck, dir));
60
+ const stamped = { ...deck, source: { ...(deck.source ?? {}), blockedSince: deck.source?.blockedSince ?? new Date().toISOString() } };
61
+ publishRequest(deckPath(dir), stamped);
62
+ signalInboxActivity();
63
+ return { id: basename(dir), dir, kind: 'deck' };
64
+ }
65
+ export function submitReview(opts) {
66
+ // A review takes any reviewable text file: a .md artifact renders as a document,
67
+ // and source code renders as a syntax-highlighted code panel.
68
+ if (!isAbsolute(opts.review.file) || !existsSync(opts.review.file))
69
+ throw new Error('review file must be an existing absolute path');
70
+ const reviewable = checkReviewableFile(opts.review.file);
71
+ if (!reviewable.ok)
72
+ throw new Error(`review file is not reviewable: ${reviewable.reason}`);
73
+ const source = realpathSync(opts.review.file);
74
+ mkdirSync(opts.dir, { recursive: true, mode: 0o700 });
75
+ const dir = realpathSync(opts.dir);
76
+ if (hasTicketProtocolState(dir))
77
+ throw new Error(`ticket protocol state already exists: ${dir}`);
78
+ const descriptor = validateReviewProjection(dir, { schema: 'humanloop.review/v1', file: source, output: resolve(opts.review.output ?? `${dir}/feedback.json`), title: opts.review.title, subtitle: opts.review.subtitle, source: opts.review.source, blockedSince: opts.review.blockedSince ?? new Date().toISOString() });
79
+ publishRequest(reviewPath(dir), descriptor);
80
+ signalInboxActivity();
81
+ return { id: basename(dir), dir, kind: 'review' };
82
+ }
83
+ function exclusiveResult(dir, result) {
84
+ return publishJsonExclusive(responsePath(dir), result);
85
+ }
86
+ function requireDeck(dir) { return validateDeck(JSON.parse(readFileSync(deckPath(dir), 'utf8'))); }
87
+ function requireReview(dir) { return validateReviewDescriptor(JSON.parse(readFileSync(reviewPath(dir), 'utf8'))); }
88
+ function validateDeckResponses(deck, raw) {
89
+ const responses = z.array(responseSchema).parse(raw);
90
+ const interactions = new Map(deck.interactions.map((interaction) => [interaction.id, interaction]));
91
+ const seen = new Set();
92
+ for (const response of responses) {
93
+ const interaction = interactions.get(response.id);
94
+ if (interaction === undefined || seen.has(response.id))
95
+ throw new Error(`response does not match a unique deck interaction: ${response.id}`);
96
+ seen.add(response.id);
97
+ const optionIds = new Set(interaction.options.map((option) => option.id));
98
+ if (response.selectedOptionId !== undefined && (!optionIds.has(response.selectedOptionId) || interaction.multiSelect === true))
99
+ throw new Error(`invalid single-select response for ${response.id}`);
100
+ if (response.selectedOptionIds !== undefined && (interaction.multiSelect !== true || response.selectedOptionIds.some((id) => !optionIds.has(id)) || new Set(response.selectedOptionIds).size !== response.selectedOptionIds.length))
101
+ throw new Error(`invalid multi-select response for ${response.id}`);
102
+ if (response.freetext !== undefined && interaction.allowFreetext !== true)
103
+ throw new Error(`freetext is not allowed for ${response.id}`);
104
+ if (response.optionComments !== undefined && (interaction.multiSelect !== true || Object.keys(response.optionComments).some((id) => !optionIds.has(id))))
105
+ throw new Error(`invalid option comments for ${response.id}`);
106
+ }
107
+ for (const interaction of deck.interactions.filter((candidate) => candidate.kind === 'notify')) {
108
+ const response = responses.find((candidate) => candidate.id === interaction.id);
109
+ if (response === undefined || (response.selectedOptionId === undefined && (response.selectedOptionIds?.length ?? 0) === 0 && (response.freetext?.trim() ?? '') === '')) {
110
+ throw new Error(`notification requires an explicit acknowledgement: ${interaction.id}`);
111
+ }
112
+ }
113
+ return responses;
114
+ }
115
+ /** Validate a deck resolution against its canonical ticket before claim takeover. */
116
+ export function validateDeckTicketResponses(dir, responses) {
117
+ const ticket = requireTicket(dir);
118
+ return validateDeckResponses(requireDeck(ticket), responses);
119
+ }
120
+ function requireClaimOwnership(dir, token) {
121
+ if (readTicketClaim(dir)?.token !== token)
122
+ throw new Error('only the current claim holder may submit a result');
123
+ }
124
+ function clearOwnedWork(dir, claimToken) { clearProgress(dir); releaseClaimLocked(dir, claimToken); }
125
+ /** Caller holds `.ticket-lock`. */
126
+ function completeDeckLocked(dir, responses, claimToken, completedAt = new Date().toISOString()) {
127
+ requireClaimOwnership(dir, claimToken);
128
+ const deck = requireDeck(dir);
129
+ const parsedResponses = validateDeckResponses(deck, responses);
130
+ const result = { schema: 'humanloop.response/v2', kind: 'deck', responses: parsedResponses, summary: buildSummary(deck, parsedResponses), completedAt };
131
+ const won = exclusiveResult(dir, result);
132
+ clearOwnedWork(dir, claimToken);
133
+ return { won, result: won ? result : readTicketResult(dir) ?? result };
134
+ }
135
+ export function completeDeck(dir, responses, claimToken, completedAt) {
136
+ const ticket = requireTicket(dir);
137
+ const completed = withTicketLock(ticket, () => completeDeckLocked(ticket, responses, claimToken, completedAt));
138
+ if (completed.won)
139
+ signalInboxActivity();
140
+ return completed;
141
+ }
142
+ function takeoverClaim(dir, owner) {
143
+ const existing = readTicketClaim(dir);
144
+ if (existing !== null)
145
+ unlinkSync(claimPath(dir));
146
+ const token = randomUUID();
147
+ const now = new Date().toISOString();
148
+ writeFileSync(claimPath(dir), `${JSON.stringify({ token, host: owner.host, pid: owner.pid, claimedAt: now, heartbeatAt: now })}\n`, { flag: 'wx', mode: 0o600 });
149
+ return token;
150
+ }
151
+ /** Atomically take a ticket's claim over, complete it, and release the takeover claim. */
152
+ export function takeoverAndCompleteDeck(dir, responses, owner) {
153
+ const ticket = requireTicket(dir);
154
+ const completed = withTicketLock(ticket, () => {
155
+ const token = takeoverClaim(ticket, owner);
156
+ try {
157
+ return completeDeckLocked(ticket, responses, token);
158
+ }
159
+ finally {
160
+ releaseClaimLocked(ticket, token);
161
+ }
162
+ });
163
+ if (completed.won)
164
+ signalInboxActivity();
165
+ return completed;
166
+ }
167
+ /** Cancellation races finalization but never requires or removes another claim. */
168
+ export function cancelTicket(dir, opts = {}) {
169
+ const ticket = requireTicket(dir);
170
+ const canceled = withTicketLock(ticket, () => {
171
+ const result = { schema: 'humanloop.cancel/v1', kind: 'canceled', canceledAt: new Date().toISOString(), ...(opts.reason === undefined ? {} : { reason: opts.reason }), ...(opts.actor === undefined ? {} : { actor: opts.actor }) };
172
+ const won = exclusiveResult(ticket, result);
173
+ return { status: won ? 'canceled' : 'already_resolved', result: won ? result : readTicketResult(ticket) ?? result };
174
+ });
175
+ if (canceled.status === 'canceled')
176
+ signalInboxActivity();
177
+ return canceled;
178
+ }
179
+ /** Write the validated review output once its review result is published. */
180
+ export function projectReviewOutput(dir) {
181
+ const result = readTicketResult(dir);
182
+ if (result === null)
183
+ return 'no_result';
184
+ if (result.kind !== 'review')
185
+ return 'not_a_review';
186
+ const ticket = requireTicket(dir);
187
+ const descriptor = validateReviewProjection(ticket, requireReview(ticket));
188
+ atomicWriteJson(descriptor.output, result.result);
189
+ return 'projected';
190
+ }