cloving 1.2.0 → 1.3.0

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 (518) hide show
  1. package/README.md +525 -185
  2. package/dist/src/agent-harness-shell.d.ts +12 -0
  3. package/dist/src/agent-harness-shell.js +90 -0
  4. package/dist/src/agent-harness-versions.d.ts +8 -0
  5. package/dist/src/agent-harness-versions.js +49 -0
  6. package/dist/src/agent-harnesses.d.ts +4 -0
  7. package/dist/src/agent-harnesses.js +13 -0
  8. package/dist/src/authority/commands.d.ts +1 -0
  9. package/dist/src/authority/commands.js +24 -4
  10. package/dist/src/authority/gate-reduction.d.ts +1 -0
  11. package/dist/src/authority/gate-reduction.js +18 -3
  12. package/dist/src/authority/gates.d.ts +2 -1
  13. package/dist/src/authority/gates.js +5 -1
  14. package/dist/src/authority/operations.js +1 -1
  15. package/dist/src/authority/reduction.d.ts +1 -1
  16. package/dist/src/authority/reduction.js +6 -1
  17. package/dist/src/authority/status-input.d.ts +1 -1
  18. package/dist/src/authority/status.d.ts +1 -0
  19. package/dist/src/authority/status.js +27 -3
  20. package/dist/src/authority/transitions.d.ts +5 -5
  21. package/dist/src/authority/transitions.js +6 -0
  22. package/dist/src/broker/actor/authority-delivery.js +1 -0
  23. package/dist/src/broker/actor/authority-queries.d.ts +7 -1
  24. package/dist/src/broker/actor/authority-queries.js +17 -2
  25. package/dist/src/broker/actor/authority-receipts.js +11 -1
  26. package/dist/src/broker/actor/authority-session.js +2 -2
  27. package/dist/src/broker/actor/authority-settings.js +4 -0
  28. package/dist/src/broker/actor/delivery-intents.d.ts +2 -1
  29. package/dist/src/broker/actor/delivery-intents.js +4 -4
  30. package/dist/src/broker/actor/effect-delivery.js +4 -1
  31. package/dist/src/broker/actor/effect-queries.d.ts +1 -0
  32. package/dist/src/broker/actor/effect-queries.js +7 -0
  33. package/dist/src/broker/actor/pin-check.js +1 -1
  34. package/dist/src/broker/actor/stop-plan.js +1 -1
  35. package/dist/src/broker/actor/turn-state.js +1 -1
  36. package/dist/src/broker/authority-admission.js +22 -9
  37. package/dist/src/broker/authority-restore.js +1 -0
  38. package/dist/src/broker/decision-restore.js +4 -4
  39. package/dist/src/broker/socket-address.d.ts +3 -1
  40. package/dist/src/broker/socket-address.js +2 -2
  41. package/dist/src/cli/arguments.d.ts +11 -13
  42. package/dist/src/cli/arguments.js +37 -107
  43. package/dist/src/cli/command-effects.d.ts +7 -0
  44. package/dist/src/cli/command-effects.js +39 -0
  45. package/dist/src/cli/commands.js +11 -4
  46. package/dist/src/cli/config-arguments.d.ts +11 -0
  47. package/dist/src/cli/config-arguments.js +59 -0
  48. package/dist/src/cli/config-command.d.ts +2 -0
  49. package/dist/src/cli/config-command.js +105 -0
  50. package/dist/src/cli/config-file.d.ts +3 -0
  51. package/dist/src/cli/config-file.js +50 -0
  52. package/dist/src/cli/config-lock.d.ts +7 -0
  53. package/dist/src/cli/config-lock.js +61 -0
  54. package/dist/src/cli/config-notice.d.ts +5 -0
  55. package/dist/src/cli/config-notice.js +46 -0
  56. package/dist/src/cli/doctor-github.d.ts +9 -0
  57. package/dist/src/cli/doctor-github.js +138 -0
  58. package/dist/src/cli/doctor-harness.d.ts +13 -0
  59. package/dist/src/cli/doctor-harness.js +242 -0
  60. package/dist/src/cli/doctor-local.d.ts +18 -0
  61. package/dist/src/cli/doctor-local.js +77 -0
  62. package/dist/src/cli/doctor-runtime.d.ts +15 -0
  63. package/dist/src/cli/doctor-runtime.js +176 -0
  64. package/dist/src/cli/doctor-service.d.ts +1 -0
  65. package/dist/src/cli/doctor-service.js +11 -0
  66. package/dist/src/cli/doctor-workflows.d.ts +3 -0
  67. package/dist/src/cli/doctor-workflows.js +45 -0
  68. package/dist/src/cli/doctor.d.ts +15 -0
  69. package/dist/src/cli/doctor.js +190 -0
  70. package/dist/src/cli/github-ci-progress.d.ts +8 -0
  71. package/dist/src/cli/github-ci-progress.js +83 -0
  72. package/dist/src/cli/github-retry.d.ts +6 -0
  73. package/dist/src/cli/github-retry.js +47 -0
  74. package/dist/src/cli/harness-probes.d.ts +22 -0
  75. package/dist/src/cli/harness-probes.js +183 -0
  76. package/dist/src/cli/main.d.ts +7 -1
  77. package/dist/src/cli/main.js +39 -61
  78. package/dist/src/cli/phone-arguments.d.ts +14 -0
  79. package/dist/src/cli/phone-arguments.js +37 -0
  80. package/dist/src/cli/phone-client.d.ts +2 -0
  81. package/dist/src/cli/phone-client.js +32 -0
  82. package/dist/src/cli/phone-command.d.ts +13 -0
  83. package/dist/src/cli/phone-command.js +101 -0
  84. package/dist/src/cli/probe-command.d.ts +36 -0
  85. package/dist/src/cli/probe-command.js +59 -0
  86. package/dist/src/cli/project-settings.d.ts +4 -0
  87. package/dist/src/cli/project-settings.js +33 -0
  88. package/dist/src/cli/render.d.ts +2 -1
  89. package/dist/src/cli/render.js +44 -28
  90. package/dist/src/cli/report-github.d.ts +18 -0
  91. package/dist/src/cli/report-github.js +200 -0
  92. package/dist/src/cli/report.d.ts +17 -0
  93. package/dist/src/cli/report.js +192 -0
  94. package/dist/src/cli/repository-arguments.d.ts +5 -0
  95. package/dist/src/cli/repository-arguments.js +34 -0
  96. package/dist/src/cli/runtime-arguments.d.ts +4 -0
  97. package/dist/src/cli/runtime-arguments.js +15 -0
  98. package/dist/src/cli/runtime-directory.d.ts +6 -2
  99. package/dist/src/cli/runtime-directory.js +72 -14
  100. package/dist/src/cli/toolchain.d.ts +2 -0
  101. package/dist/src/cli/toolchain.js +22 -2
  102. package/dist/src/cli/usage-render.d.ts +5 -0
  103. package/dist/src/cli/usage-render.js +40 -1
  104. package/dist/src/cli/usage.d.ts +3 -3
  105. package/dist/src/cli/usage.js +70 -44
  106. package/dist/src/cli/watch-actions.d.ts +2 -0
  107. package/dist/src/cli/watch-actions.js +4 -4
  108. package/dist/src/cli/watch-board-view.d.ts +1 -1
  109. package/dist/src/cli/watch-board-view.js +8 -2
  110. package/dist/src/cli/watch-board.js +23 -10
  111. package/dist/src/cli/watch-card-forms.js +2 -2
  112. package/dist/src/cli/watch-client.d.ts +1 -1
  113. package/dist/src/cli/watch-client.js +7 -2
  114. package/dist/src/cli/watch-header-view.d.ts +27 -0
  115. package/dist/src/cli/watch-header-view.js +116 -0
  116. package/dist/src/cli/watch-model.js +17 -4
  117. package/dist/src/cli/watch-page.js +48 -12
  118. package/dist/src/cli/watch-phone-client.d.ts +1 -0
  119. package/dist/src/cli/watch-phone-client.js +84 -0
  120. package/dist/src/cli/watch-phone-view.d.ts +56 -0
  121. package/dist/src/cli/watch-phone-view.js +113 -0
  122. package/dist/src/cli/watch-phone.d.ts +5 -0
  123. package/dist/src/cli/watch-phone.js +53 -0
  124. package/dist/src/cli/watch-pull-request.d.ts +3 -1
  125. package/dist/src/cli/watch-pull-request.js +4 -0
  126. package/dist/src/cli/watch-render.d.ts +9 -1
  127. package/dist/src/cli/watch-server.js +23 -5
  128. package/dist/src/cli/watch-turn.d.ts +4 -1
  129. package/dist/src/cli/watch-turn.js +37 -1
  130. package/dist/src/cli/watch-usage.js +5 -1
  131. package/dist/src/cli/watch-view.d.ts +6 -20
  132. package/dist/src/cli/watch-view.js +14 -106
  133. package/dist/src/cli.js +106 -23
  134. package/dist/src/command-settings.d.ts +16 -0
  135. package/dist/src/command-settings.js +42 -0
  136. package/dist/src/configuration-change.d.ts +11 -0
  137. package/dist/src/configuration-change.js +62 -0
  138. package/dist/src/configuration-display.d.ts +21 -0
  139. package/dist/src/configuration-display.js +69 -0
  140. package/dist/src/configuration-schema.d.ts +49 -0
  141. package/dist/src/configuration-schema.js +159 -0
  142. package/dist/src/daemon/claude-turn.d.ts +19 -5
  143. package/dist/src/daemon/claude-turn.js +116 -53
  144. package/dist/src/daemon/claude-worker.d.ts +3 -3
  145. package/dist/src/daemon/claude-worker.js +65 -76
  146. package/dist/src/daemon/command-journal.d.ts +5 -0
  147. package/dist/src/daemon/command-journal.js +50 -0
  148. package/dist/src/daemon/command-process.d.ts +28 -0
  149. package/dist/src/daemon/command-process.js +164 -0
  150. package/dist/src/daemon/command-worker.d.ts +19 -0
  151. package/dist/src/daemon/command-worker.js +182 -0
  152. package/dist/src/daemon/cursor-stream.d.ts +4 -0
  153. package/dist/src/daemon/cursor-stream.js +154 -0
  154. package/dist/src/daemon/daemon-adapters.d.ts +58 -0
  155. package/dist/src/daemon/daemon-adapters.js +102 -0
  156. package/dist/src/daemon/daemon-loops.d.ts +14 -0
  157. package/dist/src/daemon/daemon-loops.js +39 -0
  158. package/dist/src/daemon/daemon.d.ts +2 -33
  159. package/dist/src/daemon/daemon.js +126 -132
  160. package/dist/src/daemon/declared-input.d.ts +3 -0
  161. package/dist/src/daemon/declared-input.js +9 -0
  162. package/dist/src/daemon/delivery-router.js +1 -1
  163. package/dist/src/daemon/gemini-stream.d.ts +4 -0
  164. package/dist/src/daemon/gemini-stream.js +129 -0
  165. package/dist/src/daemon/github-ci-rerun.d.ts +26 -0
  166. package/dist/src/daemon/github-ci-rerun.js +92 -0
  167. package/dist/src/daemon/github-ci.js +89 -8
  168. package/dist/src/daemon/github-merge-call.d.ts +2 -0
  169. package/dist/src/daemon/github-merge.js +7 -3
  170. package/dist/src/daemon/github-methods.js +10 -0
  171. package/dist/src/daemon/github-operation.d.ts +1 -0
  172. package/dist/src/daemon/github-retry.js +8 -44
  173. package/dist/src/daemon/issue-queue.d.ts +1 -0
  174. package/dist/src/daemon/issue-queue.js +3 -26
  175. package/dist/src/daemon/notify.js +2 -1
  176. package/dist/src/daemon/opencode-stream.d.ts +5 -0
  177. package/dist/src/daemon/opencode-stream.js +87 -0
  178. package/dist/src/daemon/queue-status.d.ts +4 -0
  179. package/dist/src/daemon/queue-status.js +38 -0
  180. package/dist/src/daemon/retry-worktree.d.ts +18 -0
  181. package/dist/src/daemon/retry-worktree.js +139 -0
  182. package/dist/src/daemon/retrying-turn.d.ts +2 -0
  183. package/dist/src/daemon/retrying-turn.js +108 -30
  184. package/dist/src/daemon/schedule-journal.d.ts +19 -0
  185. package/dist/src/daemon/schedule-journal.js +57 -0
  186. package/dist/src/daemon/text-output.d.ts +18 -0
  187. package/dist/src/daemon/text-output.js +44 -0
  188. package/dist/src/daemon/ticket-registration.d.ts +5 -7
  189. package/dist/src/daemon/ticket-registration.js +85 -40
  190. package/dist/src/daemon/turn-command.d.ts +10 -0
  191. package/dist/src/daemon/turn-command.js +33 -0
  192. package/dist/src/daemon/turn-report.d.ts +18 -0
  193. package/dist/src/daemon/turn-report.js +79 -0
  194. package/dist/src/daemon/work-tree.d.ts +2 -1
  195. package/dist/src/daemon/work-tree.js +15 -12
  196. package/dist/src/daemon/workflow-generations.d.ts +32 -0
  197. package/dist/src/daemon/workflow-generations.js +57 -0
  198. package/dist/src/daemon/workflow-replay.d.ts +16 -0
  199. package/dist/src/daemon/workflow-replay.js +58 -0
  200. package/dist/src/daemon/workflow-schedules.d.ts +27 -0
  201. package/dist/src/daemon/workflow-schedules.js +185 -0
  202. package/dist/src/decision-wait.d.ts +1 -0
  203. package/dist/src/decision-wait.js +3 -0
  204. package/dist/src/delivery-backoff.d.ts +1 -0
  205. package/dist/src/delivery-backoff.js +3 -0
  206. package/dist/src/doctor-report.d.ts +24 -0
  207. package/dist/src/doctor-report.js +70 -0
  208. package/dist/src/execution-pin.d.ts +5 -0
  209. package/dist/src/execution-pin.js +67 -4
  210. package/dist/src/grok-result.d.ts +12 -0
  211. package/dist/src/grok-result.js +61 -0
  212. package/dist/src/harness-defaults.d.ts +35 -0
  213. package/dist/src/harness-defaults.js +121 -0
  214. package/dist/src/host/decision-resume.d.ts +35 -0
  215. package/dist/src/host/decision-resume.js +86 -0
  216. package/dist/src/host/gate-bridge.d.ts +48 -0
  217. package/dist/src/host/gate-bridge.js +124 -0
  218. package/dist/src/host/run-wait.d.ts +26 -0
  219. package/dist/src/host/run-wait.js +37 -0
  220. package/dist/src/host/start-delivery.d.ts +1 -1
  221. package/dist/src/host/start-delivery.js +10 -3
  222. package/dist/src/host/step-bridge-host.d.ts +6 -20
  223. package/dist/src/host/step-bridge-host.js +44 -58
  224. package/dist/src/merge-request.d.ts +19 -0
  225. package/dist/src/merge-request.js +32 -0
  226. package/dist/src/phone/canonical-json.d.ts +1 -0
  227. package/dist/src/phone/canonical-json.js +16 -0
  228. package/dist/src/phone/phone-link.d.ts +7 -0
  229. package/dist/src/phone/phone-link.js +21 -0
  230. package/dist/src/phone/qr-data.d.ts +8 -0
  231. package/dist/src/phone/qr-data.js +133 -0
  232. package/dist/src/phone/qr-matrix.d.ts +6 -0
  233. package/dist/src/phone/qr-matrix.js +175 -0
  234. package/dist/src/phone/qr-penalty.d.ts +3 -0
  235. package/dist/src/phone/qr-penalty.js +67 -0
  236. package/dist/src/phone/qr-picture.d.ts +5 -0
  237. package/dist/src/phone/qr-picture.js +24 -0
  238. package/dist/src/private-config.schema.json +263 -0
  239. package/dist/src/project-config.schema.json +65 -0
  240. package/dist/src/project-settings.d.ts +19 -0
  241. package/dist/src/project-settings.js +131 -0
  242. package/dist/src/relay/answer-check.d.ts +24 -0
  243. package/dist/src/relay/answer-check.js +145 -0
  244. package/dist/src/relay/answer-inbox.d.ts +15 -0
  245. package/dist/src/relay/answer-inbox.js +173 -0
  246. package/dist/src/relay/daemon-keys.d.ts +16 -0
  247. package/dist/src/relay/daemon-keys.js +75 -0
  248. package/dist/src/relay/decision-check.d.ts +3 -0
  249. package/dist/src/relay/decision-check.js +77 -0
  250. package/dist/src/relay/decision-close.d.ts +6 -0
  251. package/dist/src/relay/decision-close.js +72 -0
  252. package/dist/src/relay/decision-envelopes.d.ts +29 -0
  253. package/dist/src/relay/decision-envelopes.js +93 -0
  254. package/dist/src/relay/decision-watch.d.ts +14 -0
  255. package/dist/src/relay/decision-watch.js +68 -0
  256. package/dist/src/relay/envelope-post.d.ts +8 -0
  257. package/dist/src/relay/envelope-post.js +71 -0
  258. package/dist/src/relay/envelope.d.ts +28 -0
  259. package/dist/src/relay/envelope.js +53 -0
  260. package/dist/src/relay/hpke.d.ts +25 -0
  261. package/dist/src/relay/hpke.js +108 -0
  262. package/dist/src/relay/pairing-checks.d.ts +42 -0
  263. package/dist/src/relay/pairing-checks.js +172 -0
  264. package/dist/src/relay/pairing-follow.d.ts +8 -0
  265. package/dist/src/relay/pairing-follow.js +95 -0
  266. package/dist/src/relay/pairing-session.d.ts +29 -0
  267. package/dist/src/relay/pairing-session.js +87 -0
  268. package/dist/src/relay/phone-delivery.d.ts +51 -0
  269. package/dist/src/relay/phone-delivery.js +139 -0
  270. package/dist/src/relay/phone-devices.d.ts +36 -0
  271. package/dist/src/relay/phone-devices.js +46 -0
  272. package/dist/src/relay/phone-inbox.d.ts +18 -0
  273. package/dist/src/relay/phone-inbox.js +17 -0
  274. package/dist/src/relay/phone-operations.d.ts +18 -0
  275. package/dist/src/relay/phone-operations.js +121 -0
  276. package/dist/src/relay/phone-outbox.d.ts +21 -0
  277. package/dist/src/relay/phone-outbox.js +25 -0
  278. package/dist/src/relay/phone-socket.d.ts +6 -0
  279. package/dist/src/relay/phone-socket.js +63 -0
  280. package/dist/src/relay/relay-control.d.ts +7 -0
  281. package/dist/src/relay/relay-control.js +24 -0
  282. package/dist/src/relay/relay-files.d.ts +2 -0
  283. package/dist/src/relay/relay-files.js +23 -0
  284. package/dist/src/relay/relay-heartbeat.d.ts +17 -0
  285. package/dist/src/relay/relay-heartbeat.js +81 -0
  286. package/dist/src/relay/relay-http.d.ts +14 -0
  287. package/dist/src/relay/relay-http.js +63 -0
  288. package/dist/src/relay/relay-registration.d.ts +15 -0
  289. package/dist/src/relay/relay-registration.js +63 -0
  290. package/dist/src/relay/relay-service.d.ts +25 -0
  291. package/dist/src/relay/relay-service.js +216 -0
  292. package/dist/src/relay/relay-store.d.ts +48 -0
  293. package/dist/src/relay/relay-store.js +131 -0
  294. package/dist/src/relay/sealed-post.d.ts +25 -0
  295. package/dist/src/relay/sealed-post.js +52 -0
  296. package/dist/src/relay.d.ts +1 -0
  297. package/dist/src/relay.js +8 -0
  298. package/dist/src/report-statistics.d.ts +50 -0
  299. package/dist/src/report-statistics.js +70 -0
  300. package/dist/src/report.d.ts +171 -0
  301. package/dist/src/report.js +119 -0
  302. package/dist/src/repository-identity.d.ts +4 -0
  303. package/dist/src/repository-identity.js +4 -0
  304. package/dist/src/review-subject.d.ts +41 -0
  305. package/dist/src/review-subject.js +91 -0
  306. package/dist/src/run-wait.d.ts +23 -0
  307. package/dist/src/run-wait.js +20 -0
  308. package/dist/src/service/active-tickets.d.ts +4 -0
  309. package/dist/src/service/active-tickets.js +49 -0
  310. package/dist/src/service/command-effects.d.ts +4 -0
  311. package/dist/src/service/command-effects.js +16 -0
  312. package/dist/src/service/decision-handler.d.ts +4 -0
  313. package/dist/src/service/decision-handler.js +39 -4
  314. package/dist/src/service/gateway.js +18 -3
  315. package/dist/src/service/registry.d.ts +16 -3
  316. package/dist/src/service/registry.js +34 -3
  317. package/dist/src/service/replies.d.ts +9 -1
  318. package/dist/src/service/replies.js +12 -0
  319. package/dist/src/service/run-handlers.js +14 -55
  320. package/dist/src/service/run-metadata.d.ts +8 -0
  321. package/dist/src/service/run-metadata.js +53 -0
  322. package/dist/src/service/run-waits.d.ts +3 -0
  323. package/dist/src/service/run-waits.js +41 -0
  324. package/dist/src/service/service.d.ts +18 -2
  325. package/dist/src/service/service.js +23 -7
  326. package/dist/src/service/submission-handler.d.ts +0 -1
  327. package/dist/src/service/submission-handler.js +6 -34
  328. package/dist/src/service/worker-port.d.ts +1 -0
  329. package/dist/src/service/worker-totals.js +8 -23
  330. package/dist/src/step-bridge.d.ts +23 -0
  331. package/dist/src/steps/decision-gate.d.ts +2 -1
  332. package/dist/src/steps/decision-gate.js +7 -0
  333. package/dist/src/steps/merge-by-person.d.ts +2 -0
  334. package/dist/src/steps/merge-by-person.js +18 -0
  335. package/dist/src/steps/merge-when-green.d.ts +2 -0
  336. package/dist/src/steps/merge-when-green.js +62 -0
  337. package/dist/src/steps/review-by-agent.d.ts +5 -0
  338. package/dist/src/steps/review-by-agent.js +124 -0
  339. package/dist/src/steps/review-by-person.d.ts +4 -0
  340. package/dist/src/steps/review-by-person.js +16 -0
  341. package/dist/src/steps/review-subject.d.ts +2 -0
  342. package/dist/src/steps/review-subject.js +11 -0
  343. package/dist/src/steps/run-command.d.ts +2 -0
  344. package/dist/src/steps/run-command.js +15 -0
  345. package/dist/src/steps/sleep.d.ts +3 -0
  346. package/dist/src/steps/sleep.js +19 -0
  347. package/dist/src/steps/wait-for-decision.d.ts +2 -0
  348. package/dist/src/steps/wait-for-decision.js +71 -0
  349. package/dist/src/steps/wait-for-run.d.ts +5 -0
  350. package/dist/src/steps/wait-for-run.js +9 -0
  351. package/dist/src/storage/decision-snapshots.d.ts +1 -0
  352. package/dist/src/storage/decision-snapshots.js +7 -1
  353. package/dist/src/submission.d.ts +4 -0
  354. package/dist/src/submission.js +6 -2
  355. package/dist/src/testing.d.ts +29 -0
  356. package/dist/src/testing.js +264 -0
  357. package/dist/src/ticket-status-stream.d.ts +9 -0
  358. package/dist/src/ticket-status-stream.js +94 -0
  359. package/dist/src/token-prices.d.ts +12 -4
  360. package/dist/src/token-prices.js +15 -2
  361. package/dist/src/turn-profile.d.ts +1 -0
  362. package/dist/src/turn-profile.js +8 -1
  363. package/dist/src/worker-usage.d.ts +16 -0
  364. package/dist/src/worker-usage.js +57 -0
  365. package/dist/src/workflow-admission.d.ts +5 -0
  366. package/dist/src/workflow-candidate.d.ts +7 -2
  367. package/dist/src/workflow-candidate.js +47 -5
  368. package/dist/src/workflow-declaration.d.ts +21 -3
  369. package/dist/src/workflow-declaration.js +77 -9
  370. package/dist/src/workflow-discovery.d.ts +2 -1
  371. package/dist/src/workflow-discovery.js +4 -1
  372. package/dist/src/workflow-refusals.js +3 -0
  373. package/dist/src/workflow-schedule.d.ts +22 -0
  374. package/dist/src/workflow-schedule.js +53 -0
  375. package/dist/src/workflows.d.ts +11 -1
  376. package/dist/src/workflows.js +8 -0
  377. package/dist/tools/admit-workflow.d.ts +1 -0
  378. package/dist/tools/admit-workflow.js +18 -5
  379. package/dist/tools/doctor-adoption.d.ts +1 -0
  380. package/dist/tools/doctor-adoption.js +11 -0
  381. package/dist/tools/project-configuration.d.ts +4 -0
  382. package/dist/tools/project-configuration.js +47 -0
  383. package/dist/tools/self-host-processes.d.ts +1 -0
  384. package/dist/tools/self-host-processes.js +33 -22
  385. package/dist/tools/self-host-project.d.ts +4 -0
  386. package/dist/tools/self-host-project.js +61 -14
  387. package/dist/tools/self-host-runtime.d.ts +16 -0
  388. package/dist/tools/self-host-runtime.js +60 -0
  389. package/dist/tools/self-host-workflows.d.ts +1 -0
  390. package/dist/tools/self-host-workflows.js +36 -1
  391. package/dist/tools/self-host.js +86 -61
  392. package/dist/tools/workflow-candidate-counts.d.ts +6 -2
  393. package/dist/tools/workflow-candidate-counts.js +31 -16
  394. package/dist/tools/workflow-candidate-fields.d.ts +5 -0
  395. package/dist/tools/workflow-candidate-fields.js +24 -0
  396. package/dist/tools/workflow-candidate-helper-counts.d.ts +10 -0
  397. package/dist/tools/workflow-candidate-helper-counts.js +129 -0
  398. package/dist/tools/workflow-candidate-program.d.ts +2 -0
  399. package/dist/tools/workflow-candidate-program.js +36 -8
  400. package/dist/tools/workflow-candidate-source.js +77 -15
  401. package/dist/tools/workflow-candidate-syntax.d.ts +8 -2
  402. package/dist/tools/workflow-candidate-syntax.js +70 -26
  403. package/dist/tools/workflow-command.d.ts +1 -0
  404. package/dist/tools/workflow-command.js +143 -0
  405. package/dist/tools/workflow-folder-capture.d.ts +1 -0
  406. package/dist/tools/workflow-folder-capture.js +47 -2
  407. package/dist/tools/workflow-folders.d.ts +17 -1
  408. package/dist/tools/workflow-folders.js +59 -6
  409. package/dist/tools/workflow-test-hook.d.ts +7 -0
  410. package/dist/tools/workflow-test-hook.js +16 -0
  411. package/dist/tools/workflow-test-loader.d.ts +1 -0
  412. package/dist/tools/workflow-test-loader.js +10 -0
  413. package/dist/workflows/develop-ticket.js +1 -1
  414. package/dist/workflows/ticket-prompts.js +5 -1
  415. package/package.json +46 -4
  416. package/templates/develop/README.md +78 -0
  417. package/templates/develop/develop/accept.ts +11 -0
  418. package/templates/develop/develop/flow-tests.ts +357 -0
  419. package/templates/develop/develop/local.ts +40 -0
  420. package/templates/develop/develop/option-tests.ts +174 -0
  421. package/templates/develop/develop/partial-choice.ts +29 -0
  422. package/templates/develop/develop/partial.ts +28 -0
  423. package/templates/develop/develop/pull.ts +152 -0
  424. package/templates/develop/develop/queue-partial.ts +39 -0
  425. package/templates/develop/develop/refusal-tests.ts +174 -0
  426. package/templates/develop/develop/report.ts +156 -0
  427. package/templates/develop/develop/round.ts +40 -0
  428. package/templates/develop/develop/scenarios.ts +87 -0
  429. package/templates/develop/develop/turn.ts +67 -0
  430. package/templates/develop/develop.declaration.json +24 -0
  431. package/templates/develop/develop.test.ts +287 -0
  432. package/templates/develop/develop.ts +30 -0
  433. package/templates/develop/template.json +153 -0
  434. package/dist/src/chats/analysis-batches.d.ts +0 -42
  435. package/dist/src/chats/analysis-batches.js +0 -97
  436. package/dist/src/chats/analysis-checkpoint.d.ts +0 -29
  437. package/dist/src/chats/analysis-checkpoint.js +0 -31
  438. package/dist/src/chats/analysis-contract.d.ts +0 -80
  439. package/dist/src/chats/analysis-contract.js +0 -16
  440. package/dist/src/chats/analysis-data.d.ts +0 -3
  441. package/dist/src/chats/analysis-data.js +0 -85
  442. package/dist/src/chats/analysis-input.d.ts +0 -18
  443. package/dist/src/chats/analysis-input.js +0 -97
  444. package/dist/src/chats/analysis-links.d.ts +0 -2
  445. package/dist/src/chats/analysis-links.js +0 -25
  446. package/dist/src/chats/analysis-merge.d.ts +0 -16
  447. package/dist/src/chats/analysis-merge.js +0 -134
  448. package/dist/src/chats/analysis-prompt.d.ts +0 -18
  449. package/dist/src/chats/analysis-prompt.js +0 -42
  450. package/dist/src/chats/analysis-proposal.d.ts +0 -4
  451. package/dist/src/chats/analysis-proposal.js +0 -41
  452. package/dist/src/chats/analysis-provenance.d.ts +0 -4
  453. package/dist/src/chats/analysis-provenance.js +0 -99
  454. package/dist/src/chats/analysis-shape.d.ts +0 -4
  455. package/dist/src/chats/analysis-shape.js +0 -235
  456. package/dist/src/chats/analysis.d.ts +0 -3
  457. package/dist/src/chats/analysis.js +0 -42
  458. package/dist/src/chats/corpus-input.d.ts +0 -5
  459. package/dist/src/chats/corpus-input.js +0 -288
  460. package/dist/src/chats/destination.d.ts +0 -4
  461. package/dist/src/chats/destination.js +0 -96
  462. package/dist/src/chats/import.d.ts +0 -15
  463. package/dist/src/chats/import.js +0 -243
  464. package/dist/src/chats/input-file.d.ts +0 -3
  465. package/dist/src/chats/input-file.js +0 -32
  466. package/dist/src/chats/normalize.d.ts +0 -29
  467. package/dist/src/chats/normalize.js +0 -155
  468. package/dist/src/chats/previous-import.d.ts +0 -5
  469. package/dist/src/chats/previous-import.js +0 -34
  470. package/dist/src/chats/reader.d.ts +0 -21
  471. package/dist/src/chats/reader.js +0 -118
  472. package/dist/src/chats/redact-import.d.ts +0 -14
  473. package/dist/src/chats/redact-import.js +0 -141
  474. package/dist/src/chats/redaction.d.ts +0 -41
  475. package/dist/src/chats/redaction.js +0 -161
  476. package/dist/src/chats/reference-mapping.d.ts +0 -16
  477. package/dist/src/chats/reference-mapping.js +0 -153
  478. package/dist/src/chats/revision-input.d.ts +0 -3
  479. package/dist/src/chats/revision-input.js +0 -180
  480. package/dist/src/chats/revision.d.ts +0 -48
  481. package/dist/src/chats/revision.js +0 -94
  482. package/dist/src/chats/selection.d.ts +0 -25
  483. package/dist/src/chats/selection.js +0 -109
  484. package/dist/src/chats/source.d.ts +0 -23
  485. package/dist/src/chats/source.js +0 -135
  486. package/dist/src/chats/structure.d.ts +0 -57
  487. package/dist/src/chats/structure.js +0 -216
  488. package/dist/src/chats/workflow-generation-projection.d.ts +0 -8
  489. package/dist/src/chats/workflow-generation-projection.js +0 -75
  490. package/dist/src/chats/workflow-generation-source.d.ts +0 -25
  491. package/dist/src/chats/workflow-generation-source.js +0 -124
  492. package/dist/src/chats/workflow-generation-text.d.ts +0 -23
  493. package/dist/src/chats/workflow-generation-text.js +0 -74
  494. package/dist/src/chats/workflow-generation.d.ts +0 -69
  495. package/dist/src/chats/workflow-generation.js +0 -142
  496. package/dist/src/daemon/analysis-launch.d.ts +0 -5
  497. package/dist/src/daemon/analysis-launch.js +0 -81
  498. package/dist/src/daemon/analysis-token.d.ts +0 -6
  499. package/dist/src/daemon/analysis-token.js +0 -88
  500. package/dist/src/daemon/analysis-worker.d.ts +0 -20
  501. package/dist/src/daemon/analysis-worker.js +0 -271
  502. package/dist/src/daemon/chats-batch-binding.d.ts +0 -23
  503. package/dist/src/daemon/chats-batch-binding.js +0 -99
  504. package/dist/src/daemon/chats-capture.d.ts +0 -18
  505. package/dist/src/daemon/chats-capture.js +0 -194
  506. package/dist/src/daemon/chats-checkpoints.d.ts +0 -41
  507. package/dist/src/daemon/chats-checkpoints.js +0 -186
  508. package/dist/src/daemon/chats-files.d.ts +0 -42
  509. package/dist/src/daemon/chats-files.js +0 -252
  510. package/dist/src/daemon/chats-follow-up.d.ts +0 -38
  511. package/dist/src/daemon/chats-follow-up.js +0 -180
  512. package/dist/src/daemon/chats-question.d.ts +0 -15
  513. package/dist/src/daemon/chats-question.js +0 -93
  514. package/dist/src/daemon/chats-worker.d.ts +0 -13
  515. package/dist/src/daemon/chats-worker.js +0 -201
  516. package/dist/workflows/analyze-chats.d.ts +0 -15
  517. package/dist/workflows/analyze-chats.declaration.json +0 -22
  518. package/dist/workflows/analyze-chats.js +0 -250
@@ -0,0 +1,35 @@
1
+ interface RunIntent {
2
+ readonly runId: string;
3
+ readonly gateId?: string;
4
+ readonly decision?: string;
5
+ readonly answer?: string | null;
6
+ }
7
+ interface ResumeParts {
8
+ readonly runs: () => Promise<readonly {
9
+ readonly operationId: string | null;
10
+ readonly receipt: string;
11
+ }[]>;
12
+ readonly document: (digest: string) => Promise<string | undefined>;
13
+ }
14
+ export declare function reconciledDecision(parts: ResumeParts, intent: RunIntent): Promise<{
15
+ readonly kind: "accepted";
16
+ readonly receipt: string;
17
+ } | {
18
+ readonly kind: "absent";
19
+ }>;
20
+ export declare function deliveredDecision(parts: ResumeParts, request: {
21
+ readonly intent: RunIntent;
22
+ readonly signal: AbortSignal | undefined;
23
+ }): Promise<{
24
+ readonly receipt: string;
25
+ }>;
26
+ export declare function stoppedDecision(parts: ResumeParts & {
27
+ readonly cancel: (receipt: string) => Promise<string>;
28
+ }, intent: RunIntent): Promise<{
29
+ readonly kind: "stopped";
30
+ readonly receipt: string;
31
+ } | {
32
+ readonly kind: "unknown";
33
+ readonly evidence: string;
34
+ }>;
35
+ export {};
@@ -0,0 +1,86 @@
1
+ import { resumeHook } from "workflow/api";
2
+ import { getWorld } from "workflow/runtime";
3
+ import { setTimeout as delay } from "node:timers/promises";
4
+ import { decisionToken } from "../decision-wait.js";
5
+ import { namesRunIntent } from "../authority/operations.js";
6
+ async function runSubject(receipt, token) {
7
+ const world = await getWorld();
8
+ let page = await world.events.list({
9
+ runId: receipt,
10
+ resolveData: "none",
11
+ pagination: { limit: 1000, sortOrder: "asc" },
12
+ });
13
+ const events = [...page.data];
14
+ while (page.hasMore && page.cursor !== null) {
15
+ page = await world.events.list({
16
+ runId: receipt,
17
+ resolveData: "none",
18
+ pagination: { limit: 1000, sortOrder: "asc", cursor: page.cursor },
19
+ });
20
+ events.push(...page.data);
21
+ }
22
+ const created = events.find((event) => event.eventType === "hook_created" && event.eventData.token === token);
23
+ const hookId = created?.correlationId;
24
+ return {
25
+ runId: receipt,
26
+ token,
27
+ hookId,
28
+ received: hookId !== undefined &&
29
+ events.some((event) => event.eventType === "hook_received" && event.correlationId === hookId),
30
+ };
31
+ }
32
+ async function subject(parts, intent) {
33
+ if (intent.gateId === undefined)
34
+ throw new Error("missing-decision-gate");
35
+ const token = decisionToken(intent.runId, intent.gateId);
36
+ const runs = (await parts.runs()).filter((run) => namesRunIntent(run.operationId ?? "", intent.runId));
37
+ const latest = runs.at(-1);
38
+ if (latest === undefined)
39
+ throw new Error("missing-decision-run");
40
+ const matches = [];
41
+ for (const run of runs) {
42
+ const found = await runSubject(run.receipt, token);
43
+ if (found.hookId !== undefined)
44
+ matches.push(found);
45
+ }
46
+ if (matches.length > 1)
47
+ throw new Error("conflicting-decision-hooks");
48
+ return (matches[0] ?? {
49
+ runId: latest.receipt,
50
+ token,
51
+ hookId: undefined,
52
+ received: false,
53
+ });
54
+ }
55
+ export async function reconciledDecision(parts, intent) {
56
+ const found = await subject(parts, intent);
57
+ return found.received
58
+ ? { kind: "accepted", receipt: found.runId }
59
+ : { kind: "absent" };
60
+ }
61
+ export async function deliveredDecision(parts, request) {
62
+ const { intent, signal } = request;
63
+ let found = await subject(parts, intent);
64
+ while (!found.received && found.hookId === undefined) {
65
+ await delay(20, undefined, signal === undefined ? {} : { signal });
66
+ found = await subject(parts, intent);
67
+ }
68
+ if (found.received)
69
+ return { receipt: found.runId };
70
+ if (intent.decision === undefined)
71
+ throw new Error("missing-decision");
72
+ const answer = intent.answer === undefined || intent.answer === null
73
+ ? null
74
+ : await parts.document(intent.answer);
75
+ if (answer === undefined)
76
+ throw new Error("missing-decision-answer");
77
+ await resumeHook(found.token, { decision: intent.decision, answer });
78
+ return { receipt: found.runId };
79
+ }
80
+ export async function stoppedDecision(parts, intent) {
81
+ const found = await subject(parts, intent);
82
+ const status = await parts.cancel(found.runId);
83
+ return ["cancelled", "completed", "failed"].includes(status)
84
+ ? { kind: "stopped", receipt: found.runId }
85
+ : { kind: "unknown", evidence: `world-run:${found.runId} ${status}` };
86
+ }
@@ -0,0 +1,48 @@
1
+ import type { DecisionWait, GateRequest, GateResult } from "../step-bridge.ts";
2
+ export interface GateReceipt {
3
+ readonly kind: string;
4
+ readonly reason?: string;
5
+ }
6
+ export interface GateOpening {
7
+ readonly waitMode?: "hook";
8
+ readonly runId: string;
9
+ readonly commandId: string;
10
+ readonly expectedRevision: number;
11
+ readonly gateId: string;
12
+ readonly kind: "question" | "approval";
13
+ readonly prompt: string;
14
+ readonly subject: string;
15
+ readonly expiresAt?: string;
16
+ }
17
+ export interface WaitRegistration {
18
+ readonly runId: string;
19
+ readonly commandId: string;
20
+ readonly gateId: string;
21
+ }
22
+ interface GatePorts {
23
+ readonly stopped: AbortSignal;
24
+ readonly timing?: {
25
+ readonly pollMilliseconds: number;
26
+ readonly retryMilliseconds: number;
27
+ };
28
+ readonly state: () => Promise<{
29
+ readonly runs: Readonly<Record<string, {
30
+ readonly revision: number;
31
+ } | undefined>>;
32
+ readonly gates: Readonly<Record<string, unknown>>;
33
+ }>;
34
+ readonly openGate: (opening: GateOpening) => Promise<GateReceipt>;
35
+ readonly registerWait: (wait: WaitRegistration) => Promise<GateReceipt>;
36
+ }
37
+ interface GateSubject {
38
+ readonly waitMode?: "hook";
39
+ readonly runId: string;
40
+ readonly transport: string;
41
+ readonly request: GateRequest;
42
+ }
43
+ export declare function openBridgeGate(ports: GatePorts, subject: GateSubject): Promise<GateResult>;
44
+ export declare function waitForBridgeDecision(ports: GatePorts & {
45
+ readonly document: (digest: string) => Promise<string | undefined>;
46
+ readonly decisionReceived: (runId: string, gateId: string) => Promise<boolean>;
47
+ }, subject: GateSubject): Promise<DecisionWait>;
48
+ export {};
@@ -0,0 +1,124 @@
1
+ import { createHash } from "node:crypto";
2
+ import { setTimeout as delay } from "node:timers/promises";
3
+ import { gateKey } from "../authority/gates.js";
4
+ import { decisionToken } from "../decision-wait.js";
5
+ import { record } from "../protocol.js";
6
+ const committed = ["accepted", "duplicate"];
7
+ function promptDigest(request) {
8
+ return `sha256:${createHash("sha256").update(request.prompt).digest("hex")}`;
9
+ }
10
+ function sameHookSubject(value, request) {
11
+ const gate = record(value);
12
+ return (gate?.["subject"] === promptDigest(request) &&
13
+ gate["kind"] === request.kind &&
14
+ gate["wait"] === "hook");
15
+ }
16
+ async function paused(hold, milliseconds) {
17
+ await delay(milliseconds, undefined, { signal: hold.ports.stopped }).catch(() => undefined);
18
+ if (hold.ports.stopped.aborted)
19
+ await new Promise(() => undefined);
20
+ }
21
+ function verdict(hold, receipt) {
22
+ if (receipt === undefined || receipt.kind === "failed")
23
+ return hold.timing.retryMilliseconds;
24
+ if (committed.includes(receipt.kind))
25
+ return "committed";
26
+ if (receipt.reason === "service-busy")
27
+ return hold.timing.retryMilliseconds;
28
+ if (receipt.reason === "stale-revision")
29
+ return hold.timing.pollMilliseconds;
30
+ return { kind: "refused", reason: receipt.reason ?? receipt.kind };
31
+ }
32
+ async function gateCommand(hold, send) {
33
+ for (;;) {
34
+ await paused(hold, 0);
35
+ const result = verdict(hold, await send().catch(() => undefined));
36
+ if (result === "committed")
37
+ return undefined;
38
+ if (typeof result !== "number")
39
+ return result;
40
+ await paused(hold, result);
41
+ }
42
+ }
43
+ async function opening(hold, subject) {
44
+ const { runId, transport, request } = subject;
45
+ const { gateId, kind, prompt } = request;
46
+ const state = await hold.ports.state();
47
+ const run = state.runs[runId];
48
+ if (run === undefined)
49
+ return { kind: "rejected", reason: "unknown-run" };
50
+ const key = gateKey(runId, gateId);
51
+ const exists = Object.hasOwn(state.gates, key);
52
+ if (exists &&
53
+ subject.waitMode === "hook" &&
54
+ !sameHookSubject(state.gates[key], request))
55
+ return { kind: "rejected", reason: "gate-subject-changed" };
56
+ if (exists)
57
+ return { kind: "duplicate" };
58
+ return await hold.ports.openGate({
59
+ ...(subject.waitMode === undefined ? {} : { waitMode: subject.waitMode }),
60
+ runId,
61
+ commandId: `${transport}:open:${gateId}`,
62
+ expectedRevision: run.revision,
63
+ gateId,
64
+ kind,
65
+ prompt,
66
+ subject: promptDigest(request),
67
+ ...(request.expiresAt === undefined
68
+ ? {}
69
+ : { expiresAt: request.expiresAt }),
70
+ });
71
+ }
72
+ export async function openBridgeGate(ports, subject) {
73
+ const hold = {
74
+ ports,
75
+ timing: ports.timing ?? { pollMilliseconds: 20, retryMilliseconds: 1000 },
76
+ };
77
+ const refusal = await gateCommand(hold, () => opening(hold, subject));
78
+ if (refusal !== undefined)
79
+ return refusal;
80
+ if (subject.waitMode === "hook")
81
+ return {
82
+ kind: "opened",
83
+ decisionId: decisionToken(subject.runId, subject.request.gateId),
84
+ };
85
+ const waited = await gateCommand(hold, () => ports.registerWait({
86
+ runId: subject.runId,
87
+ commandId: `${subject.transport}:wait:${subject.request.gateId}`,
88
+ gateId: subject.request.gateId,
89
+ }));
90
+ return waited ?? { kind: "opened", decisionId: subject.request.gateId };
91
+ }
92
+ export async function waitForBridgeDecision(ports, subject) {
93
+ const hold = {
94
+ ports,
95
+ timing: ports.timing ?? { pollMilliseconds: 20, retryMilliseconds: 1000 },
96
+ };
97
+ await paused(hold, 0);
98
+ const state = await ports.state();
99
+ const key = gateKey(subject.runId, subject.request.gateId);
100
+ const gate = state.gates[key];
101
+ if (Object.hasOwn(state.gates, key) &&
102
+ !sameHookSubject(gate, subject.request))
103
+ throw new Error("gate-subject-changed");
104
+ const outcome = record(record(gate)?.["outcome"]);
105
+ if (outcome !== undefined &&
106
+ (await ports.decisionReceived(subject.runId, subject.request.gateId)))
107
+ return await storedDecision(ports, outcome);
108
+ const opening = await openBridgeGate(ports, { ...subject, waitMode: "hook" });
109
+ if (opening.kind !== "opened")
110
+ throw new Error(opening.reason);
111
+ return { token: opening.decisionId };
112
+ }
113
+ async function storedDecision(ports, outcome) {
114
+ const decision = ["approved", "denied", "answered", "expired"].find((value) => value === outcome["decision"]);
115
+ if (decision === undefined)
116
+ throw new Error("invalid-decision-outcome");
117
+ const digest = outcome["answer"];
118
+ if (digest !== null && typeof digest !== "string")
119
+ throw new Error("invalid-decision-answer");
120
+ const answer = digest === null ? null : await ports.document(digest);
121
+ if (answer === undefined)
122
+ throw new Error("missing-decision-answer");
123
+ return { decision, answer };
124
+ }
@@ -0,0 +1,26 @@
1
+ import { type RunWaitTarget } from "../run-wait.ts";
2
+ import type { RunWaitOutcome, RunWaitRequest } from "../step-bridge.ts";
3
+ export interface RunWaitPorts {
4
+ readonly now?: () => number;
5
+ readonly target: (runId: string) => Promise<RunWaitTarget | undefined>;
6
+ readonly observe: (report: {
7
+ readonly runId: string;
8
+ readonly commandId: string;
9
+ readonly condition: string;
10
+ readonly reason: string;
11
+ readonly evidence?: string;
12
+ readonly retryAt?: string;
13
+ readonly operationId?: string;
14
+ }) => Promise<{
15
+ readonly kind: string;
16
+ readonly reason?: string;
17
+ }>;
18
+ }
19
+ export declare function runWait(ports: RunWaitPorts, wait: {
20
+ readonly caller: {
21
+ readonly runId: string;
22
+ readonly stepId: string;
23
+ readonly startedAt: number;
24
+ };
25
+ readonly request: RunWaitRequest;
26
+ }): Promise<RunWaitOutcome>;
@@ -0,0 +1,37 @@
1
+ import { FatalError, RetryableError } from "workflow";
2
+ import { runWaitResult } from "../run-wait.js";
3
+ export async function runWait(ports, wait) {
4
+ const { caller, request } = wait;
5
+ const now = (ports.now ?? Date.now)();
6
+ const result = runWaitResult(request, {
7
+ callerRunId: caller.runId,
8
+ startedAt: caller.startedAt,
9
+ now,
10
+ target: await ports.target(request.runId),
11
+ });
12
+ const waiting = result.kind === "waiting";
13
+ const receipt = await ports.observe({
14
+ runId: caller.runId,
15
+ commandId: `${caller.stepId}:run-wait:${waiting ? "waiting" : "ended"}`,
16
+ condition: waiting ? "waiting-run" : "working",
17
+ reason: waiting ? "awaiting-run" : "in-progress",
18
+ operationId: caller.stepId,
19
+ ...(result.kind !== "waiting"
20
+ ? {}
21
+ : {
22
+ evidence: request.runId,
23
+ retryAt: new Date(result.deadline).toISOString(),
24
+ }),
25
+ });
26
+ if (!["accepted", "duplicate"].includes(receipt.kind))
27
+ throw new RetryableError("run-wait-observation-unavailable", {
28
+ retryAfter: 1000,
29
+ });
30
+ if (result.kind === "refused")
31
+ throw new FatalError(result.reason);
32
+ if (result.kind === "completed")
33
+ return result.outcome;
34
+ throw new RetryableError("awaiting-run", {
35
+ retryAfter: Math.max(1, Math.min(1000, result.deadline - now)),
36
+ });
37
+ }
@@ -33,7 +33,7 @@ export interface StartParts {
33
33
  }
34
34
  export interface StartDelivery {
35
35
  readonly reconcile: (intent: RunIntent) => Promise<RunOutcome>;
36
- readonly deliver: (intent: RunIntent) => Promise<{
36
+ readonly deliver: (intent: RunIntent, signal?: AbortSignal) => Promise<{
37
37
  readonly receipt: string;
38
38
  }>;
39
39
  readonly stop: (intent: RunIntent) => Promise<RunOutcome>;
@@ -1,5 +1,6 @@
1
1
  import { start } from "workflow/api";
2
2
  import { operationTag, runTag } from "./world-runs.js";
3
+ import { deliveredDecision, reconciledDecision, stoppedDecision, } from "./decision-resume.js";
3
4
  const ends = ["cancelled", "completed", "failed"];
4
5
  async function segments(parts, intent) {
5
6
  return (await parts.runs()).filter((run) => run.operationId === intent.operationId);
@@ -61,8 +62,14 @@ async function stopped(parts, intent) {
61
62
  }
62
63
  export function startDelivery(parts) {
63
64
  return {
64
- reconcile: (intent) => reconciled(parts, intent),
65
- deliver: (intent) => delivered(parts, intent),
66
- stop: (intent) => stopped(parts, intent),
65
+ reconcile: (intent) => intent.kind === "resume-hook"
66
+ ? reconciledDecision(parts, intent)
67
+ : reconciled(parts, intent),
68
+ deliver: (intent, signal) => intent.kind === "resume-hook"
69
+ ? deliveredDecision(parts, { intent, signal })
70
+ : delivered(parts, intent),
71
+ stop: (intent) => intent.kind === "resume-hook"
72
+ ? stoppedDecision(parts, intent)
73
+ : stopped(parts, intent),
67
74
  };
68
75
  }
@@ -1,8 +1,12 @@
1
+ import { type GateOpening, type GateReceipt, type WaitRegistration } from "./gate-bridge.ts";
2
+ export type { GateOpening, GateReceipt, WaitRegistration, } from "./gate-bridge.ts";
3
+ import { type RunWaitPorts } from "./run-wait.ts";
1
4
  import { type ProtectedRequest, type StepBridge } from "../step-bridge.ts";
2
5
  export interface StepCall {
3
6
  readonly worldRunId: string;
4
7
  readonly stepId: string;
5
8
  readonly attempt: number;
9
+ readonly startedAt?: number;
6
10
  }
7
11
  export declare function sdkStepCall(): StepCall;
8
12
  export interface OperationRead {
@@ -30,25 +34,6 @@ interface BridgeIdentity {
30
34
  export interface BridgeRequest extends ProtectedRequest, BridgeIdentity {
31
35
  readonly runId: string;
32
36
  }
33
- export interface GateReceipt {
34
- readonly kind: string;
35
- readonly reason?: string;
36
- }
37
- export interface GateOpening {
38
- readonly runId: string;
39
- readonly commandId: string;
40
- readonly expectedRevision: number;
41
- readonly gateId: string;
42
- readonly kind: "question" | "approval";
43
- readonly prompt: string;
44
- readonly subject: string;
45
- readonly expiresAt?: string;
46
- }
47
- export interface WaitRegistration {
48
- readonly runId: string;
49
- readonly commandId: string;
50
- readonly gateId: string;
51
- }
52
37
  export interface BridgeTiming {
53
38
  readonly lookupTries: number;
54
39
  readonly pollMilliseconds: number;
@@ -56,6 +41,8 @@ export interface BridgeTiming {
56
41
  }
57
42
  export declare const bridgeTiming: BridgeTiming;
58
43
  export interface BridgePorts {
44
+ readonly decisionReceived?: (runId: string, gateId: string) => Promise<boolean>;
45
+ readonly runWait?: RunWaitPorts;
59
46
  readonly call: () => StepCall;
60
47
  readonly run: (worldRunId: string) => Promise<{
61
48
  readonly runId: string;
@@ -77,4 +64,3 @@ export interface BridgePorts {
77
64
  }
78
65
  export declare function stepBridge(ports: BridgePorts): StepBridge;
79
66
  export declare function registerStepBridge(bridge: StepBridge): () => void;
80
- export {};
@@ -1,11 +1,19 @@
1
1
  import { createHash } from "node:crypto";
2
2
  import { setTimeout as delay } from "node:timers/promises";
3
3
  import { getStepMetadata, getWorkflowMetadata } from "workflow";
4
- import { gateKey } from "../authority/gates.js";
4
+ import { openBridgeGate, waitForBridgeDecision, } from "./gate-bridge.js";
5
+ import { runWait } from "./run-wait.js";
6
+ import { reconciledDecision } from "./decision-resume.js";
7
+ import { taggedRuns } from "./world-runs.js";
5
8
  import { stepBridgeKey, } from "../step-bridge.js";
6
9
  export function sdkStepCall() {
7
- const { stepId, attempt } = getStepMetadata();
8
- return { worldRunId: getWorkflowMetadata().workflowRunId, stepId, attempt };
10
+ const { stepId, attempt, stepStartedAt } = getStepMetadata();
11
+ return {
12
+ worldRunId: getWorkflowMetadata().workflowRunId,
13
+ stepId,
14
+ attempt,
15
+ startedAt: stepStartedAt.getTime(),
16
+ };
9
17
  }
10
18
  export const bridgeTiming = {
11
19
  lookupTries: 250,
@@ -129,74 +137,52 @@ async function effect(hold, request) {
129
137
  return answer;
130
138
  return await settled(hold, answer.operationId);
131
139
  }
132
- function verdict(hold, receipt) {
133
- if (receipt === undefined || receipt.kind === "failed")
134
- return hold.timing.retryMilliseconds;
135
- if (committed.includes(receipt.kind))
136
- return "committed";
137
- if (receipt.reason === "service-busy")
138
- return hold.timing.retryMilliseconds;
139
- if (receipt.reason === "stale-revision")
140
- return hold.timing.pollMilliseconds;
141
- return { kind: "refused", reason: receipt.reason ?? receipt.kind };
142
- }
143
- async function gateCommand(hold, send) {
144
- for (;;) {
145
- await paused(hold, 0);
146
- const result = verdict(hold, await send().catch(() => undefined));
147
- if (result === "committed")
148
- return undefined;
149
- if (typeof result !== "number")
150
- return result;
151
- await paused(hold, result);
152
- }
153
- }
154
- async function opening(hold, subject) {
155
- const { runId, transport, request } = subject;
156
- const { gateId, kind, prompt } = request;
157
- const state = await hold.ports.state();
158
- const run = state.runs[runId];
159
- if (run === undefined)
160
- return { kind: "rejected", reason: "unknown-run" };
161
- if (Object.hasOwn(state.gates, gateKey(runId, gateId)))
162
- return { kind: "duplicate" };
163
- return await hold.ports.openGate({
164
- runId,
165
- commandId: `${transport}:open:${gateId}`,
166
- expectedRevision: run.revision,
167
- gateId,
168
- kind,
169
- prompt,
170
- subject: `sha256:${createHash("sha256").update(prompt).digest("hex")}`,
171
- ...(request.expiresAt === undefined
172
- ? {}
173
- : { expiresAt: request.expiresAt }),
174
- });
175
- }
176
- async function gate(hold, request) {
140
+ async function gateSubject(hold, request) {
177
141
  const call = hold.ports.call();
178
142
  const world = await located(hold, call.worldRunId);
179
143
  if (world === undefined)
180
- return { kind: "unavailable", reason: "unknown-world-run" };
144
+ return undefined;
181
145
  await inWork(hold, world.runId);
182
- const subject = {
146
+ return {
147
+ request,
183
148
  runId: world.runId,
184
149
  transport: transportOf(call),
185
- request,
186
150
  };
187
- const refusal = (await gateCommand(hold, () => opening(hold, subject))) ??
188
- (await gateCommand(hold, () => hold.ports.registerWait({
189
- runId: subject.runId,
190
- commandId: `${subject.transport}:wait:${request.gateId}`,
191
- gateId: request.gateId,
192
- })));
193
- return refusal ?? { kind: "opened", decisionId: request.gateId };
151
+ }
152
+ async function gate(hold, request) {
153
+ const subject = await gateSubject(hold, request);
154
+ if (subject === undefined)
155
+ return { kind: "unavailable", reason: "unknown-world-run" };
156
+ return await openBridgeGate(hold.ports, subject);
194
157
  }
195
158
  export function stepBridge(ports) {
196
159
  const hold = { ports, timing: ports.timing ?? bridgeTiming };
197
160
  return {
198
161
  effect: (request) => effect(hold, request),
199
162
  gate: (request) => gate(hold, request),
163
+ waitForDecision: async (request) => {
164
+ const subject = await gateSubject(hold, request);
165
+ if (subject === undefined)
166
+ throw new Error("unknown-world-run");
167
+ return await waitForBridgeDecision({
168
+ ...ports,
169
+ decisionReceived: ports.decisionReceived ??
170
+ (async (runId, gateId) => (await reconciledDecision({ runs: taggedRuns, document: ports.document }, { runId, gateId })).kind === "accepted"),
171
+ }, subject);
172
+ },
173
+ waitForRun: async (request) => {
174
+ const call = ports.call();
175
+ const world = await located(hold, call.worldRunId);
176
+ if (world === undefined ||
177
+ ports.runWait === undefined ||
178
+ call.startedAt === undefined)
179
+ throw new Error("cloving-host-unavailable");
180
+ await inWork(hold, world.runId);
181
+ return await runWait(ports.runWait, {
182
+ caller: { ...world, stepId: call.stepId, startedAt: call.startedAt },
183
+ request,
184
+ });
185
+ },
200
186
  handoff: (request) => effect(hold, {
201
187
  scope: {
202
188
  phase: "handoff",
@@ -0,0 +1,19 @@
1
+ export interface PullRequest {
2
+ readonly number: number;
3
+ readonly url: string;
4
+ readonly commit: string;
5
+ readonly target: string;
6
+ }
7
+ export type MergeCheckName = "beforeMerge";
8
+ export interface MergeRequest {
9
+ readonly pull: PullRequest;
10
+ readonly check: MergeCheckName | null;
11
+ readonly round?: number;
12
+ }
13
+ export type MergeReason = "check-failed" | "merge-conflict" | "ci-failed" | "ci-pending" | "check-not-configured" | "not-approved";
14
+ export interface MergeResult {
15
+ readonly merged: boolean;
16
+ readonly reason: MergeReason | null;
17
+ readonly output: string;
18
+ }
19
+ export declare function mergeRequest(value: unknown): Required<MergeRequest>;
@@ -0,0 +1,32 @@
1
+ import { record } from "./protocol.js";
2
+ import { commitId } from "./review-subject.js";
3
+ export function mergeRequest(value) {
4
+ const request = record(value);
5
+ const pull = pullRequest(request?.["pull"]);
6
+ const check = request?.["check"];
7
+ if (request === undefined ||
8
+ pull === undefined ||
9
+ !Object.hasOwn(request, "check") ||
10
+ (check !== null && check !== "beforeMerge"))
11
+ throw new Error("invalid-merge-request");
12
+ return { pull, check, round: mergeRound(request["round"] ?? 1) };
13
+ }
14
+ function mergeRound(value) {
15
+ if (!positiveInteger(value))
16
+ throw new Error("invalid-merge-request");
17
+ return value;
18
+ }
19
+ function pullRequest(value) {
20
+ const pull = record(value);
21
+ const { number, url, commit, target } = pull ?? {};
22
+ if (!positiveInteger(number) ||
23
+ typeof url !== "string" ||
24
+ !commitId(commit) ||
25
+ typeof target !== "string" ||
26
+ target.trim() === "")
27
+ return undefined;
28
+ return { number, url, commit, target };
29
+ }
30
+ function positiveInteger(value) {
31
+ return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
32
+ }
@@ -0,0 +1 @@
1
+ export declare function canonicalJson(value: unknown): string;
@@ -0,0 +1,16 @@
1
+ export function canonicalJson(value) {
2
+ if (value === null || typeof value === "boolean" || typeof value === "string")
3
+ return JSON.stringify(value);
4
+ if (typeof value === "number" && !Number.isSafeInteger(value))
5
+ throw new Error("canonical-json-number: Only safe integers are allowed.");
6
+ if (typeof value === "number")
7
+ return String(value);
8
+ if (Array.isArray(value))
9
+ return `[${value.map(canonicalJson).join(",")}]`;
10
+ if (typeof value !== "object")
11
+ throw new Error("canonical-json-value: The value is not JSON.");
12
+ const fields = Object.keys(value)
13
+ .sort()
14
+ .map((key) => `${JSON.stringify(key)}:${canonicalJson(Reflect.get(value, key))}`);
15
+ return `{${fields.join(",")}}`;
16
+ }
@@ -0,0 +1,7 @@
1
+ export interface PhoneLink {
2
+ readonly daemonId: string;
3
+ readonly origin: string;
4
+ readonly token: string;
5
+ readonly registeredAt: string;
6
+ }
7
+ export declare function parsePhoneLink(text: string | undefined): PhoneLink | undefined;