cloving 1.3.0 → 1.4.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 (396) hide show
  1. package/README.md +235 -206
  2. package/dist/src/agent-harness-shell.d.ts +2 -1
  3. package/dist/src/agent-harness-shell.js +8 -5
  4. package/dist/src/authority/command-wait-checks.d.ts +8 -0
  5. package/dist/src/authority/command-wait-checks.js +88 -0
  6. package/dist/src/authority/command-wait-results.d.ts +15 -0
  7. package/dist/src/authority/command-wait-results.js +73 -0
  8. package/dist/src/authority/command-wait-view.d.ts +21 -0
  9. package/dist/src/authority/command-wait-view.js +34 -0
  10. package/dist/src/authority/command-waits.d.ts +39 -0
  11. package/dist/src/authority/command-waits.js +97 -0
  12. package/dist/src/authority/commands.js +22 -1
  13. package/dist/src/authority/dispatch-decision.d.ts +8 -0
  14. package/dist/src/authority/dispatch-decision.js +26 -1
  15. package/dist/src/authority/effect-requests.js +6 -3
  16. package/dist/src/authority/effect-results.js +4 -2
  17. package/dist/src/authority/history-state.d.ts +2 -0
  18. package/dist/src/authority/history-state.js +13 -1
  19. package/dist/src/authority/instants.d.ts +1 -0
  20. package/dist/src/authority/instants.js +21 -0
  21. package/dist/src/authority/reduction-state.d.ts +2 -0
  22. package/dist/src/authority/reduction-state.js +5 -0
  23. package/dist/src/authority/reduction.js +24 -0
  24. package/dist/src/authority/status-input.d.ts +2 -0
  25. package/dist/src/authority/status.d.ts +2 -0
  26. package/dist/src/authority/status.js +1 -0
  27. package/dist/src/authority/stop-sequence.d.ts +1 -0
  28. package/dist/src/authority/stop-sequence.js +2 -1
  29. package/dist/src/authority/transitions.d.ts +6 -4
  30. package/dist/src/authority/transitions.js +7 -0
  31. package/dist/src/broker/actor/authority-queries.d.ts +2 -1
  32. package/dist/src/broker/actor/authority-queries.js +14 -5
  33. package/dist/src/broker/actor/authority-receipts.js +1 -1
  34. package/dist/src/broker/actor/authority-settings.js +2 -2
  35. package/dist/src/broker/actor/authority-upgrades.d.ts +19 -2
  36. package/dist/src/broker/actor/authority-upgrades.js +7 -2
  37. package/dist/src/broker/actor/delivery-intents.js +2 -0
  38. package/dist/src/broker/actor/effect-delivery.d.ts +1 -1
  39. package/dist/src/broker/actor/effect-delivery.js +15 -2
  40. package/dist/src/broker/actor/effect-plan.js +11 -2
  41. package/dist/src/broker/actor/effect-queries.d.ts +4 -0
  42. package/dist/src/broker/actor/effect-queries.js +9 -1
  43. package/dist/src/broker/actor/effect-turn.js +2 -0
  44. package/dist/src/broker/actor/stop-plan.js +9 -3
  45. package/dist/src/broker/actor/stop-turn.d.ts +2 -0
  46. package/dist/src/broker/actor/stop-turn.js +24 -11
  47. package/dist/src/broker/actor/turn-draft.d.ts +1 -0
  48. package/dist/src/broker/actor/turn-draft.js +4 -0
  49. package/dist/src/broker/actor/turn-state.js +5 -1
  50. package/dist/src/broker/authority-admission.js +60 -0
  51. package/dist/src/broker/authority-restore.d.ts +2 -0
  52. package/dist/src/broker/authority-restore.js +35 -1
  53. package/dist/src/broker/command-wait-restore.d.ts +31 -0
  54. package/dist/src/broker/command-wait-restore.js +86 -0
  55. package/dist/src/broker/decision-restore.d.ts +1 -1
  56. package/dist/src/broker/decision-restore.js +1 -0
  57. package/dist/src/broker/effect-upgrade.d.ts +2 -0
  58. package/dist/src/broker/effect-upgrade.js +8 -2
  59. package/dist/src/cli/arguments.d.ts +13 -0
  60. package/dist/src/cli/arguments.js +42 -3
  61. package/dist/src/cli/chat-stores.d.ts +2 -0
  62. package/dist/src/cli/chat-stores.js +113 -0
  63. package/dist/src/cli/client.d.ts +4 -1
  64. package/dist/src/cli/client.js +9 -3
  65. package/dist/src/cli/command-requests.d.ts +17 -0
  66. package/dist/src/cli/command-requests.js +43 -0
  67. package/dist/src/cli/command-waits.d.ts +9 -0
  68. package/dist/src/cli/command-waits.js +51 -0
  69. package/dist/src/cli/commands.js +14 -41
  70. package/dist/src/cli/config-file.d.ts +2 -2
  71. package/dist/src/cli/config-file.js +4 -2
  72. package/dist/src/cli/doctor-workflows.d.ts +5 -2
  73. package/dist/src/cli/doctor-workflows.js +12 -7
  74. package/dist/src/cli/doctor.js +6 -9
  75. package/dist/src/cli/harness-probes.d.ts +2 -0
  76. package/dist/src/cli/harness-probes.js +1 -1
  77. package/dist/src/cli/harness-processes.d.ts +6 -0
  78. package/dist/src/cli/harness-processes.js +36 -0
  79. package/dist/src/cli/init-command.d.ts +9 -0
  80. package/dist/src/cli/init-command.js +52 -0
  81. package/dist/src/cli/init-prompt-command.d.ts +10 -0
  82. package/dist/src/cli/init-prompt-command.js +145 -0
  83. package/dist/src/cli/init-prompt.d.ts +35 -0
  84. package/dist/src/cli/init-prompt.js +74 -0
  85. package/dist/src/cli/init-selection.d.ts +13 -0
  86. package/dist/src/cli/init-selection.js +75 -0
  87. package/dist/src/cli/main.d.ts +2 -0
  88. package/dist/src/cli/main.js +37 -7
  89. package/dist/src/cli/mcp-server.d.ts +1 -0
  90. package/dist/src/cli/mcp-server.js +156 -0
  91. package/dist/src/cli/mcp-tools.d.ts +15 -0
  92. package/dist/src/cli/mcp-tools.js +80 -0
  93. package/dist/src/cli/render.d.ts +1 -1
  94. package/dist/src/cli/render.js +17 -30
  95. package/dist/src/cli/report-ci-jobs.d.ts +23 -0
  96. package/dist/src/cli/report-ci-jobs.js +103 -0
  97. package/dist/src/cli/report-ci-usage.d.ts +9 -0
  98. package/dist/src/cli/report-ci-usage.js +185 -0
  99. package/dist/src/cli/report-ci.d.ts +13 -0
  100. package/dist/src/cli/report-ci.js +74 -0
  101. package/dist/src/cli/report-closures.d.ts +6 -0
  102. package/dist/src/cli/report-closures.js +97 -0
  103. package/dist/src/cli/report-flow.d.ts +7 -0
  104. package/dist/src/cli/report-flow.js +122 -0
  105. package/dist/src/cli/report-github-reader.d.ts +29 -0
  106. package/dist/src/cli/report-github-reader.js +157 -0
  107. package/dist/src/cli/report-github.d.ts +15 -8
  108. package/dist/src/cli/report-github.js +131 -150
  109. package/dist/src/cli/report-operator.d.ts +3 -0
  110. package/dist/src/cli/report-operator.js +40 -0
  111. package/dist/src/cli/report-ready.d.ts +3 -0
  112. package/dist/src/cli/report-ready.js +96 -0
  113. package/dist/src/cli/report-text.d.ts +9 -0
  114. package/dist/src/cli/report-text.js +33 -0
  115. package/dist/src/cli/report.d.ts +1 -0
  116. package/dist/src/cli/report.js +104 -27
  117. package/dist/src/cli/runtime-arguments.d.ts +2 -1
  118. package/dist/src/cli/runtime-arguments.js +7 -2
  119. package/dist/src/cli/schedule-arguments.d.ts +14 -0
  120. package/dist/src/cli/schedule-arguments.js +26 -0
  121. package/dist/src/cli/schedule-render.d.ts +22 -0
  122. package/dist/src/cli/schedule-render.js +73 -0
  123. package/dist/src/cli/terminal-text.d.ts +3 -0
  124. package/dist/src/cli/terminal-text.js +28 -0
  125. package/dist/src/cli/usage-render.d.ts +1 -0
  126. package/dist/src/cli/usage-render.js +28 -1
  127. package/dist/src/cli/usage.d.ts +1 -1
  128. package/dist/src/cli/usage.js +50 -7
  129. package/dist/src/cli/watch-actions.js +2 -2
  130. package/dist/src/cli/watch-board-view.js +19 -2
  131. package/dist/src/cli/watch-board.d.ts +4 -2
  132. package/dist/src/cli/watch-board.js +53 -43
  133. package/dist/src/cli/watch-card-forms.d.ts +1 -1
  134. package/dist/src/cli/watch-card-forms.js +11 -10
  135. package/dist/src/cli/watch-client.d.ts +1 -1
  136. package/dist/src/cli/watch-client.js +2 -11
  137. package/dist/src/cli/watch-header-view.d.ts +0 -5
  138. package/dist/src/cli/watch-header-view.js +8 -20
  139. package/dist/src/cli/watch-model.d.ts +4 -1
  140. package/dist/src/cli/watch-model.js +17 -11
  141. package/dist/src/cli/watch-page.js +12 -14
  142. package/dist/src/cli/watch-phases.d.ts +12 -3
  143. package/dist/src/cli/watch-phases.js +68 -11
  144. package/dist/src/cli/watch-pr-board.js +1 -1
  145. package/dist/src/cli/watch-pr-command.d.ts +1 -0
  146. package/dist/src/cli/watch-pull-request.js +18 -8
  147. package/dist/src/cli/watch-reads.d.ts +2 -0
  148. package/dist/src/cli/watch-reads.js +17 -16
  149. package/dist/src/cli/watch-render.d.ts +14 -0
  150. package/dist/src/cli/watch-run-input.d.ts +0 -1
  151. package/dist/src/cli/watch-run-input.js +0 -13
  152. package/dist/src/cli/watch-server.js +6 -6
  153. package/dist/src/cli/watch-view.d.ts +0 -3
  154. package/dist/src/cli/watch-view.js +13 -13
  155. package/dist/src/cli.js +59 -5
  156. package/dist/src/command-wait.d.ts +4 -0
  157. package/dist/src/command-wait.js +45 -0
  158. package/dist/src/configuration-change.d.ts +7 -0
  159. package/dist/src/configuration-change.js +14 -0
  160. package/dist/src/configuration-schema.d.ts +9 -0
  161. package/dist/src/configuration-schema.js +6 -2
  162. package/dist/src/daemon/attachment-file.d.ts +6 -0
  163. package/dist/src/daemon/attachment-file.js +86 -0
  164. package/dist/src/daemon/attachments.d.ts +14 -0
  165. package/dist/src/daemon/attachments.js +17 -0
  166. package/dist/src/daemon/claude-recovery.d.ts +50 -0
  167. package/dist/src/daemon/claude-recovery.js +204 -0
  168. package/dist/src/daemon/claude-stream.d.ts +27 -0
  169. package/dist/src/daemon/claude-stream.js +63 -0
  170. package/dist/src/daemon/claude-turn.d.ts +11 -25
  171. package/dist/src/daemon/claude-turn.js +64 -81
  172. package/dist/src/daemon/claude-worker.d.ts +2 -1
  173. package/dist/src/daemon/claude-worker.js +124 -122
  174. package/dist/src/daemon/daemon-adapters.d.ts +2 -0
  175. package/dist/src/daemon/daemon-adapters.js +26 -2
  176. package/dist/src/daemon/daemon-loops.d.ts +3 -1
  177. package/dist/src/daemon/daemon-loops.js +3 -1
  178. package/dist/src/daemon/daemon.js +14 -6
  179. package/dist/src/daemon/github-attach.d.ts +2 -0
  180. package/dist/src/daemon/github-attach.js +149 -0
  181. package/dist/src/daemon/github-ci-filters.d.ts +6 -0
  182. package/dist/src/daemon/github-ci-filters.js +138 -0
  183. package/dist/src/daemon/github-ci-workflows.d.ts +10 -0
  184. package/dist/src/daemon/github-ci-workflows.js +148 -0
  185. package/dist/src/daemon/github-ci.js +22 -4
  186. package/dist/src/daemon/github-issue-methods.d.ts +2 -0
  187. package/dist/src/daemon/github-issue-methods.js +37 -2
  188. package/dist/src/daemon/github-merge-call.d.ts +2 -1
  189. package/dist/src/daemon/github-merge-call.js +10 -3
  190. package/dist/src/daemon/github-merge.js +52 -24
  191. package/dist/src/daemon/github-methods.js +12 -2
  192. package/dist/src/daemon/github-operation.d.ts +4 -0
  193. package/dist/src/daemon/github-operation.js +6 -0
  194. package/dist/src/daemon/github-worker.d.ts +4 -0
  195. package/dist/src/daemon/github-worker.js +6 -0
  196. package/dist/src/daemon/issue-queue.d.ts +1 -1
  197. package/dist/src/daemon/issue-queue.js +16 -11
  198. package/dist/src/daemon/notify-events.d.ts +6 -0
  199. package/dist/src/daemon/notify-events.js +84 -0
  200. package/dist/src/daemon/notify-journal.js +1 -1
  201. package/dist/src/daemon/notify-message.d.ts +4 -1
  202. package/dist/src/daemon/notify-message.js +36 -0
  203. package/dist/src/daemon/notify.d.ts +1 -1
  204. package/dist/src/daemon/notify.js +5 -77
  205. package/dist/src/daemon/operation-journal.d.ts +1 -0
  206. package/dist/src/daemon/queue-status.d.ts +9 -3
  207. package/dist/src/daemon/queue-status.js +17 -4
  208. package/dist/src/daemon/resume-index-lock.d.ts +13 -0
  209. package/dist/src/daemon/resume-index-lock.js +160 -0
  210. package/dist/src/daemon/resume-worktree.d.ts +7 -0
  211. package/dist/src/daemon/resume-worktree.js +29 -0
  212. package/dist/src/daemon/retrying-turn.d.ts +2 -12
  213. package/dist/src/daemon/retrying-turn.js +98 -172
  214. package/dist/src/daemon/schedule-control.d.ts +26 -0
  215. package/dist/src/daemon/schedule-control.js +110 -0
  216. package/dist/src/daemon/schedule-journal.d.ts +2 -15
  217. package/dist/src/daemon/schedule-journal.js +67 -4
  218. package/dist/src/daemon/ticket-registration.d.ts +2 -7
  219. package/dist/src/daemon/ticket-registration.js +15 -81
  220. package/dist/src/daemon/turn-attempt-journal.d.ts +38 -0
  221. package/dist/src/daemon/turn-attempt-journal.js +136 -0
  222. package/dist/src/daemon/turn-attempts.d.ts +47 -0
  223. package/dist/src/daemon/turn-attempts.js +166 -0
  224. package/dist/src/daemon/turn-report.d.ts +8 -1
  225. package/dist/src/daemon/turn-report.js +39 -0
  226. package/dist/src/daemon/work-tree.d.ts +9 -0
  227. package/dist/src/daemon/work-tree.js +20 -0
  228. package/dist/src/daemon/worker-profile.d.ts +8 -0
  229. package/dist/src/daemon/worker-profile.js +40 -0
  230. package/dist/src/daemon/workflow-schedules.d.ts +3 -0
  231. package/dist/src/daemon/workflow-schedules.js +98 -45
  232. package/dist/src/daemon/worktree-processes.d.ts +9 -0
  233. package/dist/src/daemon/worktree-processes.js +151 -0
  234. package/dist/src/doctor-report.d.ts +3 -5
  235. package/dist/src/doctor-report.js +6 -13
  236. package/dist/src/harness-start.d.ts +15 -0
  237. package/dist/src/harness-start.js +37 -0
  238. package/dist/src/host/command-wait.d.ts +38 -0
  239. package/dist/src/host/command-wait.js +115 -0
  240. package/dist/src/host/start-delivery.d.ts +5 -7
  241. package/dist/src/host/start-delivery.js +3 -15
  242. package/dist/src/host/step-bridge-host.d.ts +2 -0
  243. package/dist/src/host/step-bridge-host.js +21 -0
  244. package/dist/src/operation-identity.d.ts +1 -0
  245. package/dist/src/operation-identity.js +4 -0
  246. package/dist/src/private-config.schema.json +40 -0
  247. package/dist/src/project-config.schema.json +40 -0
  248. package/dist/src/project-settings.d.ts +2 -2
  249. package/dist/src/project-settings.js +3 -1
  250. package/dist/src/queue-spend.d.ts +4 -0
  251. package/dist/src/queue-spend.js +21 -0
  252. package/dist/src/relay/relay-service.d.ts +3 -0
  253. package/dist/src/relay/relay-service.js +5 -3
  254. package/dist/src/report-ci.d.ts +164 -0
  255. package/dist/src/report-ci.js +32 -0
  256. package/dist/src/report-effects.d.ts +15 -0
  257. package/dist/src/report-effects.js +212 -0
  258. package/dist/src/report-flow-types.d.ts +38 -0
  259. package/dist/src/report-flow-types.js +7 -0
  260. package/dist/src/report-flow.d.ts +43 -0
  261. package/dist/src/report-flow.js +193 -0
  262. package/dist/src/report-operator.d.ts +67 -0
  263. package/dist/src/report-operator.js +25 -0
  264. package/dist/src/report-quality.d.ts +221 -0
  265. package/dist/src/report-quality.js +94 -0
  266. package/dist/src/report-ready.d.ts +23 -0
  267. package/dist/src/report-ready.js +117 -0
  268. package/dist/src/report-statistics.d.ts +2 -1
  269. package/dist/src/report-statistics.js +40 -4
  270. package/dist/src/report.d.ts +588 -47
  271. package/dist/src/report.js +156 -41
  272. package/dist/src/schedule-progress.d.ts +33 -0
  273. package/dist/src/schedule-progress.js +45 -0
  274. package/dist/src/service/active-tickets.js +6 -6
  275. package/dist/src/service/command-waits.d.ts +34 -0
  276. package/dist/src/service/command-waits.js +86 -0
  277. package/dist/src/service/expiry.js +2 -0
  278. package/dist/src/service/gateway.js +3 -1
  279. package/dist/src/service/queue-spend.d.ts +6 -0
  280. package/dist/src/service/queue-spend.js +68 -0
  281. package/dist/src/service/replies.d.ts +8 -1
  282. package/dist/src/service/replies.js +11 -0
  283. package/dist/src/service/run-handlers.js +22 -2
  284. package/dist/src/service/run-metadata.d.ts +15 -1
  285. package/dist/src/service/run-metadata.js +93 -8
  286. package/dist/src/service/service.d.ts +4 -0
  287. package/dist/src/service/service.js +8 -8
  288. package/dist/src/service/submission-handler.js +18 -4
  289. package/dist/src/service/worker-port.js +9 -1
  290. package/dist/src/service/worker-totals.d.ts +2 -0
  291. package/dist/src/service/worker-totals.js +1 -1
  292. package/dist/src/step-bridge.d.ts +20 -0
  293. package/dist/src/steps/command-wait.d.ts +12 -0
  294. package/dist/src/steps/command-wait.js +26 -0
  295. package/dist/src/steps/open-decision-wait.d.ts +2 -0
  296. package/dist/src/steps/{decision-gate.js → open-decision-wait.js} +0 -7
  297. package/dist/src/steps/review-by-person.js +4 -1
  298. package/dist/src/steps/wait-for-command.d.ts +3 -0
  299. package/dist/src/steps/wait-for-command.js +17 -0
  300. package/dist/src/steps/wait-for-decision.js +1 -1
  301. package/dist/src/storage/command-wait-rows.d.ts +30 -0
  302. package/dist/src/storage/command-wait-rows.js +96 -0
  303. package/dist/src/storage/decision-snapshots.d.ts +8 -1
  304. package/dist/src/storage/decision-snapshots.js +15 -1
  305. package/dist/src/storage/domain-changes.d.ts +2 -0
  306. package/dist/src/storage/domain-changes.js +3 -0
  307. package/dist/src/storage/domain-schema.d.ts +13 -1
  308. package/dist/src/storage/domain-schema.js +31 -4
  309. package/dist/src/storage/effect-schema.d.ts +1 -0
  310. package/dist/src/storage/effect-schema.js +5 -0
  311. package/dist/src/testing-requests.d.ts +15 -0
  312. package/dist/src/testing-requests.js +93 -0
  313. package/dist/src/testing.d.ts +4 -10
  314. package/dist/src/testing.js +33 -86
  315. package/dist/src/worker-usage.d.ts +1 -0
  316. package/dist/src/worker-usage.js +3 -0
  317. package/dist/src/workflow-candidate.d.ts +1 -0
  318. package/dist/src/workflow-candidate.js +12 -1
  319. package/dist/src/workflow-contracts.d.ts +1 -0
  320. package/dist/src/workflow-contracts.js +9 -2
  321. package/dist/src/workflow-discovery.d.ts +2 -13
  322. package/dist/src/workflow-discovery.js +1 -13
  323. package/dist/src/workflow-refusals.js +0 -1
  324. package/dist/src/workflows.d.ts +1 -1
  325. package/dist/src/workflows.js +1 -1
  326. package/dist/tools/red-green-command.d.ts +1 -0
  327. package/dist/tools/red-green-command.js +174 -0
  328. package/dist/tools/red-green-process.d.ts +10 -0
  329. package/dist/tools/red-green-process.js +59 -0
  330. package/dist/tools/self-host-processes.d.ts +2 -0
  331. package/dist/tools/self-host-processes.js +32 -13
  332. package/dist/tools/self-host-project.js +13 -78
  333. package/dist/tools/self-host-runtime.js +1 -1
  334. package/dist/tools/self-host.js +42 -10
  335. package/dist/tools/template-command.d.ts +1 -0
  336. package/dist/tools/template-command.js +160 -0
  337. package/dist/tools/template-copy.d.ts +11 -0
  338. package/dist/tools/template-copy.js +130 -0
  339. package/dist/tools/template-files.d.ts +17 -0
  340. package/dist/tools/template-files.js +74 -0
  341. package/dist/tools/workflow-bundles.js +1 -0
  342. package/dist/tools/workflow-candidate-counts.js +2 -2
  343. package/dist/tools/workflow-candidate-shape.d.ts +3 -0
  344. package/dist/tools/workflow-candidate-shape.js +90 -0
  345. package/dist/tools/workflow-candidate-source.js +15 -1
  346. package/dist/tools/workflow-candidate-syntax.d.ts +2 -2
  347. package/dist/tools/workflow-candidate-syntax.js +24 -94
  348. package/dist/tools/workflow-command.js +1 -2
  349. package/dist/tools/workflow-folders.d.ts +2 -3
  350. package/dist/tools/workflow-folders.js +1 -1
  351. package/package.json +16 -8
  352. package/templates/develop/README.md +12 -0
  353. package/templates/develop/develop/flow-tests.ts +37 -0
  354. package/templates/develop/develop/pull.ts +5 -1
  355. package/templates/develop/develop/refusal-tests.ts +77 -0
  356. package/templates/develop/develop/turn.ts +2 -1
  357. package/templates/idea-to-issue/README.md +27 -0
  358. package/templates/idea-to-issue/idea-to-issue/effects.ts +52 -0
  359. package/templates/idea-to-issue/idea-to-issue/leave.ts +10 -0
  360. package/templates/idea-to-issue/idea-to-issue/next.ts +29 -0
  361. package/templates/idea-to-issue/idea-to-issue/post-person.ts +18 -0
  362. package/templates/idea-to-issue/idea-to-issue/post.ts +50 -0
  363. package/templates/idea-to-issue/idea-to-issue/queue.ts +27 -0
  364. package/templates/idea-to-issue/idea-to-issue/review.ts +42 -0
  365. package/templates/idea-to-issue/idea-to-issue/scenarios.ts +50 -0
  366. package/templates/idea-to-issue/idea-to-issue/turn.ts +40 -0
  367. package/templates/idea-to-issue/idea-to-issue.declaration.json +16 -0
  368. package/templates/idea-to-issue/idea-to-issue.test.ts +79 -0
  369. package/templates/idea-to-issue/idea-to-issue.ts +49 -0
  370. package/templates/idea-to-issue/template.json +81 -0
  371. package/templates/review-day/README.md +97 -0
  372. package/templates/review-day/review-day/critique.ts +58 -0
  373. package/templates/review-day/review-day/decision.ts +29 -0
  374. package/templates/review-day/review-day/facts.ts +69 -0
  375. package/templates/review-day/review-day/label.ts +29 -0
  376. package/templates/review-day/review-day/next.ts +28 -0
  377. package/templates/review-day/review-day/post.ts +27 -0
  378. package/templates/review-day/review-day/report.ts +98 -0
  379. package/templates/review-day/review-day/rules.ts +12 -0
  380. package/templates/review-day/review-day/scenarios.ts +76 -0
  381. package/templates/review-day/review-day/turn.ts +73 -0
  382. package/templates/review-day/review-day.declaration.json +16 -0
  383. package/templates/review-day/review-day.test.ts +362 -0
  384. package/templates/review-day/review-day.ts +37 -0
  385. package/templates/review-day/template.json +56 -0
  386. package/dist/src/cli/watch-start-view.d.ts +0 -18
  387. package/dist/src/cli/watch-start-view.js +0 -77
  388. package/dist/src/steps/decision-gate.d.ts +0 -3
  389. package/dist/workflows/develop-prd.d.ts +0 -7
  390. package/dist/workflows/develop-prd.js +0 -165
  391. package/dist/workflows/develop-ticket.d.ts +0 -9
  392. package/dist/workflows/develop-ticket.js +0 -207
  393. package/dist/workflows/issue-labels.d.ts +0 -16
  394. package/dist/workflows/issue-labels.js +0 -70
  395. package/dist/workflows/ticket-prompts.d.ts +0 -35
  396. package/dist/workflows/ticket-prompts.js +0 -147
@@ -43,7 +43,7 @@ const outcomes = {
43
43
  },
44
44
  handoff_requested: {
45
45
  keys: ["cycleId", "kind", "promotionId"],
46
- optional: ["ticketStatus", "issueUpdate", "reason"],
46
+ optional: ["ticketStatus", "issueUpdate", "reason", "report"],
47
47
  parse: (fields) => {
48
48
  const cycleId = textField(fields, {
49
49
  key: "cycleId",
@@ -58,6 +58,9 @@ const outcomes = {
58
58
  const ticketStatus = fields["ticketStatus"];
59
59
  const issueUpdate = fields["issueUpdate"];
60
60
  const reason = fields["reason"];
61
+ const report = fields["report"];
62
+ if (!validReport(report))
63
+ return null;
61
64
  if (issueUpdate !== undefined && issueUpdate !== "failed")
62
65
  return null;
63
66
  if (ticketStatus !== undefined && !isTicketStatus(ticketStatus))
@@ -68,11 +71,15 @@ const outcomes = {
68
71
  kind: "handoff_requested",
69
72
  cycleId,
70
73
  promotionId,
71
- ...Object.fromEntries(Object.entries({ issueUpdate, ticketStatus, reason }).filter(([, value]) => value !== undefined)),
74
+ ...Object.fromEntries(Object.entries({ issueUpdate, ticketStatus, reason, report }).filter(([, value]) => value !== undefined)),
72
75
  };
73
76
  },
74
77
  },
75
78
  };
79
+ function validReport(report) {
80
+ return (report === undefined ||
81
+ (typeof report === "string" && report.length > 0 && report.length <= 65536));
82
+ }
76
83
  export function validateDevelopmentInput(value) {
77
84
  const fields = exactFields(value, { required: ["cycleId"] });
78
85
  const cycleId = fields && textField(fields, { key: "cycleId", pattern: identifier });
@@ -1,19 +1,8 @@
1
- export interface WorkflowReservation {
2
- readonly baseName?: string;
3
- readonly workflowId?: string;
4
- readonly functionName?: string;
5
- }
6
1
  export interface WorkflowDiscoveryIdentity {
7
2
  readonly queue?: boolean;
8
3
  readonly baseName: string;
9
4
  readonly workflowId: string | undefined;
10
5
  readonly functionNames: readonly string[];
11
6
  }
12
- export type WorkflowConflictCode = "workflow-conflict" | "bundled-name-reserved" | "queue-workflow-conflict";
13
- export declare function workflowConflicts(candidates: readonly WorkflowDiscoveryIdentity[], bundled: readonly WorkflowReservation[]): readonly (readonly WorkflowConflictCode[])[];
14
- export declare const bundledWorkflowIds: {
15
- readonly ticket: "develop-ticket";
16
- readonly issue: "develop-issue";
17
- readonly prompt: "develop-prompt";
18
- readonly prd: "develop-prd";
19
- };
7
+ export type WorkflowConflictCode = "workflow-conflict" | "queue-workflow-conflict";
8
+ export declare function workflowConflicts(candidates: readonly WorkflowDiscoveryIdentity[]): readonly (readonly WorkflowConflictCode[])[];
@@ -5,32 +5,20 @@ function identityKeys(identity) {
5
5
  ...identity.functionNames.map((name) => `function:${name}`),
6
6
  ];
7
7
  }
8
- export function workflowConflicts(candidates, bundled) {
8
+ export function workflowConflicts(candidates) {
9
9
  const keys = candidates.map(identityKeys);
10
10
  const counts = new Map();
11
11
  for (const names of keys) {
12
12
  for (const name of new Set(names))
13
13
  counts.set(name, (counts.get(name) ?? 0) + 1);
14
14
  }
15
- const reserved = new Set(bundled.flatMap((entry) => identityKeys({
16
- ...entry,
17
- functionNames: entry.functionName === undefined ? [] : [entry.functionName],
18
- })));
19
15
  const queued = candidates.filter((candidate) => candidate.queue === true);
20
16
  return keys.map((names, index) => {
21
17
  const codes = [];
22
18
  if (queued.length > 1 && candidates[index]?.queue === true)
23
19
  codes.push("queue-workflow-conflict");
24
- if (names.some((name) => reserved.has(name)))
25
- codes.push("bundled-name-reserved");
26
20
  if (names.some((name) => (counts.get(name) ?? 0) > 1))
27
21
  codes.push("workflow-conflict");
28
22
  return codes;
29
23
  });
30
24
  }
31
- export const bundledWorkflowIds = {
32
- ticket: "develop-ticket",
33
- issue: "develop-issue",
34
- prompt: "develop-prompt",
35
- prd: "develop-prd",
36
- };
@@ -12,7 +12,6 @@ const refusalCodes = new Set([
12
12
  "effect-limit",
13
13
  "direct-effect",
14
14
  "workflow-conflict",
15
- "bundled-name-reserved",
16
15
  "unsafe-workflow-path",
17
16
  "workflow-read-failed",
18
17
  "workflow-source-changed",
@@ -1,6 +1,5 @@
1
1
  export { loadCycle, type CycleLoad } from "./steps/load-cycle.ts";
2
2
  export { protectedEffect } from "./steps/protected-effect.ts";
3
- export { decisionGate } from "./steps/decision-gate.ts";
4
3
  export { waitForDecision } from "./steps/wait-for-decision.ts";
5
4
  export { reviewByPerson } from "./steps/review-by-person.ts";
6
5
  export { reviewByAgent } from "./steps/review-by-agent.ts";
@@ -11,6 +10,7 @@ export type { MergeCheckName, MergeReason, MergeRequest, MergeResult, PullReques
11
10
  export { handoff } from "./steps/handoff.ts";
12
11
  export { waitForRun } from "./steps/wait-for-run.ts";
13
12
  export { runCommand } from "./steps/run-command.ts";
13
+ export { waitForCommand, type CommandWaitRequest, type CommandWaitOutcome, } from "./steps/wait-for-command.ts";
14
14
  export { sleep } from "./steps/sleep.ts";
15
15
  export type { CommandRequest, GateRequest, GateResult, DecisionResult, HandoffRequest, HandoffValue, RunWaitRequest, RunWaitOutcome, ProtectedRequest, ProtectedResult, ProtectedScope, } from "./step-bridge.ts";
16
16
  export type { CycleOutcome, DevelopmentInput } from "./workflow-contracts.ts";
@@ -1,6 +1,5 @@
1
1
  export { loadCycle } from "./steps/load-cycle.js";
2
2
  export { protectedEffect } from "./steps/protected-effect.js";
3
- export { decisionGate } from "./steps/decision-gate.js";
4
3
  export { waitForDecision } from "./steps/wait-for-decision.js";
5
4
  export { reviewByPerson } from "./steps/review-by-person.js";
6
5
  export { reviewByAgent } from "./steps/review-by-agent.js";
@@ -9,5 +8,6 @@ export { mergeWhenGreen } from "./steps/merge-when-green.js";
9
8
  export { handoff } from "./steps/handoff.js";
10
9
  export { waitForRun } from "./steps/wait-for-run.js";
11
10
  export { runCommand } from "./steps/run-command.js";
11
+ export { waitForCommand, } from "./steps/wait-for-command.js";
12
12
  export { sleep } from "./steps/sleep.js";
13
13
  export { ticketStatus } from "./ticket-status.js";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,174 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { mkdtempSync, rmSync } from "node:fs";
3
+ import { tmpdir } from "node:os";
4
+ import { join } from "node:path";
5
+ import { record } from "../src/protocol.js";
6
+ import { configuration } from "../src/configuration-schema.js";
7
+ import { parseCommandSeconds } from "../src/command-settings.js";
8
+ import { redGreenProcess } from "./red-green-process.js";
9
+ function git(argumentsList) {
10
+ return execFileSync("git", [...argumentsList], {
11
+ encoding: "utf8",
12
+ stdio: ["ignore", "pipe", "pipe"],
13
+ });
14
+ }
15
+ async function run(input) {
16
+ const temporary = mkdtempSync(join(tmpdir(), "cloving-red-green-"));
17
+ const tree = join(temporary, "tree");
18
+ try {
19
+ git(["worktree", "add", "--detach", tree, input.revision]);
20
+ if (input.revision !== input.head)
21
+ git([
22
+ "--literal-pathspecs",
23
+ "-C",
24
+ tree,
25
+ "restore",
26
+ "--source",
27
+ input.head,
28
+ "--worktree",
29
+ "--",
30
+ ...input.files,
31
+ ]);
32
+ const options = {
33
+ directory: tree,
34
+ signal: input.signal,
35
+ milliseconds: input.milliseconds,
36
+ };
37
+ const prepared = input.prepare === undefined
38
+ ? undefined
39
+ : await redGreenProcess(input.prepare, options);
40
+ if (prepared !== undefined && prepared.status !== 0)
41
+ return { ...prepared, prepareFailed: true };
42
+ const tested = await redGreenProcess([...input.test, ...input.files], options);
43
+ return tested;
44
+ }
45
+ finally {
46
+ git(["worktree", "remove", "--force", tree]);
47
+ rmSync(temporary, { recursive: true, force: true });
48
+ }
49
+ }
50
+ async function redGreenCommand(signal) {
51
+ if (process.argv.slice(2).includes("--help")) {
52
+ process.stdout.write('Usage: cloving red-green\n\nReads {"head":"<full commit ID>"} on standard input.\nCLOVING_RED_GREEN configures test, testFiles, prepare, assertionPattern and skipPattern.\nPrints one JSON verdict from temporary detached worktrees.\n');
53
+ return;
54
+ }
55
+ let text = "";
56
+ for await (const chunk of process.stdin)
57
+ text += String(chunk);
58
+ const head = inputHead(text);
59
+ const { settings, assertion, skip } = redGreenSettings();
60
+ const { test, testFiles: prefixes, prepare } = settings;
61
+ if (git(["cat-file", "-t", head]).trim() !== "commit")
62
+ throw new Error("invalid-red-green-input: head must be a full commit ID");
63
+ if (git(["rev-parse", "--verify", head]).trim() !== head.toLowerCase())
64
+ throw new Error("invalid-red-green-input: head must be a full commit ID");
65
+ const base = git(["merge-base", head, "refs/remotes/origin/HEAD"]).trim();
66
+ const files = changedTests({ base, head, prefixes });
67
+ if (files.length === 0) {
68
+ process.stdout.write(JSON.stringify({
69
+ verdict: "no-test-change",
70
+ base,
71
+ head,
72
+ files,
73
+ output: "",
74
+ }) + "\n");
75
+ return;
76
+ }
77
+ const milliseconds = parseCommandSeconds(process.env["CLOVING_COMMAND_SECONDS"]) * 1000;
78
+ const options = { head, files, test, prepare, signal, milliseconds };
79
+ const red = await run({ ...options, revision: base });
80
+ signal.throwIfAborted();
81
+ const green = await run({ ...options, revision: head });
82
+ signal.throwIfAborted();
83
+ const result = classify({ red, green, assertion, skip });
84
+ process.stdout.write(JSON.stringify({
85
+ ...result,
86
+ output: result.output.slice(-16000),
87
+ base,
88
+ head,
89
+ files,
90
+ }) + "\n");
91
+ }
92
+ function changedTests(input) {
93
+ return git([
94
+ "diff",
95
+ "--no-renames",
96
+ "--name-only",
97
+ "--diff-filter=AMT",
98
+ "-z",
99
+ input.base,
100
+ input.head,
101
+ ])
102
+ .split("\0")
103
+ .filter((file) => input.prefixes.some((prefix) => file.startsWith(prefix)));
104
+ }
105
+ function classify(input) {
106
+ const { red, green, assertion, skip } = input;
107
+ for (const result of [red, green])
108
+ if (result.prepareFailed === true)
109
+ return { verdict: "prepare-failed", output: result.output };
110
+ for (const result of [red, green])
111
+ if (skip.test(result.output))
112
+ return { verdict: "skipped-test", output: result.output };
113
+ if (red.status === 0)
114
+ return { verdict: "false-red", output: red.output };
115
+ if (red.status === null || !assertion.test(red.output))
116
+ return { verdict: "red-not-assertion", output: red.output };
117
+ if (green.status !== 0)
118
+ return { verdict: "green-failed", output: green.output };
119
+ return { verdict: "accepted", output: green.output };
120
+ }
121
+ function inputHead(text) {
122
+ let input;
123
+ try {
124
+ input = JSON.parse(text);
125
+ }
126
+ catch {
127
+ throw new Error("invalid-red-green-input: expected JSON with a full commit ID in head");
128
+ }
129
+ const head = record(input)?.["head"];
130
+ if (typeof head !== "string" ||
131
+ !/^(?:[a-fA-F0-9]{40}|[a-fA-F0-9]{64})$/.test(head))
132
+ throw new Error("invalid-red-green-input: head must be a full commit ID");
133
+ return head;
134
+ }
135
+ function redGreenSettings() {
136
+ try {
137
+ const value = JSON.parse(process.env["CLOVING_RED_GREEN"] ?? "null");
138
+ const settings = configuration({ version: 1, checks: { redGreen: value } }, "project").checks?.redGreen;
139
+ if (settings === undefined)
140
+ throw new Error("missing settings");
141
+ return {
142
+ settings,
143
+ assertion: new RegExp(settings.assertionPattern ?? "ERR_ASSERTION"),
144
+ skip: new RegExp(settings.skipPattern ?? "# SKIP\\b"),
145
+ };
146
+ }
147
+ catch (error) {
148
+ throw new Error("invalid-CLOVING_RED_GREEN: " +
149
+ (error instanceof Error ? error.message : String(error)), { cause: error });
150
+ }
151
+ }
152
+ const controller = new AbortController();
153
+ const interrupt = () => {
154
+ controller.abort();
155
+ };
156
+ process.on("disconnect", interrupt);
157
+ if (!process.connected)
158
+ interrupt();
159
+ process.on("SIGTERM", interrupt);
160
+ process.on("SIGINT", interrupt);
161
+ try {
162
+ await redGreenCommand(controller.signal);
163
+ }
164
+ catch (error) {
165
+ process.stderr.write((error instanceof Error ? error.message : String(error)) + "\n");
166
+ process.exitCode = 1;
167
+ }
168
+ finally {
169
+ process.off("disconnect", interrupt);
170
+ if (process.connected)
171
+ process.disconnect?.();
172
+ process.off("SIGTERM", interrupt);
173
+ process.off("SIGINT", interrupt);
174
+ }
@@ -0,0 +1,10 @@
1
+ export interface RunResult {
2
+ readonly status: number | null;
3
+ readonly output: string;
4
+ readonly prepareFailed?: boolean;
5
+ }
6
+ export declare function redGreenProcess(argumentsList: readonly string[], options: {
7
+ readonly directory: string;
8
+ readonly signal: AbortSignal;
9
+ readonly milliseconds: number;
10
+ }): Promise<RunResult>;
@@ -0,0 +1,59 @@
1
+ import { spawn } from "node:child_process";
2
+ import { addAbortListener } from "node:events";
3
+ function stop(child) {
4
+ if (child.pid === undefined)
5
+ return;
6
+ try {
7
+ process.kill(-child.pid, "SIGKILL");
8
+ }
9
+ catch (error) {
10
+ if (Reflect.get(Object(error), "code") !== "ESRCH")
11
+ child.kill("SIGKILL");
12
+ }
13
+ }
14
+ export async function redGreenProcess(argumentsList, options) {
15
+ options.signal.throwIfAborted();
16
+ const child = spawn(argumentsList[0] ?? "", argumentsList.slice(1), {
17
+ cwd: options.directory,
18
+ stdio: ["ignore", "pipe", "pipe"],
19
+ detached: true,
20
+ env: { ...process.env, NODE_TEST_CONTEXT: undefined },
21
+ });
22
+ let output = "";
23
+ let stopped = false;
24
+ child.stdout.setEncoding("utf8");
25
+ child.stderr.setEncoding("utf8");
26
+ child.stdout.on("data", (chunk) => {
27
+ output += chunk;
28
+ });
29
+ child.stderr.on("data", (chunk) => {
30
+ output += chunk;
31
+ });
32
+ child.once("error", (error) => {
33
+ output += error.message;
34
+ });
35
+ const closed = new Promise((resolve) => {
36
+ child.once("close", (status) => {
37
+ resolve({ status: stopped ? null : status, output });
38
+ });
39
+ });
40
+ const terminate = () => {
41
+ stopped = true;
42
+ stop(child);
43
+ child.stdout.destroy();
44
+ child.stderr.destroy();
45
+ };
46
+ const listener = addAbortListener(options.signal, terminate);
47
+ const timeout = setTimeout(() => {
48
+ output += "\nred-green command timed out\n";
49
+ terminate();
50
+ }, options.milliseconds);
51
+ try {
52
+ return await closed;
53
+ }
54
+ finally {
55
+ clearTimeout(timeout);
56
+ listener[Symbol.dispose]();
57
+ stop(child);
58
+ }
59
+ }
@@ -1,4 +1,5 @@
1
1
  export interface HostProcesses {
2
+ readonly environment?: Readonly<NodeJS.ProcessEnv>;
2
3
  readonly project: string;
3
4
  readonly product: string;
4
5
  readonly runtime: string;
@@ -7,5 +8,6 @@ export interface HostProcesses {
7
8
  readonly watchPort: string;
8
9
  readonly phoneRelay: string;
9
10
  readonly updateMilliseconds: number | undefined;
11
+ readonly stopMilliseconds?: number;
10
12
  }
11
13
  export declare function hostedPrograms(settings: HostProcesses): Promise<number>;
@@ -18,13 +18,26 @@ function launched(argumentsList, settings) {
18
18
  settle(status ?? 1);
19
19
  });
20
20
  });
21
- return { child, ended };
21
+ return { name: settings.name, child, ended };
22
22
  }
23
- async function stopped(programs) {
23
+ async function stopped(programs, milliseconds) {
24
24
  for (const program of programs)
25
- if (!program.child.killed)
25
+ if (!program.child.killed &&
26
+ program.child.exitCode === null &&
27
+ program.child.signalCode === null)
26
28
  program.child.kill("SIGTERM");
27
- await Promise.all(programs.map((program) => program.ended));
29
+ await Promise.all(programs.map(async (program) => {
30
+ const timer = setTimeout(() => {
31
+ if (program.child.kill("SIGKILL"))
32
+ process.stderr.write(`Cloving stopped the ${program.name} child with SIGKILL after ${String(milliseconds / 1000)} s\n`);
33
+ }, milliseconds);
34
+ try {
35
+ await program.ended;
36
+ }
37
+ finally {
38
+ clearTimeout(timer);
39
+ }
40
+ }));
28
41
  }
29
42
  function updatingGit(settings, stopping) {
30
43
  const git = promisify(execFile);
@@ -97,9 +110,10 @@ function productChild(settings, argumentsList) {
97
110
  join(settings.product, `src/${program}${extname(import.meta.filename)}`),
98
111
  ...rest,
99
112
  ], {
113
+ name: program === "cli" ? "watch" : program,
100
114
  directory: settings.product,
101
115
  environment: {
102
- ...process.env,
116
+ ...(settings.environment ?? process.env),
103
117
  CLOVING_RUNTIME_DIR: settings.runtime,
104
118
  CLOVING_WATCH_REPOSITORY: settings.repository,
105
119
  },
@@ -107,8 +121,9 @@ function productChild(settings, argumentsList) {
107
121
  }
108
122
  function hostedChildren(settings) {
109
123
  const daemon = launched([join(settings.project, "start.mjs")], {
124
+ name: "daemon",
110
125
  directory: settings.project,
111
- environment: process.env,
126
+ environment: settings.environment ?? process.env,
112
127
  });
113
128
  const watch = settings.watchPort === "off"
114
129
  ? []
@@ -127,15 +142,19 @@ export async function hostedPrograms(settings) {
127
142
  const { daemon, programs } = hostedChildren(settings);
128
143
  const stopping = new AbortController();
129
144
  let updating = false;
130
- const interrupt = () => {
145
+ let shutdown;
146
+ const stop = () => (shutdown ??= stopped(programs, settings.stopMilliseconds ?? 60000));
147
+ const signal = (signal) => {
131
148
  stopping.abort();
132
149
  for (const program of programs)
133
- program.child.kill("SIGINT");
150
+ program.child.kill(signal);
151
+ shutdown = stop();
152
+ };
153
+ const interrupt = () => {
154
+ signal("SIGINT");
134
155
  };
135
156
  const terminate = () => {
136
- stopping.abort();
137
- for (const program of programs)
138
- program.child.kill("SIGTERM");
157
+ signal("SIGTERM");
139
158
  };
140
159
  process.on("SIGINT", interrupt);
141
160
  process.on("SIGTERM", terminate);
@@ -143,7 +162,7 @@ export async function hostedPrograms(settings) {
143
162
  stopping: stopping.signal,
144
163
  stop: async () => {
145
164
  updating = true;
146
- await stopped(programs);
165
+ await stop();
147
166
  },
148
167
  });
149
168
  try {
@@ -159,7 +178,7 @@ export async function hostedPrograms(settings) {
159
178
  }
160
179
  finally {
161
180
  stopping.abort();
162
- await stopped(programs);
181
+ await stop();
163
182
  await polling;
164
183
  process.off("SIGINT", interrupt);
165
184
  process.off("SIGTERM", terminate);
@@ -1,13 +1,12 @@
1
1
  import { spawn } from "node:child_process";
2
2
  import { createHash } from "node:crypto";
3
- import { copyFile, mkdir, readFile, rm, symlink, writeFile, } from "node:fs/promises";
3
+ import { mkdir, readFile, rm, symlink, writeFile } from "node:fs/promises";
4
4
  import { findPackageJSON } from "node:module";
5
- import { basename, dirname, extname, join, resolve } from "node:path";
5
+ import { dirname, extname, join, resolve } from "node:path";
6
6
  import packageMetadata from "#package" with { type: "json" };
7
7
  import { record } from "../src/protocol.js";
8
8
  import { isWorkflowDeclaration, } from "../src/workflow-declaration.js";
9
- import { bundledWorkflowIds, } from "../src/workflow-discovery.js";
10
- import { workflowDeclarations, workflowFiles, workflowManifests, } from "./self-host-workflows.js";
9
+ import { workflowManifests } from "./self-host-workflows.js";
11
10
  import { loadWorkflowFolders, } from "./workflow-folders.js";
12
11
  import { isWorkflowManifest } from "./workflow-manifest.js";
13
12
  import { retainWorkflowBundle } from "./workflow-bundles.js";
@@ -17,9 +16,6 @@ async function initializeProject(settings) {
17
16
  await rm(project, { recursive: true, force: true });
18
17
  await mkdir(join(project, "workflows"), { recursive: true, mode: 0o700 });
19
18
  await writeFile(join(project, "package.json"), '{"name":"cloving-self-host","private":true,"type":"module"}');
20
- const files = await workflowFiles(join(product, "workflows"));
21
- for (const file of files)
22
- await copyWorkflow(settings, file);
23
19
  const modules = join(project, "node_modules");
24
20
  await mkdir(join(modules, "cloving"), { recursive: true });
25
21
  const dependencies = new Map(Object.keys(packageMetadata.dependencies).map((name) => [name, join(product, "package.json")]));
@@ -46,7 +42,6 @@ async function initializeProject(settings) {
46
42
  `./src/${subpath.slice("./workflows/".length) || "workflows"}${extname(import.meta.filename)}`,
47
43
  ])),
48
44
  }));
49
- return files;
50
45
  }
51
46
  async function compile(settings) {
52
47
  const { product, project } = settings;
@@ -70,23 +65,6 @@ async function compile(settings) {
70
65
  throw new Error("The compiled workflow manifest is invalid.");
71
66
  return compiled;
72
67
  }
73
- function reservations(input) {
74
- const { files, manifests, declarations } = input;
75
- return [
76
- ...files.map((file) => ({
77
- baseName: basename(file, extname(file)),
78
- })),
79
- ...Object.entries(manifests).map(([functionName, manifest]) => ({
80
- baseName: manifest.name,
81
- workflowId: manifest.workflowId,
82
- functionName,
83
- })),
84
- ...[
85
- ...Object.values(bundledWorkflowIds),
86
- ...declarations.map((item) => item.workflowId),
87
- ].map((workflowId) => ({ workflowId })),
88
- ];
89
- }
90
68
  async function stageCandidates(project, candidates) {
91
69
  if (candidates.length === 0)
92
70
  return [];
@@ -135,37 +113,6 @@ function operatorDeclaration(staged, compiled) {
135
113
  functionName: workflow.workflowId.slice(workflow.workflowId.lastIndexOf("//") + 2),
136
114
  };
137
115
  }
138
- async function copyWorkflow(settings, file) {
139
- const { product, project } = settings;
140
- await copyFile(join(product, "workflows", file), join(project, "workflows", file));
141
- const sidecar = `${basename(file, extname(file))}.declaration.json`;
142
- const declaration = await readFile(join(product, "workflows", sidecar)).catch((error) => {
143
- if (error instanceof Error && "code" in error && error.code === "ENOENT")
144
- return undefined;
145
- throw error;
146
- });
147
- if (declaration !== undefined)
148
- await writeFile(join(project, "workflows", sidecar), declaration);
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
116
  async function writeManifests(project, compiled) {
170
117
  const manifests = {};
171
118
  for (const [functionName, manifest] of Object.entries(compiled)) {
@@ -180,21 +127,13 @@ async function writeManifests(project, compiled) {
180
127
  }
181
128
  export async function preparedProject(settings) {
182
129
  const { product, project } = settings;
183
- const files = await initializeProject(settings);
184
- let compiled = await compile(settings);
185
- const bundled = workflowManifests(compiled);
186
- const declarations = await workflowDeclarations(join(project, "workflows"), bundled);
187
- const folders = await loadWorkflowFolders({
188
- ...settings,
189
- bundled: reservations({ files, manifests: bundled, declarations }),
190
- }, { packageRoot: await workflowPackageRoot(product) });
130
+ await initializeProject(settings);
131
+ const folders = await loadWorkflowFolders(settings, {
132
+ packageRoot: await workflowPackageRoot(product),
133
+ });
191
134
  const staged = await stageCandidates(project, folders.candidates);
192
- if (staged.length > 0)
193
- compiled = await compile(settings);
194
- const combined = [
195
- ...declarations,
196
- ...staged.map((candidate) => operatorDeclaration({ ...candidate, project }, compiled)),
197
- ];
135
+ const compiled = await compile(settings);
136
+ const combined = staged.map((candidate) => operatorDeclaration({ ...candidate, project }, compiled));
198
137
  const manifests = await writeManifests(project, workflowManifests(compiled, combined));
199
138
  await writeFile(join(project, "declarations.json"), JSON.stringify(combined));
200
139
  await writeFile(join(project, "dependencies.json"), await workflowBundleDependencies({
@@ -206,15 +145,11 @@ export async function preparedProject(settings) {
206
145
  repository: folders.repository,
207
146
  directory: join(dirname(project), "workflow-bundles"),
208
147
  });
209
- const workflows = bundledListings({
210
- product,
211
- files,
212
- manifests: bundled,
213
- declarations,
214
- });
215
- workflows.push(...folders.workflows);
148
+ const modules = join(dirname(project), "workflow-bundles/node_modules");
149
+ await rm(modules, { force: true });
150
+ await symlink(join(project, "node_modules"), modules);
216
151
  return {
217
- workflows,
152
+ workflows: folders.workflows,
218
153
  repository: folders.repository,
219
154
  bundleDigest,
220
155
  manifests,
@@ -45,7 +45,7 @@ export async function adoptRuntimeDirectory(input) {
45
45
  }
46
46
  async function belongsToRepository(directory, repository) {
47
47
  try {
48
- const ids = (await readdir(directory)).filter((id) => id !== ".history");
48
+ const ids = (await readdir(directory)).filter((id) => id !== ".history" && id !== "node_modules");
49
49
  if (ids.length === 0)
50
50
  return false;
51
51
  for (const id of ids)