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
@@ -1,7 +1,17 @@
1
1
  export { loadCycle, type CycleLoad } from "./steps/load-cycle.ts";
2
2
  export { protectedEffect } from "./steps/protected-effect.ts";
3
3
  export { decisionGate } from "./steps/decision-gate.ts";
4
+ export { waitForDecision } from "./steps/wait-for-decision.ts";
5
+ export { reviewByPerson } from "./steps/review-by-person.ts";
6
+ export { reviewByAgent } from "./steps/review-by-agent.ts";
7
+ export { mergeByPerson } from "./steps/merge-by-person.ts";
8
+ export { mergeWhenGreen } from "./steps/merge-when-green.ts";
9
+ export type { ReviewSubject, CommitReviewSubject, DraftReviewSubject, ReviewResult, Reviewer, } from "./review-subject.ts";
10
+ export type { MergeCheckName, MergeReason, MergeRequest, MergeResult, PullRequest, } from "./merge-request.ts";
4
11
  export { handoff } from "./steps/handoff.ts";
5
- export type { GateRequest, GateResult, HandoffRequest, HandoffValue, ProtectedRequest, ProtectedResult, ProtectedScope, } from "./step-bridge.ts";
12
+ export { waitForRun } from "./steps/wait-for-run.ts";
13
+ export { runCommand } from "./steps/run-command.ts";
14
+ export { sleep } from "./steps/sleep.ts";
15
+ export type { CommandRequest, GateRequest, GateResult, DecisionResult, HandoffRequest, HandoffValue, RunWaitRequest, RunWaitOutcome, ProtectedRequest, ProtectedResult, ProtectedScope, } from "./step-bridge.ts";
6
16
  export type { CycleOutcome, DevelopmentInput } from "./workflow-contracts.ts";
7
17
  export { ticketStatus, type TicketStatus } from "./ticket-status.ts";
@@ -1,5 +1,13 @@
1
1
  export { loadCycle } from "./steps/load-cycle.js";
2
2
  export { protectedEffect } from "./steps/protected-effect.js";
3
3
  export { decisionGate } from "./steps/decision-gate.js";
4
+ export { waitForDecision } from "./steps/wait-for-decision.js";
5
+ export { reviewByPerson } from "./steps/review-by-person.js";
6
+ export { reviewByAgent } from "./steps/review-by-agent.js";
7
+ export { mergeByPerson } from "./steps/merge-by-person.js";
8
+ export { mergeWhenGreen } from "./steps/merge-when-green.js";
4
9
  export { handoff } from "./steps/handoff.js";
10
+ export { waitForRun } from "./steps/wait-for-run.js";
11
+ export { runCommand } from "./steps/run-command.js";
12
+ export { sleep } from "./steps/sleep.js";
5
13
  export { ticketStatus } from "./ticket-status.js";
@@ -10,4 +10,5 @@ export type WorkflowCandidateAdmission = {
10
10
  export declare function admitWorkflowCandidate(input: {
11
11
  readonly source: string;
12
12
  readonly declaration: unknown;
13
+ readonly helpers?: Readonly<Record<string, string>>;
13
14
  }, installed?: CandidatePackageOptions): Promise<WorkflowCandidateAdmission>;
@@ -5,30 +5,34 @@ import { tmpdir } from "node:os";
5
5
  import { findPackageJSON } from "node:module";
6
6
  import { dirname, extname, join, resolve } from "node:path";
7
7
  import { fileURLToPath } from "node:url";
8
- import { checkWorkflowCandidate, } from "../src/workflow-candidate.js";
8
+ import { checkWorkflowCandidate, candidateDeclarationRefusals, workflowHelperPath, } from "../src/workflow-candidate.js";
9
9
  import { candidatePackageRoot, } from "./workflow-candidate-program.js";
10
10
  import { analyzeWorkflowCandidate } from "./workflow-candidate-source.js";
11
11
  import { isWorkflowManifest } from "./workflow-manifest.js";
12
12
  export async function admitWorkflowCandidate(input, installed = {}) {
13
13
  const { source, declaration } = input;
14
+ const refusal = candidateDeclarationRefusals(declaration);
15
+ if (refusal.length > 0)
16
+ return { kind: "refused", codes: refusal };
14
17
  if (Buffer.from(source, "utf8").toString("utf8") !== source)
15
18
  return { kind: "refused", codes: ["unsupported-source"] };
16
19
  try {
17
20
  const packageRoot = resolve(installed.packageRoot ?? candidatePackageRoot);
18
- const facts = analyzeWorkflowCandidate(source, { packageRoot });
21
+ const helpers = input.helpers ?? {};
22
+ const facts = analyzeWorkflowCandidate(source, { packageRoot, helpers });
19
23
  const codes = checkWorkflowCandidate({ declaration, ...facts });
20
24
  if (codes.length > 0)
21
25
  return { kind: "refused", codes };
22
- return await compiledCandidate(source, packageRoot);
26
+ return await compiledCandidate({ source, helpers, packageRoot });
23
27
  }
24
28
  catch {
25
29
  return { kind: "refused", codes: ["compile-failed"] };
26
30
  }
27
31
  }
28
- async function compiledCandidate(source, packageRoot) {
32
+ async function compiledCandidate(input) {
29
33
  const directory = await realpath(await mkdtemp(join(tmpdir(), "cloving-candidate-")));
30
34
  try {
31
- await prepareCandidateProject(directory, { source, packageRoot });
35
+ await prepareCandidateProject(directory, input);
32
36
  if (!(await compile(directory)))
33
37
  return { kind: "refused", codes: ["compile-failed"] };
34
38
  const artifactDirectory = join(directory, "artifacts");
@@ -37,6 +41,8 @@ async function compiledCandidate(source, packageRoot) {
37
41
  Object.values(manifest.workflows ?? {}).flatMap((entries) => Object.values(entries)).length !== 1)
38
42
  return { kind: "refused", codes: ["compile-failed"] };
39
43
  const digest = createHash("sha256");
44
+ for (const [name, content] of Object.entries(input.helpers).sort(([left], [right]) => (left < right ? -1 : Number(left > right))))
45
+ digest.update(JSON.stringify([name, content]));
40
46
  for (const name of [
41
47
  "manifest.json",
42
48
  "flow.mjs",
@@ -73,6 +79,13 @@ async function prepareCandidateProject(directory, input) {
73
79
  include: ["workflows/candidate.ts"],
74
80
  }));
75
81
  await writeFile(join(directory, "workflows/candidate.ts"), source, "utf8");
82
+ for (const [name, content] of Object.entries(input.helpers)) {
83
+ if (workflowHelperPath("candidate.ts", `./${name}`) !== name)
84
+ throw new Error("invalid-workflow-helper");
85
+ const path = join(directory, "workflows", name);
86
+ await mkdir(dirname(path), { recursive: true });
87
+ await writeFile(path, content, "utf8");
88
+ }
76
89
  }
77
90
  function compile(directory) {
78
91
  const extension = extname(fileURLToPath(import.meta.url));
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ import { selectRuntimeDirectory } from "./self-host-runtime.js";
2
+ const [runtime, repository, legacyRuntime, adoptionRecord] = process.argv.slice(2);
3
+ if (runtime === undefined || repository === undefined)
4
+ process.exitCode = 1;
5
+ else
6
+ process.stdout.write(JSON.stringify(await selectRuntimeDirectory({
7
+ runtime,
8
+ repository,
9
+ legacyRuntime,
10
+ adoptionRecord,
11
+ })) + "\n");
@@ -0,0 +1,4 @@
1
+ import { resolveSettings } from "../src/project-settings.ts";
2
+ export declare function topLevel(given: string): string;
3
+ export declare function projectRoot(given: string): Promise<string>;
4
+ export declare function projectConfiguration(repository: string, environment: Readonly<NodeJS.ProcessEnv>): Promise<ReturnType<typeof resolveSettings>>;
@@ -0,0 +1,47 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { createHash } from "node:crypto";
3
+ import { readFile, realpath } from "node:fs/promises";
4
+ import { homedir } from "node:os";
5
+ import { basename, join, resolve } from "node:path";
6
+ import { configurationRoot, resolveSettings } from "../src/project-settings.js";
7
+ import { repositoryFileName } from "../src/repository-identity.js";
8
+ async function settingsFile(file) {
9
+ try {
10
+ return await readFile(file.path, "utf8");
11
+ }
12
+ catch (error) {
13
+ if (error instanceof Error && "code" in error && error.code === "ENOENT")
14
+ return undefined;
15
+ throw new Error(`unreadable-config-file: ${file.scope}`, { cause: error });
16
+ }
17
+ }
18
+ export function topLevel(given) {
19
+ try {
20
+ return execFileSync("git", ["-C", given, "rev-parse", "--show-toplevel"], {
21
+ encoding: "utf8",
22
+ stdio: ["ignore", "pipe", "ignore"],
23
+ }).trim();
24
+ }
25
+ catch {
26
+ return given;
27
+ }
28
+ }
29
+ export function projectRoot(given) {
30
+ return realpath(topLevel(resolve(given)));
31
+ }
32
+ export async function projectConfiguration(repository, environment) {
33
+ const projectName = repositoryFileName({
34
+ name: basename(repository),
35
+ sha256: createHash("sha256").update(repository).digest("hex"),
36
+ });
37
+ return resolveSettings(environment, {
38
+ project: await settingsFile({
39
+ path: join(repository, ".cloving/config.json"),
40
+ scope: "project",
41
+ }),
42
+ private: await settingsFile({
43
+ path: join(configurationRoot(environment, homedir()), "cloving/projects", `${projectName}.json`),
44
+ scope: "private",
45
+ }),
46
+ });
47
+ }
@@ -5,6 +5,7 @@ export interface HostProcesses {
5
5
  readonly directory: string;
6
6
  readonly repository: string;
7
7
  readonly watchPort: string;
8
+ readonly phoneRelay: string;
8
9
  readonly updateMilliseconds: number | undefined;
9
10
  }
10
11
  export declare function hostedPrograms(settings: HostProcesses): Promise<number>;
@@ -1,5 +1,6 @@
1
1
  import { execFile, spawn } from "node:child_process";
2
2
  import { addAbortListener } from "node:events";
3
+ import { rm } from "node:fs/promises";
3
4
  import { extname, join } from "node:path";
4
5
  import { setTimeout as delay } from "node:timers/promises";
5
6
  import { promisify } from "node:util";
@@ -21,7 +22,8 @@ function launched(argumentsList, settings) {
21
22
  }
22
23
  async function stopped(programs) {
23
24
  for (const program of programs)
24
- program.child.kill("SIGTERM");
25
+ if (!program.child.killed)
26
+ program.child.kill("SIGTERM");
25
27
  await Promise.all(programs.map((program) => program.ended));
26
28
  }
27
29
  function updatingGit(settings, stopping) {
@@ -51,8 +53,10 @@ function updatingGit(settings, stopping) {
51
53
  };
52
54
  }
53
55
  async function polled(settings, lifecycle) {
54
- if (settings.updateMilliseconds === undefined)
56
+ if (settings.updateMilliseconds === undefined) {
57
+ await rm(join(settings.directory, "pending-self-update"), { force: true });
55
58
  return;
59
+ }
56
60
  const cancelled = () => lifecycle.stopping.aborted;
57
61
  const updater = selfUpdater({
58
62
  directory: settings.directory,
@@ -87,33 +91,40 @@ async function polled(settings, lifecycle) {
87
91
  }
88
92
  return undefined;
89
93
  }
94
+ function productChild(settings, argumentsList) {
95
+ const [program, ...rest] = argumentsList;
96
+ return launched([
97
+ join(settings.product, `src/${program}${extname(import.meta.filename)}`),
98
+ ...rest,
99
+ ], {
100
+ directory: settings.product,
101
+ environment: {
102
+ ...process.env,
103
+ CLOVING_RUNTIME_DIR: settings.runtime,
104
+ CLOVING_WATCH_REPOSITORY: settings.repository,
105
+ },
106
+ });
107
+ }
90
108
  function hostedChildren(settings) {
91
109
  const daemon = launched([join(settings.project, "start.mjs")], {
92
110
  directory: settings.project,
93
111
  environment: process.env,
94
112
  });
95
- if (settings.watchPort === "off")
96
- return [daemon];
97
- return [
98
- daemon,
99
- launched([
100
- join(settings.product, `src/cli${extname(import.meta.filename)}`),
101
- "watch",
102
- "--port",
103
- settings.watchPort,
104
- ], {
105
- directory: settings.product,
106
- environment: {
107
- ...process.env,
108
- CLOVING_RUNTIME_DIR: settings.runtime,
109
- CLOVING_WATCH_REPOSITORY: settings.repository,
110
- },
111
- }),
112
- ];
113
+ const watch = settings.watchPort === "off"
114
+ ? []
115
+ : [
116
+ productChild(settings, [
117
+ "cli",
118
+ "watch",
119
+ "--port",
120
+ settings.watchPort,
121
+ ]),
122
+ ];
123
+ const relay = settings.phoneRelay === "off" ? [] : [productChild(settings, ["relay"])];
124
+ return { daemon, programs: [daemon, ...watch, ...relay] };
113
125
  }
114
126
  export async function hostedPrograms(settings) {
115
- const programs = hostedChildren(settings);
116
- const daemon = programs[0];
127
+ const { daemon, programs } = hostedChildren(settings);
117
128
  const stopping = new AbortController();
118
129
  let updating = false;
119
130
  const interrupt = () => {
@@ -1,14 +1,18 @@
1
1
  import { type DeclaredWorkflow } from "../src/workflow-declaration.ts";
2
2
  import type { WorkflowRefusal } from "../src/workflow-refusals.ts";
3
+ import { type WorkflowListing } from "./workflow-folders.ts";
3
4
  interface ProjectSettings {
4
5
  readonly product: string;
5
6
  readonly project: string;
6
7
  readonly repository: string;
7
8
  readonly home: string;
8
9
  readonly xdgConfigHome?: string | undefined;
10
+ readonly userFolder?: string | undefined;
9
11
  }
10
12
  export interface RegisteredWorkflows {
13
+ readonly workflows: readonly WorkflowListing[];
11
14
  readonly repository: string;
15
+ readonly bundleDigest: string;
12
16
  readonly manifests: Readonly<Record<string, string>>;
13
17
  readonly declarations: readonly DeclaredWorkflow[];
14
18
  readonly workflowRefusals: readonly WorkflowRefusal[];
@@ -22,8 +22,13 @@ async function initializeProject(settings) {
22
22
  await copyWorkflow(settings, file);
23
23
  const modules = join(project, "node_modules");
24
24
  await mkdir(join(modules, "cloving"), { recursive: true });
25
- for (const name of Object.keys(packageMetadata.dependencies)) {
26
- const location = findPackageJSON(name, join(product, "package.json"));
25
+ const dependencies = new Map(Object.keys(packageMetadata.dependencies).map((name) => [name, join(product, "package.json")]));
26
+ const sdk = findPackageJSON("workflow", join(product, "package.json"));
27
+ if (sdk === undefined)
28
+ throw new Error("missing-runtime-dependency: workflow");
29
+ dependencies.set("@workflow/core", sdk);
30
+ for (const [name, from] of dependencies) {
31
+ const location = findPackageJSON(name, from);
27
32
  if (location === undefined)
28
33
  throw new Error(`missing-runtime-dependency: ${name}`);
29
34
  await mkdir(dirname(join(modules, name)), { recursive: true });
@@ -95,11 +100,21 @@ async function stageCandidates(project, candidates) {
95
100
  candidate.baseName,
96
101
  candidate.source,
97
102
  candidate.declaration,
103
+ Object.entries(candidate.helpers).sort(([left], [right]) => left < right ? -1 : Number(left > right)),
98
104
  ]))
99
105
  .digest("hex");
100
- const file = join(directory, `${name}.ts`);
106
+ const root = Object.keys(candidate.helpers).length > 0
107
+ ? join(directory, name)
108
+ : directory;
109
+ await mkdir(root, { recursive: true, mode: 0o700 });
110
+ const file = join(root, `${name}.ts`);
101
111
  await writeFile(file, candidate.source);
102
- await writeFile(join(directory, `${name}.declaration.json`), candidate.declaration);
112
+ await writeFile(join(root, `${name}.declaration.json`), candidate.declaration);
113
+ for (const [path, source] of Object.entries(candidate.helpers)) {
114
+ const destination = join(root, path);
115
+ await mkdir(dirname(destination), { recursive: true, mode: 0o700 });
116
+ await writeFile(destination, source);
117
+ }
103
118
  staged.push({ candidate, file });
104
119
  }
105
120
  return staged;
@@ -132,6 +147,37 @@ async function copyWorkflow(settings, file) {
132
147
  if (declaration !== undefined)
133
148
  await writeFile(join(project, "workflows", sidecar), declaration);
134
149
  }
150
+ function bundledListings(input) {
151
+ const { product, files, manifests, declarations } = input;
152
+ const byFunction = new Map(declarations.map(({ functionName, ...declaration }) => [
153
+ functionName,
154
+ declaration,
155
+ ]));
156
+ return Object.entries(manifests).map(([functionName, manifest]) => {
157
+ const declaration = byFunction.get(functionName);
158
+ const file = files.find((file) => basename(file, extname(file)) === manifest.name);
159
+ return {
160
+ scope: "bundled",
161
+ workflowId: declaration?.workflowId ?? manifest.name,
162
+ file: join(product, "workflows", file ?? manifest.name),
163
+ admitted: true,
164
+ codes: [],
165
+ ...(declaration === undefined ? {} : { declaration }),
166
+ };
167
+ });
168
+ }
169
+ async function writeManifests(project, compiled) {
170
+ const manifests = {};
171
+ for (const [functionName, manifest] of Object.entries(compiled)) {
172
+ const path = join(project, `${manifest.name}.workflow.json`);
173
+ await writeFile(path, JSON.stringify(manifest));
174
+ Object.defineProperty(manifests, functionName, {
175
+ value: path,
176
+ enumerable: true,
177
+ });
178
+ }
179
+ return manifests;
180
+ }
135
181
  export async function preparedProject(settings) {
136
182
  const { product, project } = settings;
137
183
  const files = await initializeProject(settings);
@@ -149,27 +195,28 @@ export async function preparedProject(settings) {
149
195
  ...declarations,
150
196
  ...staged.map((candidate) => operatorDeclaration({ ...candidate, project }, compiled)),
151
197
  ];
152
- const manifests = {};
153
- for (const [functionName, manifest] of Object.entries(workflowManifests(compiled, combined))) {
154
- const path = join(project, `${manifest.name}.workflow.json`);
155
- await writeFile(path, JSON.stringify(manifest));
156
- Object.defineProperty(manifests, functionName, {
157
- value: path,
158
- enumerable: true,
159
- });
160
- }
198
+ const manifests = await writeManifests(project, workflowManifests(compiled, combined));
161
199
  await writeFile(join(project, "declarations.json"), JSON.stringify(combined));
162
200
  await writeFile(join(project, "dependencies.json"), await workflowBundleDependencies({
163
201
  product,
164
202
  packages: Object.keys(packageMetadata.dependencies),
165
203
  }));
166
- await retainWorkflowBundle({
204
+ const bundleDigest = await retainWorkflowBundle({
167
205
  project,
168
206
  repository: folders.repository,
169
207
  directory: join(dirname(project), "workflow-bundles"),
170
208
  });
209
+ const workflows = bundledListings({
210
+ product,
211
+ files,
212
+ manifests: bundled,
213
+ declarations,
214
+ });
215
+ workflows.push(...folders.workflows);
171
216
  return {
217
+ workflows,
172
218
  repository: folders.repository,
219
+ bundleDigest,
173
220
  manifests,
174
221
  declarations: combined,
175
222
  workflowRefusals: folders.refusals,
@@ -0,0 +1,16 @@
1
+ interface RuntimeSelection {
2
+ readonly runtime: string;
3
+ readonly repository: string;
4
+ readonly legacyRuntime: string | undefined;
5
+ readonly adoptionRecord: string | undefined;
6
+ }
7
+ export declare function selectRuntimeDirectory(input: RuntimeSelection): Promise<{
8
+ readonly runtime: string;
9
+ readonly note: string;
10
+ readonly adoptionRecord?: string;
11
+ }>;
12
+ export declare function adoptRuntimeDirectory(input: RuntimeSelection): Promise<{
13
+ readonly runtime: string;
14
+ readonly note: string;
15
+ }>;
16
+ export {};
@@ -0,0 +1,60 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { link, mkdir, readdir, rm, writeFile } from "node:fs/promises";
3
+ import { dirname, join } from "node:path";
4
+ import { readRetainedWorkflowBundle } from "./workflow-bundles.js";
5
+ export async function selectRuntimeDirectory(input) {
6
+ const { runtime, repository, legacyRuntime, adoptionRecord } = input;
7
+ if (legacyRuntime === undefined ||
8
+ adoptionRecord === undefined ||
9
+ runtime === legacyRuntime)
10
+ return { runtime, note: "" };
11
+ const directory = join(dirname(legacyRuntime), "workflow-bundles");
12
+ if (!(await belongsToRepository(directory, repository)))
13
+ return {
14
+ runtime,
15
+ note: `Legacy runtime ${legacyRuntime} was not adopted: retained bundles are absent, damaged or belong to another repository.`,
16
+ };
17
+ return { runtime: legacyRuntime, note: "", adoptionRecord };
18
+ }
19
+ export async function adoptRuntimeDirectory(input) {
20
+ const selected = await selectRuntimeDirectory(input);
21
+ const adoptionRecord = selected.adoptionRecord;
22
+ if (adoptionRecord === undefined)
23
+ return { runtime: selected.runtime, note: selected.note };
24
+ const { repository } = input;
25
+ const legacyRuntime = selected.runtime;
26
+ await mkdir(dirname(adoptionRecord), { recursive: true, mode: 0o700 });
27
+ const contents = JSON.stringify({
28
+ schemaVersion: 1,
29
+ repository,
30
+ runtimeDirectory: legacyRuntime,
31
+ });
32
+ const temporary = `${adoptionRecord}.${randomUUID()}.tmp`;
33
+ try {
34
+ await writeFile(temporary, contents, {
35
+ flag: "wx",
36
+ mode: 0o600,
37
+ flush: true,
38
+ });
39
+ await link(temporary, adoptionRecord);
40
+ }
41
+ finally {
42
+ await rm(temporary, { force: true });
43
+ }
44
+ return { runtime: legacyRuntime, note: "" };
45
+ }
46
+ async function belongsToRepository(directory, repository) {
47
+ try {
48
+ const ids = (await readdir(directory)).filter((id) => id !== ".history");
49
+ if (ids.length === 0)
50
+ return false;
51
+ for (const id of ids)
52
+ if ((await readRetainedWorkflowBundle({ directory, repository, id }))
53
+ .kind !== "available")
54
+ return false;
55
+ return true;
56
+ }
57
+ catch {
58
+ return false;
59
+ }
60
+ }
@@ -12,4 +12,5 @@ interface HostManifest {
12
12
  export declare function workflowFiles(directory: string): Promise<string[]>;
13
13
  export declare function workflowDeclarations(directory: string, manifests: Readonly<Record<string, HostManifest>>): Promise<readonly DeclaredWorkflow[]>;
14
14
  export declare function workflowManifests(compiled: WorkflowManifest, declarations?: readonly DeclaredWorkflow[]): Readonly<Record<string, HostManifest>>;
15
+ export declare function workflowBundleLoader(): string;
15
16
  export {};
@@ -6,7 +6,8 @@ export async function workflowFiles(directory) {
6
6
  return entries
7
7
  .filter((entry) => entry.isFile() &&
8
8
  /\.(?:ts|js)$/.test(entry.name) &&
9
- !entry.name.endsWith(".d.ts"))
9
+ !entry.name.endsWith(".d.ts") &&
10
+ !entry.name.endsWith(".test.ts"))
10
11
  .map((entry) => entry.name)
11
12
  .sort();
12
13
  }
@@ -76,3 +77,37 @@ export function workflowManifests(compiled, declarations = []) {
76
77
  });
77
78
  }));
78
79
  }
80
+ export function workflowBundleLoader() {
81
+ return `
82
+ import { AsyncLocalStorage } from "node:async_hooks";
83
+ import { pathToFileURL } from "node:url";
84
+ const bundleRegistries = new AsyncLocalStorage();
85
+ const registryKeys = ["@workflow/core//registeredSteps", "workflow-class-registry"].map(Symbol.for);
86
+ for (const key of registryKeys) {
87
+ let current = globalThis[key] ?? new Map();
88
+ Object.defineProperty(globalThis, key, {
89
+ configurable: true,
90
+ get: () => bundleRegistries.getStore()?.get(key) ?? current,
91
+ set: (value) => {
92
+ const scope = bundleRegistries.getStore();
93
+ if (scope === undefined) current = value;
94
+ else scope.set(key, value);
95
+ },
96
+ });
97
+ }
98
+ const loadedBundles = new Map();
99
+ const loadWorkflowBundle = (directory) => {
100
+ const known = loadedBundles.get(directory);
101
+ if (known !== undefined) return known;
102
+ const scope = new Map(registryKeys.map((key) => [key, new Map()]));
103
+ const loaded = bundleRegistries.run(scope, async () => {
104
+ const workflows = await import(pathToFileURL(directory + "/artifacts/client.mjs").href);
105
+ const { POST } = await import(pathToFileURL(directory + "/artifacts/flow.mjs").href);
106
+ if (typeof POST !== "function") throw new Error("pinned-workflow-unavailable");
107
+ return { workflows, handler: (request) => bundleRegistries.run(scope, () => POST(request)) };
108
+ });
109
+ loadedBundles.set(directory, loaded);
110
+ return loaded;
111
+ };
112
+ `;
113
+ }