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
@@ -1,4 +1,4 @@
1
- import { adapters, recoverCommands, } from "./daemon-adapters.js";
1
+ import { adapters, recoverCommands, recoverClaude, } from "./daemon-adapters.js";
2
2
  import { mkdir, realpath } from "node:fs/promises";
3
3
  import { join } from "node:path";
4
4
  import { registerStepBridge, sdkStepCall, stepBridge, } from "../host/step-bridge-host.js";
@@ -12,8 +12,14 @@ import { commandEffects } from "./command-journal.js";
12
12
  import { worldDirectory } from "./host-environment.js";
13
13
  import { pinnedWorkflowHandler } from "./workflow-replay.js";
14
14
  import { scheduledDeclarations } from "./workflow-schedules.js";
15
+ import { scheduleConnection } from "./schedule-control.js";
16
+ import { queueConnection } from "./queue-control.js";
15
17
  import { daemonLoops } from "./daemon-loops.js";
16
- import { ticketRegistrations, ticketRegistrationTable, issueWorkflow, } from "./ticket-registration.js";
18
+ import { authorityRuns, recordRetention } from "./record-sweep.js";
19
+ import { turnDetailsPlace } from "./turn-details.js";
20
+ import { defaultRetention } from "../record-retention.js";
21
+ import { clovingVersion } from "../cli/toolchain.js";
22
+ import { daemonRegistrations, queueWorkflowId, workflowReload, } from "./workflow-reload.js";
17
23
  export const turnLeaseMilliseconds = 4 * 3_600_000;
18
24
  export const loopMilliseconds = 250;
19
25
  export const bridgeTiming = {
@@ -65,45 +71,6 @@ async function hosted(settings, hosting) {
65
71
  },
66
72
  };
67
73
  }
68
- async function daemonRegistrations(settings) {
69
- const conflict = settings.workflowRefusals?.find((refusal) => refusal.codes.includes("queue-workflow-conflict"));
70
- if (conflict !== undefined)
71
- return {
72
- table: [],
73
- admitted: {
74
- kind: "rejected",
75
- detail: `queue-workflow-conflict: ${conflict.scope} ${conflict.label}`,
76
- },
77
- };
78
- const table = ticketRegistrationTable({
79
- repository: settings.repository,
80
- command: settings.ticketCommand,
81
- nextCommand: settings.nextCommand,
82
- githubCommand: settings.githubCommand,
83
- }, settings.declarations);
84
- const admitted = await ticketRegistrations(settings.manifests, {
85
- table,
86
- commands: settings.commands ?? {},
87
- ...(settings.bundleDigest === undefined
88
- ? {}
89
- : { bundleDigest: settings.bundleDigest }),
90
- });
91
- return {
92
- table,
93
- admitted: admitted.kind === "rejected"
94
- ? admitted
95
- : {
96
- ...admitted,
97
- registrations: admitted.registrations.map((registration) => ({
98
- ...registration,
99
- ...(settings.queueMilliseconds !== undefined &&
100
- registration.workflowId === queueWorkflowId(settings)
101
- ? { admission: settings.queueLanes ?? 1, queue: true }
102
- : {}),
103
- })),
104
- },
105
- };
106
- }
107
74
  export async function startDaemon(givenSettings) {
108
75
  const repository = await realpath(givenSettings.repository);
109
76
  const scheduled = scheduledDeclarations(givenSettings, {
@@ -118,16 +85,56 @@ export async function startDaemon(givenSettings) {
118
85
  repository,
119
86
  });
120
87
  }
88
+ function controlConnections() {
89
+ return { schedules: scheduleConnection(), queues: queueConnection() };
90
+ }
91
+ function retentionReads(settings, ports) {
92
+ return turnDetailsPlace({
93
+ directory: settings.directory,
94
+ retention: settings.retention ?? defaultRetention,
95
+ runs: async (runIds) => authorityRuns(await ports)(runIds),
96
+ now: settings.retentionClock ?? Date.now,
97
+ });
98
+ }
99
+ function rejectedOpening(detail) {
100
+ return {
101
+ kind: "refused",
102
+ reason: detail.startsWith("queue-workflow-conflict")
103
+ ? "queue-workflow-conflict"
104
+ : "workflow-rejected",
105
+ detail,
106
+ };
107
+ }
108
+ function workflowOptions(settings, parts) {
109
+ const { reloadCommand, loadBundle } = settings;
110
+ const { generations, turnSettings } = parts;
111
+ return {
112
+ workflowBundles: {
113
+ directory: join(settings.directory, "workflow-bundles"),
114
+ repository: settings.repository,
115
+ },
116
+ workflowRefusals: settings.workflowRefusals ?? [],
117
+ retainedWorkflow: generations.available,
118
+ ...(settings.bundleDigest === undefined
119
+ ? {}
120
+ : { bundleDigest: settings.bundleDigest }),
121
+ ...(reloadCommand === undefined || loadBundle === undefined
122
+ ? {}
123
+ : {
124
+ reload: workflowReload({
125
+ ...settings,
126
+ reloadCommand,
127
+ loadBundle,
128
+ generations,
129
+ turnSettings,
130
+ }),
131
+ }),
132
+ };
133
+ }
121
134
  async function openDaemon(settings) {
122
135
  const { table, admitted } = await daemonRegistrations(settings);
123
136
  if (admitted.kind === "rejected")
124
- return {
125
- kind: "refused",
126
- reason: admitted.detail.startsWith("queue-workflow-conflict")
127
- ? "queue-workflow-conflict"
128
- : "workflow-rejected",
129
- detail: admitted.detail,
130
- };
137
+ return rejectedOpening(admitted.detail);
131
138
  const given = Promise.withResolvers();
132
139
  const generations = workflowGenerations({
133
140
  ...settings,
@@ -138,18 +145,21 @@ async function openDaemon(settings) {
138
145
  const { worker, github, runs, handoff, commands } = resources;
139
146
  await mkdir(join(settings.directory, "state"), { recursive: true });
140
147
  await mkdir(settings.runtimeDirectory, { recursive: true, mode: 0o700 });
148
+ const controls = controlConnections();
141
149
  const opening = await startService({
150
+ version: clovingVersion,
151
+ schedule: controls.schedules.request,
152
+ queue: controls.queues.port,
153
+ ...(settings.queueDailySpendLimitUsd === undefined
154
+ ? {}
155
+ : { queueDailySpendLimitUsd: settings.queueDailySpendLimitUsd }),
142
156
  workerHarness: worker.harness,
157
+ turnDetails: retentionReads(settings, given.promise),
143
158
  commandEffects: commandEffects(join(settings.directory, "commands")),
144
159
  stateDirectory: join(settings.directory, "state"),
145
160
  runtimeDirectory: settings.runtimeDirectory,
146
- workflowBundles: {
147
- directory: join(settings.directory, "workflow-bundles"),
148
- repository: settings.repository,
149
- },
150
- workflowRefusals: settings.workflowRefusals ?? [],
161
+ ...workflowOptions(settings, { ...resources, generations }),
151
162
  workflows: admitted.registrations,
152
- retainedWorkflow: generations.available,
153
163
  delivery: deliveryRouter({
154
164
  runs,
155
165
  effects: { claude: worker, github, handoff, command: commands },
@@ -164,16 +174,18 @@ async function openDaemon(settings) {
164
174
  await closeWorkers(resources);
165
175
  return opening;
166
176
  }
167
- const running = { ...resources, service: opening.service };
177
+ const running = { ...resources, ...controls, service: opening.service };
168
178
  await recoverWorkers(running, given.promise);
169
179
  return {
170
180
  kind: "started",
171
- daemon: await runningDaemon(settings, running),
181
+ daemon: await runningDaemon(settings, { ...running, ports: given.promise }),
172
182
  };
173
183
  }
174
184
  async function recoverWorkers(resources, ports) {
175
185
  try {
176
- await recoverCommands(resources.commands, await ports);
186
+ const host = await ports;
187
+ await recoverCommands(resources.commands, host);
188
+ await recoverClaude(resources.worker, host);
177
189
  }
178
190
  catch (error) {
179
191
  await Promise.allSettled([
@@ -192,12 +204,22 @@ async function closeWorkers(resources) {
192
204
  }
193
205
  async function runningDaemon(settings, resources) {
194
206
  const { service, github } = resources;
207
+ const retention = await recordRetention({
208
+ directory: settings.directory,
209
+ retention: settings.retention ?? defaultRetention,
210
+ runs: authorityRuns(await resources.ports),
211
+ now: settings.retentionClock ?? Date.now,
212
+ log: (line) => process.stderr.write(line),
213
+ });
195
214
  await github.scan();
196
215
  const loops = await daemonLoops({
197
216
  ...settings,
217
+ scheduleConnection: resources.schedules,
218
+ queueConnection: resources.queues,
198
219
  submit: service.worker.submit,
199
220
  queueWorkflowId: queueWorkflowId(settings),
200
221
  }).catch(async (error) => {
222
+ await retention.stop();
201
223
  await closeWorkers(resources);
202
224
  await service.close();
203
225
  throw error;
@@ -205,13 +227,10 @@ async function runningDaemon(settings, resources) {
205
227
  return {
206
228
  socket: service.socket,
207
229
  close: async () => {
230
+ await retention.stop();
208
231
  await loops.stop();
209
232
  await closeWorkers(resources);
210
233
  await service.close();
211
234
  },
212
235
  };
213
236
  }
214
- function queueWorkflowId(settings) {
215
- return (settings.declarations?.find((declaration) => declaration.queue === true)
216
- ?.workflowId ?? issueWorkflow);
217
- }
@@ -0,0 +1,2 @@
1
+ import { type Operation } from "./github-operation.ts";
2
+ export declare function attachAsset(operation: Operation): Promise<unknown>;
@@ -0,0 +1,222 @@
1
+ import { rm, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { copiedAttachment, openedAttachment } from "./attachment-file.js";
4
+ import { attachmentFolder } from "./attachments.js";
5
+ import { repositoryName } from "./github-issue-methods.js";
6
+ import { issuePrivacy, operatorPrivateTexts } from "./github-issue-privacy.js";
7
+ import { field, repositoryPath, text, } from "./github-operation.js";
8
+ import { githubRead } from "./github-retry.js";
9
+ import { inTurn } from "./merge-turns.js";
10
+ function isList(value) {
11
+ return Array.isArray(value);
12
+ }
13
+ function validName(name) {
14
+ return /^[\w-][\w.-]*\.(?:mp4|webm|png)$/.test(name) && !name.includes("..");
15
+ }
16
+ function validRelease(release) {
17
+ return /^[a-z][a-z0-9-]{0,63}$/.test(release) && !/^v\d/.test(release);
18
+ }
19
+ function placeOf(operation) {
20
+ const place = operation.payload["place"] ?? "comment";
21
+ if (place !== "comment" && place !== "description")
22
+ throw new Error("invalid-payload");
23
+ return place;
24
+ }
25
+ function attachmentOf(operation) {
26
+ const number = operation.payload["number"];
27
+ const name = text(operation, "name");
28
+ const release = text(operation, "release");
29
+ const comment = text(operation, "comment");
30
+ if (typeof number !== "number" || !Number.isSafeInteger(number) || number < 1)
31
+ throw new Error("invalid-payload");
32
+ if (!validName(name) || !validRelease(release) || comment.length > 4000)
33
+ throw new Error("invalid-payload");
34
+ return { number, name, release, comment, place: placeOf(operation) };
35
+ }
36
+ function attachedFile(operation, name) {
37
+ return openedAttachment({
38
+ folder: attachmentFolder({
39
+ worktrees: operation.settings.worktrees,
40
+ target: operation.target,
41
+ }),
42
+ name,
43
+ });
44
+ }
45
+ async function pages(operation, path) {
46
+ const reply = JSON.parse(await githubRead(operation, ["api", "--paginate", "--slurp", path]));
47
+ if (!isList(reply))
48
+ throw new Error("github-call-failed");
49
+ return reply.flatMap((page) => {
50
+ if (!isList(page))
51
+ throw new Error("github-call-failed");
52
+ return page;
53
+ });
54
+ }
55
+ async function releaseOf(operation, tag) {
56
+ const releases = await pages(operation, `${repositoryPath}/releases?per_page=100`);
57
+ return releases.find((item) => field(item, "tag_name") === tag);
58
+ }
59
+ async function ensuredRelease(operation, release) {
60
+ if ((await releaseOf(operation, release)) !== undefined)
61
+ return;
62
+ try {
63
+ await operation.calls.gh([
64
+ "release",
65
+ "create",
66
+ release,
67
+ "--prerelease",
68
+ "--latest=false",
69
+ "--title",
70
+ "Pull request demos",
71
+ "--notes",
72
+ "Demo videos of pull requests. Cloving uploads them.",
73
+ ]);
74
+ }
75
+ catch (error) {
76
+ if ((await releaseOf(operation, release)) === undefined)
77
+ throw error;
78
+ }
79
+ }
80
+ async function uploaded(operation, attachment) {
81
+ const { release } = attachment;
82
+ await ensuredRelease(operation, release);
83
+ const asset = `pr-${String(attachment.number)}-${attachment.name}`;
84
+ const copy = join(operation.folder, asset);
85
+ try {
86
+ await copiedAttachment(attachment.file, copy);
87
+ await operation.calls.gh(["release", "upload", release, copy, "--clobber"]);
88
+ }
89
+ finally {
90
+ await rm(copy, { force: true });
91
+ }
92
+ const assets = field(await releaseOf(operation, release), "assets");
93
+ const found = isList(assets)
94
+ ? assets.find((item) => field(item, "name") === asset)
95
+ : undefined;
96
+ const url = field(found, "browser_download_url");
97
+ if (typeof url !== "string" || !url.startsWith("https://"))
98
+ throw new Error("github-call-failed");
99
+ return url;
100
+ }
101
+ async function ownLogin(operation) {
102
+ const user = JSON.parse(await githubRead(operation, ["api", "user"]));
103
+ const login = field(user, "login");
104
+ if (typeof login !== "string" || login === "")
105
+ throw new Error("github-call-failed");
106
+ return login;
107
+ }
108
+ async function commented(operation, attachment) {
109
+ const { number, name, url } = attachment;
110
+ const marker = `<!-- cloving-attachment:${String(number)}:${name} -->`;
111
+ const body = `${attachment.comment}\n\n[${name}](${url})\n\n${marker}`;
112
+ const comments = await pages(operation, `${repositoryPath}/issues/${String(number)}/comments?per_page=100`);
113
+ const login = await ownLogin(operation);
114
+ const known = comments.find((item) => {
115
+ const existing = field(item, "body");
116
+ return (typeof existing === "string" &&
117
+ existing.includes(marker) &&
118
+ field(field(item, "user"), "login") === login);
119
+ });
120
+ const id = field(known, "id");
121
+ if (typeof id === "number") {
122
+ await operation.calls.gh([
123
+ "api",
124
+ "-X",
125
+ "PATCH",
126
+ `${repositoryPath}/issues/comments/${String(id)}`,
127
+ "-f",
128
+ `body=${body}`,
129
+ ]);
130
+ return;
131
+ }
132
+ await operation.calls.gh([
133
+ "api",
134
+ `${repositoryPath}/issues/${String(number)}/comments`,
135
+ "-f",
136
+ `body=${body}`,
137
+ ]);
138
+ }
139
+ function withSection(body, marks) {
140
+ const from = body.indexOf(marks.start);
141
+ const to = from < 0 ? -1 : body.indexOf(marks.end, from);
142
+ if (to >= 0)
143
+ return (body.slice(0, from) + marks.section + body.slice(to + marks.end.length));
144
+ const kept = body.trimEnd();
145
+ return kept === "" ? marks.section : `${kept}\n\n${marks.section}`;
146
+ }
147
+ async function pullBody(operation, number) {
148
+ const pull = JSON.parse(await githubRead(operation, [
149
+ "api",
150
+ `${repositoryPath}/pulls/${String(number)}`,
151
+ ]));
152
+ const body = field(pull, "body");
153
+ return typeof body === "string" ? body : "";
154
+ }
155
+ function attachedUrl(body, marks) {
156
+ const from = body.indexOf(marks.start);
157
+ const to = from < 0 ? -1 : body.indexOf(marks.end, from);
158
+ const url = to < 0 ? "" : (body.slice(from, to).trimEnd().split("\n").at(-1) ?? "");
159
+ if (!/^https:\/\/github\.com\/user-attachments\/assets\/[\w-]+$/.test(url))
160
+ throw new Error("github-call-failed");
161
+ return url;
162
+ }
163
+ async function described(operation, attachment) {
164
+ const { number, name } = attachment;
165
+ const start = `<!-- cloving-attachment:${String(number)}:${name} -->`;
166
+ const end = `<!-- /cloving-attachment:${String(number)}:${name} -->`;
167
+ const section = `${start}\n${attachment.comment}\n\n![${name}](./${name})\n${end}`;
168
+ const copy = join(operation.folder, name);
169
+ const text = join(operation.folder, "body.md");
170
+ const turn = {
171
+ key: `${operation.settings.repository}#pull-${String(number)}`,
172
+ signal: operation.signal,
173
+ };
174
+ try {
175
+ await copiedAttachment(attachment.file, copy);
176
+ await inTurn(turn, async () => {
177
+ const current = await pullBody(operation, number);
178
+ await writeFile(text, withSection(current, { start, end, section }), "utf8");
179
+ await operation.calls.gh([
180
+ "pr",
181
+ "edit",
182
+ String(number),
183
+ "--body-file",
184
+ text,
185
+ "--attach",
186
+ copy,
187
+ ]);
188
+ });
189
+ }
190
+ finally {
191
+ await rm(copy, { force: true });
192
+ await rm(text, { force: true });
193
+ }
194
+ return attachedUrl(await pullBody(operation, number), {
195
+ start,
196
+ end,
197
+ });
198
+ }
199
+ async function delivered(operation, attachment) {
200
+ if (attachment.place === "description")
201
+ return await described(operation, attachment);
202
+ const url = await uploaded(operation, attachment);
203
+ await commented(operation, { ...attachment, url });
204
+ return url;
205
+ }
206
+ export async function attachAsset(operation) {
207
+ const attachment = attachmentOf(operation);
208
+ operatorPrivateTexts(operation.settings);
209
+ const repository = repositoryName(await operation.calls.gh(["repo", "view", "--json", "nameWithOwner"]));
210
+ issuePrivacy(attachment.comment, {
211
+ settings: operation.settings,
212
+ repository,
213
+ });
214
+ const file = await attachedFile(operation, attachment.name);
215
+ try {
216
+ const url = await delivered(operation, { ...attachment, file });
217
+ return { number: attachment.number, url };
218
+ }
219
+ finally {
220
+ await file.close();
221
+ }
222
+ }
@@ -24,7 +24,7 @@ function failureDetail(error, place) {
24
24
  const text = typeof stderr === "string" ? stderr : "";
25
25
  return {
26
26
  detail: githubText(text, place).slice(-2_000),
27
- status: Number(/\(HTTP (\d{3})\)/.exec(text)?.[1]),
27
+ status: Number(/\bHTTP (\d{3})\b/.exec(text)?.[1]),
28
28
  };
29
29
  }
30
30
  export function githubText(text, settings) {
@@ -0,0 +1,6 @@
1
+ export declare function triggerKind(trigger: unknown): "push" | "event";
2
+ export declare function pullRequestTrigger(source: string): unknown;
3
+ export declare function workflowApplies(trigger: unknown, context: {
4
+ readonly branch: string;
5
+ readonly paths: readonly string[];
6
+ }): boolean;
@@ -0,0 +1,138 @@
1
+ import { parse } from "yaml";
2
+ function isRecord(value) {
3
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4
+ }
5
+ export function triggerKind(trigger) {
6
+ if (!isRecord(trigger))
7
+ return "push";
8
+ const types = patterns(trigger["types"]);
9
+ return types === undefined || types.includes("synchronize")
10
+ ? "push"
11
+ : "event";
12
+ }
13
+ export function pullRequestTrigger(source) {
14
+ try {
15
+ const document = parse(source, { merge: true });
16
+ if (!isRecord(document) || !("on" in document))
17
+ return true;
18
+ const events = document["on"];
19
+ if (typeof events === "string")
20
+ return events === "pull_request";
21
+ if (Array.isArray(events))
22
+ return events.includes("pull_request");
23
+ if (isRecord(events))
24
+ return "pull_request" in events ? events["pull_request"] : false;
25
+ return true;
26
+ }
27
+ catch {
28
+ return true;
29
+ }
30
+ }
31
+ function patternToken(token) {
32
+ if (token === "**/")
33
+ return { kind: "directory" };
34
+ if (token === "*" || token === "**")
35
+ return {
36
+ kind: "character",
37
+ matcher: token === "*" ? /[^/]/ : /[\s\S]/,
38
+ optional: true,
39
+ repeat: true,
40
+ };
41
+ const literal = token.startsWith("\\") ? token.slice(1) : token;
42
+ const source = token.startsWith("[")
43
+ ? token
44
+ : literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
45
+ return {
46
+ kind: "character",
47
+ matcher: new RegExp(`^${source}$`),
48
+ optional: false,
49
+ repeat: false,
50
+ };
51
+ }
52
+ function patternTokens(source) {
53
+ const tokens = [];
54
+ for (const raw of source.match(/\*\*\/|\*\*|\*|\[[a-zA-Z0-9-]+\]|\\[\s\S]|[\s\S]/g) ?? []) {
55
+ if (raw !== "?" && raw !== "+") {
56
+ tokens.push(patternToken(raw));
57
+ continue;
58
+ }
59
+ const previous = tokens.pop();
60
+ if (previous?.kind !== "character" || previous.optional || previous.repeat)
61
+ throw new Error("invalid-workflow-filter");
62
+ tokens.push({ ...previous, optional: raw === "?", repeat: raw === "+" });
63
+ }
64
+ return tokens;
65
+ }
66
+ function advanceDirectory({ value, previous, }) {
67
+ let reachable = false;
68
+ return Array.from({ length: value.length + 1 }, (_, index) => {
69
+ const matches = previous[index] === true || (reachable && value[index - 1] === "/");
70
+ reachable ||= previous[index] === true;
71
+ return matches;
72
+ });
73
+ }
74
+ function advancePattern(token, input) {
75
+ const { value, previous } = input;
76
+ const next = [];
77
+ for (let index = 0; index <= value.length; index += 1) {
78
+ const consumes = index > 0 && token.matcher.test(value[index - 1] ?? "");
79
+ next[index] =
80
+ (token.optional && previous[index] === true) ||
81
+ (consumes &&
82
+ (previous[index - 1] === true ||
83
+ (token.repeat && next[index - 1] === true)));
84
+ }
85
+ return next;
86
+ }
87
+ function matchesPattern(value, source) {
88
+ let previous = [true];
89
+ for (const token of patternTokens(source))
90
+ previous =
91
+ token.kind === "directory"
92
+ ? advanceDirectory({ value, previous })
93
+ : advancePattern(token, { value, previous });
94
+ return previous[value.length] === true;
95
+ }
96
+ function selected(value, patterns) {
97
+ let included = false;
98
+ for (const pattern of patterns) {
99
+ const negative = pattern.startsWith("!");
100
+ const source = negative ? pattern.slice(1) : pattern;
101
+ try {
102
+ if (matchesPattern(value, source))
103
+ included = !negative;
104
+ }
105
+ catch {
106
+ return undefined;
107
+ }
108
+ }
109
+ return included;
110
+ }
111
+ function patterns(value) {
112
+ if (!Array.isArray(value) || value.length === 0)
113
+ return undefined;
114
+ return value.every((item) => typeof item === "string")
115
+ ? value
116
+ : undefined;
117
+ }
118
+ function allows(values, filters) {
119
+ const include = patterns(filters.include);
120
+ const ignore = patterns(filters.ignore);
121
+ if (include !== undefined &&
122
+ !values.some((value) => selected(value, include) !== false))
123
+ return false;
124
+ return (ignore === undefined ||
125
+ values.some((value) => selected(value, ignore) !== true));
126
+ }
127
+ export function workflowApplies(trigger, context) {
128
+ if (!isRecord(trigger))
129
+ return trigger !== false;
130
+ return (allows([context.branch], {
131
+ include: trigger["branches"],
132
+ ignore: trigger["branches-ignore"],
133
+ }) &&
134
+ allows(context.paths, {
135
+ include: trigger["paths"],
136
+ ignore: trigger["paths-ignore"],
137
+ }));
138
+ }
@@ -0,0 +1,10 @@
1
+ import { type Operation } from "./github-operation.ts";
2
+ export interface ExpectedWorkflow {
3
+ readonly path: string;
4
+ readonly kind: "push" | "event";
5
+ }
6
+ export declare function pullRequestWorkflows(operation: Operation, commit: string): Promise<readonly ExpectedWorkflow[]>;
7
+ export declare function pendingWorkflows(operation: Operation, input: {
8
+ readonly commit: string;
9
+ readonly workflows: readonly ExpectedWorkflow[];
10
+ }): Promise<readonly string[]>;