cloving 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (484) hide show
  1. package/README.md +329 -215
  2. package/dist/src/agent-harness-shell.d.ts +2 -1
  3. package/dist/src/agent-harness-shell.js +8 -5
  4. package/dist/src/authority/command-wait-checks.d.ts +8 -0
  5. package/dist/src/authority/command-wait-checks.js +88 -0
  6. package/dist/src/authority/command-wait-results.d.ts +15 -0
  7. package/dist/src/authority/command-wait-results.js +73 -0
  8. package/dist/src/authority/command-wait-view.d.ts +21 -0
  9. package/dist/src/authority/command-wait-view.js +34 -0
  10. package/dist/src/authority/command-waits.d.ts +39 -0
  11. package/dist/src/authority/command-waits.js +97 -0
  12. package/dist/src/authority/commands.js +22 -1
  13. package/dist/src/authority/dispatch-decision.d.ts +8 -0
  14. package/dist/src/authority/dispatch-decision.js +26 -1
  15. package/dist/src/authority/effect-requests.js +6 -3
  16. package/dist/src/authority/effect-results.js +4 -2
  17. package/dist/src/authority/history-state.d.ts +2 -0
  18. package/dist/src/authority/history-state.js +13 -1
  19. package/dist/src/authority/instants.d.ts +1 -0
  20. package/dist/src/authority/instants.js +21 -0
  21. package/dist/src/authority/reduction-state.d.ts +2 -0
  22. package/dist/src/authority/reduction-state.js +5 -0
  23. package/dist/src/authority/reduction.js +24 -0
  24. package/dist/src/authority/status-input.d.ts +2 -0
  25. package/dist/src/authority/status.d.ts +2 -0
  26. package/dist/src/authority/status.js +1 -0
  27. package/dist/src/authority/stop-sequence.d.ts +1 -0
  28. package/dist/src/authority/stop-sequence.js +2 -1
  29. package/dist/src/authority/transitions.d.ts +6 -4
  30. package/dist/src/authority/transitions.js +7 -0
  31. package/dist/src/broker/actor/authority-health.d.ts +9 -0
  32. package/dist/src/broker/actor/authority-health.js +24 -0
  33. package/dist/src/broker/actor/authority-queries.d.ts +2 -1
  34. package/dist/src/broker/actor/authority-queries.js +14 -5
  35. package/dist/src/broker/actor/authority-receipts.js +1 -1
  36. package/dist/src/broker/actor/authority-runtime.d.ts +4 -2
  37. package/dist/src/broker/actor/authority-runtime.js +29 -20
  38. package/dist/src/broker/actor/authority-session.d.ts +6 -19
  39. package/dist/src/broker/actor/authority-session.js +66 -88
  40. package/dist/src/broker/actor/authority-settings.d.ts +2 -1
  41. package/dist/src/broker/actor/authority-settings.js +6 -3
  42. package/dist/src/broker/actor/authority-upgrades.d.ts +23 -2
  43. package/dist/src/broker/actor/authority-upgrades.js +8 -2
  44. package/dist/src/broker/actor/authority-watchdog.d.ts +6 -2
  45. package/dist/src/broker/actor/authority-watchdog.js +31 -9
  46. package/dist/src/broker/actor/authority.js +3 -1
  47. package/dist/src/broker/actor/delivery-intents.js +2 -0
  48. package/dist/src/broker/actor/effect-delivery.d.ts +1 -1
  49. package/dist/src/broker/actor/effect-delivery.js +15 -2
  50. package/dist/src/broker/actor/effect-plan.js +11 -2
  51. package/dist/src/broker/actor/effect-queries.d.ts +4 -0
  52. package/dist/src/broker/actor/effect-queries.js +9 -1
  53. package/dist/src/broker/actor/effect-turn.js +2 -0
  54. package/dist/src/broker/actor/projection-memory.d.ts +43 -0
  55. package/dist/src/broker/actor/projection-memory.js +207 -0
  56. package/dist/src/broker/actor/runtime-parts.d.ts +5 -0
  57. package/dist/src/broker/actor/runtime-parts.js +8 -3
  58. package/dist/src/broker/actor/stop-plan.js +9 -3
  59. package/dist/src/broker/actor/stop-turn.d.ts +2 -0
  60. package/dist/src/broker/actor/stop-turn.js +24 -11
  61. package/dist/src/broker/actor/turn-draft.d.ts +1 -0
  62. package/dist/src/broker/actor/turn-draft.js +4 -0
  63. package/dist/src/broker/actor/turn-state.js +5 -1
  64. package/dist/src/broker/authority-admission.js +60 -0
  65. package/dist/src/broker/authority-restore.d.ts +2 -0
  66. package/dist/src/broker/authority-restore.js +35 -1
  67. package/dist/src/broker/command-wait-restore.d.ts +31 -0
  68. package/dist/src/broker/command-wait-restore.js +86 -0
  69. package/dist/src/broker/decision-restore.d.ts +1 -1
  70. package/dist/src/broker/decision-restore.js +1 -0
  71. package/dist/src/broker/effect-upgrade.d.ts +3 -0
  72. package/dist/src/broker/effect-upgrade.js +11 -2
  73. package/dist/src/cli/arguments.d.ts +13 -0
  74. package/dist/src/cli/arguments.js +43 -3
  75. package/dist/src/cli/chat-stores.d.ts +2 -0
  76. package/dist/src/cli/chat-stores.js +113 -0
  77. package/dist/src/cli/client.d.ts +7 -2
  78. package/dist/src/cli/client.js +13 -7
  79. package/dist/src/cli/command-requests.d.ts +46 -0
  80. package/dist/src/cli/command-requests.js +84 -0
  81. package/dist/src/cli/command-waits.d.ts +9 -0
  82. package/dist/src/cli/command-waits.js +51 -0
  83. package/dist/src/cli/commands.js +70 -88
  84. package/dist/src/cli/config-file.d.ts +2 -2
  85. package/dist/src/cli/config-file.js +4 -2
  86. package/dist/src/cli/config-notice.js +5 -2
  87. package/dist/src/cli/doctor-retention.d.ts +2 -0
  88. package/dist/src/cli/doctor-retention.js +93 -0
  89. package/dist/src/cli/doctor-workflows.d.ts +5 -2
  90. package/dist/src/cli/doctor-workflows.js +12 -7
  91. package/dist/src/cli/doctor.js +11 -9
  92. package/dist/src/cli/harness-probes.d.ts +2 -0
  93. package/dist/src/cli/harness-probes.js +1 -1
  94. package/dist/src/cli/harness-processes.d.ts +6 -0
  95. package/dist/src/cli/harness-processes.js +36 -0
  96. package/dist/src/cli/init-command.d.ts +9 -0
  97. package/dist/src/cli/init-command.js +52 -0
  98. package/dist/src/cli/init-prompt-command.d.ts +10 -0
  99. package/dist/src/cli/init-prompt-command.js +145 -0
  100. package/dist/src/cli/init-prompt.d.ts +35 -0
  101. package/dist/src/cli/init-prompt.js +74 -0
  102. package/dist/src/cli/init-selection.d.ts +13 -0
  103. package/dist/src/cli/init-selection.js +75 -0
  104. package/dist/src/cli/main.d.ts +2 -0
  105. package/dist/src/cli/main.js +37 -7
  106. package/dist/src/cli/mcp-server.d.ts +1 -0
  107. package/dist/src/cli/mcp-server.js +156 -0
  108. package/dist/src/cli/mcp-tools.d.ts +15 -0
  109. package/dist/src/cli/mcp-tools.js +242 -0
  110. package/dist/src/cli/queue-arguments.d.ts +15 -0
  111. package/dist/src/cli/queue-arguments.js +31 -0
  112. package/dist/src/cli/queue-render.d.ts +3 -0
  113. package/dist/src/cli/queue-render.js +26 -0
  114. package/dist/src/cli/reload-render.d.ts +2 -0
  115. package/dist/src/cli/reload-render.js +12 -0
  116. package/dist/src/cli/render.d.ts +1 -1
  117. package/dist/src/cli/render.js +54 -38
  118. package/dist/src/cli/report-ci-jobs.d.ts +23 -0
  119. package/dist/src/cli/report-ci-jobs.js +103 -0
  120. package/dist/src/cli/report-ci-usage.d.ts +9 -0
  121. package/dist/src/cli/report-ci-usage.js +185 -0
  122. package/dist/src/cli/report-ci.d.ts +13 -0
  123. package/dist/src/cli/report-ci.js +74 -0
  124. package/dist/src/cli/report-closures.d.ts +6 -0
  125. package/dist/src/cli/report-closures.js +97 -0
  126. package/dist/src/cli/report-flow.d.ts +7 -0
  127. package/dist/src/cli/report-flow.js +122 -0
  128. package/dist/src/cli/report-github-reader.d.ts +29 -0
  129. package/dist/src/cli/report-github-reader.js +157 -0
  130. package/dist/src/cli/report-github.d.ts +15 -8
  131. package/dist/src/cli/report-github.js +131 -150
  132. package/dist/src/cli/report-operator.d.ts +3 -0
  133. package/dist/src/cli/report-operator.js +40 -0
  134. package/dist/src/cli/report-ready.d.ts +3 -0
  135. package/dist/src/cli/report-ready.js +96 -0
  136. package/dist/src/cli/report-text.d.ts +9 -0
  137. package/dist/src/cli/report-text.js +33 -0
  138. package/dist/src/cli/report.d.ts +1 -0
  139. package/dist/src/cli/report.js +104 -27
  140. package/dist/src/cli/runtime-arguments.d.ts +18 -3
  141. package/dist/src/cli/runtime-arguments.js +29 -20
  142. package/dist/src/cli/schedule-arguments.d.ts +14 -0
  143. package/dist/src/cli/schedule-arguments.js +26 -0
  144. package/dist/src/cli/schedule-render.d.ts +22 -0
  145. package/dist/src/cli/schedule-render.js +73 -0
  146. package/dist/src/cli/terminal-text.d.ts +3 -0
  147. package/dist/src/cli/terminal-text.js +28 -0
  148. package/dist/src/cli/toolchain.d.ts +1 -0
  149. package/dist/src/cli/toolchain.js +1 -0
  150. package/dist/src/cli/usage-render.d.ts +1 -0
  151. package/dist/src/cli/usage-render.js +28 -1
  152. package/dist/src/cli/usage.d.ts +2 -2
  153. package/dist/src/cli/usage.js +89 -11
  154. package/dist/src/cli/watch-actions.js +2 -2
  155. package/dist/src/cli/watch-api-document.d.ts +430 -0
  156. package/dist/src/cli/watch-api-document.js +291 -0
  157. package/dist/src/cli/watch-api-run.d.ts +56 -0
  158. package/dist/src/cli/watch-api-run.js +112 -0
  159. package/dist/src/cli/watch-api.d.ts +17 -0
  160. package/dist/src/cli/watch-api.js +230 -0
  161. package/dist/src/cli/watch-board-view.js +19 -2
  162. package/dist/src/cli/watch-board.d.ts +4 -2
  163. package/dist/src/cli/watch-board.js +53 -43
  164. package/dist/src/cli/watch-card-forms.d.ts +1 -1
  165. package/dist/src/cli/watch-card-forms.js +11 -10
  166. package/dist/src/cli/watch-client.d.ts +1 -1
  167. package/dist/src/cli/watch-client.js +2 -11
  168. package/dist/src/cli/watch-header-view.d.ts +1 -5
  169. package/dist/src/cli/watch-header-view.js +17 -21
  170. package/dist/src/cli/watch-model.d.ts +5 -1
  171. package/dist/src/cli/watch-model.js +20 -11
  172. package/dist/src/cli/watch-page.js +15 -15
  173. package/dist/src/cli/watch-phases.d.ts +12 -3
  174. package/dist/src/cli/watch-phases.js +68 -11
  175. package/dist/src/cli/watch-pr-board.js +1 -1
  176. package/dist/src/cli/watch-pr-command.d.ts +1 -0
  177. package/dist/src/cli/watch-pull-request.js +18 -8
  178. package/dist/src/cli/watch-reads.d.ts +3 -0
  179. package/dist/src/cli/watch-reads.js +22 -20
  180. package/dist/src/cli/watch-render.d.ts +15 -0
  181. package/dist/src/cli/watch-run-input.d.ts +0 -1
  182. package/dist/src/cli/watch-run-input.js +0 -13
  183. package/dist/src/cli/watch-server.js +24 -10
  184. package/dist/src/cli/watch-view.d.ts +0 -3
  185. package/dist/src/cli/watch-view.js +13 -13
  186. package/dist/src/cli.js +73 -12
  187. package/dist/src/command-wait.d.ts +4 -0
  188. package/dist/src/command-wait.js +45 -0
  189. package/dist/src/configuration-change.d.ts +7 -0
  190. package/dist/src/configuration-change.js +14 -0
  191. package/dist/src/configuration-display.js +2 -0
  192. package/dist/src/configuration-schema.d.ts +14 -0
  193. package/dist/src/configuration-schema.js +6 -2
  194. package/dist/src/daemon/attachment-file.d.ts +6 -0
  195. package/dist/src/daemon/attachment-file.js +86 -0
  196. package/dist/src/daemon/attachments.d.ts +14 -0
  197. package/dist/src/daemon/attachments.js +17 -0
  198. package/dist/src/daemon/claude-recovery.d.ts +50 -0
  199. package/dist/src/daemon/claude-recovery.js +208 -0
  200. package/dist/src/daemon/claude-stream.d.ts +27 -0
  201. package/dist/src/daemon/claude-stream.js +63 -0
  202. package/dist/src/daemon/claude-turn.d.ts +11 -25
  203. package/dist/src/daemon/claude-turn.js +64 -81
  204. package/dist/src/daemon/claude-worker.d.ts +5 -4
  205. package/dist/src/daemon/claude-worker.js +127 -126
  206. package/dist/src/daemon/daemon-adapters.d.ts +9 -0
  207. package/dist/src/daemon/daemon-adapters.js +33 -5
  208. package/dist/src/daemon/daemon-loops.d.ts +5 -1
  209. package/dist/src/daemon/daemon-loops.js +18 -10
  210. package/dist/src/daemon/daemon.js +80 -61
  211. package/dist/src/daemon/github-attach.d.ts +2 -0
  212. package/dist/src/daemon/github-attach.js +222 -0
  213. package/dist/src/daemon/github-calls.js +1 -1
  214. package/dist/src/daemon/github-ci-filters.d.ts +6 -0
  215. package/dist/src/daemon/github-ci-filters.js +138 -0
  216. package/dist/src/daemon/github-ci-workflows.d.ts +10 -0
  217. package/dist/src/daemon/github-ci-workflows.js +148 -0
  218. package/dist/src/daemon/github-ci.js +22 -4
  219. package/dist/src/daemon/github-issue-methods.d.ts +2 -0
  220. package/dist/src/daemon/github-issue-methods.js +37 -2
  221. package/dist/src/daemon/github-merge-call.d.ts +2 -1
  222. package/dist/src/daemon/github-merge-call.js +10 -3
  223. package/dist/src/daemon/github-merge.js +52 -24
  224. package/dist/src/daemon/github-methods.js +18 -4
  225. package/dist/src/daemon/github-operation.d.ts +4 -0
  226. package/dist/src/daemon/github-operation.js +6 -0
  227. package/dist/src/daemon/github-worker.d.ts +4 -0
  228. package/dist/src/daemon/github-worker.js +6 -0
  229. package/dist/src/daemon/issue-queue.d.ts +4 -1
  230. package/dist/src/daemon/issue-queue.js +76 -78
  231. package/dist/src/daemon/merge-turns.d.ts +10 -0
  232. package/dist/src/daemon/merge-turns.js +37 -0
  233. package/dist/src/daemon/notify-events.d.ts +6 -0
  234. package/dist/src/daemon/notify-events.js +84 -0
  235. package/dist/src/daemon/notify-journal.js +1 -1
  236. package/dist/src/daemon/notify-message.d.ts +4 -1
  237. package/dist/src/daemon/notify-message.js +36 -0
  238. package/dist/src/daemon/notify.d.ts +1 -1
  239. package/dist/src/daemon/notify.js +5 -77
  240. package/dist/src/daemon/operation-journal.d.ts +1 -0
  241. package/dist/src/daemon/queue-control.d.ts +13 -0
  242. package/dist/src/daemon/queue-control.js +86 -0
  243. package/dist/src/daemon/queue-journal.d.ts +20 -0
  244. package/dist/src/daemon/queue-journal.js +89 -0
  245. package/dist/src/daemon/queue-status.d.ts +9 -3
  246. package/dist/src/daemon/queue-status.js +17 -4
  247. package/dist/src/daemon/record-archive.d.ts +19 -0
  248. package/dist/src/daemon/record-archive.js +82 -0
  249. package/dist/src/daemon/record-sweep.d.ts +24 -0
  250. package/dist/src/daemon/record-sweep.js +147 -0
  251. package/dist/src/daemon/resume-index-lock.d.ts +13 -0
  252. package/dist/src/daemon/resume-index-lock.js +160 -0
  253. package/dist/src/daemon/resume-worktree.d.ts +7 -0
  254. package/dist/src/daemon/resume-worktree.js +29 -0
  255. package/dist/src/daemon/retrying-turn.d.ts +2 -12
  256. package/dist/src/daemon/retrying-turn.js +98 -172
  257. package/dist/src/daemon/schedule-control.d.ts +26 -0
  258. package/dist/src/daemon/schedule-control.js +110 -0
  259. package/dist/src/daemon/schedule-journal.d.ts +2 -15
  260. package/dist/src/daemon/schedule-journal.js +67 -4
  261. package/dist/src/daemon/settings-reload.d.ts +26 -0
  262. package/dist/src/daemon/settings-reload.js +82 -0
  263. package/dist/src/daemon/ticket-registration.d.ts +2 -7
  264. package/dist/src/daemon/ticket-registration.js +15 -81
  265. package/dist/src/daemon/turn-attempt-journal.d.ts +38 -0
  266. package/dist/src/daemon/turn-attempt-journal.js +136 -0
  267. package/dist/src/daemon/turn-attempts.d.ts +47 -0
  268. package/dist/src/daemon/turn-attempts.js +166 -0
  269. package/dist/src/daemon/turn-details.d.ts +4 -0
  270. package/dist/src/daemon/turn-details.js +33 -0
  271. package/dist/src/daemon/turn-report.d.ts +8 -1
  272. package/dist/src/daemon/turn-report.js +39 -0
  273. package/dist/src/daemon/work-tree.d.ts +9 -0
  274. package/dist/src/daemon/work-tree.js +20 -0
  275. package/dist/src/daemon/worker-profile.d.ts +9 -0
  276. package/dist/src/daemon/worker-profile.js +44 -0
  277. package/dist/src/daemon/workflow-generations.d.ts +7 -4
  278. package/dist/src/daemon/workflow-generations.js +22 -14
  279. package/dist/src/daemon/workflow-reload.d.ts +41 -0
  280. package/dist/src/daemon/workflow-reload.js +244 -0
  281. package/dist/src/daemon/workflow-replay.d.ts +2 -1
  282. package/dist/src/daemon/workflow-replay.js +7 -3
  283. package/dist/src/daemon/workflow-schedules.d.ts +3 -0
  284. package/dist/src/daemon/workflow-schedules.js +98 -45
  285. package/dist/src/daemon/worktree-processes.d.ts +9 -0
  286. package/dist/src/daemon/worktree-processes.js +151 -0
  287. package/dist/src/doctor-report.d.ts +4 -6
  288. package/dist/src/doctor-report.js +8 -13
  289. package/dist/src/harness-start.d.ts +15 -0
  290. package/dist/src/harness-start.js +37 -0
  291. package/dist/src/host/command-wait.d.ts +38 -0
  292. package/dist/src/host/command-wait.js +115 -0
  293. package/dist/src/host/start-delivery.d.ts +5 -7
  294. package/dist/src/host/start-delivery.js +3 -15
  295. package/dist/src/host/step-bridge-host.d.ts +2 -0
  296. package/dist/src/host/step-bridge-host.js +21 -0
  297. package/dist/src/operation-identity.d.ts +1 -0
  298. package/dist/src/operation-identity.js +4 -0
  299. package/dist/src/private-config.schema.json +71 -0
  300. package/dist/src/project-config.schema.json +40 -0
  301. package/dist/src/project-settings.d.ts +16 -2
  302. package/dist/src/project-settings.js +35 -1
  303. package/dist/src/queue-spend.d.ts +4 -0
  304. package/dist/src/queue-spend.js +21 -0
  305. package/dist/src/queue-state.d.ts +26 -0
  306. package/dist/src/queue-state.js +34 -0
  307. package/dist/src/record-retention.d.ts +46 -0
  308. package/dist/src/record-retention.js +81 -0
  309. package/dist/src/relay/relay-service.d.ts +3 -0
  310. package/dist/src/relay/relay-service.js +5 -3
  311. package/dist/src/report-ci.d.ts +164 -0
  312. package/dist/src/report-ci.js +32 -0
  313. package/dist/src/report-effects.d.ts +15 -0
  314. package/dist/src/report-effects.js +212 -0
  315. package/dist/src/report-flow-types.d.ts +38 -0
  316. package/dist/src/report-flow-types.js +7 -0
  317. package/dist/src/report-flow.d.ts +43 -0
  318. package/dist/src/report-flow.js +193 -0
  319. package/dist/src/report-operator.d.ts +67 -0
  320. package/dist/src/report-operator.js +25 -0
  321. package/dist/src/report-quality.d.ts +221 -0
  322. package/dist/src/report-quality.js +94 -0
  323. package/dist/src/report-ready.d.ts +23 -0
  324. package/dist/src/report-ready.js +117 -0
  325. package/dist/src/report-statistics.d.ts +2 -1
  326. package/dist/src/report-statistics.js +40 -4
  327. package/dist/src/report.d.ts +588 -47
  328. package/dist/src/report.js +156 -41
  329. package/dist/src/schedule-progress.d.ts +33 -0
  330. package/dist/src/schedule-progress.js +45 -0
  331. package/dist/src/service/active-tickets.js +11 -6
  332. package/dist/src/service/command-waits.d.ts +34 -0
  333. package/dist/src/service/command-waits.js +86 -0
  334. package/dist/src/service/dispatcher.d.ts +4 -0
  335. package/dist/src/service/dispatcher.js +33 -0
  336. package/dist/src/service/expiry.js +2 -0
  337. package/dist/src/service/gateway.js +3 -1
  338. package/dist/src/service/queue-handlers.d.ts +4 -0
  339. package/dist/src/service/queue-handlers.js +32 -0
  340. package/dist/src/service/queue-spend.d.ts +6 -0
  341. package/dist/src/service/queue-spend.js +68 -0
  342. package/dist/src/service/registry.d.ts +28 -2
  343. package/dist/src/service/registry.js +48 -0
  344. package/dist/src/service/replies.d.ts +22 -8
  345. package/dist/src/service/replies.js +16 -2
  346. package/dist/src/service/run-handlers.js +37 -12
  347. package/dist/src/service/run-metadata.d.ts +15 -1
  348. package/dist/src/service/run-metadata.js +93 -8
  349. package/dist/src/service/service.d.ts +11 -3
  350. package/dist/src/service/service.js +22 -37
  351. package/dist/src/service/submission-handler.js +18 -4
  352. package/dist/src/service/worker-port.js +9 -1
  353. package/dist/src/service/worker-totals.d.ts +6 -0
  354. package/dist/src/service/worker-totals.js +8 -1
  355. package/dist/src/service/workflow-reload.d.ts +35 -0
  356. package/dist/src/service/workflow-reload.js +52 -0
  357. package/dist/src/step-bridge.d.ts +20 -0
  358. package/dist/src/steps/command-wait.d.ts +12 -0
  359. package/dist/src/steps/command-wait.js +26 -0
  360. package/dist/src/steps/open-decision-wait.d.ts +2 -0
  361. package/dist/src/steps/{decision-gate.js → open-decision-wait.js} +0 -7
  362. package/dist/src/steps/review-by-person.js +4 -1
  363. package/dist/src/steps/wait-for-command.d.ts +3 -0
  364. package/dist/src/steps/wait-for-command.js +17 -0
  365. package/dist/src/steps/wait-for-decision.js +1 -1
  366. package/dist/src/storage/command-wait-rows.d.ts +30 -0
  367. package/dist/src/storage/command-wait-rows.js +96 -0
  368. package/dist/src/storage/decision-snapshots.d.ts +8 -2
  369. package/dist/src/storage/decision-snapshots.js +16 -8
  370. package/dist/src/storage/domain-changes.d.ts +3 -1
  371. package/dist/src/storage/domain-changes.js +4 -0
  372. package/dist/src/storage/domain-schema.d.ts +16 -1
  373. package/dist/src/storage/domain-schema.js +35 -4
  374. package/dist/src/storage/effect-schema.d.ts +2 -0
  375. package/dist/src/storage/effect-schema.js +9 -0
  376. package/dist/src/storage/projection-changes.d.ts +12 -0
  377. package/dist/src/storage/projection-changes.js +194 -0
  378. package/dist/src/storage/projection-lookups.d.ts +7 -0
  379. package/dist/src/storage/projection-lookups.js +30 -0
  380. package/dist/src/testing-requests.d.ts +15 -0
  381. package/dist/src/testing-requests.js +93 -0
  382. package/dist/src/testing.d.ts +4 -10
  383. package/dist/src/testing.js +33 -86
  384. package/dist/src/worker-usage.d.ts +1 -0
  385. package/dist/src/worker-usage.js +3 -0
  386. package/dist/src/workflow-candidate.d.ts +1 -0
  387. package/dist/src/workflow-candidate.js +12 -1
  388. package/dist/src/workflow-contracts.d.ts +1 -0
  389. package/dist/src/workflow-contracts.js +9 -2
  390. package/dist/src/workflow-declaration.d.ts +1 -0
  391. package/dist/src/workflow-declaration.js +3 -0
  392. package/dist/src/workflow-discovery.d.ts +2 -13
  393. package/dist/src/workflow-discovery.js +1 -13
  394. package/dist/src/workflow-refusals.js +0 -1
  395. package/dist/src/workflows.d.ts +1 -1
  396. package/dist/src/workflows.js +1 -1
  397. package/dist/tools/compile-workflows.js +3 -0
  398. package/dist/tools/project-configuration.d.ts +7 -2
  399. package/dist/tools/project-configuration.js +30 -1
  400. package/dist/tools/red-green-command.d.ts +1 -0
  401. package/dist/tools/red-green-command.js +174 -0
  402. package/dist/tools/red-green-process.d.ts +10 -0
  403. package/dist/tools/red-green-process.js +59 -0
  404. package/dist/tools/self-host-processes.d.ts +2 -0
  405. package/dist/tools/self-host-processes.js +69 -26
  406. package/dist/tools/self-host-project.d.ts +2 -0
  407. package/dist/tools/self-host-project.js +30 -77
  408. package/dist/tools/self-host-runtime.js +1 -1
  409. package/dist/tools/self-host.js +76 -34
  410. package/dist/tools/template-command.d.ts +1 -0
  411. package/dist/tools/template-command.js +160 -0
  412. package/dist/tools/template-copy.d.ts +11 -0
  413. package/dist/tools/template-copy.js +130 -0
  414. package/dist/tools/template-files.d.ts +17 -0
  415. package/dist/tools/template-files.js +74 -0
  416. package/dist/tools/workflow-bundles.js +1 -0
  417. package/dist/tools/workflow-candidate-counts.js +2 -2
  418. package/dist/tools/workflow-candidate-program.d.ts +4 -2
  419. package/dist/tools/workflow-candidate-program.js +30 -11
  420. package/dist/tools/workflow-candidate-shape.d.ts +3 -0
  421. package/dist/tools/workflow-candidate-shape.js +90 -0
  422. package/dist/tools/workflow-candidate-source.d.ts +1 -0
  423. package/dist/tools/workflow-candidate-source.js +26 -4
  424. package/dist/tools/workflow-candidate-syntax.d.ts +2 -2
  425. package/dist/tools/workflow-candidate-syntax.js +24 -94
  426. package/dist/tools/workflow-command.js +1 -2
  427. package/dist/tools/workflow-folders.d.ts +2 -3
  428. package/dist/tools/workflow-folders.js +1 -1
  429. package/package.json +17 -9
  430. package/templates/develop/README.md +93 -4
  431. package/templates/develop/develop/flow-tests.ts +38 -1
  432. package/templates/develop/develop/interruption-tests.ts +157 -0
  433. package/templates/develop/develop/local.ts +1 -0
  434. package/templates/develop/develop/option-tests.ts +138 -9
  435. package/templates/develop/develop/pull.ts +5 -1
  436. package/templates/develop/develop/red-green.ts +55 -0
  437. package/templates/develop/develop/refusal-tests.ts +77 -0
  438. package/templates/develop/develop/report.ts +31 -11
  439. package/templates/develop/develop/round.ts +1 -0
  440. package/templates/develop/develop/scenarios.ts +27 -0
  441. package/templates/develop/develop/turn.ts +28 -7
  442. package/templates/develop/develop.declaration.json +1 -1
  443. package/templates/develop/develop.test.ts +4 -0
  444. package/templates/develop/template.json +29 -2
  445. package/templates/idea-to-issue/README.md +27 -0
  446. package/templates/idea-to-issue/idea-to-issue/effects.ts +52 -0
  447. package/templates/idea-to-issue/idea-to-issue/leave.ts +10 -0
  448. package/templates/idea-to-issue/idea-to-issue/next.ts +29 -0
  449. package/templates/idea-to-issue/idea-to-issue/post-person.ts +18 -0
  450. package/templates/idea-to-issue/idea-to-issue/post.ts +50 -0
  451. package/templates/idea-to-issue/idea-to-issue/queue.ts +27 -0
  452. package/templates/idea-to-issue/idea-to-issue/review.ts +42 -0
  453. package/templates/idea-to-issue/idea-to-issue/scenarios.ts +50 -0
  454. package/templates/idea-to-issue/idea-to-issue/turn.ts +40 -0
  455. package/templates/idea-to-issue/idea-to-issue.declaration.json +16 -0
  456. package/templates/idea-to-issue/idea-to-issue.test.ts +79 -0
  457. package/templates/idea-to-issue/idea-to-issue.ts +49 -0
  458. package/templates/idea-to-issue/template.json +81 -0
  459. package/templates/review-day/README.md +97 -0
  460. package/templates/review-day/review-day/critique.ts +58 -0
  461. package/templates/review-day/review-day/decision.ts +29 -0
  462. package/templates/review-day/review-day/facts.ts +69 -0
  463. package/templates/review-day/review-day/label.ts +29 -0
  464. package/templates/review-day/review-day/next.ts +28 -0
  465. package/templates/review-day/review-day/post.ts +27 -0
  466. package/templates/review-day/review-day/report.ts +98 -0
  467. package/templates/review-day/review-day/rules.ts +12 -0
  468. package/templates/review-day/review-day/scenarios.ts +76 -0
  469. package/templates/review-day/review-day/turn.ts +73 -0
  470. package/templates/review-day/review-day.declaration.json +16 -0
  471. package/templates/review-day/review-day.test.ts +362 -0
  472. package/templates/review-day/review-day.ts +37 -0
  473. package/templates/review-day/template.json +56 -0
  474. package/dist/src/cli/watch-start-view.d.ts +0 -18
  475. package/dist/src/cli/watch-start-view.js +0 -77
  476. package/dist/src/steps/decision-gate.d.ts +0 -3
  477. package/dist/workflows/develop-prd.d.ts +0 -7
  478. package/dist/workflows/develop-prd.js +0 -165
  479. package/dist/workflows/develop-ticket.d.ts +0 -9
  480. package/dist/workflows/develop-ticket.js +0 -207
  481. package/dist/workflows/issue-labels.d.ts +0 -16
  482. package/dist/workflows/issue-labels.js +0 -70
  483. package/dist/workflows/ticket-prompts.d.ts +0 -35
  484. package/dist/workflows/ticket-prompts.js +0 -147
@@ -0,0 +1,148 @@
1
+ import { pullRequestTrigger, triggerKind, workflowApplies, } from "./github-ci-filters.js";
2
+ import { field, repositoryPath } from "./github-operation.js";
3
+ import { githubRead } from "./github-retry.js";
4
+ async function pullBase(operation) {
5
+ const pull = JSON.parse(await githubRead(operation, [
6
+ "api",
7
+ `${repositoryPath}/pulls/${String(operation.payload["number"])}`,
8
+ ]));
9
+ if (typeof pull !== "object" || pull === null || !("base" in pull))
10
+ throw new Error("github-call-failed");
11
+ const baseData = pull.base;
12
+ if (typeof baseData !== "object" || baseData === null)
13
+ throw new Error("github-call-failed");
14
+ const base = field(baseData, "sha");
15
+ const branch = field(baseData, "ref");
16
+ if (typeof base !== "string" ||
17
+ !/^[0-9a-f]{40,64}$/.test(base) ||
18
+ typeof branch !== "string")
19
+ throw new Error("github-call-failed");
20
+ return { base, branch };
21
+ }
22
+ async function appliesToPull(operation, input) {
23
+ const { commit, trigger } = input;
24
+ if (trigger === false)
25
+ return false;
26
+ if (typeof trigger !== "object" || trigger === null)
27
+ return true;
28
+ if (!["paths", "paths-ignore", "branches", "branches-ignore"].some((key) => Object.hasOwn(trigger, key)))
29
+ return true;
30
+ const { base, branch } = await pullBase(operation);
31
+ await operation.calls.git(operation.settings.repository, [
32
+ "fetch",
33
+ "--quiet",
34
+ "--no-tags",
35
+ "origin",
36
+ base,
37
+ ]);
38
+ const paths = await operation.calls.git(operation.settings.repository, [
39
+ "diff",
40
+ "--name-only",
41
+ "-z",
42
+ `${base}...${commit}`,
43
+ ]);
44
+ return workflowApplies(trigger, {
45
+ branch,
46
+ paths: paths.split("\0").filter((path) => path !== ""),
47
+ });
48
+ }
49
+ export async function pullRequestWorkflows(operation, commit) {
50
+ const read = (parts) => operation.calls.git(operation.settings.repository, parts);
51
+ const paths = await read([
52
+ "ls-tree",
53
+ "-r",
54
+ "--name-only",
55
+ "-z",
56
+ commit,
57
+ "--",
58
+ ".github/workflows",
59
+ ]);
60
+ const workflows = [];
61
+ for (const path of paths.split("\0")) {
62
+ if (!/^\.github\/workflows\/[^/]+\.ya?ml$/.test(path))
63
+ continue;
64
+ const trigger = pullRequestTrigger(await read(["show", `${commit}:${path}`]));
65
+ if (await appliesToPull(operation, { commit, trigger }))
66
+ workflows.push({ path, kind: triggerKind(trigger) });
67
+ }
68
+ if (workflows.length === 0)
69
+ return workflows;
70
+ const inactive = await inactiveWorkflows(operation);
71
+ return workflows.filter((workflow) => !inactive.has(workflow.path));
72
+ }
73
+ function isList(value) {
74
+ return Array.isArray(value);
75
+ }
76
+ async function actionPages(operation, request) {
77
+ const pages = JSON.parse(await githubRead(operation, ["api", "--paginate", "--slurp", request.path]));
78
+ if (!isList(pages) || pages.length === 0)
79
+ throw new Error("github-call-failed");
80
+ return pages.flatMap((page) => {
81
+ if (typeof page !== "object" || page === null)
82
+ throw new Error("github-call-failed");
83
+ const items = field(page, request.key);
84
+ if (!isList(items))
85
+ throw new Error("github-call-failed");
86
+ return items;
87
+ });
88
+ }
89
+ async function inactiveWorkflows(operation) {
90
+ const workflows = await actionPages(operation, {
91
+ path: `${repositoryPath}/actions/workflows?per_page=100`,
92
+ key: "workflows",
93
+ });
94
+ const inactive = new Set();
95
+ for (const workflow of workflows) {
96
+ if (typeof workflow !== "object" || workflow === null)
97
+ throw new Error("github-call-failed");
98
+ const path = field(workflow, "path");
99
+ const state = field(workflow, "state");
100
+ if (typeof path !== "string" || typeof state !== "string")
101
+ throw new Error("github-call-failed");
102
+ if (state !== "active")
103
+ inactive.add(path);
104
+ }
105
+ return inactive;
106
+ }
107
+ function isWorkflowRun(value) {
108
+ if (typeof value !== "object" || value === null)
109
+ return false;
110
+ const conclusion = field(value, "conclusion");
111
+ return (typeof field(value, "id") === "number" &&
112
+ ["path", "head_sha", "event", "status"].every((key) => typeof field(value, key) === "string") &&
113
+ (conclusion === null || typeof conclusion === "string"));
114
+ }
115
+ async function workflowRuns(operation, commit) {
116
+ const runs = await actionPages(operation, {
117
+ path: `${repositoryPath}/actions/runs?head_sha=${commit}&event=pull_request&per_page=100`,
118
+ key: "workflow_runs",
119
+ });
120
+ if (!runs.every(isWorkflowRun))
121
+ throw new Error("github-call-failed");
122
+ return runs;
123
+ }
124
+ export async function pendingWorkflows(operation, input) {
125
+ if (input.workflows.length === 0)
126
+ return [];
127
+ const paths = input.workflows.map((workflow) => workflow.path);
128
+ const latest = new Map();
129
+ for (const run of await workflowRuns(operation, input.commit)) {
130
+ if (run.head_sha !== input.commit || run.event !== "pull_request")
131
+ continue;
132
+ const path = paths
133
+ .filter((expected) => run.path === expected || run.path.startsWith(`${expected}@`))
134
+ .sort((left, right) => right.length - left.length)[0];
135
+ if (path === undefined)
136
+ continue;
137
+ if (run.id > (latest.get(path)?.id ?? -1))
138
+ latest.set(path, run);
139
+ }
140
+ const pending = input.workflows.filter((workflow) => {
141
+ const run = latest.get(workflow.path);
142
+ if (run === undefined)
143
+ return workflow.kind === "push";
144
+ return (run.status !== "completed" ||
145
+ !["success", "neutral", "skipped"].includes(run.conclusion ?? ""));
146
+ });
147
+ return pending.length === 0 ? [] : ["waiting for GitHub Actions checks"];
148
+ }
@@ -2,6 +2,7 @@ import { settingsEnvironment } from "../cli/project-settings.js";
2
2
  import { setTimeout as delay } from "node:timers/promises";
3
3
  import { githubText } from "./github-calls.js";
4
4
  import { githubRead } from "./github-retry.js";
5
+ import { pendingWorkflows, pullRequestWorkflows, } from "./github-ci-workflows.js";
5
6
  import { ciWait, workflowAttempt, attemptChecks, rerunCi, attemptOutput, } from "./github-ci-rerun.js";
6
7
  import { field, githubTiming, repositoryPath, } from "./github-operation.js";
7
8
  function isCheckRun(value) {
@@ -203,16 +204,29 @@ async function ciFailureOutput(operation, input) {
203
204
  current,
204
205
  ]);
205
206
  }
206
- export async function waitForCi(operation, commit) {
207
- const { pollMilliseconds: poll, ciGraceMilliseconds: grace, ciLimitMilliseconds: limit, } = {
207
+ async function ciSettings(operation, commit) {
208
+ const timing = {
208
209
  ...githubTiming,
209
210
  ciGraceMilliseconds: 60_000,
210
211
  ciLimitMilliseconds: 5_400_000,
211
212
  ...operation.settings.timing,
212
213
  };
214
+ const required = requiredChecks(operation);
215
+ const workflows = required === undefined ? await pullRequestWorkflows(operation, commit) : [];
216
+ return {
217
+ required,
218
+ workflows,
219
+ poll: timing.pollMilliseconds,
220
+ limit: timing.ciLimitMilliseconds,
221
+ grace: workflows.some((workflow) => workflow.kind === "push")
222
+ ? Infinity
223
+ : timing.ciGraceMilliseconds,
224
+ };
225
+ }
226
+ export async function waitForCi(operation, commit) {
213
227
  const wait = await ciWait(operation, commit);
214
228
  const started = wait.startedAt;
215
- const required = requiredChecks(operation);
229
+ const { required, workflows, grace, poll, limit } = await ciSettings(operation, commit);
216
230
  const names = new Set(required);
217
231
  for (;;) {
218
232
  const checks = latestRuns(await checkRuns(operation, commit), required);
@@ -232,7 +246,11 @@ export async function waitForCi(operation, commit) {
232
246
  failed: retried.failures,
233
247
  }),
234
248
  };
235
- const pending = [...pendingChecks(checks, names), ...retried.pending];
249
+ const pending = [
250
+ ...pendingChecks(checks, names),
251
+ ...retried.pending,
252
+ ...(await pendingWorkflows(operation, { commit, workflows })),
253
+ ];
236
254
  if (pending.length === 0 &&
237
255
  (required !== undefined ||
238
256
  names.size > 0 ||
@@ -1,3 +1,5 @@
1
1
  import { type Operation } from "./github-operation.ts";
2
+ export declare function repositoryName(reply: string): string;
3
+ export declare function captureDraft(operation: Operation): Promise<unknown>;
2
4
  export declare function createIssue(operation: Operation): Promise<unknown>;
3
5
  export declare function discard(operation: Operation): Promise<unknown>;
@@ -1,4 +1,5 @@
1
1
  import { existsSync } from "node:fs";
2
+ import { createHash } from "node:crypto";
2
3
  import { lstat, readFile } from "node:fs/promises";
3
4
  import { basename, join } from "node:path";
4
5
  import { existingTree, removeWorktree, repositoryPath, text, } from "./github-operation.js";
@@ -30,7 +31,7 @@ function issuePage(line) {
30
31
  throw new Error("github-call-failed");
31
32
  return page.map((issue) => issueOf(issue));
32
33
  }
33
- function repositoryName(reply) {
34
+ export function repositoryName(reply) {
34
35
  const repository = JSON.parse(reply);
35
36
  if (typeof repository !== "object" ||
36
37
  repository === null ||
@@ -50,6 +51,28 @@ async function draftOf(operation) {
50
51
  throw new Error("draft-not-available");
51
52
  return readFile(path, "utf8");
52
53
  }
54
+ function draftDigest(text) {
55
+ return "sha256:" + createHash("sha256").update(text).digest("hex");
56
+ }
57
+ export async function captureDraft(operation) {
58
+ const text = await draftOf(operation);
59
+ const capture = { text, digest: draftDigest(text) };
60
+ if (Buffer.byteLength(JSON.stringify(capture)) > 65_536)
61
+ throw new Error("draft-too-large");
62
+ return capture;
63
+ }
64
+ function checkDraftDigest(operation, draft) {
65
+ if (!Object.hasOwn(operation.payload, "expectedDigests"))
66
+ return;
67
+ const digests = operation.payload["expectedDigests"];
68
+ if (!Array.isArray(digests) ||
69
+ digests.length === 0 ||
70
+ !digests.every((digest) => typeof digest === "string" && /^sha256:[0-9a-f]{64}$/.test(digest)))
71
+ throw new Error("invalid-payload");
72
+ const current = draftDigest(draft);
73
+ if (!digests.every((digest) => digest === current))
74
+ throw new Error("draft-changed");
75
+ }
53
76
  async function knownIssue(operation, marker) {
54
77
  const output = await operation.calls.gh([
55
78
  "api",
@@ -62,7 +85,10 @@ async function knownIssue(operation, marker) {
62
85
  }
63
86
  export async function createIssue(operation) {
64
87
  operatorPrivateTexts(operation.settings);
65
- const draft = await draftOf(operation);
88
+ const draft = Object.hasOwn(operation.payload, "text")
89
+ ? reportText(operation)
90
+ : await draftOf(operation);
91
+ checkDraftDigest(operation, draft);
66
92
  const [heading = "", ...lines] = draft.split("\n");
67
93
  if (!heading.startsWith("# ") || heading.slice(2).trim() === "")
68
94
  throw new Error("invalid-draft");
@@ -89,6 +115,15 @@ export async function createIssue(operation) {
89
115
  const url = printed.trim().split("\n").at(-1) ?? "";
90
116
  return issueFromUrl(url);
91
117
  }
118
+ function reportText(operation) {
119
+ if (Object.hasOwn(operation.payload, "draft") ||
120
+ Object.hasOwn(operation.payload, "expectedDigests"))
121
+ throw new Error("invalid-payload");
122
+ const report = text(operation, "text");
123
+ if (Buffer.byteLength(report) > 65536)
124
+ throw new Error("draft-too-large");
125
+ return report;
126
+ }
92
127
  export async function discard(operation) {
93
128
  const place = treePlace({
94
129
  worktrees: operation.settings.worktrees,
@@ -9,8 +9,9 @@ export declare function knownMerge(operation: Operation, expected: ReviewedPull
9
9
  readonly updated: string;
10
10
  }): Promise<{
11
11
  readonly head: string;
12
+ readonly open: boolean;
12
13
  readonly merged: string | undefined;
13
14
  }>;
14
15
  export declare function mergePull(operation: Operation, pull: ReviewedPull & {
15
16
  readonly updated: string;
16
- }): Promise<string>;
17
+ }): Promise<string | Error>;
@@ -15,11 +15,12 @@ export async function knownMerge(operation, expected) {
15
15
  `${repositoryPath}/pulls/${String(expected.number)}`,
16
16
  ]));
17
17
  const head = commitOf(field(pull, "head"), "sha");
18
+ const open = field(pull, "state") === "open";
18
19
  if (field(pull, "merged") !== true)
19
- return { head, merged: undefined };
20
+ return { head, open, merged: undefined };
20
21
  if (head !== expected.commit && head !== expected.updated)
21
22
  throw new Error("merged-other-commit");
22
- return { head, merged: commitOf(pull, "merge_commit_sha") };
23
+ return { head, open, merged: commitOf(pull, "merge_commit_sha") };
23
24
  }
24
25
  async function mergedNow(operation, pull) {
25
26
  const reply = JSON.parse(await operation.calls.gh([
@@ -63,11 +64,17 @@ export function mergePull(operation, pull) {
63
64
  },
64
65
  statuses: pull.updated === pull.commit ? [] : [405, 409],
65
66
  }).catch(async (error) => {
66
- if (!(error instanceof Error) || error.message !== "github-network-failed")
67
+ if (!(error instanceof Error))
68
+ throw error;
69
+ const refused = error.message === "github-call-failed" &&
70
+ [405, 409].includes(Number(field(error, "status")));
71
+ if (error.message !== "github-network-failed" && !refused)
67
72
  throw error;
68
73
  const known = await knownMerge(operation, pull);
69
74
  if (known.merged !== undefined)
70
75
  return known.merged;
76
+ if (refused && known.open)
77
+ return error;
71
78
  throw error;
72
79
  });
73
80
  }
@@ -136,35 +136,64 @@ async function readyHead(operation, pull) {
136
136
  let recorded = pull.recorded;
137
137
  let remote = pull.remote;
138
138
  for (let attempt = 0; attempt < 3; attempt += 1) {
139
- const updated = await refreshed(operation, {
139
+ const updated = await pushedHead(operation, {
140
+ ...pull,
140
141
  tree,
141
- commit: pull.commit,
142
142
  recorded,
143
- check: pull.check,
143
+ remote,
144
144
  });
145
- if (updated !== pull.commit && recorded !== updated)
146
- await writeRecord(operation.folder, {
147
- name: "updated-head.json",
148
- value: { commit: pull.commit, updated },
149
- });
150
- if (updated !== pull.commit && remote !== updated)
151
- await operation.calls.git(tree.path, [
152
- "push",
153
- "--quiet",
154
- "origin",
155
- `${updated}:refs/heads/${tree.branch}`,
156
- ]);
157
145
  const ci = await waitForCi(operation, updated);
158
146
  if (ci !== undefined)
159
147
  return ci;
160
- const newest = await fetched(operation, await defaultBranch(operation));
161
- if ((await operation.calls.git(tree.path, ["merge-base", updated, newest])).trim() === newest)
162
- return updated;
163
148
  recorded = updated;
164
149
  remote = updated;
150
+ if (!(await containsBase(operation, updated)))
151
+ continue;
152
+ const merged = await mergePull(operation, { ...pull, updated });
153
+ if (typeof merged === "string")
154
+ return { updated, merged };
155
+ if (await containsBase(operation, updated))
156
+ throw merged;
157
+ await recordRefusal(operation, { error: merged, updated, attempt });
165
158
  }
166
159
  throw new Error("base-moved");
167
160
  }
161
+ async function recordRefusal(operation, refusal) {
162
+ const observation = await operation.observe?.({
163
+ condition: "working",
164
+ reason: "github-merge-refused",
165
+ evidence: `github-merge/HTTP-${String(field(refusal.error, "status"))}/head-${refusal.updated}/merge-main`,
166
+ attempt: refusal.attempt + 1,
167
+ limit: 3,
168
+ });
169
+ if (observation !== undefined &&
170
+ !["accepted", "duplicate"].includes(observation.kind))
171
+ throw new Error("github-call-failed");
172
+ }
173
+ async function pushedHead(operation, pull) {
174
+ const updated = await refreshed(operation, pull);
175
+ if (updated !== pull.commit && pull.recorded !== updated)
176
+ await writeRecord(operation.folder, {
177
+ name: "updated-head.json",
178
+ value: { commit: pull.commit, updated },
179
+ });
180
+ if (updated !== pull.commit && pull.remote !== updated)
181
+ await operation.calls.git(pull.tree.path, [
182
+ "push",
183
+ "--quiet",
184
+ "origin",
185
+ `${updated}:refs/heads/${pull.tree.branch}`,
186
+ ]);
187
+ return updated;
188
+ }
189
+ async function containsBase(operation, updated) {
190
+ const newest = await fetched(operation, await defaultBranch(operation));
191
+ return ((await operation.calls.git(existingTree(operation).path, [
192
+ "merge-base",
193
+ updated,
194
+ newest,
195
+ ])).trim() === newest);
196
+ }
168
197
  function checkOutput(cause) {
169
198
  return commandOutput(cause).slice(-6_000);
170
199
  }
@@ -209,12 +238,11 @@ async function completedMerge(operation, pull) {
209
238
  ...pull,
210
239
  updated: recorded ?? pull.commit,
211
240
  });
212
- const updated = known.merged === undefined
241
+ const result = known.merged === undefined
213
242
  ? await readyHead(operation, { ...pull, recorded, remote: known.head })
214
- : (recorded ?? pull.commit);
215
- if (typeof updated !== "string")
216
- return updated;
217
- const merged = known.merged ?? (await mergePull(operation, { ...pull, updated }));
243
+ : { updated: recorded ?? pull.commit, merged: known.merged };
244
+ if ("reason" in result)
245
+ return result;
218
246
  await removed(operation, place);
219
- return { number: pull.number, commit: pull.commit, updated, merged };
247
+ return { number: pull.number, commit: pull.commit, ...result };
220
248
  }
@@ -2,15 +2,21 @@ import { setTimeout as delay } from "node:timers/promises";
2
2
  import { appendFile } from "node:fs/promises";
3
3
  import { join } from "node:path";
4
4
  import { findingsOf, scoreOf, } from "./github-calls.js";
5
+ import { attachAsset } from "./github-attach.js";
5
6
  import { closeIssue, partialIssue } from "./github-ticket-status.js";
6
7
  import { merge } from "./github-merge.js";
7
- import { createIssue, discard } from "./github-issue-methods.js";
8
+ import { inMergeTurn } from "./merge-turns.js";
9
+ import { captureDraft, createIssue, discard, repositoryName, } from "./github-issue-methods.js";
8
10
  import { existingTree, defaultBranch, changeChecked, field, githubTiming, repositoryPath, text, } from "./github-operation.js";
9
11
  import { workTree } from "./work-tree.js";
10
12
  const triggerText = "@greptileai";
11
13
  const maximumReviewRequests = 3;
12
14
  export const methodReasons = new Set([
15
+ "attachment-not-available",
16
+ "attachment-too-large",
13
17
  "draft-not-available",
18
+ "draft-changed",
19
+ "draft-too-large",
14
20
  "invalid-draft",
15
21
  "post-uncertain",
16
22
  "private-texts-not-set",
@@ -77,7 +83,10 @@ function labels(operation, name) {
77
83
  });
78
84
  }
79
85
  async function label(operation) {
80
- const repository = `${text(operation, "owner")}/${text(operation, "repository")}`;
86
+ const repository = !Object.hasOwn(operation.payload, "owner") &&
87
+ !Object.hasOwn(operation.payload, "repository")
88
+ ? repositoryName(await operation.calls.gh(["repo", "view", "--json", "nameWithOwner"]))
89
+ : `${text(operation, "owner")}/${text(operation, "repository")}`;
81
90
  const number = integer(operation, "number");
82
91
  if (!/^[\w.-]+\/[\w.-]+$/.test(repository) || !Number.isSafeInteger(number))
83
92
  throw new Error("invalid-payload");
@@ -262,15 +271,20 @@ export const methods = new Map([
262
271
  ["partial-issue", partialIssue],
263
272
  ["label", label],
264
273
  ["create-issue", createIssue],
274
+ ["capture-draft", captureDraft],
265
275
  ["discard", discard],
266
276
  ["open-pr", openPull],
277
+ ["attach-asset", attachAsset],
267
278
  ["wait-review", waitReview],
268
279
  [
269
280
  "merge",
270
- (operation) => merge(operation, {
281
+ (operation) => inMergeTurn({
282
+ repository: operation.settings.repository,
283
+ signal: operation.signal,
284
+ }, () => merge(operation, {
271
285
  number: integer(operation, "number"),
272
286
  commit: text(operation, "commit"),
273
287
  check: mergeCheck(operation),
274
- }),
288
+ })),
275
289
  ],
276
290
  ]);
@@ -1,4 +1,5 @@
1
1
  import type { CallSettings, Calls } from "./github-calls.ts";
2
+ import type { ObservationReport } from "../service/worker-port.ts";
2
3
  export interface GithubTiming {
3
4
  readonly pollMilliseconds: number;
4
5
  readonly triggerMilliseconds: number;
@@ -20,6 +21,9 @@ export interface Operation {
20
21
  readonly payload: Readonly<Record<string, unknown>>;
21
22
  readonly signal: AbortSignal;
22
23
  readonly folder: string;
24
+ readonly observe?: (report: Pick<ObservationReport, "condition" | "reason" | "evidence" | "attempt" | "limit">) => Promise<{
25
+ readonly kind: string;
26
+ } | undefined>;
23
27
  }
24
28
  export interface Place {
25
29
  readonly path: string;
@@ -1,6 +1,8 @@
1
1
  import { homedir } from "node:os";
2
2
  import { existsSync } from "node:fs";
3
3
  import { join } from "node:path";
4
+ import { rm } from "node:fs/promises";
5
+ import { attachmentFolder } from "./attachments.js";
4
6
  import { treePlace } from "./work-tree.js";
5
7
  export const githubTiming = {
6
8
  pollMilliseconds: 30_000,
@@ -32,6 +34,10 @@ export async function removeWorktree(operation, place) {
32
34
  await repository(["worktree", "remove", "--force", place.path]);
33
35
  if ((await repository(["branch", "--list", place.branch])).trim() !== "")
34
36
  await repository(["branch", "-D", place.branch]);
37
+ await rm(attachmentFolder({
38
+ worktrees: operation.settings.worktrees,
39
+ target: operation.target,
40
+ }), { recursive: true, force: true });
35
41
  }
36
42
  export async function defaultBranch(operation) {
37
43
  const reference = await operation.calls.git(operation.settings.repository, [
@@ -1,4 +1,5 @@
1
1
  import type { Delivery } from "../broker/actor/delivery-intents.ts";
2
+ import type { ObservationReport } from "../service/worker-port.ts";
2
3
  import { type MethodSettings } from "./github-methods.ts";
3
4
  import { type WorkerReport } from "./operation-journal.ts";
4
5
  export type { GithubTiming } from "./github-methods.ts";
@@ -6,6 +7,9 @@ export interface GithubWorkerSettings extends MethodSettings {
6
7
  readonly journal: string;
7
8
  readonly document: (digest: string) => Promise<string | undefined>;
8
9
  readonly report: (report: WorkerReport) => Promise<unknown>;
10
+ readonly observe?: (report: ObservationReport) => Promise<{
11
+ readonly kind: string;
12
+ }>;
9
13
  readonly operationStatus: (operationId: string) => Promise<string | undefined>;
10
14
  readonly runStatus: (runId: string) => Promise<string | undefined>;
11
15
  }
@@ -47,6 +47,12 @@ async function outcome(parts, run) {
47
47
  target: intent.target,
48
48
  payload,
49
49
  signal,
50
+ observe: async (observation) => settings.observe?.({
51
+ ...observation,
52
+ runId: intent.runId,
53
+ operationId: intent.operationId,
54
+ commandId: `github:${run.key}:merge-refused:${String(observation.attempt)}`,
55
+ }),
50
56
  });
51
57
  return {
52
58
  outcome: "completed",
@@ -1,12 +1,15 @@
1
+ import { type QueuePort } from "../queue-state.ts";
1
2
  interface QueueSettings {
2
3
  readonly directory: string;
3
4
  readonly runtimeDirectory: string;
4
5
  readonly intervalMilliseconds: number;
5
6
  readonly lanes?: number;
6
7
  readonly resetQueue?: boolean;
7
- readonly workflowId?: string;
8
+ readonly workflowId: string;
8
9
  }
9
10
  export declare function issueQueue(settings: QueueSettings): {
10
11
  readonly stop: () => Promise<void>;
12
+ readonly port: QueuePort;
13
+ readonly ready: Promise<void>;
11
14
  };
12
15
  export {};