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
@@ -1,4 +1,5 @@
1
- import { metadataOf, outcomeOf } from "./run-metadata.js";
1
+ import { commandWaitDisplay } from "./command-waits.js";
2
+ import { scheduleMetadata, scheduledMetadata, metadataOf, outcomeOf, ticketMetadataPage, workflowMetadata, } from "./run-metadata.js";
2
3
  import { linksOf } from "../authority/handoff-chain.js";
3
4
  import { runView, unresolvedEffects, } from "../authority/status.js";
4
5
  import { record } from "../protocol.js";
@@ -13,6 +14,7 @@ async function snapshot(context) {
13
14
  const state = await authority.state();
14
15
  const sequences = await authority.queries.sequences();
15
16
  return {
17
+ now: context.clock(),
16
18
  links: await authority.queries.runLinks(),
17
19
  state,
18
20
  operations: await authority.operations(),
@@ -64,9 +66,16 @@ async function viewOf(context, scope) {
64
66
  if (run === undefined)
65
67
  return undefined;
66
68
  const details = state.details[run.runId];
69
+ const workflowId = scope.snapshot.workflowIds[run.runId] ?? run.workflow;
67
70
  const effects = await effectInput(context, run.runId);
68
71
  const input = {
69
72
  ...effects,
73
+ commandWaits: await commandWaitDisplay({
74
+ authority: context.authority,
75
+ runId: run.runId,
76
+ waits: state.commandWaits,
77
+ now: scope.snapshot.now,
78
+ }),
70
79
  closure: run.status === "cancelled"
71
80
  ? await context.authority.effects.closure(run.runId)
72
81
  : null,
@@ -84,10 +93,14 @@ async function viewOf(context, scope) {
84
93
  };
85
94
  return {
86
95
  ...runView(input),
96
+ ...(await scheduledMetadata(context, {
97
+ runId: run.runId,
98
+ workflowId,
99
+ })),
87
100
  commandOperations: effects.commandOperations,
88
101
  ...linksOf({ runId: run.runId, ...scope.snapshot.links[run.runId] }),
89
102
  input: await submittedInput(context, details?.submission),
90
- workflowId: scope.snapshot.workflowIds[run.runId] ?? run.workflow,
103
+ workflowId,
91
104
  latestAt: times[run.runId] ?? null,
92
105
  unresolvedEffects: unresolvedEffects(input),
93
106
  feedback: await feedbackOf(context, { state, runId: run.runId }),
@@ -96,6 +109,7 @@ async function viewOf(context, scope) {
96
109
  function summary(view) {
97
110
  return {
98
111
  runId: view.runId,
112
+ ...(view.scheduled === undefined ? {} : { scheduled: view.scheduled }),
99
113
  ...linksOf(view),
100
114
  input: view.input,
101
115
  workflowId: view.workflowId,
@@ -106,6 +120,7 @@ function summary(view) {
106
120
  latestSequence: view.latestSequence,
107
121
  latestAt: view.latestAt,
108
122
  pendingDecisions: view.pendingDecisions,
123
+ commandWaits: view.commandWaits,
109
124
  };
110
125
  }
111
126
  function full(view) {
@@ -145,6 +160,7 @@ async function listed(context, page) {
145
160
  const runs = views.filter((view) => view !== undefined).map(summary);
146
161
  return result("run-list", {
147
162
  ...(await queueOverview(context)),
163
+ ...(await scheduleMetadata(context)),
148
164
  workflows: context.registry.workflowIds,
149
165
  workflowRefusals: context.workflowRefusals ?? [],
150
166
  ...(Object.keys(context.registry.workflowStages).length === 0
@@ -165,12 +181,16 @@ function listParameters(parameters) {
165
181
  return { after, limit };
166
182
  }
167
183
  export async function status(context, parameters) {
184
+ if (parameters["metadata"] === "workflows")
185
+ return workflowMetadata(context, parameters["runIds"]);
168
186
  if (parameters["runIds"] !== undefined)
169
187
  return queueRunStatuses(context, parameters["runIds"]);
170
188
  const { runId } = parameters;
171
189
  const page = listParameters(parameters);
172
190
  if (page === undefined)
173
191
  return invalidRequest("The status request is not valid.");
192
+ if (parameters["metadata"] === "tickets")
193
+ return ticketMetadataPage(context, page);
174
194
  const current = await snapshot(context);
175
195
  if (runId === undefined)
176
196
  return listed(context, { snapshot: current, ...page });
@@ -1,8 +1,22 @@
1
1
  import { type Fields } from "../protocol.ts";
2
2
  import type { RunView } from "../authority/status.ts";
3
- import type { ServiceContext } from "./replies.ts";
3
+ import { type ServiceContext } from "./replies.ts";
4
+ export declare function workflowMetadata(context: ServiceContext, runIds: unknown): Promise<import("../protocol.ts").Reply>;
5
+ export declare function ticketMetadataPage(context: ServiceContext, page: {
6
+ readonly after: string;
7
+ readonly limit: number;
8
+ }): Promise<import("../protocol.ts").Reply>;
4
9
  export declare function outcomeOf(context: ServiceContext, view: Pick<RunView, "state" | "runId" | "latestSequence">): Promise<Fields | null>;
5
10
  export declare function metadataOf(context: ServiceContext, source: {
6
11
  readonly workflowId: string;
7
12
  readonly digest: string | null | undefined;
8
13
  }): Promise<Fields>;
14
+ export declare function scheduleMetadata(context: ServiceContext): Promise<Fields>;
15
+ export declare function scheduledMetadata(context: ServiceContext, run: {
16
+ readonly runId: string;
17
+ readonly workflowId: string;
18
+ }): Promise<{
19
+ readonly scheduled?: {
20
+ readonly slot: number;
21
+ };
22
+ }>;
@@ -1,5 +1,43 @@
1
1
  import { issueIdentity } from "../issue-identity.js";
2
2
  import { record } from "../protocol.js";
3
+ import { invalidRequest, isIdentifier, result, } from "./replies.js";
4
+ export async function workflowMetadata(context, runIds) {
5
+ if (!Array.isArray(runIds) ||
6
+ runIds.length === 0 ||
7
+ runIds.length > 500 ||
8
+ !runIds.every(isIdentifier) ||
9
+ new Set(runIds).size !== runIds.length)
10
+ return invalidRequest("Workflow metadata needs one to 500 distinct run IDs.");
11
+ const identities = await context.authority.queries.workflowIds(runIds);
12
+ return result("run-workflow-metadata", {
13
+ runs: runIds.map((runId) => ({
14
+ runId,
15
+ workflowId: identities[runId] ?? null,
16
+ })),
17
+ });
18
+ }
19
+ export async function ticketMetadataPage(context, page) {
20
+ const state = await context.authority.state();
21
+ const identifiers = Object.keys(state.runs)
22
+ .sort()
23
+ .filter((runId) => runId > page.after);
24
+ const shown = identifiers.slice(0, page.limit);
25
+ const runs = [];
26
+ for (const runId of shown) {
27
+ const digest = state.details[runId]?.input;
28
+ const document = digest
29
+ ? await context.authority.queries.document(digest)
30
+ : "{}";
31
+ const input = record(JSON.parse(document ?? "null"));
32
+ if (input === undefined)
33
+ throw new Error("report-ticket-metadata-unavailable");
34
+ runs.push({ runId, ticketId: ticketIdOf(input) });
35
+ }
36
+ return result("run-ticket-metadata", {
37
+ runs,
38
+ next: identifiers.length > shown.length ? shown.at(-1) : null,
39
+ });
40
+ }
3
41
  export async function outcomeOf(context, view) {
4
42
  if (view.state !== "completed")
5
43
  return null;
@@ -20,13 +58,22 @@ export async function outcomeOf(context, view) {
20
58
  ...(issueUpdate === "failed" ? { issueUpdate } : {}),
21
59
  };
22
60
  }
61
+ function ticketOf(input) {
62
+ const declared = record(record(input?.["input"])?.["ticket"]);
63
+ const id = declared === undefined ? input?.["ticketId"] : declared["id"];
64
+ const text = declared === undefined ? input?.["ticket"] : declared["text"];
65
+ return {
66
+ id: typeof id === "string" ? id : undefined,
67
+ text: typeof text === "string" ? text : undefined,
68
+ };
69
+ }
23
70
  function titleOf(input, workflowId) {
24
- const ticket = input?.["ticket"];
25
- if (typeof ticket !== "string")
71
+ const ticket = ticketOf(input).text;
72
+ if (ticket === undefined)
26
73
  return null;
27
74
  const fallback = `Cloving task ${String(input?.["cycleId"])}`;
28
75
  const lines = ticket.split("\n");
29
- if (workflowId === "develop-prompt") {
76
+ if (workflowId === "develop-prompt" && !Object.hasOwn(input ?? {}, "input")) {
30
77
  const first = lines.find((line) => /\S/.test(line));
31
78
  return first === undefined
32
79
  ? fallback
@@ -42,12 +89,50 @@ export async function metadataOf(context, source) {
42
89
  ? await context.authority.queries.document(source.digest)
43
90
  : undefined;
44
91
  const input = record(JSON.parse(document ?? "null"));
45
- const ticketId = input?.["ticketId"];
46
92
  return {
47
- ticketId: typeof ticketId === "string" && ticketId !== "" ? ticketId : null,
93
+ ticketId: ticketIdOf(input),
48
94
  title: titleOf(input, source.workflowId),
49
- ...(source.workflowId === "develop-issue"
50
- ? { issueIdentity: issueIdentity(input?.["ticket"]) }
51
- : {}),
95
+ ...(ticketOf(input).text === undefined
96
+ ? {}
97
+ : { issueIdentity: issueIdentity(ticketOf(input).text) }),
98
+ };
99
+ }
100
+ function ticketIdOf(input) {
101
+ const ticketId = ticketOf(input).id;
102
+ return ticketId === undefined || ticketId === "" ? null : ticketId;
103
+ }
104
+ export async function scheduleMetadata(context) {
105
+ if (context.schedule === undefined)
106
+ return {};
107
+ const reply = await context.schedule({ action: "list" });
108
+ if (reply.kind !== "result" || !Array.isArray(reply.result["schedules"]))
109
+ return { schedules: { status: "unavailable" } };
110
+ const schedules = reply.result["schedules"];
111
+ if (schedules.length === 0)
112
+ return {};
113
+ return {
114
+ schedules: schedules.map((value) => {
115
+ const schedule = record(value) ?? {};
116
+ return Object.fromEntries([
117
+ "workflowId",
118
+ "everySeconds",
119
+ "state",
120
+ "failuresInRow",
121
+ "nextAt",
122
+ "stoppedAt",
123
+ ].map((name) => [name, schedule[name]]));
124
+ }),
52
125
  };
53
126
  }
127
+ export async function scheduledMetadata(context, run) {
128
+ const commandId = (await context.authority.queries.run(run.runId))
129
+ ?.admissionCommandId;
130
+ const prefix = `schedule:${run.workflowId}:`;
131
+ if (typeof commandId !== "string" || !commandId.startsWith(prefix))
132
+ return {};
133
+ const suffix = commandId.slice(prefix.length);
134
+ const slot = Number(suffix);
135
+ return /^(0|[1-9][0-9]*)$/.test(suffix) && Number.isSafeInteger(slot)
136
+ ? { scheduled: { slot } }
137
+ : {};
138
+ }
@@ -5,6 +5,7 @@ import { type ServiceContext } from "./replies.ts";
5
5
  import { type WorkerPort } from "./worker-port.ts";
6
6
  import type { RunWaitTarget } from "../run-wait.ts";
7
7
  import type { CommandEffects } from "../command-settings.ts";
8
+ import { type CommandWaitPort } from "./command-waits.ts";
8
9
  export type { WorkflowRegistration } from "./registry.ts";
9
10
  export type { EffectReply, EffectReport, EffectRequest, WorkerPort, } from "./worker-port.ts";
10
11
  export interface ServiceTiming {
@@ -27,6 +28,7 @@ export interface ServiceHost {
27
28
  readonly reports?: () => readonly unknown[];
28
29
  }
29
30
  export interface HostPorts {
31
+ readonly commandWait: CommandWaitPort;
30
32
  readonly runWait?: {
31
33
  readonly target: (runId: string) => Promise<RunWaitTarget | undefined>;
32
34
  readonly observe: WorkerPort["observe"];
@@ -48,6 +50,8 @@ export interface HostPorts {
48
50
  readonly registerWait: WorkerPort["registerWait"];
49
51
  }
50
52
  export interface ServiceOptions {
53
+ readonly schedule?: NonNullable<ServiceContext["schedule"]>;
54
+ readonly queueDailySpendLimitUsd?: number;
51
55
  readonly workerHarness?: ServiceContext["workerHarness"];
52
56
  readonly commandEffects?: CommandEffects;
53
57
  readonly stateDirectory: string;
@@ -9,12 +9,13 @@ import { events } from "./event-handler.js";
9
9
  import { expiryScan } from "./expiry.js";
10
10
  import { commandGateway, workerCommandBound } from "./gateway.js";
11
11
  import { workflowRegistry, } from "./registry.js";
12
- import { failed, queryMetadata } from "./replies.js";
12
+ import { errorMessage, failed, queryMetadata, scheduleRequest, } from "./replies.js";
13
13
  import { runCommand, status } from "./run-handlers.js";
14
14
  import { submissionHandler } from "./submission-handler.js";
15
15
  import { connectionLimits, listen, reachable } from "./transport.js";
16
16
  import { workerPort } from "./worker-port.js";
17
17
  import { runWaitTarget } from "./run-waits.js";
18
+ import { commandWaitPort } from "./command-waits.js";
18
19
  export const serviceTiming = {
19
20
  authority: authorityTiming,
20
21
  expiryScanMilliseconds: 1_000,
@@ -59,6 +60,7 @@ function dispatcher(context) {
59
60
  const run = submissionHandler(context);
60
61
  const operations = new Map([
61
62
  ["run", (request) => run(request.parameters)],
63
+ ["schedule", (request) => scheduleRequest(context, request.parameters)],
62
64
  ["status", (request) => status(context, request.parameters)],
63
65
  ["questions", (request) => questions(context, request.parameters)],
64
66
  ["decision", (request) => decision(context, request.parameters)],
@@ -149,7 +151,7 @@ export async function startService(options) {
149
151
  const { authority } = opening;
150
152
  const gateway = serviceGateway(authority, { options, registry });
151
153
  const worker = workerPort({ gateway, authority });
152
- const host = await hosted(options, hostPorts(authority, { worker, registry }));
154
+ const host = await hosted(options, hostPorts(authority, { worker, registry, gateway }));
153
155
  if (host.kind === "refused") {
154
156
  await authority.close();
155
157
  return host;
@@ -169,8 +171,8 @@ export async function startService(options) {
169
171
  };
170
172
  }
171
173
  catch (error) {
172
- const unclosed = await released(authority, host.host).then(() => "", (failure) => `; the close failed: ${message(failure)}`);
173
- return refused("transport-failure", `${message(error)}${unclosed}`);
174
+ const unclosed = await released(authority, host.host).then(() => "", (failure) => `; the close failed: ${errorMessage(failure)}`);
175
+ return refused("transport-failure", `${errorMessage(error)}${unclosed}`);
174
176
  }
175
177
  }
176
178
  function serviceGateway(authority, parts) {
@@ -186,6 +188,7 @@ function serviceGateway(authority, parts) {
186
188
  function hostPorts(authority, parts) {
187
189
  const { worker, registry } = parts;
188
190
  return {
191
+ commandWait: commandWaitPort({ authority, gateway: parts.gateway }),
189
192
  runWait: {
190
193
  target: (runId) => runWaitTarget(authority, runId),
191
194
  observe: worker.observe,
@@ -217,14 +220,11 @@ function hostPorts(authority, parts) {
217
220
  },
218
221
  };
219
222
  }
220
- function message(error) {
221
- return String(Reflect.get(Object(error), "message"));
222
- }
223
223
  async function hosted(options, ports) {
224
224
  try {
225
225
  return { kind: "started", host: await options.host?.(ports) };
226
226
  }
227
227
  catch (error) {
228
- return refused("host-unavailable", message(error));
228
+ return refused("host-unavailable", errorMessage(error));
229
229
  }
230
230
  }
@@ -7,6 +7,7 @@ import { documentDigest } from "../broker/decision-restore.js";
7
7
  import { record } from "../protocol.js";
8
8
  import { checkResolution, checkSubmission, hasTicketField, normalizedRequest, } from "../submission.js";
9
9
  import { activeWorkflow } from "./active-tickets.js";
10
+ import { queueSpend } from "./queue-spend.js";
10
11
  import { committed, failed, invalidRequest, publicReceipt, rejection, result, } from "./replies.js";
11
12
  export function runIdentity(commandId) {
12
13
  return `run-${createHash("sha256").update(commandId).digest("hex").slice(0, 32)}`;
@@ -125,6 +126,9 @@ async function admit(context, admission) {
125
126
  const { input } = resolution;
126
127
  if (Buffer.byteLength(input) > context.documentBytes)
127
128
  return unresolved(context, { kind: "failure", commandId });
129
+ const held = await spendRefusal(context, admission);
130
+ if (held !== undefined)
131
+ return held;
128
132
  const receipt = await context.gateway.execute({
129
133
  principal: "operator",
130
134
  command: {
@@ -155,9 +159,20 @@ async function admit(context, admission) {
155
159
  replayed: receipt.kind === "duplicate",
156
160
  });
157
161
  }
162
+ async function spendRefusal(context, admission) {
163
+ if (admission.workflow.manifest.queue !== true)
164
+ return undefined;
165
+ const spend = record((await queueSpend(context))["spend"]);
166
+ return spend?.["holding"] === true
167
+ ? failed("queue-spend-limit", {
168
+ commandId: admission.commandId,
169
+ detail: "Queue holding for spend limit.",
170
+ })
171
+ : undefined;
172
+ }
158
173
  function admissionRefusal(workflow, request) {
159
- const { workflowId, commandId, submission, activeTickets } = request;
160
- const tickets = workflowId === "develop-issue" || hasTicketField(workflow.submission);
174
+ const { commandId, submission, activeTickets } = request;
175
+ const tickets = hasTicketField(workflow.submission);
161
176
  if (tickets &&
162
177
  typeof submission["ticket"] === "string" &&
163
178
  activeTickets.some((input) => input["ticketId"] === submission["ticket"]))
@@ -235,8 +250,7 @@ export function submissionHandler(context) {
235
250
  return (parameters) => {
236
251
  const keys = [`command:${String(parameters["commandId"])}`];
237
252
  const workflowId = String(parameters["workflowId"]);
238
- if (workflowId === "develop-issue" ||
239
- hasTicketField(context.registry.byId(workflowId)?.submission) ||
253
+ if (hasTicketField(context.registry.byId(workflowId)?.submission) ||
240
254
  context.registry.byId(workflowId)?.admission !== undefined)
241
255
  keys.push(`workflow:${workflowId}`);
242
256
  const next = () => submitted(context, parameters);
@@ -86,7 +86,7 @@ function effectPort(parts) {
86
86
  command: {
87
87
  kind: "report-effect",
88
88
  ...rest,
89
- ...(result === undefined ? {} : { result: documentDigest(result) }),
89
+ ...reportedResult({ result, worker: report.worker }),
90
90
  },
91
91
  documents: result === undefined ? [] : [result],
92
92
  epoch: epoch ?? authority.epoch,
@@ -124,3 +124,11 @@ export function workerPort(parts) {
124
124
  ...effectPort(parts),
125
125
  };
126
126
  }
127
+ function reportedResult(report) {
128
+ if (report.result === undefined)
129
+ return {};
130
+ return {
131
+ result: documentDigest(report.result),
132
+ ...(report.worker === "command" ? { commandOutput: report.result } : {}),
133
+ };
134
+ }
@@ -1,3 +1,5 @@
1
+ import { type Fields } from "../protocol.ts";
1
2
  import { type WorkerTotals } from "../worker-usage.ts";
2
3
  import type { ServiceContext } from "./replies.ts";
4
+ export declare function reportFields(text: string | undefined): Fields;
3
5
  export declare function usageTotals(context: ServiceContext, runId: string): Promise<WorkerTotals>;
@@ -1,6 +1,6 @@
1
1
  import { record } from "../protocol.js";
2
2
  import { priceOf, usageOf, attemptsOf, workerTotals, } from "../worker-usage.js";
3
- function reportFields(text) {
3
+ export function reportFields(text) {
4
4
  try {
5
5
  return record(JSON.parse(text ?? "null")) ?? {};
6
6
  }
@@ -64,6 +64,22 @@ export interface RunWaitOutcome {
64
64
  readonly reason: string | null;
65
65
  readonly promotionId: string | null;
66
66
  }
67
+ export interface CommandWaitRequest {
68
+ readonly name: string;
69
+ readonly input: HandoffValue;
70
+ }
71
+ export type CommandWaitOutcome = {
72
+ readonly kind: "ready";
73
+ readonly value: HandoffValue;
74
+ } | {
75
+ readonly kind: "timed-out" | "failed" | "refused" | "unavailable";
76
+ readonly reason: string;
77
+ };
78
+ export type CommandWaitProgress = CommandWaitOutcome | {
79
+ readonly kind: "pending";
80
+ readonly deadline: number;
81
+ readonly nextCheckAt: number;
82
+ };
67
83
  export interface CommandRequest {
68
84
  readonly scope: ProtectedScope;
69
85
  readonly name: string;
@@ -80,6 +96,10 @@ export type GateResult = {
80
96
  readonly reason: string;
81
97
  };
82
98
  export interface StepBridge {
99
+ readonly openCommandWait?: (request: CommandWaitRequest) => Promise<CommandWaitProgress>;
100
+ readonly checkCommandWait?: (request: {
101
+ readonly name: string;
102
+ }) => Promise<CommandWaitProgress>;
83
103
  readonly effect: (request: ProtectedRequest) => Promise<ProtectedResult>;
84
104
  readonly gate: (request: GateRequest) => Promise<GateResult>;
85
105
  readonly waitForDecision?: (request: GateRequest) => Promise<DecisionWait>;
@@ -0,0 +1,12 @@
1
+ import { type CommandWaitRequest, type CommandWaitProgress } from "../command-wait.ts";
2
+ export declare function openCommandWait(request: CommandWaitRequest): Promise<CommandWaitProgress>;
3
+ export declare namespace openCommandWait {
4
+ var maxRetries: number;
5
+ }
6
+ export declare function checkCommandWait(request: {
7
+ readonly name: string;
8
+ }): Promise<CommandWaitProgress>;
9
+ export declare namespace checkCommandWait {
10
+ var maxRetries: number;
11
+ }
12
+ export declare function commandWaitDate(milliseconds: number): Date;
@@ -0,0 +1,26 @@
1
+ import { isStepBridge, stepBridgeKey } from "../step-bridge.js";
2
+ import { isCommandWaitRequest, } from "../command-wait.js";
3
+ export async function openCommandWait(request) {
4
+ "use step";
5
+ if (!isCommandWaitRequest(request))
6
+ return { kind: "refused", reason: "invalid-command-wait-request" };
7
+ const bridge = Reflect.get(globalThis, Symbol.for(stepBridgeKey));
8
+ if (!isStepBridge(bridge) || bridge.openCommandWait === undefined)
9
+ return { kind: "unavailable", reason: "cloving-host-unavailable" };
10
+ return await bridge.openCommandWait({
11
+ name: request.name,
12
+ input: request.input,
13
+ });
14
+ }
15
+ export async function checkCommandWait(request) {
16
+ "use step";
17
+ const bridge = Reflect.get(globalThis, Symbol.for(stepBridgeKey));
18
+ if (!isStepBridge(bridge) || bridge.checkCommandWait === undefined)
19
+ return { kind: "unavailable", reason: "cloving-host-unavailable" };
20
+ return await bridge.checkCommandWait({ name: request.name });
21
+ }
22
+ openCommandWait.maxRetries = 0;
23
+ checkCommandWait.maxRetries = 0;
24
+ export function commandWaitDate(milliseconds) {
25
+ return new Date(milliseconds);
26
+ }
@@ -0,0 +1,2 @@
1
+ import { type GateRequest, type DecisionWait } from "../step-bridge.ts";
2
+ export declare function openDecisionWait(request: GateRequest): Promise<DecisionWait>;
@@ -1,11 +1,4 @@
1
1
  import { isStepBridge, stepBridgeKey, } from "../step-bridge.js";
2
- export async function decisionGate(request) {
3
- "use step";
4
- const bridge = Reflect.get(globalThis, Symbol.for(stepBridgeKey));
5
- if (!isStepBridge(bridge))
6
- return { kind: "unavailable", reason: "cloving-host-unavailable" };
7
- return await bridge.gate(request);
8
- }
9
2
  export async function openDecisionWait(request) {
10
3
  "use step";
11
4
  const bridge = Reflect.get(globalThis, Symbol.for(stepBridgeKey));
@@ -1,11 +1,14 @@
1
1
  import { snapshotReviewSubject } from "./review-subject.js";
2
2
  import { waitForDecision } from "./wait-for-decision.js";
3
3
  export async function reviewByPerson(request) {
4
+ let draft = "draft" in request.subject ? request.subject.draft : null;
5
+ if (draft !== null && request.subject.commit !== undefined)
6
+ draft = `${request.subject.commit}\n${draft}`;
4
7
  const snapshot = await snapshotReviewSubject(request.subject);
5
8
  const decision = await waitForDecision({
6
9
  gateId: `review:${snapshot.subjectDigest}`,
7
10
  kind: "approval",
8
- prompt: `Review this subject:\n${snapshot.prompt}`,
11
+ prompt: `Review this subject:\n${draft ?? snapshot.prompt}`,
9
12
  });
10
13
  return {
11
14
  accepted: decision.decision === "approved",
@@ -0,0 +1,3 @@
1
+ import { type CommandWaitRequest, type CommandWaitOutcome } from "../command-wait.ts";
2
+ export type { CommandWaitRequest, CommandWaitOutcome, } from "../command-wait.ts";
3
+ export declare function waitForCommand(request: CommandWaitRequest): Promise<CommandWaitOutcome>;
@@ -0,0 +1,17 @@
1
+ import { sleep } from "workflow";
2
+ import { isCommandWaitRequest, } from "../command-wait.js";
3
+ import { openCommandWait, checkCommandWait, commandWaitDate, } from "./command-wait.js";
4
+ export async function waitForCommand(request) {
5
+ if (!isCommandWaitRequest(request))
6
+ return { kind: "refused", reason: "invalid-command-wait-request" };
7
+ let result = await openCommandWait({
8
+ name: request.name,
9
+ input: request.input,
10
+ });
11
+ while (result.kind === "pending") {
12
+ result = await checkCommandWait({ name: request.name });
13
+ if (result.kind === "pending")
14
+ await sleep(commandWaitDate(Math.min(result.deadline, result.nextCheckAt)));
15
+ }
16
+ return result;
17
+ }
@@ -51,7 +51,7 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
51
51
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
52
52
  });
53
53
  import { createHook } from "workflow";
54
- import { openDecisionWait } from "./decision-gate.js";
54
+ import { openDecisionWait } from "./open-decision-wait.js";
55
55
  export async function waitForDecision(request) {
56
56
  const env_1 = { stack: [], error: void 0, hasError: false };
57
57
  try {
@@ -0,0 +1,30 @@
1
+ import { type SqlConnection } from "./domain-rows.ts";
2
+ import { type Statement } from "./statements.ts";
3
+ export declare const commandWaitSchema = "\nCREATE TABLE command_waits (\n run_id TEXT NOT NULL REFERENCES runs (run_id) DEFERRABLE INITIALLY DEFERRED,\n name TEXT NOT NULL,\n command TEXT NOT NULL,\n input_digest TEXT NOT NULL REFERENCES documents (digest) DEFERRABLE INITIALLY DEFERRED,\n maximum_wait_seconds INTEGER NOT NULL,\n poll_every_seconds INTEGER NOT NULL,\n started_at INTEGER NOT NULL,\n deadline INTEGER NOT NULL,\n next_check_at INTEGER,\n state TEXT NOT NULL,\n settled_at INTEGER,\n reason TEXT,\n PRIMARY KEY (run_id, name)\n) STRICT;\n";
4
+ export declare const commandWaitCheckSchema = "\nALTER TABLE command_waits ADD COLUMN check_count INTEGER NOT NULL DEFAULT 0;\nALTER TABLE command_waits ADD COLUMN check_operation TEXT;\nALTER TABLE command_waits ADD COLUMN last_check_settled_at INTEGER;\nALTER TABLE command_waits ADD COLUMN result TEXT;\n";
5
+ export interface CommandWaitRow {
6
+ readonly runId: string;
7
+ readonly name: string;
8
+ readonly command: string;
9
+ readonly inputDigest: string;
10
+ readonly maximumWaitSeconds: number;
11
+ readonly pollEverySeconds: number;
12
+ readonly startedAt: number;
13
+ readonly deadline: number;
14
+ readonly nextCheckAt: number | null;
15
+ readonly state: string;
16
+ readonly checkCount: number;
17
+ readonly checkOperation: string | null;
18
+ readonly lastCheckSettledAt: number | null;
19
+ readonly result: string | null;
20
+ readonly settledAt: number | null;
21
+ readonly reason: string | null;
22
+ }
23
+ export declare function commandWaitRow(value: unknown): CommandWaitRow;
24
+ export declare function loadCommandWaits(connection: SqlConnection, scope?: {
25
+ readonly runId?: string;
26
+ readonly version?: "opened";
27
+ }): Promise<readonly CommandWaitRow[]>;
28
+ export declare function commandWaitStatements(rows: readonly CommandWaitRow[], scope?: {
29
+ readonly version?: "opened";
30
+ }): readonly Statement[];