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,139 @@
1
+ import { spawn } from "node:child_process";
2
+ import { lstat } from "node:fs/promises";
3
+ import { resolve } from "node:path";
4
+ function kill(child) {
5
+ if (child.pid === undefined)
6
+ return;
7
+ try {
8
+ process.kill(-child.pid, "SIGKILL");
9
+ }
10
+ catch {
11
+ child.kill("SIGKILL");
12
+ }
13
+ }
14
+ export async function retryGit(tree, parts) {
15
+ if (tree.signal.aborted)
16
+ return { text: "", code: null };
17
+ const child = spawn("git", ["-C", tree.directory, ...parts], {
18
+ stdio: ["ignore", "pipe", "ignore"],
19
+ detached: true,
20
+ env: { ...process.env, GIT_TERMINAL_PROMPT: "0" },
21
+ });
22
+ const closed = Promise.withResolvers();
23
+ let text = "";
24
+ const stop = () => {
25
+ kill(child);
26
+ child.stdout.destroy();
27
+ closed.resolve(null);
28
+ };
29
+ const timer = setTimeout(stop, 30_000);
30
+ tree.signal.addEventListener("abort", stop, { once: true });
31
+ child.stdout.setEncoding("utf8");
32
+ child.stdout.on("data", (chunk) => {
33
+ text += chunk;
34
+ if (Buffer.byteLength(text) > 1_048_576)
35
+ stop();
36
+ });
37
+ child.once("error", () => {
38
+ closed.resolve(null);
39
+ });
40
+ child.once("close", closed.resolve);
41
+ const code = await closed.promise;
42
+ clearTimeout(timer);
43
+ tree.signal.removeEventListener("abort", stop);
44
+ return { text: text.trim(), code };
45
+ }
46
+ export async function turnHead(tree) {
47
+ const head = await retryGit(tree, ["rev-parse", "--verify", "HEAD"]);
48
+ return head.code === 0 && /^[a-f0-9]{40,64}$/.test(head.text)
49
+ ? head.text
50
+ : null;
51
+ }
52
+ async function remoteState(tree) {
53
+ const branch = await retryGit(tree, ["symbolic-ref", "--short", "HEAD"]);
54
+ if (branch.code !== 0 || tree.signal.aborted)
55
+ return "unknown";
56
+ const reference = `refs/heads/${branch.text}`;
57
+ const remote = await retryGit(tree, [
58
+ "ls-remote",
59
+ "--exit-code",
60
+ "--heads",
61
+ "origin",
62
+ reference,
63
+ ]);
64
+ if (remote.code === 2)
65
+ return "not pushed";
66
+ if (remote.code !== 0)
67
+ return "unknown";
68
+ const tracking = `refs/remotes/origin/${branch.text}`;
69
+ const fetched = await retryGit(tree, [
70
+ "fetch",
71
+ "--no-tags",
72
+ "origin",
73
+ `+${reference}:${tracking}`,
74
+ ]);
75
+ return fetched.code === 0 ? tracking : "unknown";
76
+ }
77
+ async function pushState(tree, evidence) {
78
+ const { commit, remote } = evidence;
79
+ if (!remote.startsWith("refs/"))
80
+ return remote;
81
+ const ancestor = await retryGit(tree, [
82
+ "merge-base",
83
+ "--is-ancestor",
84
+ commit,
85
+ remote,
86
+ ]);
87
+ if (ancestor.code === 1)
88
+ return "not pushed";
89
+ return ancestor.code === 0 ? "pushed" : "unknown";
90
+ }
91
+ export async function retryEvidence(tree, startCommit) {
92
+ const remote = await remoteState(tree);
93
+ if (startCommit === null || tree.signal.aborted)
94
+ return "unknown: commits since the start of this turn could not be determined.";
95
+ const commits = await retryGit(tree, [
96
+ "log",
97
+ "--format=%H %s",
98
+ `${startCommit}..HEAD`,
99
+ "--",
100
+ ]);
101
+ if (commits.code !== 0)
102
+ return "unknown: commits since the start of this turn could not be listed.";
103
+ const lines = [];
104
+ for (const line of commits.text.split("\n").filter(Boolean)) {
105
+ const commit = line.split(" ")[0] ?? "";
106
+ const state = await pushState(tree, { commit, remote });
107
+ lines.push(`${commit} ${state}${line.slice(commit.length)}`);
108
+ }
109
+ if (lines.length > 0)
110
+ return lines.join("\n");
111
+ return remote === "unknown"
112
+ ? "unknown: remote push state could not be determined; no local commits since the start of this turn."
113
+ : "No commits since the start of this turn.";
114
+ }
115
+ export async function indexFailure(tree) {
116
+ const lookup = await retryGit(tree, [
117
+ "rev-parse",
118
+ "--git-path",
119
+ "index.lock",
120
+ ]);
121
+ const unknown = {
122
+ reason: "worktree-index-unknown",
123
+ fix: "Check that the work tree and its git index path are accessible before starting another turn.",
124
+ };
125
+ if (lookup.code !== 0 || lookup.text === "")
126
+ return unknown;
127
+ const lockPath = resolve(tree.directory, lookup.text);
128
+ try {
129
+ await lstat(lockPath);
130
+ return {
131
+ reason: "worktree-index-locked",
132
+ lockPath,
133
+ fix: "Remove the index lock when no git process uses the work tree, then start another turn.",
134
+ };
135
+ }
136
+ catch (error) {
137
+ return Reflect.get(Object(error), "code") === "ENOENT" ? null : unknown;
138
+ }
139
+ }
@@ -6,6 +6,8 @@ export interface RetrySettings {
6
6
  readonly retryDelay?: (milliseconds: number, signal: AbortSignal) => Promise<void>;
7
7
  }
8
8
  interface RetryOptions extends RetrySettings {
9
+ readonly stopping?: AbortController;
10
+ readonly stopMilliseconds?: number;
9
11
  readonly metadata: Readonly<Record<string, unknown>>;
10
12
  }
11
13
  export declare function startRetriedTurn(start: TurnStart, options: RetryOptions): Promise<RunningTurn>;
@@ -3,10 +3,12 @@ import { mkdir } from "node:fs/promises";
3
3
  import { setTimeout as delay } from "node:timers/promises";
4
4
  import { priceOf, sumUsage, usageOf, } from "../worker-usage.js";
5
5
  import { commandModel, replaceCommandModel, estimatedCostUsd, priceForModel, } from "../token-prices.js";
6
- import { analysisCommand } from "./analysis-launch.js";
7
- import { capacityRefusal, startTurn, } from "./claude-turn.js";
6
+ import { capacityRefusal, retryKind, startTurn, } from "./claude-turn.js";
7
+ import { turnHead, retryEvidence, indexFailure } from "./retry-worktree.js";
8
8
  import { readRecord, writeRecord } from "./operation-journal.js";
9
- const waits = [60_000, 180_000];
9
+ import { nativeHarness } from "../harness-defaults.js";
10
+ const waits = { capacity: [60_000, 180_000], network: [600_000, 2_400_000] };
11
+ const networkContinuation = "An earlier attempt stopped because the network was not available. Continue from the current state of the work tree. Check each earlier commit, push, review comment and message. Do not repeat a write that is done. Stop and report a write whose result is not known.";
10
12
  const continuation = "An earlier attempt stopped because the model was at capacity; continue from the current state of the work tree.\n\n";
11
13
  function written(folder, entry) {
12
14
  return writeRecord(folder, { ...entry, permissions: "private" });
@@ -49,12 +51,13 @@ function controlled(attempts, start) {
49
51
  }
50
52
  function attemptCommand(attempts, attempt) {
51
53
  const { start, options } = attempts;
52
- const original = start.mode === "analysis" ? analysisCommand() : start.command;
53
- const fallback = start.mode === "analysis"
54
- ? undefined
55
- : options.fallbackModels?.[attempt - 3];
54
+ const original = start.command;
55
+ const previous = attempts.ends[attempt - 2];
56
+ const fallback = previous !== undefined && kindOf(attempts, previous) === "capacity"
57
+ ? options.fallbackModels?.[attempt - 3]
58
+ : undefined;
56
59
  const command = fallback === undefined ? original : replaceCommandModel(original, fallback);
57
- const model = commandModel(command);
60
+ const model = start.output === "text" ? null : commandModel(command);
58
61
  return {
59
62
  command,
60
63
  model,
@@ -65,30 +68,66 @@ function attemptCommand(attempts, attempt) {
65
68
  }
66
69
  function attemptUsage(attempts, completion) {
67
70
  const { end, attempt } = completion;
68
- const model = end.result?.model ?? attemptCommand(attempts, attempt).model;
69
- const usage = end.result?.usage ?? usageOf(null);
71
+ const result = end.result ?? {
72
+ model: null,
73
+ usage: usageOf(null),
74
+ costUsd: null,
75
+ pricingModel: undefined,
76
+ };
77
+ const model = result.model ?? attemptCommand(attempts, attempt).model;
78
+ const usage = result.usage;
70
79
  return {
71
80
  attempt,
81
+ retryKind: kindOf(attempts, end),
72
82
  model,
83
+ ...(end.result?.models === undefined ? {} : { models: end.result.models }),
73
84
  usage,
74
- costUsd: end.result?.costUsd ?? null,
75
- estimatedCostUsd: estimatedCostUsd(usage, {
76
- worker: attempts.start.mode === "analysis"
77
- ? "claude"
78
- : (attempts.start.worker ?? "claude"),
79
- price: priceForModel(attempts.options.tokenPrices ?? {}, model),
80
- }),
85
+ costUsd: result.costUsd,
86
+ estimatedCostUsd: attemptEstimate(attempts, { end, model, usage }),
81
87
  };
82
88
  }
83
- async function launched(attempts) {
89
+ function attemptEstimate(attempts, result) {
90
+ const worker = attempts.start.worker ?? "claude";
91
+ if (!nativeHarness(worker))
92
+ return null;
93
+ const models = result.end.result?.models;
94
+ const prices = attempts.options.tokenPrices ?? {};
95
+ return estimatedCostUsd(result.usage, worker === "gemini" && models !== undefined
96
+ ? { worker, models, prices }
97
+ : {
98
+ worker,
99
+ price: priceForModel(prices, result.end.result?.pricingModel === undefined
100
+ ? result.model
101
+ : result.end.result.pricingModel),
102
+ });
103
+ }
104
+ function kindOf(attempts, end) {
105
+ const { worker, output } = attempts.start;
106
+ if (output === "text" || !["claude", "codex"].includes(worker ?? "claude"))
107
+ return null;
108
+ if (worker !== "codex")
109
+ return retryKind(end.result);
110
+ return capacityRefusal(end.result) ? "capacity" : null;
111
+ }
112
+ async function promptOf(attempts) {
113
+ const { start, ends, stopping, turnStartCommit } = attempts;
114
+ if (ends.length === 0)
115
+ return start.prompt;
116
+ if (!ends.some((end) => kindOf(attempts, end) === "network"))
117
+ return continuation + start.prompt;
118
+ const evidence = await retryEvidence({ directory: start.directory, signal: stopping.signal }, turnStartCommit);
119
+ return `${networkContinuation}\n\nCommits since the start of this turn:\n${evidence}\n\n${start.prompt}`;
120
+ }
121
+ async function launched(attempts, prompt = attempts.start.prompt) {
84
122
  const { start, options, ends } = attempts;
85
123
  const attempt = ends.length + 1;
86
124
  const selected = attemptCommand(attempts, attempt);
87
- const folder = start.mode === "analysis" || attempt === 1
125
+ const folder = attempt === 1
88
126
  ? start.folder
89
127
  : join(start.folder, `attempt-${String(attempt)}`);
90
128
  const entry = {
91
129
  ...options.metadata,
130
+ turnStartCommit: attempts.turnStartCommit,
92
131
  model: selected.model,
93
132
  ...(selected.fallbackReason === undefined
94
133
  ? {}
@@ -113,9 +152,7 @@ async function launched(attempts) {
113
152
  command: selected.command,
114
153
  folder,
115
154
  ...(attempt === 1 ? {} : { activityFolder: start.folder }),
116
- prompt: start.mode === "analysis" || attempt === 1
117
- ? start.prompt
118
- : continuation + start.prompt,
155
+ prompt,
119
156
  });
120
157
  try {
121
158
  const value = { ...entry, phase: "running", processId: turn.processId };
@@ -149,6 +186,7 @@ async function recordedEnd(attempts, completion) {
149
186
  name,
150
187
  value: {
151
188
  ...options.metadata,
189
+ turnStartCommit: attempts.turnStartCommit,
152
190
  ...attemptUsage(attempts, { end, attempt }),
153
191
  ...(selected.fallbackReason === undefined
154
192
  ? {}
@@ -168,6 +206,7 @@ async function waited(attempts, milliseconds) {
168
206
  name: "started.json",
169
207
  value: {
170
208
  ...options.metadata,
209
+ turnStartCommit: attempts.turnStartCommit,
171
210
  startedAt: attempts.startedAt,
172
211
  attempt: ends.length,
173
212
  phase: "waiting",
@@ -183,6 +222,27 @@ async function waited(attempts, milliseconds) {
183
222
  throw error;
184
223
  });
185
224
  }
225
+ async function preparedRetry(attempts) {
226
+ const prompt = await promptOf(attempts);
227
+ const failure = await indexFailure({
228
+ directory: attempts.start.directory,
229
+ signal: attempts.stopping.signal,
230
+ });
231
+ if (cancelled(attempts))
232
+ return { ...combined(attempts), stopped: true };
233
+ if (failure !== null) {
234
+ await written(attempts.start.folder, {
235
+ name: "retry-failure.json",
236
+ value: failure,
237
+ });
238
+ return {
239
+ ...combined(attempts),
240
+ reason: failure.reason,
241
+ detail: `${failure.fix}${failure.lockPath === undefined ? "" : ` Lock: ${failure.lockPath}`}`,
242
+ };
243
+ }
244
+ return prompt;
245
+ }
186
246
  async function finished(attempts, first) {
187
247
  const { ends } = attempts;
188
248
  let turn = first;
@@ -190,15 +250,17 @@ async function finished(attempts, first) {
190
250
  const end = await turn.ended;
191
251
  ends.push(end);
192
252
  await recordedEnd(attempts, { processId: turn.processId, end });
193
- const milliseconds = waits[ends.length - 1];
194
- if (cancelled(attempts) ||
195
- !capacityRefusal(end.result) ||
196
- milliseconds === undefined)
253
+ const kind = kindOf(attempts, end);
254
+ const milliseconds = kind === null ? undefined : waits[kind][ends.length - 1];
255
+ if (cancelled(attempts) || milliseconds === undefined)
197
256
  break;
198
257
  await waited(attempts, milliseconds);
199
258
  if (cancelled(attempts))
200
259
  return { ...combined(attempts), stopped: true };
201
- turn = await launched(attempts);
260
+ const prepared = await preparedRetry(attempts);
261
+ if (typeof prepared !== "string")
262
+ return prepared;
263
+ turn = await launched(attempts, prepared);
202
264
  }
203
265
  return {
204
266
  ...combined(attempts),
@@ -209,17 +271,33 @@ function cancelled(attempts) {
209
271
  return attempts.stopping.signal.aborted;
210
272
  }
211
273
  export async function startRetriedTurn(start, options) {
274
+ const stopping = options.stopping ?? new AbortController();
275
+ const turnStartCommit = await turnHead({
276
+ directory: start.directory,
277
+ signal: stopping.signal,
278
+ });
212
279
  const attempts = {
280
+ turnStartCommit,
213
281
  start,
214
282
  startedAt: new Date().toISOString(),
215
283
  options,
216
- stopping: new AbortController(),
284
+ stopping,
217
285
  ends: [],
218
- grace: { milliseconds: 2_000 },
286
+ grace: { milliseconds: options.stopMilliseconds ?? 2_000 },
219
287
  };
220
288
  const turn = await launched(attempts);
221
289
  if (turn === undefined)
222
- throw new Error("turn-start-stopped");
290
+ return {
291
+ processId: null,
292
+ ended: Promise.resolve({
293
+ exitCode: null,
294
+ result: undefined,
295
+ stopped: true,
296
+ }),
297
+ stop: () => {
298
+ stopping.abort();
299
+ },
300
+ };
223
301
  return {
224
302
  processId: turn.processId,
225
303
  ended: finished(attempts, turn),
@@ -0,0 +1,19 @@
1
+ import { type Fields } from "../protocol.ts";
2
+ export type PendingSlot = {
3
+ readonly kind: "run";
4
+ readonly input: Fields;
5
+ } | {
6
+ readonly kind: "skip";
7
+ readonly runId: string;
8
+ };
9
+ export interface ScheduleProgress {
10
+ readonly everySeconds: number;
11
+ readonly nextAt: number;
12
+ readonly lastSlot: number;
13
+ readonly activeCommandId?: string;
14
+ readonly pending?: PendingSlot;
15
+ }
16
+ export declare function scheduleJournal(directory: string): Promise<{
17
+ readonly entries: Map<string, ScheduleProgress>;
18
+ readonly save: () => Promise<void>;
19
+ }>;
@@ -0,0 +1,57 @@
1
+ import { readFile, rename, writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { record } from "../protocol.js";
4
+ import { isCommandId, isRecordKey } from "../authority/commands.js";
5
+ function pendingSlot(value) {
6
+ const fields = record(value);
7
+ if (fields?.["kind"] === "run")
8
+ return record(fields["input"]) !== undefined;
9
+ return fields?.["kind"] === "skip" && isRecordKey(fields["runId"]);
10
+ }
11
+ function whole(value) {
12
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
13
+ }
14
+ function timing(fields) {
15
+ const { everySeconds, nextAt, lastSlot } = fields;
16
+ return (whole(everySeconds) &&
17
+ everySeconds >= 60 &&
18
+ everySeconds <= 86400 &&
19
+ whole(nextAt) &&
20
+ whole(lastSlot));
21
+ }
22
+ function isProgress(value) {
23
+ const fields = record(value);
24
+ if (fields === undefined)
25
+ return false;
26
+ const { activeCommandId, pending } = fields;
27
+ return (timing(fields) &&
28
+ (activeCommandId === undefined || isCommandId(activeCommandId)) &&
29
+ (pending === undefined || pendingSlot(pending)));
30
+ }
31
+ export async function scheduleJournal(directory) {
32
+ const file = join(directory, "schedules.json");
33
+ const text = await readFile(file, "utf8").catch((error) => {
34
+ if (error instanceof Error && "code" in error && error.code === "ENOENT")
35
+ return "{}";
36
+ throw error;
37
+ });
38
+ const parsed = record(JSON.parse(text));
39
+ if (parsed === undefined)
40
+ throw new Error("invalid-schedule-state");
41
+ const entries = new Map();
42
+ for (const [workflowId, value] of Object.entries(parsed)) {
43
+ if (!isProgress(value))
44
+ throw new Error("invalid-schedule-state");
45
+ entries.set(workflowId, value);
46
+ }
47
+ return {
48
+ entries,
49
+ save: async () => {
50
+ await writeFile(`${file}.tmp`, JSON.stringify(Object.fromEntries(entries)) + "\n", {
51
+ mode: 0o600,
52
+ flush: true,
53
+ });
54
+ await rename(`${file}.tmp`, file);
55
+ },
56
+ };
57
+ }
@@ -0,0 +1,18 @@
1
+ import type { ChildProcessWithoutNullStreams } from "node:child_process";
2
+ import type { WriteStream } from "node:fs";
3
+ export declare function textOutput(child: ChildProcessWithoutNullStreams, options: {
4
+ readonly output: WriteStream;
5
+ readonly limit: number;
6
+ }): (exitCode: number | null) => Promise<{
7
+ text: string;
8
+ failed: boolean;
9
+ model: null;
10
+ costUsd: null;
11
+ usage: import("../worker-usage.ts").WorkerUsage;
12
+ sessionId: null;
13
+ turns: null;
14
+ reviewFeedback?: string;
15
+ reviewVerdict: import("../review-subject.ts").ReviewVerdict | null;
16
+ ticketStatus: import("../ticket-status.ts").TicketStatus;
17
+ ticketStatusTooLarge?: true;
18
+ }>;
@@ -0,0 +1,44 @@
1
+ import { usageOf } from "../worker-usage.js";
2
+ import { reviewReportStream } from "../review-subject.js";
3
+ import { ticketStatusStream } from "../ticket-status-stream.js";
4
+ export function textOutput(child, options) {
5
+ const { output, limit } = options;
6
+ const status = ticketStatusStream(limit);
7
+ const verdict = reviewReportStream(limit);
8
+ let text = "";
9
+ let error = "";
10
+ child.stderr.setEncoding("utf8");
11
+ child.stderr.on("data", (chunk) => {
12
+ error = (error + chunk).slice(-limit);
13
+ });
14
+ child.stdout.setEncoding("utf8");
15
+ child.stdout.on("data", (chunk) => {
16
+ text = (text + chunk).slice(-limit);
17
+ status.write(chunk);
18
+ verdict.write(chunk);
19
+ if (!output.write(chunk)) {
20
+ child.stdout.pause();
21
+ output.once("drain", () => {
22
+ child.stdout.resume();
23
+ });
24
+ }
25
+ });
26
+ return async (exitCode) => {
27
+ await new Promise((resolve) => output.end(resolve));
28
+ const review = verdict.result();
29
+ return {
30
+ ...status.result(),
31
+ reviewVerdict: review.reviewVerdict,
32
+ ...(review.reviewVerdict === null
33
+ ? {}
34
+ : { reviewFeedback: review.feedback }),
35
+ text: exitCode === 0 ? text : error,
36
+ failed: exitCode !== 0,
37
+ model: null,
38
+ costUsd: null,
39
+ usage: usageOf(null),
40
+ sessionId: null,
41
+ turns: null,
42
+ };
43
+ };
44
+ }
@@ -1,5 +1,6 @@
1
- import type { DeclaredWorkflow, WorkflowStage } from "../workflow-declaration.ts";
1
+ import { type DeclaredWorkflow } from "../workflow-declaration.ts";
2
2
  import type { Resolver, WorkflowRegistration } from "../service/registry.ts";
3
+ import type { LocalCommands } from "../command-settings.ts";
3
4
  export declare const ticketWorkflow: "develop-ticket";
4
5
  export declare const promptWorkflow: "develop-prompt";
5
6
  export declare const issueWorkflow: "develop-issue";
@@ -18,15 +19,10 @@ export interface TicketSource {
18
19
  readonly githubCommand?: readonly string[] | undefined;
19
20
  readonly skipTickets?: readonly string[];
20
21
  }
21
- export interface TicketRegistration {
22
- readonly workflowId: string;
22
+ export interface TicketRegistration extends Omit<WorkflowRegistration, "manifest" | "availability" | "admission"> {
23
23
  readonly functionName: string;
24
- readonly resolver: Resolver;
25
- readonly submission: WorkflowRegistration["submission"];
26
24
  readonly effectLimit: number;
27
25
  readonly capabilities?: readonly string[];
28
- readonly stages?: readonly WorkflowStage[];
29
- readonly handoffs?: readonly string[];
30
26
  }
31
27
  export declare function ticketResolver(source: TicketSource): Resolver;
32
28
  export declare function issueResolver(source: TicketSource): Resolver;
@@ -34,4 +30,6 @@ export declare function promptResolver(repository: string): Resolver;
34
30
  export declare function ticketRegistrationTable(source: TicketSource, declarations?: readonly DeclaredWorkflow[]): readonly TicketRegistration[];
35
31
  export declare function ticketRegistrations(manifests: Readonly<Record<string, string | undefined>>, options: {
36
32
  readonly table: readonly TicketRegistration[];
33
+ readonly bundleDigest?: string;
34
+ readonly commands?: LocalCommands;
37
35
  }): Promise<TicketRegistrations>;