cloving 1.2.0 → 1.3.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 (518) hide show
  1. package/README.md +525 -185
  2. package/dist/src/agent-harness-shell.d.ts +12 -0
  3. package/dist/src/agent-harness-shell.js +90 -0
  4. package/dist/src/agent-harness-versions.d.ts +8 -0
  5. package/dist/src/agent-harness-versions.js +49 -0
  6. package/dist/src/agent-harnesses.d.ts +4 -0
  7. package/dist/src/agent-harnesses.js +13 -0
  8. package/dist/src/authority/commands.d.ts +1 -0
  9. package/dist/src/authority/commands.js +24 -4
  10. package/dist/src/authority/gate-reduction.d.ts +1 -0
  11. package/dist/src/authority/gate-reduction.js +18 -3
  12. package/dist/src/authority/gates.d.ts +2 -1
  13. package/dist/src/authority/gates.js +5 -1
  14. package/dist/src/authority/operations.js +1 -1
  15. package/dist/src/authority/reduction.d.ts +1 -1
  16. package/dist/src/authority/reduction.js +6 -1
  17. package/dist/src/authority/status-input.d.ts +1 -1
  18. package/dist/src/authority/status.d.ts +1 -0
  19. package/dist/src/authority/status.js +27 -3
  20. package/dist/src/authority/transitions.d.ts +5 -5
  21. package/dist/src/authority/transitions.js +6 -0
  22. package/dist/src/broker/actor/authority-delivery.js +1 -0
  23. package/dist/src/broker/actor/authority-queries.d.ts +7 -1
  24. package/dist/src/broker/actor/authority-queries.js +17 -2
  25. package/dist/src/broker/actor/authority-receipts.js +11 -1
  26. package/dist/src/broker/actor/authority-session.js +2 -2
  27. package/dist/src/broker/actor/authority-settings.js +4 -0
  28. package/dist/src/broker/actor/delivery-intents.d.ts +2 -1
  29. package/dist/src/broker/actor/delivery-intents.js +4 -4
  30. package/dist/src/broker/actor/effect-delivery.js +4 -1
  31. package/dist/src/broker/actor/effect-queries.d.ts +1 -0
  32. package/dist/src/broker/actor/effect-queries.js +7 -0
  33. package/dist/src/broker/actor/pin-check.js +1 -1
  34. package/dist/src/broker/actor/stop-plan.js +1 -1
  35. package/dist/src/broker/actor/turn-state.js +1 -1
  36. package/dist/src/broker/authority-admission.js +22 -9
  37. package/dist/src/broker/authority-restore.js +1 -0
  38. package/dist/src/broker/decision-restore.js +4 -4
  39. package/dist/src/broker/socket-address.d.ts +3 -1
  40. package/dist/src/broker/socket-address.js +2 -2
  41. package/dist/src/cli/arguments.d.ts +11 -13
  42. package/dist/src/cli/arguments.js +37 -107
  43. package/dist/src/cli/command-effects.d.ts +7 -0
  44. package/dist/src/cli/command-effects.js +39 -0
  45. package/dist/src/cli/commands.js +11 -4
  46. package/dist/src/cli/config-arguments.d.ts +11 -0
  47. package/dist/src/cli/config-arguments.js +59 -0
  48. package/dist/src/cli/config-command.d.ts +2 -0
  49. package/dist/src/cli/config-command.js +105 -0
  50. package/dist/src/cli/config-file.d.ts +3 -0
  51. package/dist/src/cli/config-file.js +50 -0
  52. package/dist/src/cli/config-lock.d.ts +7 -0
  53. package/dist/src/cli/config-lock.js +61 -0
  54. package/dist/src/cli/config-notice.d.ts +5 -0
  55. package/dist/src/cli/config-notice.js +46 -0
  56. package/dist/src/cli/doctor-github.d.ts +9 -0
  57. package/dist/src/cli/doctor-github.js +138 -0
  58. package/dist/src/cli/doctor-harness.d.ts +13 -0
  59. package/dist/src/cli/doctor-harness.js +242 -0
  60. package/dist/src/cli/doctor-local.d.ts +18 -0
  61. package/dist/src/cli/doctor-local.js +77 -0
  62. package/dist/src/cli/doctor-runtime.d.ts +15 -0
  63. package/dist/src/cli/doctor-runtime.js +176 -0
  64. package/dist/src/cli/doctor-service.d.ts +1 -0
  65. package/dist/src/cli/doctor-service.js +11 -0
  66. package/dist/src/cli/doctor-workflows.d.ts +3 -0
  67. package/dist/src/cli/doctor-workflows.js +45 -0
  68. package/dist/src/cli/doctor.d.ts +15 -0
  69. package/dist/src/cli/doctor.js +190 -0
  70. package/dist/src/cli/github-ci-progress.d.ts +8 -0
  71. package/dist/src/cli/github-ci-progress.js +83 -0
  72. package/dist/src/cli/github-retry.d.ts +6 -0
  73. package/dist/src/cli/github-retry.js +47 -0
  74. package/dist/src/cli/harness-probes.d.ts +22 -0
  75. package/dist/src/cli/harness-probes.js +183 -0
  76. package/dist/src/cli/main.d.ts +7 -1
  77. package/dist/src/cli/main.js +39 -61
  78. package/dist/src/cli/phone-arguments.d.ts +14 -0
  79. package/dist/src/cli/phone-arguments.js +37 -0
  80. package/dist/src/cli/phone-client.d.ts +2 -0
  81. package/dist/src/cli/phone-client.js +32 -0
  82. package/dist/src/cli/phone-command.d.ts +13 -0
  83. package/dist/src/cli/phone-command.js +101 -0
  84. package/dist/src/cli/probe-command.d.ts +36 -0
  85. package/dist/src/cli/probe-command.js +59 -0
  86. package/dist/src/cli/project-settings.d.ts +4 -0
  87. package/dist/src/cli/project-settings.js +33 -0
  88. package/dist/src/cli/render.d.ts +2 -1
  89. package/dist/src/cli/render.js +44 -28
  90. package/dist/src/cli/report-github.d.ts +18 -0
  91. package/dist/src/cli/report-github.js +200 -0
  92. package/dist/src/cli/report.d.ts +17 -0
  93. package/dist/src/cli/report.js +192 -0
  94. package/dist/src/cli/repository-arguments.d.ts +5 -0
  95. package/dist/src/cli/repository-arguments.js +34 -0
  96. package/dist/src/cli/runtime-arguments.d.ts +4 -0
  97. package/dist/src/cli/runtime-arguments.js +15 -0
  98. package/dist/src/cli/runtime-directory.d.ts +6 -2
  99. package/dist/src/cli/runtime-directory.js +72 -14
  100. package/dist/src/cli/toolchain.d.ts +2 -0
  101. package/dist/src/cli/toolchain.js +22 -2
  102. package/dist/src/cli/usage-render.d.ts +5 -0
  103. package/dist/src/cli/usage-render.js +40 -1
  104. package/dist/src/cli/usage.d.ts +3 -3
  105. package/dist/src/cli/usage.js +70 -44
  106. package/dist/src/cli/watch-actions.d.ts +2 -0
  107. package/dist/src/cli/watch-actions.js +4 -4
  108. package/dist/src/cli/watch-board-view.d.ts +1 -1
  109. package/dist/src/cli/watch-board-view.js +8 -2
  110. package/dist/src/cli/watch-board.js +23 -10
  111. package/dist/src/cli/watch-card-forms.js +2 -2
  112. package/dist/src/cli/watch-client.d.ts +1 -1
  113. package/dist/src/cli/watch-client.js +7 -2
  114. package/dist/src/cli/watch-header-view.d.ts +27 -0
  115. package/dist/src/cli/watch-header-view.js +116 -0
  116. package/dist/src/cli/watch-model.js +17 -4
  117. package/dist/src/cli/watch-page.js +48 -12
  118. package/dist/src/cli/watch-phone-client.d.ts +1 -0
  119. package/dist/src/cli/watch-phone-client.js +84 -0
  120. package/dist/src/cli/watch-phone-view.d.ts +56 -0
  121. package/dist/src/cli/watch-phone-view.js +113 -0
  122. package/dist/src/cli/watch-phone.d.ts +5 -0
  123. package/dist/src/cli/watch-phone.js +53 -0
  124. package/dist/src/cli/watch-pull-request.d.ts +3 -1
  125. package/dist/src/cli/watch-pull-request.js +4 -0
  126. package/dist/src/cli/watch-render.d.ts +9 -1
  127. package/dist/src/cli/watch-server.js +23 -5
  128. package/dist/src/cli/watch-turn.d.ts +4 -1
  129. package/dist/src/cli/watch-turn.js +37 -1
  130. package/dist/src/cli/watch-usage.js +5 -1
  131. package/dist/src/cli/watch-view.d.ts +6 -20
  132. package/dist/src/cli/watch-view.js +14 -106
  133. package/dist/src/cli.js +106 -23
  134. package/dist/src/command-settings.d.ts +16 -0
  135. package/dist/src/command-settings.js +42 -0
  136. package/dist/src/configuration-change.d.ts +11 -0
  137. package/dist/src/configuration-change.js +62 -0
  138. package/dist/src/configuration-display.d.ts +21 -0
  139. package/dist/src/configuration-display.js +69 -0
  140. package/dist/src/configuration-schema.d.ts +49 -0
  141. package/dist/src/configuration-schema.js +159 -0
  142. package/dist/src/daemon/claude-turn.d.ts +19 -5
  143. package/dist/src/daemon/claude-turn.js +116 -53
  144. package/dist/src/daemon/claude-worker.d.ts +3 -3
  145. package/dist/src/daemon/claude-worker.js +65 -76
  146. package/dist/src/daemon/command-journal.d.ts +5 -0
  147. package/dist/src/daemon/command-journal.js +50 -0
  148. package/dist/src/daemon/command-process.d.ts +28 -0
  149. package/dist/src/daemon/command-process.js +164 -0
  150. package/dist/src/daemon/command-worker.d.ts +19 -0
  151. package/dist/src/daemon/command-worker.js +182 -0
  152. package/dist/src/daemon/cursor-stream.d.ts +4 -0
  153. package/dist/src/daemon/cursor-stream.js +154 -0
  154. package/dist/src/daemon/daemon-adapters.d.ts +58 -0
  155. package/dist/src/daemon/daemon-adapters.js +102 -0
  156. package/dist/src/daemon/daemon-loops.d.ts +14 -0
  157. package/dist/src/daemon/daemon-loops.js +39 -0
  158. package/dist/src/daemon/daemon.d.ts +2 -33
  159. package/dist/src/daemon/daemon.js +126 -132
  160. package/dist/src/daemon/declared-input.d.ts +3 -0
  161. package/dist/src/daemon/declared-input.js +9 -0
  162. package/dist/src/daemon/delivery-router.js +1 -1
  163. package/dist/src/daemon/gemini-stream.d.ts +4 -0
  164. package/dist/src/daemon/gemini-stream.js +129 -0
  165. package/dist/src/daemon/github-ci-rerun.d.ts +26 -0
  166. package/dist/src/daemon/github-ci-rerun.js +92 -0
  167. package/dist/src/daemon/github-ci.js +89 -8
  168. package/dist/src/daemon/github-merge-call.d.ts +2 -0
  169. package/dist/src/daemon/github-merge.js +7 -3
  170. package/dist/src/daemon/github-methods.js +10 -0
  171. package/dist/src/daemon/github-operation.d.ts +1 -0
  172. package/dist/src/daemon/github-retry.js +8 -44
  173. package/dist/src/daemon/issue-queue.d.ts +1 -0
  174. package/dist/src/daemon/issue-queue.js +3 -26
  175. package/dist/src/daemon/notify.js +2 -1
  176. package/dist/src/daemon/opencode-stream.d.ts +5 -0
  177. package/dist/src/daemon/opencode-stream.js +87 -0
  178. package/dist/src/daemon/queue-status.d.ts +4 -0
  179. package/dist/src/daemon/queue-status.js +38 -0
  180. package/dist/src/daemon/retry-worktree.d.ts +18 -0
  181. package/dist/src/daemon/retry-worktree.js +139 -0
  182. package/dist/src/daemon/retrying-turn.d.ts +2 -0
  183. package/dist/src/daemon/retrying-turn.js +108 -30
  184. package/dist/src/daemon/schedule-journal.d.ts +19 -0
  185. package/dist/src/daemon/schedule-journal.js +57 -0
  186. package/dist/src/daemon/text-output.d.ts +18 -0
  187. package/dist/src/daemon/text-output.js +44 -0
  188. package/dist/src/daemon/ticket-registration.d.ts +5 -7
  189. package/dist/src/daemon/ticket-registration.js +85 -40
  190. package/dist/src/daemon/turn-command.d.ts +10 -0
  191. package/dist/src/daemon/turn-command.js +33 -0
  192. package/dist/src/daemon/turn-report.d.ts +18 -0
  193. package/dist/src/daemon/turn-report.js +79 -0
  194. package/dist/src/daemon/work-tree.d.ts +2 -1
  195. package/dist/src/daemon/work-tree.js +15 -12
  196. package/dist/src/daemon/workflow-generations.d.ts +32 -0
  197. package/dist/src/daemon/workflow-generations.js +57 -0
  198. package/dist/src/daemon/workflow-replay.d.ts +16 -0
  199. package/dist/src/daemon/workflow-replay.js +58 -0
  200. package/dist/src/daemon/workflow-schedules.d.ts +27 -0
  201. package/dist/src/daemon/workflow-schedules.js +185 -0
  202. package/dist/src/decision-wait.d.ts +1 -0
  203. package/dist/src/decision-wait.js +3 -0
  204. package/dist/src/delivery-backoff.d.ts +1 -0
  205. package/dist/src/delivery-backoff.js +3 -0
  206. package/dist/src/doctor-report.d.ts +24 -0
  207. package/dist/src/doctor-report.js +70 -0
  208. package/dist/src/execution-pin.d.ts +5 -0
  209. package/dist/src/execution-pin.js +67 -4
  210. package/dist/src/grok-result.d.ts +12 -0
  211. package/dist/src/grok-result.js +61 -0
  212. package/dist/src/harness-defaults.d.ts +35 -0
  213. package/dist/src/harness-defaults.js +121 -0
  214. package/dist/src/host/decision-resume.d.ts +35 -0
  215. package/dist/src/host/decision-resume.js +86 -0
  216. package/dist/src/host/gate-bridge.d.ts +48 -0
  217. package/dist/src/host/gate-bridge.js +124 -0
  218. package/dist/src/host/run-wait.d.ts +26 -0
  219. package/dist/src/host/run-wait.js +37 -0
  220. package/dist/src/host/start-delivery.d.ts +1 -1
  221. package/dist/src/host/start-delivery.js +10 -3
  222. package/dist/src/host/step-bridge-host.d.ts +6 -20
  223. package/dist/src/host/step-bridge-host.js +44 -58
  224. package/dist/src/merge-request.d.ts +19 -0
  225. package/dist/src/merge-request.js +32 -0
  226. package/dist/src/phone/canonical-json.d.ts +1 -0
  227. package/dist/src/phone/canonical-json.js +16 -0
  228. package/dist/src/phone/phone-link.d.ts +7 -0
  229. package/dist/src/phone/phone-link.js +21 -0
  230. package/dist/src/phone/qr-data.d.ts +8 -0
  231. package/dist/src/phone/qr-data.js +133 -0
  232. package/dist/src/phone/qr-matrix.d.ts +6 -0
  233. package/dist/src/phone/qr-matrix.js +175 -0
  234. package/dist/src/phone/qr-penalty.d.ts +3 -0
  235. package/dist/src/phone/qr-penalty.js +67 -0
  236. package/dist/src/phone/qr-picture.d.ts +5 -0
  237. package/dist/src/phone/qr-picture.js +24 -0
  238. package/dist/src/private-config.schema.json +263 -0
  239. package/dist/src/project-config.schema.json +65 -0
  240. package/dist/src/project-settings.d.ts +19 -0
  241. package/dist/src/project-settings.js +131 -0
  242. package/dist/src/relay/answer-check.d.ts +24 -0
  243. package/dist/src/relay/answer-check.js +145 -0
  244. package/dist/src/relay/answer-inbox.d.ts +15 -0
  245. package/dist/src/relay/answer-inbox.js +173 -0
  246. package/dist/src/relay/daemon-keys.d.ts +16 -0
  247. package/dist/src/relay/daemon-keys.js +75 -0
  248. package/dist/src/relay/decision-check.d.ts +3 -0
  249. package/dist/src/relay/decision-check.js +77 -0
  250. package/dist/src/relay/decision-close.d.ts +6 -0
  251. package/dist/src/relay/decision-close.js +72 -0
  252. package/dist/src/relay/decision-envelopes.d.ts +29 -0
  253. package/dist/src/relay/decision-envelopes.js +93 -0
  254. package/dist/src/relay/decision-watch.d.ts +14 -0
  255. package/dist/src/relay/decision-watch.js +68 -0
  256. package/dist/src/relay/envelope-post.d.ts +8 -0
  257. package/dist/src/relay/envelope-post.js +71 -0
  258. package/dist/src/relay/envelope.d.ts +28 -0
  259. package/dist/src/relay/envelope.js +53 -0
  260. package/dist/src/relay/hpke.d.ts +25 -0
  261. package/dist/src/relay/hpke.js +108 -0
  262. package/dist/src/relay/pairing-checks.d.ts +42 -0
  263. package/dist/src/relay/pairing-checks.js +172 -0
  264. package/dist/src/relay/pairing-follow.d.ts +8 -0
  265. package/dist/src/relay/pairing-follow.js +95 -0
  266. package/dist/src/relay/pairing-session.d.ts +29 -0
  267. package/dist/src/relay/pairing-session.js +87 -0
  268. package/dist/src/relay/phone-delivery.d.ts +51 -0
  269. package/dist/src/relay/phone-delivery.js +139 -0
  270. package/dist/src/relay/phone-devices.d.ts +36 -0
  271. package/dist/src/relay/phone-devices.js +46 -0
  272. package/dist/src/relay/phone-inbox.d.ts +18 -0
  273. package/dist/src/relay/phone-inbox.js +17 -0
  274. package/dist/src/relay/phone-operations.d.ts +18 -0
  275. package/dist/src/relay/phone-operations.js +121 -0
  276. package/dist/src/relay/phone-outbox.d.ts +21 -0
  277. package/dist/src/relay/phone-outbox.js +25 -0
  278. package/dist/src/relay/phone-socket.d.ts +6 -0
  279. package/dist/src/relay/phone-socket.js +63 -0
  280. package/dist/src/relay/relay-control.d.ts +7 -0
  281. package/dist/src/relay/relay-control.js +24 -0
  282. package/dist/src/relay/relay-files.d.ts +2 -0
  283. package/dist/src/relay/relay-files.js +23 -0
  284. package/dist/src/relay/relay-heartbeat.d.ts +17 -0
  285. package/dist/src/relay/relay-heartbeat.js +81 -0
  286. package/dist/src/relay/relay-http.d.ts +14 -0
  287. package/dist/src/relay/relay-http.js +63 -0
  288. package/dist/src/relay/relay-registration.d.ts +15 -0
  289. package/dist/src/relay/relay-registration.js +63 -0
  290. package/dist/src/relay/relay-service.d.ts +25 -0
  291. package/dist/src/relay/relay-service.js +216 -0
  292. package/dist/src/relay/relay-store.d.ts +48 -0
  293. package/dist/src/relay/relay-store.js +131 -0
  294. package/dist/src/relay/sealed-post.d.ts +25 -0
  295. package/dist/src/relay/sealed-post.js +52 -0
  296. package/dist/src/relay.d.ts +1 -0
  297. package/dist/src/relay.js +8 -0
  298. package/dist/src/report-statistics.d.ts +50 -0
  299. package/dist/src/report-statistics.js +70 -0
  300. package/dist/src/report.d.ts +171 -0
  301. package/dist/src/report.js +119 -0
  302. package/dist/src/repository-identity.d.ts +4 -0
  303. package/dist/src/repository-identity.js +4 -0
  304. package/dist/src/review-subject.d.ts +41 -0
  305. package/dist/src/review-subject.js +91 -0
  306. package/dist/src/run-wait.d.ts +23 -0
  307. package/dist/src/run-wait.js +20 -0
  308. package/dist/src/service/active-tickets.d.ts +4 -0
  309. package/dist/src/service/active-tickets.js +49 -0
  310. package/dist/src/service/command-effects.d.ts +4 -0
  311. package/dist/src/service/command-effects.js +16 -0
  312. package/dist/src/service/decision-handler.d.ts +4 -0
  313. package/dist/src/service/decision-handler.js +39 -4
  314. package/dist/src/service/gateway.js +18 -3
  315. package/dist/src/service/registry.d.ts +16 -3
  316. package/dist/src/service/registry.js +34 -3
  317. package/dist/src/service/replies.d.ts +9 -1
  318. package/dist/src/service/replies.js +12 -0
  319. package/dist/src/service/run-handlers.js +14 -55
  320. package/dist/src/service/run-metadata.d.ts +8 -0
  321. package/dist/src/service/run-metadata.js +53 -0
  322. package/dist/src/service/run-waits.d.ts +3 -0
  323. package/dist/src/service/run-waits.js +41 -0
  324. package/dist/src/service/service.d.ts +18 -2
  325. package/dist/src/service/service.js +23 -7
  326. package/dist/src/service/submission-handler.d.ts +0 -1
  327. package/dist/src/service/submission-handler.js +6 -34
  328. package/dist/src/service/worker-port.d.ts +1 -0
  329. package/dist/src/service/worker-totals.js +8 -23
  330. package/dist/src/step-bridge.d.ts +23 -0
  331. package/dist/src/steps/decision-gate.d.ts +2 -1
  332. package/dist/src/steps/decision-gate.js +7 -0
  333. package/dist/src/steps/merge-by-person.d.ts +2 -0
  334. package/dist/src/steps/merge-by-person.js +18 -0
  335. package/dist/src/steps/merge-when-green.d.ts +2 -0
  336. package/dist/src/steps/merge-when-green.js +62 -0
  337. package/dist/src/steps/review-by-agent.d.ts +5 -0
  338. package/dist/src/steps/review-by-agent.js +124 -0
  339. package/dist/src/steps/review-by-person.d.ts +4 -0
  340. package/dist/src/steps/review-by-person.js +16 -0
  341. package/dist/src/steps/review-subject.d.ts +2 -0
  342. package/dist/src/steps/review-subject.js +11 -0
  343. package/dist/src/steps/run-command.d.ts +2 -0
  344. package/dist/src/steps/run-command.js +15 -0
  345. package/dist/src/steps/sleep.d.ts +3 -0
  346. package/dist/src/steps/sleep.js +19 -0
  347. package/dist/src/steps/wait-for-decision.d.ts +2 -0
  348. package/dist/src/steps/wait-for-decision.js +71 -0
  349. package/dist/src/steps/wait-for-run.d.ts +5 -0
  350. package/dist/src/steps/wait-for-run.js +9 -0
  351. package/dist/src/storage/decision-snapshots.d.ts +1 -0
  352. package/dist/src/storage/decision-snapshots.js +7 -1
  353. package/dist/src/submission.d.ts +4 -0
  354. package/dist/src/submission.js +6 -2
  355. package/dist/src/testing.d.ts +29 -0
  356. package/dist/src/testing.js +264 -0
  357. package/dist/src/ticket-status-stream.d.ts +9 -0
  358. package/dist/src/ticket-status-stream.js +94 -0
  359. package/dist/src/token-prices.d.ts +12 -4
  360. package/dist/src/token-prices.js +15 -2
  361. package/dist/src/turn-profile.d.ts +1 -0
  362. package/dist/src/turn-profile.js +8 -1
  363. package/dist/src/worker-usage.d.ts +16 -0
  364. package/dist/src/worker-usage.js +57 -0
  365. package/dist/src/workflow-admission.d.ts +5 -0
  366. package/dist/src/workflow-candidate.d.ts +7 -2
  367. package/dist/src/workflow-candidate.js +47 -5
  368. package/dist/src/workflow-declaration.d.ts +21 -3
  369. package/dist/src/workflow-declaration.js +77 -9
  370. package/dist/src/workflow-discovery.d.ts +2 -1
  371. package/dist/src/workflow-discovery.js +4 -1
  372. package/dist/src/workflow-refusals.js +3 -0
  373. package/dist/src/workflow-schedule.d.ts +22 -0
  374. package/dist/src/workflow-schedule.js +53 -0
  375. package/dist/src/workflows.d.ts +11 -1
  376. package/dist/src/workflows.js +8 -0
  377. package/dist/tools/admit-workflow.d.ts +1 -0
  378. package/dist/tools/admit-workflow.js +18 -5
  379. package/dist/tools/doctor-adoption.d.ts +1 -0
  380. package/dist/tools/doctor-adoption.js +11 -0
  381. package/dist/tools/project-configuration.d.ts +4 -0
  382. package/dist/tools/project-configuration.js +47 -0
  383. package/dist/tools/self-host-processes.d.ts +1 -0
  384. package/dist/tools/self-host-processes.js +33 -22
  385. package/dist/tools/self-host-project.d.ts +4 -0
  386. package/dist/tools/self-host-project.js +61 -14
  387. package/dist/tools/self-host-runtime.d.ts +16 -0
  388. package/dist/tools/self-host-runtime.js +60 -0
  389. package/dist/tools/self-host-workflows.d.ts +1 -0
  390. package/dist/tools/self-host-workflows.js +36 -1
  391. package/dist/tools/self-host.js +86 -61
  392. package/dist/tools/workflow-candidate-counts.d.ts +6 -2
  393. package/dist/tools/workflow-candidate-counts.js +31 -16
  394. package/dist/tools/workflow-candidate-fields.d.ts +5 -0
  395. package/dist/tools/workflow-candidate-fields.js +24 -0
  396. package/dist/tools/workflow-candidate-helper-counts.d.ts +10 -0
  397. package/dist/tools/workflow-candidate-helper-counts.js +129 -0
  398. package/dist/tools/workflow-candidate-program.d.ts +2 -0
  399. package/dist/tools/workflow-candidate-program.js +36 -8
  400. package/dist/tools/workflow-candidate-source.js +77 -15
  401. package/dist/tools/workflow-candidate-syntax.d.ts +8 -2
  402. package/dist/tools/workflow-candidate-syntax.js +70 -26
  403. package/dist/tools/workflow-command.d.ts +1 -0
  404. package/dist/tools/workflow-command.js +143 -0
  405. package/dist/tools/workflow-folder-capture.d.ts +1 -0
  406. package/dist/tools/workflow-folder-capture.js +47 -2
  407. package/dist/tools/workflow-folders.d.ts +17 -1
  408. package/dist/tools/workflow-folders.js +59 -6
  409. package/dist/tools/workflow-test-hook.d.ts +7 -0
  410. package/dist/tools/workflow-test-hook.js +16 -0
  411. package/dist/tools/workflow-test-loader.d.ts +1 -0
  412. package/dist/tools/workflow-test-loader.js +10 -0
  413. package/dist/workflows/develop-ticket.js +1 -1
  414. package/dist/workflows/ticket-prompts.js +5 -1
  415. package/package.json +46 -4
  416. package/templates/develop/README.md +78 -0
  417. package/templates/develop/develop/accept.ts +11 -0
  418. package/templates/develop/develop/flow-tests.ts +357 -0
  419. package/templates/develop/develop/local.ts +40 -0
  420. package/templates/develop/develop/option-tests.ts +174 -0
  421. package/templates/develop/develop/partial-choice.ts +29 -0
  422. package/templates/develop/develop/partial.ts +28 -0
  423. package/templates/develop/develop/pull.ts +152 -0
  424. package/templates/develop/develop/queue-partial.ts +39 -0
  425. package/templates/develop/develop/refusal-tests.ts +174 -0
  426. package/templates/develop/develop/report.ts +156 -0
  427. package/templates/develop/develop/round.ts +40 -0
  428. package/templates/develop/develop/scenarios.ts +87 -0
  429. package/templates/develop/develop/turn.ts +67 -0
  430. package/templates/develop/develop.declaration.json +24 -0
  431. package/templates/develop/develop.test.ts +287 -0
  432. package/templates/develop/develop.ts +30 -0
  433. package/templates/develop/template.json +153 -0
  434. package/dist/src/chats/analysis-batches.d.ts +0 -42
  435. package/dist/src/chats/analysis-batches.js +0 -97
  436. package/dist/src/chats/analysis-checkpoint.d.ts +0 -29
  437. package/dist/src/chats/analysis-checkpoint.js +0 -31
  438. package/dist/src/chats/analysis-contract.d.ts +0 -80
  439. package/dist/src/chats/analysis-contract.js +0 -16
  440. package/dist/src/chats/analysis-data.d.ts +0 -3
  441. package/dist/src/chats/analysis-data.js +0 -85
  442. package/dist/src/chats/analysis-input.d.ts +0 -18
  443. package/dist/src/chats/analysis-input.js +0 -97
  444. package/dist/src/chats/analysis-links.d.ts +0 -2
  445. package/dist/src/chats/analysis-links.js +0 -25
  446. package/dist/src/chats/analysis-merge.d.ts +0 -16
  447. package/dist/src/chats/analysis-merge.js +0 -134
  448. package/dist/src/chats/analysis-prompt.d.ts +0 -18
  449. package/dist/src/chats/analysis-prompt.js +0 -42
  450. package/dist/src/chats/analysis-proposal.d.ts +0 -4
  451. package/dist/src/chats/analysis-proposal.js +0 -41
  452. package/dist/src/chats/analysis-provenance.d.ts +0 -4
  453. package/dist/src/chats/analysis-provenance.js +0 -99
  454. package/dist/src/chats/analysis-shape.d.ts +0 -4
  455. package/dist/src/chats/analysis-shape.js +0 -235
  456. package/dist/src/chats/analysis.d.ts +0 -3
  457. package/dist/src/chats/analysis.js +0 -42
  458. package/dist/src/chats/corpus-input.d.ts +0 -5
  459. package/dist/src/chats/corpus-input.js +0 -288
  460. package/dist/src/chats/destination.d.ts +0 -4
  461. package/dist/src/chats/destination.js +0 -96
  462. package/dist/src/chats/import.d.ts +0 -15
  463. package/dist/src/chats/import.js +0 -243
  464. package/dist/src/chats/input-file.d.ts +0 -3
  465. package/dist/src/chats/input-file.js +0 -32
  466. package/dist/src/chats/normalize.d.ts +0 -29
  467. package/dist/src/chats/normalize.js +0 -155
  468. package/dist/src/chats/previous-import.d.ts +0 -5
  469. package/dist/src/chats/previous-import.js +0 -34
  470. package/dist/src/chats/reader.d.ts +0 -21
  471. package/dist/src/chats/reader.js +0 -118
  472. package/dist/src/chats/redact-import.d.ts +0 -14
  473. package/dist/src/chats/redact-import.js +0 -141
  474. package/dist/src/chats/redaction.d.ts +0 -41
  475. package/dist/src/chats/redaction.js +0 -161
  476. package/dist/src/chats/reference-mapping.d.ts +0 -16
  477. package/dist/src/chats/reference-mapping.js +0 -153
  478. package/dist/src/chats/revision-input.d.ts +0 -3
  479. package/dist/src/chats/revision-input.js +0 -180
  480. package/dist/src/chats/revision.d.ts +0 -48
  481. package/dist/src/chats/revision.js +0 -94
  482. package/dist/src/chats/selection.d.ts +0 -25
  483. package/dist/src/chats/selection.js +0 -109
  484. package/dist/src/chats/source.d.ts +0 -23
  485. package/dist/src/chats/source.js +0 -135
  486. package/dist/src/chats/structure.d.ts +0 -57
  487. package/dist/src/chats/structure.js +0 -216
  488. package/dist/src/chats/workflow-generation-projection.d.ts +0 -8
  489. package/dist/src/chats/workflow-generation-projection.js +0 -75
  490. package/dist/src/chats/workflow-generation-source.d.ts +0 -25
  491. package/dist/src/chats/workflow-generation-source.js +0 -124
  492. package/dist/src/chats/workflow-generation-text.d.ts +0 -23
  493. package/dist/src/chats/workflow-generation-text.js +0 -74
  494. package/dist/src/chats/workflow-generation.d.ts +0 -69
  495. package/dist/src/chats/workflow-generation.js +0 -142
  496. package/dist/src/daemon/analysis-launch.d.ts +0 -5
  497. package/dist/src/daemon/analysis-launch.js +0 -81
  498. package/dist/src/daemon/analysis-token.d.ts +0 -6
  499. package/dist/src/daemon/analysis-token.js +0 -88
  500. package/dist/src/daemon/analysis-worker.d.ts +0 -20
  501. package/dist/src/daemon/analysis-worker.js +0 -271
  502. package/dist/src/daemon/chats-batch-binding.d.ts +0 -23
  503. package/dist/src/daemon/chats-batch-binding.js +0 -99
  504. package/dist/src/daemon/chats-capture.d.ts +0 -18
  505. package/dist/src/daemon/chats-capture.js +0 -194
  506. package/dist/src/daemon/chats-checkpoints.d.ts +0 -41
  507. package/dist/src/daemon/chats-checkpoints.js +0 -186
  508. package/dist/src/daemon/chats-files.d.ts +0 -42
  509. package/dist/src/daemon/chats-files.js +0 -252
  510. package/dist/src/daemon/chats-follow-up.d.ts +0 -38
  511. package/dist/src/daemon/chats-follow-up.js +0 -180
  512. package/dist/src/daemon/chats-question.d.ts +0 -15
  513. package/dist/src/daemon/chats-question.js +0 -93
  514. package/dist/src/daemon/chats-worker.d.ts +0 -13
  515. package/dist/src/daemon/chats-worker.js +0 -201
  516. package/dist/workflows/analyze-chats.d.ts +0 -15
  517. package/dist/workflows/analyze-chats.declaration.json +0 -22
  518. package/dist/workflows/analyze-chats.js +0 -250
@@ -0,0 +1,92 @@
1
+ import { field, repositoryPath } from "./github-operation.js";
2
+ import { githubRead } from "./github-retry.js";
3
+ import { operationKey, writeRecord } from "./operation-journal.js";
4
+ import { readFile } from "node:fs/promises";
5
+ import { join } from "node:path";
6
+ function isRerun(value) {
7
+ return (typeof field(value, "run") === "string" &&
8
+ /^\d+$/.test(String(field(value, "run"))) &&
9
+ typeof field(value, "requestedAt") === "number" &&
10
+ typeof field(value, "output") === "string");
11
+ }
12
+ export async function ciWait(operation, commit) {
13
+ const text = await readFile(join(operation.folder, `ci-${operationKey(commit)}.json`), "utf8").catch((error) => {
14
+ if (field(error, "code") === "ENOENT")
15
+ return undefined;
16
+ throw error;
17
+ });
18
+ if (text === undefined)
19
+ return { commit, startedAt: Date.now(), reruns: [] };
20
+ const stored = JSON.parse(text);
21
+ const startedAt = field(stored, "startedAt");
22
+ const reruns = field(stored, "reruns");
23
+ if (field(stored, "commit") !== commit ||
24
+ typeof startedAt !== "number" ||
25
+ !Array.isArray(reruns) ||
26
+ !reruns.every(isRerun))
27
+ throw new Error("github-call-failed");
28
+ return { commit, startedAt, reruns };
29
+ }
30
+ export async function workflowAttempt(operation, run) {
31
+ const value = JSON.parse(await githubRead(operation, [
32
+ "api",
33
+ `${repositoryPath}/actions/runs/${run}`,
34
+ ]));
35
+ const attempt = field(value, "run_attempt");
36
+ const status = field(value, "status");
37
+ if (typeof attempt !== "number" ||
38
+ !Number.isSafeInteger(attempt) ||
39
+ attempt < 1 ||
40
+ typeof status !== "string")
41
+ throw new Error("github-call-failed");
42
+ return { attempt, status };
43
+ }
44
+ export async function attemptChecks(operation, workflow) {
45
+ const pages = JSON.parse(await githubRead(operation, [
46
+ "api",
47
+ "--paginate",
48
+ "--slurp",
49
+ `${repositoryPath}/actions/runs/${workflow.run}/attempts/${String(workflow.attempt)}/jobs?per_page=100`,
50
+ ]));
51
+ if (!Array.isArray(pages) || pages.length === 0)
52
+ throw new Error("github-call-failed");
53
+ const ids = new Set();
54
+ for (const page of pages) {
55
+ const jobs = field(page, "jobs");
56
+ if (!Array.isArray(jobs))
57
+ throw new Error("github-call-failed");
58
+ for (const job of jobs) {
59
+ const id = /\/check-runs\/(\d+)$/.exec(String(field(job, "check_run_url")))?.[1];
60
+ if (id === undefined)
61
+ throw new Error("github-call-failed");
62
+ ids.add(Number(id));
63
+ }
64
+ }
65
+ return ids;
66
+ }
67
+ export async function rerunCi(operation, request) {
68
+ const { wait, rerun } = request;
69
+ wait.reruns.push(rerun);
70
+ await writeRecord(operation.folder, {
71
+ name: `ci-${operationKey(wait.commit)}.json`,
72
+ value: wait,
73
+ permissions: "private",
74
+ });
75
+ if (Date.now() >= request.deadline)
76
+ return;
77
+ try {
78
+ await operation.calls.gh(["run", "rerun", rerun.run, "--failed"]);
79
+ }
80
+ catch (error) {
81
+ operation.signal.throwIfAborted();
82
+ throw Object.assign(new Error("github-network-failed", { cause: error }), {
83
+ detail: field(error, "detail"),
84
+ });
85
+ }
86
+ }
87
+ export function attemptOutput(attempts) {
88
+ const allowance = Math.floor(6_000 / attempts.length) - 40;
89
+ return attempts
90
+ .map((output, index) => `Attempt ${String(index + 1)}:\n${output.length <= allowance ? output : output.slice(0, 400) + "\n…\n" + output.slice(-(allowance - 404))}`)
91
+ .join("\n");
92
+ }
@@ -1,6 +1,8 @@
1
+ import { settingsEnvironment } from "../cli/project-settings.js";
1
2
  import { setTimeout as delay } from "node:timers/promises";
2
3
  import { githubText } from "./github-calls.js";
3
4
  import { githubRead } from "./github-retry.js";
5
+ import { ciWait, workflowAttempt, attemptChecks, rerunCi, attemptOutput, } from "./github-ci-rerun.js";
4
6
  import { field, githubTiming, repositoryPath, } from "./github-operation.js";
5
7
  function isCheckRun(value) {
6
8
  const conclusion = field(value, "conclusion");
@@ -117,12 +119,18 @@ async function failedOutput(operation, checks) {
117
119
  .join("\n")
118
120
  .slice(0, 6_000);
119
121
  }
122
+ function requiredCheckNames(operation) {
123
+ if (operation.settings.requiredChecks !== undefined)
124
+ return operation.settings.requiredChecks === null
125
+ ? undefined
126
+ : operation.settings.requiredChecks;
127
+ const setting = settingsEnvironment({ ...process.env, ...operation.settings.environment }, operation.settings.repository)["CLOVING_REQUIRED_CHECKS"];
128
+ return setting === undefined ? undefined : JSON.parse(setting);
129
+ }
120
130
  function requiredChecks(operation) {
121
- const setting = operation.settings.environment?.["CLOVING_REQUIRED_CHECKS"] ??
122
- process.env["CLOVING_REQUIRED_CHECKS"];
123
- if (setting === undefined)
131
+ const names = requiredCheckNames(operation);
132
+ if (names === undefined)
124
133
  return undefined;
125
- const names = JSON.parse(setting);
126
134
  if (!Array.isArray(names) ||
127
135
  !names.every((name) => typeof name === "string" && name.trim() !== ""))
128
136
  throw new Error("invalid-payload");
@@ -131,6 +139,70 @@ function requiredChecks(operation) {
131
139
  function pendingChecks(checks, names) {
132
140
  return [...names].filter((name) => !checks.some((check) => check.name === name && check.status === "completed"));
133
141
  }
142
+ function runOf(check) {
143
+ return check.app?.slug === "github-actions"
144
+ ? /\/actions\/runs\/(\d+)/.exec(check.details_url ?? "")?.[1]
145
+ : undefined;
146
+ }
147
+ async function rerunBeforeDeadline(operation, request) {
148
+ if (Date.now() >= request.deadline)
149
+ return;
150
+ const output = await failedOutput(operation, request.checks);
151
+ const requestedAt = Date.now();
152
+ if (requestedAt >= request.deadline)
153
+ return;
154
+ await rerunCi(operation, {
155
+ wait: request.wait,
156
+ rerun: { run: request.run, requestedAt, output },
157
+ deadline: request.deadline,
158
+ });
159
+ }
160
+ async function rerunFailedChecks(operation, input) {
161
+ const { wait, failed } = input;
162
+ const failures = failed.filter((check) => runOf(check) === undefined);
163
+ const pending = [];
164
+ const runs = new Set(failed.flatMap((check) => runOf(check) ?? []));
165
+ for (const run of runs) {
166
+ const checks = failed.filter((check) => runOf(check) === run);
167
+ const recorded = wait.reruns.find((rerun) => rerun.run === run);
168
+ const workflow = await workflowAttempt(operation, run);
169
+ if (workflow.attempt === 1 &&
170
+ recorded === undefined &&
171
+ workflow.status === "completed")
172
+ await rerunBeforeDeadline(operation, {
173
+ wait,
174
+ run,
175
+ checks,
176
+ deadline: input.deadline,
177
+ });
178
+ if (workflow.attempt === 1) {
179
+ pending.push(`workflow ${run} rerun`);
180
+ continue;
181
+ }
182
+ const ids = await attemptChecks(operation, {
183
+ run,
184
+ attempt: workflow.attempt,
185
+ });
186
+ const current = checks.filter((check) => ids.has(check.id));
187
+ if (current.length === 0) {
188
+ pending.push(`workflow ${run} rerun`);
189
+ continue;
190
+ }
191
+ failures.push(...current);
192
+ }
193
+ return { failures, pending };
194
+ }
195
+ async function ciFailureOutput(operation, input) {
196
+ const { wait, failed } = input;
197
+ const previous = wait.reruns.filter((rerun) => failed.some((check) => runOf(check) === rerun.run));
198
+ const current = await failedOutput(operation, failed);
199
+ return previous.length === 0
200
+ ? current
201
+ : attemptOutput([
202
+ previous.map((rerun) => rerun.output).join("\n"),
203
+ current,
204
+ ]);
205
+ }
134
206
  export async function waitForCi(operation, commit) {
135
207
  const { pollMilliseconds: poll, ciGraceMilliseconds: grace, ciLimitMilliseconds: limit, } = {
136
208
  ...githubTiming,
@@ -138,7 +210,8 @@ export async function waitForCi(operation, commit) {
138
210
  ciLimitMilliseconds: 5_400_000,
139
211
  ...operation.settings.timing,
140
212
  };
141
- const started = Date.now();
213
+ const wait = await ciWait(operation, commit);
214
+ const started = wait.startedAt;
142
215
  const required = requiredChecks(operation);
143
216
  const names = new Set(required);
144
217
  for (;;) {
@@ -146,12 +219,20 @@ export async function waitForCi(operation, commit) {
146
219
  for (const check of checks)
147
220
  names.add(check.name);
148
221
  const failed = checks.filter((check) => check.status === "completed" && !passing.has(check.conclusion ?? ""));
149
- if (failed.length > 0)
222
+ const retried = await rerunFailedChecks(operation, {
223
+ wait,
224
+ failed,
225
+ deadline: started + limit,
226
+ });
227
+ if (retried.failures.length > 0)
150
228
  return {
151
229
  reason: "ci-failed",
152
- output: await failedOutput(operation, failed),
230
+ output: await ciFailureOutput(operation, {
231
+ wait,
232
+ failed: retried.failures,
233
+ }),
153
234
  };
154
- const pending = pendingChecks(checks, names);
235
+ const pending = [...pendingChecks(checks, names), ...retried.pending];
155
236
  if (pending.length === 0 &&
156
237
  (required !== undefined ||
157
238
  names.size > 0 ||
@@ -1,7 +1,9 @@
1
1
  import { type Operation } from "./github-operation.ts";
2
+ export type MergeCheck = "beforeMerge" | null;
2
3
  export interface ReviewedPull {
3
4
  readonly number: number;
4
5
  readonly commit: string;
6
+ readonly check?: MergeCheck | undefined;
5
7
  }
6
8
  export declare function knownMerge(operation: Operation, expected: ReviewedPull & {
7
9
  readonly updated: string;
@@ -69,12 +69,13 @@ async function updatedTree(operation, place) {
69
69
  async function checked(operation, place) {
70
70
  await changeChecked(operation, place);
71
71
  const head = await headOf(operation, place.tree);
72
- if (operation.settings.check !== undefined)
73
- await operation.calls.run(operation.settings.check, place.tree.path);
72
+ const command = place.check === null ? undefined : operation.settings.check;
73
+ if (command !== undefined)
74
+ await operation.calls.run(command, place.tree.path);
74
75
  await clean(operation, place.tree);
75
76
  if ((await headOf(operation, place.tree)) !== head)
76
77
  throw new Error("uncommitted-change");
77
- if (head !== place.commit && operation.settings.check === undefined)
78
+ if (head !== place.commit && command === undefined && place.check !== null)
78
79
  throw new Error("check-required");
79
80
  return head;
80
81
  }
@@ -139,6 +140,7 @@ async function readyHead(operation, pull) {
139
140
  tree,
140
141
  commit: pull.commit,
141
142
  recorded,
143
+ check: pull.check,
142
144
  });
143
145
  if (updated !== pull.commit && recorded !== updated)
144
146
  await writeRecord(operation.folder, {
@@ -175,6 +177,8 @@ function commandOutput(cause) {
175
177
  .join("");
176
178
  }
177
179
  export async function merge(operation, pull) {
180
+ if (pull.check === "beforeMerge" && operation.settings.check === undefined)
181
+ throw new Error("check-not-configured");
178
182
  try {
179
183
  return await completedMerge(operation, pull);
180
184
  }
@@ -21,6 +21,7 @@ export const methodReasons = new Set([
21
21
  "check-failed",
22
22
  "merge-conflict",
23
23
  "check-required",
24
+ "check-not-configured",
24
25
  "base-moved",
25
26
  "head-not-updated",
26
27
  "uncommitted-change",
@@ -37,6 +38,14 @@ function integer(operation, name) {
37
38
  throw new Error("invalid-payload");
38
39
  return value;
39
40
  }
41
+ function mergeCheck(operation) {
42
+ if (!Object.hasOwn(operation.payload, "check"))
43
+ return undefined;
44
+ const value = operation.payload["check"];
45
+ if (value === null || value === "beforeMerge")
46
+ return value;
47
+ throw new Error("invalid-payload");
48
+ }
40
49
  async function prepare(operation) {
41
50
  const { settings, calls, target, signal } = operation;
42
51
  await calls.git(settings.repository, ["fetch", "--quiet", "origin"]);
@@ -261,6 +270,7 @@ export const methods = new Map([
261
270
  (operation) => merge(operation, {
262
271
  number: integer(operation, "number"),
263
272
  commit: text(operation, "commit"),
273
+ check: mergeCheck(operation),
264
274
  }),
265
275
  ],
266
276
  ]);
@@ -10,6 +10,7 @@ export declare const githubTiming: GithubTiming;
10
10
  export interface MethodSettings extends CallSettings {
11
11
  readonly worktrees: string;
12
12
  readonly timing?: GithubTiming;
13
+ readonly requiredChecks?: readonly string[] | null;
13
14
  readonly check?: readonly string[];
14
15
  }
15
16
  export interface Operation {
@@ -1,49 +1,13 @@
1
- import { setTimeout as delay } from "node:timers/promises";
2
- import { field, githubTiming } from "./github-operation.js";
3
- function transient(error) {
4
- if (!(error instanceof Error) || error.message !== "github-call-failed")
5
- return false;
6
- const detail = field(error, "detail");
7
- if (typeof detail !== "string")
8
- return false;
9
- const status = field(error, "status");
10
- if ([500, 502, 503, 504].includes(Number(status)))
11
- return true;
12
- return ((status === undefined ||
13
- (typeof status === "number" && Number.isNaN(status))) &&
14
- /TLS handshake timeout|connection reset|i\/o timeout|\bEOF\b/i.test(detail));
15
- }
16
- function retryFactor(error, retry) {
17
- const network = transient(error);
18
- if (!network && !retry.statuses.includes(Number(field(error, "status"))))
19
- throw error;
20
- if (retry.attempt < 2)
21
- return network ? retry.attempt + 1 : 1;
22
- if (!network)
23
- throw error;
24
- throw Object.assign(new Error("github-network-failed", { cause: error }), {
25
- detail: field(error, "detail"),
1
+ import { githubRetry } from "../cli/github-retry.js";
2
+ import { githubTiming } from "./github-operation.js";
3
+ export function retryGithub(operation, retry) {
4
+ return githubRetry({
5
+ ...retry,
6
+ signal: operation.signal,
7
+ pollMilliseconds: (operation.settings.timing ?? githubTiming)
8
+ .pollMilliseconds,
26
9
  });
27
10
  }
28
- export async function retryGithub(operation, retry) {
29
- const timing = operation.settings.timing ?? githubTiming;
30
- for (let attempt = 0;; attempt += 1) {
31
- operation.signal.throwIfAborted();
32
- try {
33
- return await retry.action(attempt);
34
- }
35
- catch (error) {
36
- operation.signal.throwIfAborted();
37
- const factor = retryFactor(error, {
38
- attempt,
39
- statuses: retry.statuses ?? [],
40
- });
41
- await delay(timing.pollMilliseconds * factor, undefined, {
42
- signal: operation.signal,
43
- });
44
- }
45
- }
46
- }
47
11
  export function githubRead(operation, parts) {
48
12
  return retryGithub(operation, { action: () => operation.calls.gh(parts) });
49
13
  }
@@ -4,6 +4,7 @@ interface QueueSettings {
4
4
  readonly intervalMilliseconds: number;
5
5
  readonly lanes?: number;
6
6
  readonly resetQueue?: boolean;
7
+ readonly workflowId?: string;
7
8
  }
8
9
  export declare function issueQueue(settings: QueueSettings): {
9
10
  readonly stop: () => Promise<void>;
@@ -1,3 +1,4 @@
1
+ import { activeQueueRuns } from "./queue-status.js";
1
2
  import { randomUUID } from "node:crypto";
2
3
  import { readFile, rename, rm, writeFile } from "node:fs/promises";
3
4
  import { join } from "node:path";
@@ -147,30 +148,6 @@ async function completed(settings, pending) {
147
148
  await retired(pending, ending);
148
149
  return pendingRuns;
149
150
  }
150
- async function active(runtimeDirectory) {
151
- let count = 0;
152
- let after = "";
153
- do {
154
- const reply = await send(runtimeDirectory, {
155
- operation: "status",
156
- parameters: { after, limit: 500 },
157
- });
158
- if (reply.kind === "error")
159
- throw new Error(reply.error.code);
160
- const runs = reply.result["runs"];
161
- if (!Array.isArray(runs))
162
- throw new Error("invalid-run-list");
163
- count += runs.filter((value) => {
164
- const run = record(value);
165
- return run?.["workflowId"] === "develop-issue" && !terminal(run);
166
- }).length;
167
- const next = reply.result["next"];
168
- if (next !== null && (typeof next !== "string" || next <= after))
169
- throw new Error("invalid-run-page");
170
- after = next;
171
- } while (after !== null);
172
- return count;
173
- }
174
151
  async function submit(settings, pending) {
175
152
  const commandId = pending.retryCommandId ?? randomUUID();
176
153
  pending.commands.add(commandId);
@@ -178,7 +155,7 @@ async function submit(settings, pending) {
178
155
  const reply = await send(settings.runtimeDirectory, {
179
156
  operation: "run",
180
157
  parameters: {
181
- workflowId: "develop-issue",
158
+ workflowId: settings.workflowId ?? "develop-issue",
182
159
  source: "ticket",
183
160
  submission: { ticket: "next" },
184
161
  commandId,
@@ -279,7 +256,7 @@ async function cycle(settings, signal) {
279
256
  await holding(pendingRuns);
280
257
  continue;
281
258
  }
282
- const activeRuns = await active(settings.runtimeDirectory);
259
+ const activeRuns = await activeQueueRuns(settings);
283
260
  const held = await holding(activeRuns);
284
261
  if (activeRuns >= lanes || activeRuns < pendingRuns)
285
262
  continue;
@@ -2,6 +2,7 @@ import { recordedNotifications, saveNotifications, } from "./notify-journal.js";
2
2
  import { spawn } from "node:child_process";
3
3
  import { join } from "node:path";
4
4
  import { send } from "../cli/client.js";
5
+ import { deliveryBackoffMilliseconds } from "../delivery-backoff.js";
5
6
  import { record } from "../protocol.js";
6
7
  import { decisionNotification, outcomeNotification, } from "./notify-message.js";
7
8
  const retentionMilliseconds = 7 * 24 * 60 * 60_000;
@@ -132,7 +133,7 @@ async function prepareDelivery(journal, entry) {
132
133
  });
133
134
  if (entry.attempts === 5)
134
135
  return undefined;
135
- const backoff = [0, 60_000, 300_000, 900_000, 3_600_000][entry.attempts] ?? 0;
136
+ const backoff = deliveryBackoffMilliseconds[entry.attempts] ?? 0;
136
137
  if (entry.lastAttemptAt !== null &&
137
138
  Date.now() - entry.lastAttemptAt < backoff)
138
139
  return undefined;
@@ -0,0 +1,5 @@
1
+ export declare function opencodeStream(): {
2
+ line: (line: string) => readonly string[];
3
+ stderr: (chunk: string) => void;
4
+ result: (exitCode: number | null) => string;
5
+ };
@@ -0,0 +1,87 @@
1
+ import { record } from "../protocol.js";
2
+ import { sumUsage, usageOf, tokenCount, } from "../worker-usage.js";
3
+ function parsed(line) {
4
+ try {
5
+ return record(JSON.parse(line)) ?? {};
6
+ }
7
+ catch {
8
+ return {};
9
+ }
10
+ }
11
+ function tokens(value) {
12
+ const counts = record(value) ?? {};
13
+ const cache = record(counts["cache"]) ?? {};
14
+ const output = tokenCount(counts["output"]);
15
+ const reasoning = tokenCount(counts["reasoning"]);
16
+ return usageOf({
17
+ input_tokens: counts["input"],
18
+ cache_read_input_tokens: cache["read"],
19
+ output_tokens: output === null || reasoning === null ? null : output + reasoning,
20
+ });
21
+ }
22
+ function errorMessage(value) {
23
+ const error = record(value) ?? {};
24
+ const data = record(error["data"]) ?? {};
25
+ const message = data["message"] ?? error["name"];
26
+ return typeof message === "string" ? message : "opencode error";
27
+ }
28
+ function translated(line, state) {
29
+ const event = parsed(line);
30
+ const part = record(event["part"]) ?? {};
31
+ if (typeof event["sessionID"] === "string")
32
+ state.sessionId = event["sessionID"];
33
+ if (typeof event["model"] === "string")
34
+ state.model = event["model"];
35
+ if (event["type"] === "error")
36
+ state.error = errorMessage(event["error"]);
37
+ if (event["type"] === "step_finish") {
38
+ state.steps.push(tokens(part["tokens"]));
39
+ state.reason = part["reason"];
40
+ }
41
+ if (event["type"] !== "text" || typeof part["text"] !== "string")
42
+ return [];
43
+ state.message = part["text"];
44
+ return [
45
+ JSON.stringify({
46
+ type: "assistant",
47
+ message: { content: [{ type: "text", text: state.message }] },
48
+ }),
49
+ ];
50
+ }
51
+ function result(exitCode, state) {
52
+ const success = exitCode === 0 && state.error === null && state.reason === "stop";
53
+ const failure = exitCode === 0
54
+ ? "opencode ended without a final stop step"
55
+ : `opencode ended with the code ${String(exitCode)}`;
56
+ return JSON.stringify({
57
+ type: "result",
58
+ subtype: success ? "success" : "error_during_execution",
59
+ is_error: !success,
60
+ result: success
61
+ ? state.message
62
+ : state.error || state.stderr.trim() || failure,
63
+ total_cost_usd: null,
64
+ model: state.model,
65
+ usage: sumUsage(state.steps),
66
+ session_id: state.sessionId,
67
+ num_turns: state.steps.length,
68
+ });
69
+ }
70
+ export function opencodeStream() {
71
+ const state = {
72
+ steps: [],
73
+ message: "",
74
+ sessionId: null,
75
+ model: null,
76
+ reason: null,
77
+ error: null,
78
+ stderr: "",
79
+ };
80
+ return {
81
+ line: (line) => translated(line, state),
82
+ stderr: (chunk) => {
83
+ state.stderr = (state.stderr + chunk).slice(-16_000);
84
+ },
85
+ result: (exitCode) => result(exitCode, state),
86
+ };
87
+ }
@@ -0,0 +1,4 @@
1
+ export declare function activeQueueRuns(settings: {
2
+ readonly runtimeDirectory: string;
3
+ readonly workflowId?: string;
4
+ }): Promise<number>;
@@ -0,0 +1,38 @@
1
+ import { send } from "../cli/client.js";
2
+ import { record } from "../protocol.js";
3
+ function queueBusy(value) {
4
+ const busy = record(value)?.["busy"];
5
+ if (typeof busy !== "number")
6
+ return undefined;
7
+ if (!Number.isSafeInteger(busy) || busy < 0)
8
+ throw new Error("invalid-queue-status");
9
+ return busy;
10
+ }
11
+ export async function activeQueueRuns(settings) {
12
+ let count = 0;
13
+ let after = "";
14
+ do {
15
+ const reply = await send(settings.runtimeDirectory, {
16
+ operation: "status",
17
+ parameters: { after, limit: 500 },
18
+ });
19
+ if (reply.kind === "error")
20
+ throw new Error(reply.error.code);
21
+ const busy = queueBusy(reply.result["queue"]);
22
+ if (busy !== undefined)
23
+ return busy;
24
+ const runs = reply.result["runs"];
25
+ if (!Array.isArray(runs))
26
+ throw new Error("invalid-run-list");
27
+ count += runs.filter((value) => {
28
+ const run = record(value);
29
+ return (run?.["workflowId"] === (settings.workflowId ?? "develop-issue") &&
30
+ !["completed", "failed", "cancelled"].includes(String(run["state"])));
31
+ }).length;
32
+ const next = reply.result["next"];
33
+ if (next !== null && (typeof next !== "string" || next <= after))
34
+ throw new Error("invalid-run-page");
35
+ after = next;
36
+ } while (after !== null);
37
+ return count;
38
+ }
@@ -0,0 +1,18 @@
1
+ export interface RetryTree {
2
+ readonly directory: string;
3
+ readonly signal: AbortSignal;
4
+ }
5
+ interface GitResult {
6
+ readonly text: string;
7
+ readonly code: number | null;
8
+ }
9
+ export declare function retryGit(tree: RetryTree, parts: readonly string[]): Promise<GitResult>;
10
+ export declare function turnHead(tree: RetryTree): Promise<string | null>;
11
+ export declare function retryEvidence(tree: RetryTree, startCommit: string | null): Promise<string>;
12
+ export interface IndexFailure {
13
+ readonly reason: "worktree-index-unknown" | "worktree-index-locked";
14
+ readonly lockPath?: string;
15
+ readonly fix: string;
16
+ }
17
+ export declare function indexFailure(tree: RetryTree): Promise<IndexFailure | null>;
18
+ export {};