cloving 1.3.0 → 1.5.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 (484) hide show
  1. package/README.md +329 -215
  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-health.d.ts +9 -0
  32. package/dist/src/broker/actor/authority-health.js +24 -0
  33. package/dist/src/broker/actor/authority-queries.d.ts +2 -1
  34. package/dist/src/broker/actor/authority-queries.js +14 -5
  35. package/dist/src/broker/actor/authority-receipts.js +1 -1
  36. package/dist/src/broker/actor/authority-runtime.d.ts +4 -2
  37. package/dist/src/broker/actor/authority-runtime.js +29 -20
  38. package/dist/src/broker/actor/authority-session.d.ts +6 -19
  39. package/dist/src/broker/actor/authority-session.js +66 -88
  40. package/dist/src/broker/actor/authority-settings.d.ts +2 -1
  41. package/dist/src/broker/actor/authority-settings.js +6 -3
  42. package/dist/src/broker/actor/authority-upgrades.d.ts +23 -2
  43. package/dist/src/broker/actor/authority-upgrades.js +8 -2
  44. package/dist/src/broker/actor/authority-watchdog.d.ts +6 -2
  45. package/dist/src/broker/actor/authority-watchdog.js +31 -9
  46. package/dist/src/broker/actor/authority.js +3 -1
  47. package/dist/src/broker/actor/delivery-intents.js +2 -0
  48. package/dist/src/broker/actor/effect-delivery.d.ts +1 -1
  49. package/dist/src/broker/actor/effect-delivery.js +15 -2
  50. package/dist/src/broker/actor/effect-plan.js +11 -2
  51. package/dist/src/broker/actor/effect-queries.d.ts +4 -0
  52. package/dist/src/broker/actor/effect-queries.js +9 -1
  53. package/dist/src/broker/actor/effect-turn.js +2 -0
  54. package/dist/src/broker/actor/projection-memory.d.ts +43 -0
  55. package/dist/src/broker/actor/projection-memory.js +207 -0
  56. package/dist/src/broker/actor/runtime-parts.d.ts +5 -0
  57. package/dist/src/broker/actor/runtime-parts.js +8 -3
  58. package/dist/src/broker/actor/stop-plan.js +9 -3
  59. package/dist/src/broker/actor/stop-turn.d.ts +2 -0
  60. package/dist/src/broker/actor/stop-turn.js +24 -11
  61. package/dist/src/broker/actor/turn-draft.d.ts +1 -0
  62. package/dist/src/broker/actor/turn-draft.js +4 -0
  63. package/dist/src/broker/actor/turn-state.js +5 -1
  64. package/dist/src/broker/authority-admission.js +60 -0
  65. package/dist/src/broker/authority-restore.d.ts +2 -0
  66. package/dist/src/broker/authority-restore.js +35 -1
  67. package/dist/src/broker/command-wait-restore.d.ts +31 -0
  68. package/dist/src/broker/command-wait-restore.js +86 -0
  69. package/dist/src/broker/decision-restore.d.ts +1 -1
  70. package/dist/src/broker/decision-restore.js +1 -0
  71. package/dist/src/broker/effect-upgrade.d.ts +3 -0
  72. package/dist/src/broker/effect-upgrade.js +11 -2
  73. package/dist/src/cli/arguments.d.ts +13 -0
  74. package/dist/src/cli/arguments.js +43 -3
  75. package/dist/src/cli/chat-stores.d.ts +2 -0
  76. package/dist/src/cli/chat-stores.js +113 -0
  77. package/dist/src/cli/client.d.ts +7 -2
  78. package/dist/src/cli/client.js +13 -7
  79. package/dist/src/cli/command-requests.d.ts +46 -0
  80. package/dist/src/cli/command-requests.js +84 -0
  81. package/dist/src/cli/command-waits.d.ts +9 -0
  82. package/dist/src/cli/command-waits.js +51 -0
  83. package/dist/src/cli/commands.js +70 -88
  84. package/dist/src/cli/config-file.d.ts +2 -2
  85. package/dist/src/cli/config-file.js +4 -2
  86. package/dist/src/cli/config-notice.js +5 -2
  87. package/dist/src/cli/doctor-retention.d.ts +2 -0
  88. package/dist/src/cli/doctor-retention.js +93 -0
  89. package/dist/src/cli/doctor-workflows.d.ts +5 -2
  90. package/dist/src/cli/doctor-workflows.js +12 -7
  91. package/dist/src/cli/doctor.js +11 -9
  92. package/dist/src/cli/harness-probes.d.ts +2 -0
  93. package/dist/src/cli/harness-probes.js +1 -1
  94. package/dist/src/cli/harness-processes.d.ts +6 -0
  95. package/dist/src/cli/harness-processes.js +36 -0
  96. package/dist/src/cli/init-command.d.ts +9 -0
  97. package/dist/src/cli/init-command.js +52 -0
  98. package/dist/src/cli/init-prompt-command.d.ts +10 -0
  99. package/dist/src/cli/init-prompt-command.js +145 -0
  100. package/dist/src/cli/init-prompt.d.ts +35 -0
  101. package/dist/src/cli/init-prompt.js +74 -0
  102. package/dist/src/cli/init-selection.d.ts +13 -0
  103. package/dist/src/cli/init-selection.js +75 -0
  104. package/dist/src/cli/main.d.ts +2 -0
  105. package/dist/src/cli/main.js +37 -7
  106. package/dist/src/cli/mcp-server.d.ts +1 -0
  107. package/dist/src/cli/mcp-server.js +156 -0
  108. package/dist/src/cli/mcp-tools.d.ts +15 -0
  109. package/dist/src/cli/mcp-tools.js +242 -0
  110. package/dist/src/cli/queue-arguments.d.ts +15 -0
  111. package/dist/src/cli/queue-arguments.js +31 -0
  112. package/dist/src/cli/queue-render.d.ts +3 -0
  113. package/dist/src/cli/queue-render.js +26 -0
  114. package/dist/src/cli/reload-render.d.ts +2 -0
  115. package/dist/src/cli/reload-render.js +12 -0
  116. package/dist/src/cli/render.d.ts +1 -1
  117. package/dist/src/cli/render.js +54 -38
  118. package/dist/src/cli/report-ci-jobs.d.ts +23 -0
  119. package/dist/src/cli/report-ci-jobs.js +103 -0
  120. package/dist/src/cli/report-ci-usage.d.ts +9 -0
  121. package/dist/src/cli/report-ci-usage.js +185 -0
  122. package/dist/src/cli/report-ci.d.ts +13 -0
  123. package/dist/src/cli/report-ci.js +74 -0
  124. package/dist/src/cli/report-closures.d.ts +6 -0
  125. package/dist/src/cli/report-closures.js +97 -0
  126. package/dist/src/cli/report-flow.d.ts +7 -0
  127. package/dist/src/cli/report-flow.js +122 -0
  128. package/dist/src/cli/report-github-reader.d.ts +29 -0
  129. package/dist/src/cli/report-github-reader.js +157 -0
  130. package/dist/src/cli/report-github.d.ts +15 -8
  131. package/dist/src/cli/report-github.js +131 -150
  132. package/dist/src/cli/report-operator.d.ts +3 -0
  133. package/dist/src/cli/report-operator.js +40 -0
  134. package/dist/src/cli/report-ready.d.ts +3 -0
  135. package/dist/src/cli/report-ready.js +96 -0
  136. package/dist/src/cli/report-text.d.ts +9 -0
  137. package/dist/src/cli/report-text.js +33 -0
  138. package/dist/src/cli/report.d.ts +1 -0
  139. package/dist/src/cli/report.js +104 -27
  140. package/dist/src/cli/runtime-arguments.d.ts +18 -3
  141. package/dist/src/cli/runtime-arguments.js +29 -20
  142. package/dist/src/cli/schedule-arguments.d.ts +14 -0
  143. package/dist/src/cli/schedule-arguments.js +26 -0
  144. package/dist/src/cli/schedule-render.d.ts +22 -0
  145. package/dist/src/cli/schedule-render.js +73 -0
  146. package/dist/src/cli/terminal-text.d.ts +3 -0
  147. package/dist/src/cli/terminal-text.js +28 -0
  148. package/dist/src/cli/toolchain.d.ts +1 -0
  149. package/dist/src/cli/toolchain.js +1 -0
  150. package/dist/src/cli/usage-render.d.ts +1 -0
  151. package/dist/src/cli/usage-render.js +28 -1
  152. package/dist/src/cli/usage.d.ts +2 -2
  153. package/dist/src/cli/usage.js +89 -11
  154. package/dist/src/cli/watch-actions.js +2 -2
  155. package/dist/src/cli/watch-api-document.d.ts +430 -0
  156. package/dist/src/cli/watch-api-document.js +291 -0
  157. package/dist/src/cli/watch-api-run.d.ts +56 -0
  158. package/dist/src/cli/watch-api-run.js +112 -0
  159. package/dist/src/cli/watch-api.d.ts +17 -0
  160. package/dist/src/cli/watch-api.js +230 -0
  161. package/dist/src/cli/watch-board-view.js +19 -2
  162. package/dist/src/cli/watch-board.d.ts +4 -2
  163. package/dist/src/cli/watch-board.js +53 -43
  164. package/dist/src/cli/watch-card-forms.d.ts +1 -1
  165. package/dist/src/cli/watch-card-forms.js +11 -10
  166. package/dist/src/cli/watch-client.d.ts +1 -1
  167. package/dist/src/cli/watch-client.js +2 -11
  168. package/dist/src/cli/watch-header-view.d.ts +1 -5
  169. package/dist/src/cli/watch-header-view.js +17 -21
  170. package/dist/src/cli/watch-model.d.ts +5 -1
  171. package/dist/src/cli/watch-model.js +20 -11
  172. package/dist/src/cli/watch-page.js +15 -15
  173. package/dist/src/cli/watch-phases.d.ts +12 -3
  174. package/dist/src/cli/watch-phases.js +68 -11
  175. package/dist/src/cli/watch-pr-board.js +1 -1
  176. package/dist/src/cli/watch-pr-command.d.ts +1 -0
  177. package/dist/src/cli/watch-pull-request.js +18 -8
  178. package/dist/src/cli/watch-reads.d.ts +3 -0
  179. package/dist/src/cli/watch-reads.js +22 -20
  180. package/dist/src/cli/watch-render.d.ts +15 -0
  181. package/dist/src/cli/watch-run-input.d.ts +0 -1
  182. package/dist/src/cli/watch-run-input.js +0 -13
  183. package/dist/src/cli/watch-server.js +24 -10
  184. package/dist/src/cli/watch-view.d.ts +0 -3
  185. package/dist/src/cli/watch-view.js +13 -13
  186. package/dist/src/cli.js +73 -12
  187. package/dist/src/command-wait.d.ts +4 -0
  188. package/dist/src/command-wait.js +45 -0
  189. package/dist/src/configuration-change.d.ts +7 -0
  190. package/dist/src/configuration-change.js +14 -0
  191. package/dist/src/configuration-display.js +2 -0
  192. package/dist/src/configuration-schema.d.ts +14 -0
  193. package/dist/src/configuration-schema.js +6 -2
  194. package/dist/src/daemon/attachment-file.d.ts +6 -0
  195. package/dist/src/daemon/attachment-file.js +86 -0
  196. package/dist/src/daemon/attachments.d.ts +14 -0
  197. package/dist/src/daemon/attachments.js +17 -0
  198. package/dist/src/daemon/claude-recovery.d.ts +50 -0
  199. package/dist/src/daemon/claude-recovery.js +208 -0
  200. package/dist/src/daemon/claude-stream.d.ts +27 -0
  201. package/dist/src/daemon/claude-stream.js +63 -0
  202. package/dist/src/daemon/claude-turn.d.ts +11 -25
  203. package/dist/src/daemon/claude-turn.js +64 -81
  204. package/dist/src/daemon/claude-worker.d.ts +5 -4
  205. package/dist/src/daemon/claude-worker.js +127 -126
  206. package/dist/src/daemon/daemon-adapters.d.ts +9 -0
  207. package/dist/src/daemon/daemon-adapters.js +33 -5
  208. package/dist/src/daemon/daemon-loops.d.ts +5 -1
  209. package/dist/src/daemon/daemon-loops.js +18 -10
  210. package/dist/src/daemon/daemon.js +80 -61
  211. package/dist/src/daemon/github-attach.d.ts +2 -0
  212. package/dist/src/daemon/github-attach.js +222 -0
  213. package/dist/src/daemon/github-calls.js +1 -1
  214. package/dist/src/daemon/github-ci-filters.d.ts +6 -0
  215. package/dist/src/daemon/github-ci-filters.js +138 -0
  216. package/dist/src/daemon/github-ci-workflows.d.ts +10 -0
  217. package/dist/src/daemon/github-ci-workflows.js +148 -0
  218. package/dist/src/daemon/github-ci.js +22 -4
  219. package/dist/src/daemon/github-issue-methods.d.ts +2 -0
  220. package/dist/src/daemon/github-issue-methods.js +37 -2
  221. package/dist/src/daemon/github-merge-call.d.ts +2 -1
  222. package/dist/src/daemon/github-merge-call.js +10 -3
  223. package/dist/src/daemon/github-merge.js +52 -24
  224. package/dist/src/daemon/github-methods.js +18 -4
  225. package/dist/src/daemon/github-operation.d.ts +4 -0
  226. package/dist/src/daemon/github-operation.js +6 -0
  227. package/dist/src/daemon/github-worker.d.ts +4 -0
  228. package/dist/src/daemon/github-worker.js +6 -0
  229. package/dist/src/daemon/issue-queue.d.ts +4 -1
  230. package/dist/src/daemon/issue-queue.js +76 -78
  231. package/dist/src/daemon/merge-turns.d.ts +10 -0
  232. package/dist/src/daemon/merge-turns.js +37 -0
  233. package/dist/src/daemon/notify-events.d.ts +6 -0
  234. package/dist/src/daemon/notify-events.js +84 -0
  235. package/dist/src/daemon/notify-journal.js +1 -1
  236. package/dist/src/daemon/notify-message.d.ts +4 -1
  237. package/dist/src/daemon/notify-message.js +36 -0
  238. package/dist/src/daemon/notify.d.ts +1 -1
  239. package/dist/src/daemon/notify.js +5 -77
  240. package/dist/src/daemon/operation-journal.d.ts +1 -0
  241. package/dist/src/daemon/queue-control.d.ts +13 -0
  242. package/dist/src/daemon/queue-control.js +86 -0
  243. package/dist/src/daemon/queue-journal.d.ts +20 -0
  244. package/dist/src/daemon/queue-journal.js +89 -0
  245. package/dist/src/daemon/queue-status.d.ts +9 -3
  246. package/dist/src/daemon/queue-status.js +17 -4
  247. package/dist/src/daemon/record-archive.d.ts +19 -0
  248. package/dist/src/daemon/record-archive.js +82 -0
  249. package/dist/src/daemon/record-sweep.d.ts +24 -0
  250. package/dist/src/daemon/record-sweep.js +147 -0
  251. package/dist/src/daemon/resume-index-lock.d.ts +13 -0
  252. package/dist/src/daemon/resume-index-lock.js +160 -0
  253. package/dist/src/daemon/resume-worktree.d.ts +7 -0
  254. package/dist/src/daemon/resume-worktree.js +29 -0
  255. package/dist/src/daemon/retrying-turn.d.ts +2 -12
  256. package/dist/src/daemon/retrying-turn.js +98 -172
  257. package/dist/src/daemon/schedule-control.d.ts +26 -0
  258. package/dist/src/daemon/schedule-control.js +110 -0
  259. package/dist/src/daemon/schedule-journal.d.ts +2 -15
  260. package/dist/src/daemon/schedule-journal.js +67 -4
  261. package/dist/src/daemon/settings-reload.d.ts +26 -0
  262. package/dist/src/daemon/settings-reload.js +82 -0
  263. package/dist/src/daemon/ticket-registration.d.ts +2 -7
  264. package/dist/src/daemon/ticket-registration.js +15 -81
  265. package/dist/src/daemon/turn-attempt-journal.d.ts +38 -0
  266. package/dist/src/daemon/turn-attempt-journal.js +136 -0
  267. package/dist/src/daemon/turn-attempts.d.ts +47 -0
  268. package/dist/src/daemon/turn-attempts.js +166 -0
  269. package/dist/src/daemon/turn-details.d.ts +4 -0
  270. package/dist/src/daemon/turn-details.js +33 -0
  271. package/dist/src/daemon/turn-report.d.ts +8 -1
  272. package/dist/src/daemon/turn-report.js +39 -0
  273. package/dist/src/daemon/work-tree.d.ts +9 -0
  274. package/dist/src/daemon/work-tree.js +20 -0
  275. package/dist/src/daemon/worker-profile.d.ts +9 -0
  276. package/dist/src/daemon/worker-profile.js +44 -0
  277. package/dist/src/daemon/workflow-generations.d.ts +7 -4
  278. package/dist/src/daemon/workflow-generations.js +22 -14
  279. package/dist/src/daemon/workflow-reload.d.ts +41 -0
  280. package/dist/src/daemon/workflow-reload.js +244 -0
  281. package/dist/src/daemon/workflow-replay.d.ts +2 -1
  282. package/dist/src/daemon/workflow-replay.js +7 -3
  283. package/dist/src/daemon/workflow-schedules.d.ts +3 -0
  284. package/dist/src/daemon/workflow-schedules.js +98 -45
  285. package/dist/src/daemon/worktree-processes.d.ts +9 -0
  286. package/dist/src/daemon/worktree-processes.js +151 -0
  287. package/dist/src/doctor-report.d.ts +4 -6
  288. package/dist/src/doctor-report.js +8 -13
  289. package/dist/src/harness-start.d.ts +15 -0
  290. package/dist/src/harness-start.js +37 -0
  291. package/dist/src/host/command-wait.d.ts +38 -0
  292. package/dist/src/host/command-wait.js +115 -0
  293. package/dist/src/host/start-delivery.d.ts +5 -7
  294. package/dist/src/host/start-delivery.js +3 -15
  295. package/dist/src/host/step-bridge-host.d.ts +2 -0
  296. package/dist/src/host/step-bridge-host.js +21 -0
  297. package/dist/src/operation-identity.d.ts +1 -0
  298. package/dist/src/operation-identity.js +4 -0
  299. package/dist/src/private-config.schema.json +71 -0
  300. package/dist/src/project-config.schema.json +40 -0
  301. package/dist/src/project-settings.d.ts +16 -2
  302. package/dist/src/project-settings.js +35 -1
  303. package/dist/src/queue-spend.d.ts +4 -0
  304. package/dist/src/queue-spend.js +21 -0
  305. package/dist/src/queue-state.d.ts +26 -0
  306. package/dist/src/queue-state.js +34 -0
  307. package/dist/src/record-retention.d.ts +46 -0
  308. package/dist/src/record-retention.js +81 -0
  309. package/dist/src/relay/relay-service.d.ts +3 -0
  310. package/dist/src/relay/relay-service.js +5 -3
  311. package/dist/src/report-ci.d.ts +164 -0
  312. package/dist/src/report-ci.js +32 -0
  313. package/dist/src/report-effects.d.ts +15 -0
  314. package/dist/src/report-effects.js +212 -0
  315. package/dist/src/report-flow-types.d.ts +38 -0
  316. package/dist/src/report-flow-types.js +7 -0
  317. package/dist/src/report-flow.d.ts +43 -0
  318. package/dist/src/report-flow.js +193 -0
  319. package/dist/src/report-operator.d.ts +67 -0
  320. package/dist/src/report-operator.js +25 -0
  321. package/dist/src/report-quality.d.ts +221 -0
  322. package/dist/src/report-quality.js +94 -0
  323. package/dist/src/report-ready.d.ts +23 -0
  324. package/dist/src/report-ready.js +117 -0
  325. package/dist/src/report-statistics.d.ts +2 -1
  326. package/dist/src/report-statistics.js +40 -4
  327. package/dist/src/report.d.ts +588 -47
  328. package/dist/src/report.js +156 -41
  329. package/dist/src/schedule-progress.d.ts +33 -0
  330. package/dist/src/schedule-progress.js +45 -0
  331. package/dist/src/service/active-tickets.js +11 -6
  332. package/dist/src/service/command-waits.d.ts +34 -0
  333. package/dist/src/service/command-waits.js +86 -0
  334. package/dist/src/service/dispatcher.d.ts +4 -0
  335. package/dist/src/service/dispatcher.js +33 -0
  336. package/dist/src/service/expiry.js +2 -0
  337. package/dist/src/service/gateway.js +3 -1
  338. package/dist/src/service/queue-handlers.d.ts +4 -0
  339. package/dist/src/service/queue-handlers.js +32 -0
  340. package/dist/src/service/queue-spend.d.ts +6 -0
  341. package/dist/src/service/queue-spend.js +68 -0
  342. package/dist/src/service/registry.d.ts +28 -2
  343. package/dist/src/service/registry.js +48 -0
  344. package/dist/src/service/replies.d.ts +22 -8
  345. package/dist/src/service/replies.js +16 -2
  346. package/dist/src/service/run-handlers.js +37 -12
  347. package/dist/src/service/run-metadata.d.ts +15 -1
  348. package/dist/src/service/run-metadata.js +93 -8
  349. package/dist/src/service/service.d.ts +11 -3
  350. package/dist/src/service/service.js +22 -37
  351. package/dist/src/service/submission-handler.js +18 -4
  352. package/dist/src/service/worker-port.js +9 -1
  353. package/dist/src/service/worker-totals.d.ts +6 -0
  354. package/dist/src/service/worker-totals.js +8 -1
  355. package/dist/src/service/workflow-reload.d.ts +35 -0
  356. package/dist/src/service/workflow-reload.js +52 -0
  357. package/dist/src/step-bridge.d.ts +20 -0
  358. package/dist/src/steps/command-wait.d.ts +12 -0
  359. package/dist/src/steps/command-wait.js +26 -0
  360. package/dist/src/steps/open-decision-wait.d.ts +2 -0
  361. package/dist/src/steps/{decision-gate.js → open-decision-wait.js} +0 -7
  362. package/dist/src/steps/review-by-person.js +4 -1
  363. package/dist/src/steps/wait-for-command.d.ts +3 -0
  364. package/dist/src/steps/wait-for-command.js +17 -0
  365. package/dist/src/steps/wait-for-decision.js +1 -1
  366. package/dist/src/storage/command-wait-rows.d.ts +30 -0
  367. package/dist/src/storage/command-wait-rows.js +96 -0
  368. package/dist/src/storage/decision-snapshots.d.ts +8 -2
  369. package/dist/src/storage/decision-snapshots.js +16 -8
  370. package/dist/src/storage/domain-changes.d.ts +3 -1
  371. package/dist/src/storage/domain-changes.js +4 -0
  372. package/dist/src/storage/domain-schema.d.ts +16 -1
  373. package/dist/src/storage/domain-schema.js +35 -4
  374. package/dist/src/storage/effect-schema.d.ts +2 -0
  375. package/dist/src/storage/effect-schema.js +9 -0
  376. package/dist/src/storage/projection-changes.d.ts +12 -0
  377. package/dist/src/storage/projection-changes.js +194 -0
  378. package/dist/src/storage/projection-lookups.d.ts +7 -0
  379. package/dist/src/storage/projection-lookups.js +30 -0
  380. package/dist/src/testing-requests.d.ts +15 -0
  381. package/dist/src/testing-requests.js +93 -0
  382. package/dist/src/testing.d.ts +4 -10
  383. package/dist/src/testing.js +33 -86
  384. package/dist/src/worker-usage.d.ts +1 -0
  385. package/dist/src/worker-usage.js +3 -0
  386. package/dist/src/workflow-candidate.d.ts +1 -0
  387. package/dist/src/workflow-candidate.js +12 -1
  388. package/dist/src/workflow-contracts.d.ts +1 -0
  389. package/dist/src/workflow-contracts.js +9 -2
  390. package/dist/src/workflow-declaration.d.ts +1 -0
  391. package/dist/src/workflow-declaration.js +3 -0
  392. package/dist/src/workflow-discovery.d.ts +2 -13
  393. package/dist/src/workflow-discovery.js +1 -13
  394. package/dist/src/workflow-refusals.js +0 -1
  395. package/dist/src/workflows.d.ts +1 -1
  396. package/dist/src/workflows.js +1 -1
  397. package/dist/tools/compile-workflows.js +3 -0
  398. package/dist/tools/project-configuration.d.ts +7 -2
  399. package/dist/tools/project-configuration.js +30 -1
  400. package/dist/tools/red-green-command.d.ts +1 -0
  401. package/dist/tools/red-green-command.js +174 -0
  402. package/dist/tools/red-green-process.d.ts +10 -0
  403. package/dist/tools/red-green-process.js +59 -0
  404. package/dist/tools/self-host-processes.d.ts +2 -0
  405. package/dist/tools/self-host-processes.js +69 -26
  406. package/dist/tools/self-host-project.d.ts +2 -0
  407. package/dist/tools/self-host-project.js +30 -77
  408. package/dist/tools/self-host-runtime.js +1 -1
  409. package/dist/tools/self-host.js +76 -34
  410. package/dist/tools/template-command.d.ts +1 -0
  411. package/dist/tools/template-command.js +160 -0
  412. package/dist/tools/template-copy.d.ts +11 -0
  413. package/dist/tools/template-copy.js +130 -0
  414. package/dist/tools/template-files.d.ts +17 -0
  415. package/dist/tools/template-files.js +74 -0
  416. package/dist/tools/workflow-bundles.js +1 -0
  417. package/dist/tools/workflow-candidate-counts.js +2 -2
  418. package/dist/tools/workflow-candidate-program.d.ts +4 -2
  419. package/dist/tools/workflow-candidate-program.js +30 -11
  420. package/dist/tools/workflow-candidate-shape.d.ts +3 -0
  421. package/dist/tools/workflow-candidate-shape.js +90 -0
  422. package/dist/tools/workflow-candidate-source.d.ts +1 -0
  423. package/dist/tools/workflow-candidate-source.js +26 -4
  424. package/dist/tools/workflow-candidate-syntax.d.ts +2 -2
  425. package/dist/tools/workflow-candidate-syntax.js +24 -94
  426. package/dist/tools/workflow-command.js +1 -2
  427. package/dist/tools/workflow-folders.d.ts +2 -3
  428. package/dist/tools/workflow-folders.js +1 -1
  429. package/package.json +17 -9
  430. package/templates/develop/README.md +93 -4
  431. package/templates/develop/develop/flow-tests.ts +38 -1
  432. package/templates/develop/develop/interruption-tests.ts +157 -0
  433. package/templates/develop/develop/local.ts +1 -0
  434. package/templates/develop/develop/option-tests.ts +138 -9
  435. package/templates/develop/develop/pull.ts +5 -1
  436. package/templates/develop/develop/red-green.ts +55 -0
  437. package/templates/develop/develop/refusal-tests.ts +77 -0
  438. package/templates/develop/develop/report.ts +31 -11
  439. package/templates/develop/develop/round.ts +1 -0
  440. package/templates/develop/develop/scenarios.ts +27 -0
  441. package/templates/develop/develop/turn.ts +28 -7
  442. package/templates/develop/develop.declaration.json +1 -1
  443. package/templates/develop/develop.test.ts +4 -0
  444. package/templates/develop/template.json +29 -2
  445. package/templates/idea-to-issue/README.md +27 -0
  446. package/templates/idea-to-issue/idea-to-issue/effects.ts +52 -0
  447. package/templates/idea-to-issue/idea-to-issue/leave.ts +10 -0
  448. package/templates/idea-to-issue/idea-to-issue/next.ts +29 -0
  449. package/templates/idea-to-issue/idea-to-issue/post-person.ts +18 -0
  450. package/templates/idea-to-issue/idea-to-issue/post.ts +50 -0
  451. package/templates/idea-to-issue/idea-to-issue/queue.ts +27 -0
  452. package/templates/idea-to-issue/idea-to-issue/review.ts +42 -0
  453. package/templates/idea-to-issue/idea-to-issue/scenarios.ts +50 -0
  454. package/templates/idea-to-issue/idea-to-issue/turn.ts +40 -0
  455. package/templates/idea-to-issue/idea-to-issue.declaration.json +16 -0
  456. package/templates/idea-to-issue/idea-to-issue.test.ts +79 -0
  457. package/templates/idea-to-issue/idea-to-issue.ts +49 -0
  458. package/templates/idea-to-issue/template.json +81 -0
  459. package/templates/review-day/README.md +97 -0
  460. package/templates/review-day/review-day/critique.ts +58 -0
  461. package/templates/review-day/review-day/decision.ts +29 -0
  462. package/templates/review-day/review-day/facts.ts +69 -0
  463. package/templates/review-day/review-day/label.ts +29 -0
  464. package/templates/review-day/review-day/next.ts +28 -0
  465. package/templates/review-day/review-day/post.ts +27 -0
  466. package/templates/review-day/review-day/report.ts +98 -0
  467. package/templates/review-day/review-day/rules.ts +12 -0
  468. package/templates/review-day/review-day/scenarios.ts +76 -0
  469. package/templates/review-day/review-day/turn.ts +73 -0
  470. package/templates/review-day/review-day.declaration.json +16 -0
  471. package/templates/review-day/review-day.test.ts +362 -0
  472. package/templates/review-day/review-day.ts +37 -0
  473. package/templates/review-day/template.json +56 -0
  474. package/dist/src/cli/watch-start-view.d.ts +0 -18
  475. package/dist/src/cli/watch-start-view.js +0 -77
  476. package/dist/src/steps/decision-gate.d.ts +0 -3
  477. package/dist/workflows/develop-prd.d.ts +0 -7
  478. package/dist/workflows/develop-prd.js +0 -165
  479. package/dist/workflows/develop-ticket.d.ts +0 -9
  480. package/dist/workflows/develop-ticket.js +0 -207
  481. package/dist/workflows/issue-labels.d.ts +0 -16
  482. package/dist/workflows/issue-labels.js +0 -70
  483. package/dist/workflows/ticket-prompts.d.ts +0 -35
  484. package/dist/workflows/ticket-prompts.js +0 -147
@@ -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>;
@@ -1,4 +1,4 @@
1
- import { execFile, spawn } from "node:child_process";
1
+ import { execFile, spawn, } from "node:child_process";
2
2
  import { addAbortListener } from "node:events";
3
3
  import { rm } from "node:fs/promises";
4
4
  import { extname, join } from "node:path";
@@ -10,7 +10,7 @@ function launched(argumentsList, settings) {
10
10
  const child = spawn(process.execPath, argumentsList, {
11
11
  cwd: settings.directory,
12
12
  env: settings.environment,
13
- stdio: "inherit",
13
+ stdio: settings.stdio ?? "inherit",
14
14
  });
15
15
  const ended = new Promise((settle, reject) => {
16
16
  child.once("error", reject);
@@ -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,35 +121,63 @@ 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,
127
+ stdio: ["inherit", "inherit", "inherit", "ipc"],
112
128
  });
113
- const watch = settings.watchPort === "off"
114
- ? []
115
- : [
116
- productChild(settings, [
117
- "cli",
118
- "watch",
119
- "--port",
120
- settings.watchPort,
121
- ]),
122
- ];
123
129
  const relay = settings.phoneRelay === "off" ? [] : [productChild(settings, ["relay"])];
124
- return { daemon, programs: [daemon, ...watch, ...relay] };
130
+ return { daemon, programs: [daemon, ...relay] };
131
+ }
132
+ function daemonStart(daemon) {
133
+ return new Promise((settle) => {
134
+ daemon.child.once("message", () => {
135
+ settle("started");
136
+ });
137
+ daemon.ended.then(() => {
138
+ settle("ended");
139
+ }, () => {
140
+ settle("ended");
141
+ });
142
+ });
143
+ }
144
+ function watchAfterStart(settings, hosting) {
145
+ if (settings.watchPort === "off")
146
+ return Promise.resolve();
147
+ return daemonStart(hosting.daemon).then((start) => {
148
+ if (start === "ended" || hosting.stopped())
149
+ return;
150
+ const watch = productChild(settings, [
151
+ "cli",
152
+ "watch",
153
+ "--port",
154
+ settings.watchPort,
155
+ ]);
156
+ hosting.programs.splice(1, 0, watch);
157
+ });
125
158
  }
126
159
  export async function hostedPrograms(settings) {
127
160
  const { daemon, programs } = hostedChildren(settings);
128
161
  const stopping = new AbortController();
129
162
  let updating = false;
130
- const interrupt = () => {
163
+ let shutdown;
164
+ const watching = watchAfterStart(settings, {
165
+ daemon,
166
+ programs,
167
+ stopped: () => shutdown !== undefined,
168
+ });
169
+ const stop = () => (shutdown ??= stopped(programs, settings.stopMilliseconds ?? 60000));
170
+ const signal = (signal) => {
131
171
  stopping.abort();
132
172
  for (const program of programs)
133
- program.child.kill("SIGINT");
173
+ program.child.kill(signal);
174
+ shutdown = stop();
175
+ };
176
+ const interrupt = () => {
177
+ signal("SIGINT");
134
178
  };
135
179
  const terminate = () => {
136
- stopping.abort();
137
- for (const program of programs)
138
- program.child.kill("SIGTERM");
180
+ signal("SIGTERM");
139
181
  };
140
182
  process.on("SIGINT", interrupt);
141
183
  process.on("SIGTERM", terminate);
@@ -143,7 +185,7 @@ export async function hostedPrograms(settings) {
143
185
  stopping: stopping.signal,
144
186
  stop: async () => {
145
187
  updating = true;
146
- await stopped(programs);
188
+ await stop();
147
189
  },
148
190
  });
149
191
  try {
@@ -159,7 +201,8 @@ export async function hostedPrograms(settings) {
159
201
  }
160
202
  finally {
161
203
  stopping.abort();
162
- await stopped(programs);
204
+ await watching;
205
+ await stop();
163
206
  await polling;
164
207
  process.off("SIGINT", interrupt);
165
208
  process.off("SIGTERM", terminate);
@@ -8,6 +8,7 @@ interface ProjectSettings {
8
8
  readonly home: string;
9
9
  readonly xdgConfigHome?: string | undefined;
10
10
  readonly userFolder?: string | undefined;
11
+ readonly recordedProject?: string;
11
12
  }
12
13
  export interface RegisteredWorkflows {
13
14
  readonly workflows: readonly WorkflowListing[];
@@ -18,4 +19,5 @@ export interface RegisteredWorkflows {
18
19
  readonly workflowRefusals: readonly WorkflowRefusal[];
19
20
  }
20
21
  export declare function preparedProject(settings: ProjectSettings): Promise<RegisteredWorkflows>;
22
+ export declare function preparedBundle(settings: ProjectSettings): Promise<RegisteredWorkflows>;
21
23
  export {};
@@ -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,36 +113,18 @@ 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
- });
116
+ async function recordProject(settings) {
117
+ const { project, recordedProject } = settings;
118
+ if (recordedProject === undefined)
119
+ return;
120
+ for (const name of [
121
+ "flow.mjs.__wf_tmp.js.debug.json",
122
+ "steps.mjs.debug.json",
123
+ ]) {
124
+ const path = join(project, "artifacts", name);
125
+ const text = await readFile(path, "utf8");
126
+ await writeFile(path, text.replaceAll(`${project}/`, `${recordedProject}/`));
127
+ }
168
128
  }
169
129
  async function writeManifests(project, compiled) {
170
130
  const manifests = {};
@@ -179,22 +139,22 @@ async function writeManifests(project, compiled) {
179
139
  return manifests;
180
140
  }
181
141
  export async function preparedProject(settings) {
142
+ const prepared = await preparedBundle(settings);
143
+ const modules = join(dirname(settings.project), "workflow-bundles/node_modules");
144
+ await rm(modules, { force: true });
145
+ await symlink(join(settings.project, "node_modules"), modules);
146
+ return prepared;
147
+ }
148
+ export async function preparedBundle(settings) {
182
149
  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) });
150
+ await initializeProject(settings);
151
+ const folders = await loadWorkflowFolders(settings, {
152
+ packageRoot: await workflowPackageRoot(product),
153
+ });
191
154
  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
- ];
155
+ const compiled = await compile(settings);
156
+ await recordProject(settings);
157
+ const combined = staged.map((candidate) => operatorDeclaration({ ...candidate, project }, compiled));
198
158
  const manifests = await writeManifests(project, workflowManifests(compiled, combined));
199
159
  await writeFile(join(project, "declarations.json"), JSON.stringify(combined));
200
160
  await writeFile(join(project, "dependencies.json"), await workflowBundleDependencies({
@@ -206,15 +166,8 @@ export async function preparedProject(settings) {
206
166
  repository: folders.repository,
207
167
  directory: join(dirname(project), "workflow-bundles"),
208
168
  });
209
- const workflows = bundledListings({
210
- product,
211
- files,
212
- manifests: bundled,
213
- declarations,
214
- });
215
- workflows.push(...folders.workflows);
216
169
  return {
217
- workflows,
170
+ workflows: folders.workflows,
218
171
  repository: folders.repository,
219
172
  bundleDigest,
220
173
  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)
@@ -1,10 +1,9 @@
1
1
  import { turnHarness, harnessDefaults, nativeHarness, } from "../src/harness-defaults.js";
2
2
  import { absoluteWorkflowFolder } from "../src/project-settings.js";
3
- import { projectConfiguration, projectRoot, topLevel, } from "./project-configuration.js";
4
- import { isProfilesFile } from "../src/turn-profile.js";
3
+ import { retentionSettings, } from "../src/record-retention.js";
4
+ import { configurationDigests, configuredTurnSettings, projectConfiguration, projectRoot, topLevel, } from "./project-configuration.js";
5
5
  import { parseCommands, parseCommandSeconds, } from "../src/command-settings.js";
6
- import { parseFallbackModels, parseTokenPrices, } from "../src/token-prices.js";
7
- import { readFile, writeFile } from "node:fs/promises";
6
+ import { writeFile } from "node:fs/promises";
8
7
  import { homedir } from "node:os";
9
8
  import { dirname, extname, join, resolve } from "node:path";
10
9
  import { pathToFileURL } from "node:url";
@@ -14,6 +13,7 @@ import { hostedPrograms } from "./self-host-processes.js";
14
13
  import { workflowBundleLoader } from "./self-host-workflows.js";
15
14
  import { adoptRuntimeDirectory } from "./self-host-runtime.js";
16
15
  import { parseSchedulesSetting } from "../src/workflow-schedule.js";
16
+ import { checkSubmission } from "../src/submission.js";
17
17
  const product = resolve(import.meta.dirname, "..");
18
18
  const flags = process.argv.slice(2);
19
19
  function flag(name) {
@@ -65,19 +65,12 @@ function checkedWorker(name) {
65
65
  });
66
66
  }
67
67
  }
68
- async function profilesFile() {
69
- const path = environment["CLOVING_PROFILES"];
70
- if (path === undefined)
71
- return configuration.profiles;
72
- try {
73
- const value = JSON.parse(await readFile(path, "utf8"));
74
- if (isProfilesFile(value))
75
- return value.profiles;
76
- }
77
- catch {
78
- throw new Error("The daemon did not start: invalid-profiles");
79
- }
80
- throw new Error("The daemon did not start: invalid-profiles");
68
+ function startRefusal(error) {
69
+ if (error instanceof Error && error.message === "invalid-profiles")
70
+ throw new Error("The daemon did not start: invalid-profiles", {
71
+ cause: error,
72
+ });
73
+ throw error;
81
74
  }
82
75
  function queueLanes() {
83
76
  const value = environment["CLOVING_QUEUE_LANES"];
@@ -89,7 +82,18 @@ function queueLanes() {
89
82
  throw new Error("The daemon did not start: queue-lanes-needs-queue");
90
83
  return Number(value);
91
84
  }
92
- function queueInterval(commands) {
85
+ function queueSpendLimit() {
86
+ const value = environment["CLOVING_QUEUE_DAILY_SPEND_USD"];
87
+ if (value === undefined)
88
+ return undefined;
89
+ const limit = Number(value);
90
+ if (!Number.isFinite(limit) || limit <= 0)
91
+ throw new Error("The daemon did not start: invalid-queue-spend-limit");
92
+ if (environment["CLOVING_QUEUE_SECONDS"] === undefined)
93
+ throw new Error("The daemon did not start: queue-spend-limit-needs-queue");
94
+ return limit;
95
+ }
96
+ function queueInterval() {
93
97
  const value = environment["CLOVING_QUEUE_SECONDS"];
94
98
  if (value === undefined)
95
99
  return undefined;
@@ -99,10 +103,6 @@ function queueInterval(commands) {
99
103
  seconds < 10 ||
100
104
  seconds > 3600)
101
105
  throw new Error("The daemon did not start: invalid-queue-seconds");
102
- if (!commands.nextCommand?.length)
103
- throw new Error("The daemon did not start: queue-needs-next-command");
104
- if (!commands.ticketCommand?.length)
105
- throw new Error("The daemon did not start: queue-needs-ticket-command");
106
106
  return seconds * 1000;
107
107
  }
108
108
  function listed(name) {
@@ -118,6 +118,12 @@ function source(file) {
118
118
  return JSON.stringify(pathToFileURL(join(product, file.replace(/\.ts$/, extname(import.meta.filename)))).href);
119
119
  }
120
120
  async function launchers(commands, workflows) {
121
+ const queueEnabled = commands.queueMilliseconds !== undefined &&
122
+ workflows.declarations.some((declaration) => declaration.queue === true);
123
+ if (queueEnabled && !commands.nextCommand?.length)
124
+ throw new Error("The daemon did not start: queue-needs-next-command");
125
+ if (queueEnabled && !commands.ticketCommand?.length)
126
+ throw new Error("The daemon did not start: queue-needs-ticket-command");
121
127
  const settings = {
122
128
  ...commands,
123
129
  directory,
@@ -139,11 +145,29 @@ if (opening.kind !== "started") {
139
145
  process.exit(1);
140
146
  }
141
147
  process.stdout.write(${JSON.stringify(guide(workflows))});
148
+ process.send?.("started");
149
+ process.channel?.unref();
142
150
  const stop = async () => { await opening.daemon.close(); process.exit(0); };
143
151
  process.once("SIGINT", stop);
144
152
  process.once("SIGTERM", stop);
145
153
  `);
146
154
  }
155
+ function runCommand(declaration) {
156
+ const { workflowId, input } = declaration;
157
+ for (const [field, value, argument] of [
158
+ ["ticket", "ticket-id", "--ticket <ticket-id>"],
159
+ ["prompt", "task text", '--prompt "<text>"'],
160
+ ]) {
161
+ const checked = checkSubmission(input, {
162
+ workflowId,
163
+ source: field,
164
+ submission: { [field]: value },
165
+ });
166
+ if (checked.kind === "valid")
167
+ return ` ${client} run ${workflowId} ${argument}`;
168
+ }
169
+ return ` ${client} run ${workflowId} --input <json-file>`;
170
+ }
147
171
  function guide(workflows) {
148
172
  return [
149
173
  "Cloving runs. Stop it with Control-C.",
@@ -154,21 +178,18 @@ function guide(workflows) {
154
178
  ...Object.entries(configuration.sources).map(([field, source]) => `${field}: ${source}`),
155
179
  ...workflows.workflowRefusals.map((refusal) => `Refused workflow ${refusal.scope} ${refusal.label}: ${refusal.codes.join(", ")}`),
156
180
  "Commands for a second terminal:",
157
- ` ${client} run develop-ticket --ticket <ticket-id>`,
158
- ` ${client} run develop-issue --ticket <ticket-id>`,
159
- ` ${client} run develop-prompt --prompt "<the text of the task>"`,
160
- ` ${client} run develop-prd --prompt "<the idea>"`,
181
+ ...(workflows.declarations.length === 0
182
+ ? ["No workflow. Run: cloving init"]
183
+ : workflows.declarations.map(runCommand)),
161
184
  ` ${client} status`,
162
185
  ` ${client} questions`,
163
186
  ` ${client} watch`,
164
187
  "",
165
188
  ].join("\n");
166
189
  }
167
- const tokenPrices = parseTokenPrices(environment["CLOVING_TOKEN_PRICES"]);
190
+ const { tokenPrices, fallbackModels, profiles } = await configuredTurnSettings(configuration).catch(startRefusal);
168
191
  const commands = parseCommands(environment["CLOVING_COMMANDS"]);
169
192
  const commandSeconds = parseCommandSeconds(environment["CLOVING_COMMAND_SECONDS"]);
170
- const fallbackModels = parseFallbackModels(environment["CLOVING_FALLBACK_MODELS"]);
171
- const profiles = await profilesFile();
172
193
  const schedules = parseSchedulesSetting(environment["CLOVING_SCHEDULES"]);
173
194
  const worker = selectedWorker();
174
195
  function nativeCommands() {
@@ -187,16 +208,21 @@ const harness = configuration.harness ?? {};
187
208
  const command = turnHarness({ worker, workerCommands, harness }).command;
188
209
  const nextCommand = listed("CLOVING_NEXT_COMMAND");
189
210
  const ticketCommand = listed("CLOVING_TICKET_COMMAND");
211
+ const queueDailySpendLimitUsd = queueSpendLimit();
190
212
  const lanes = queueLanes();
191
- const queueMilliseconds = queueInterval({ nextCommand, ticketCommand });
192
- const manifests = await preparedProject({
193
- product,
194
- project,
213
+ const queueMilliseconds = queueInterval();
214
+ const retention = retentionSettings(environment);
215
+ const places = {
195
216
  repository,
196
217
  home: homedir(),
197
218
  xdgConfigHome: environment["XDG_CONFIG_HOME"],
219
+ };
220
+ const folders = {
221
+ ...places,
198
222
  userFolder: absoluteWorkflowFolder(environment["CLOVING_WORKFLOW_FOLDER"]),
199
- });
223
+ };
224
+ const profilesPath = environment["CLOVING_PROFILES"];
225
+ const manifests = await preparedProject({ product, project, ...folders });
200
226
  await launchers({
201
227
  commands,
202
228
  commandSeconds,
@@ -208,19 +234,35 @@ await launchers({
208
234
  harness,
209
235
  shell: environment["SHELL"] ?? "/bin/sh",
210
236
  profiles,
237
+ settingDigests: configurationDigests(configuration, profiles),
211
238
  command,
212
239
  ticketCommand,
213
240
  nextCommand,
214
241
  queueMilliseconds,
215
242
  queueLanes: lanes,
243
+ queueDailySpendLimitUsd,
216
244
  resetQueue: flags.includes("--reset-queue"),
245
+ retention,
217
246
  notifyCommand: listed("CLOVING_NOTIFY_COMMAND"),
218
247
  githubCommand: listed("CLOVING_GH_COMMAND"),
219
248
  requiredChecks: listed("CLOVING_REQUIRED_CHECKS") ?? null,
220
249
  checkCommand: listed("CLOVING_CHECK_COMMAND"),
221
250
  privateTexts: listed("CLOVING_PRIVATE_TEXTS"),
251
+ reloadCommand: [
252
+ process.execPath,
253
+ join(product, `tools/self-host-reload${extname(import.meta.filename)}`),
254
+ JSON.stringify({
255
+ directory,
256
+ ...places,
257
+ ...(profilesPath === undefined
258
+ ? {}
259
+ : { profilesFile: resolve(profilesPath) }),
260
+ fileVariables: Object.keys(environment).filter((name) => process.env[name] === undefined),
261
+ }),
262
+ ],
222
263
  }, manifests);
223
264
  process.exitCode = await hostedPrograms({
265
+ environment,
224
266
  project,
225
267
  product,
226
268
  runtime,
@@ -0,0 +1 @@
1
+ export declare function templateCommand(argumentsList: readonly string[]): Promise<number>;