cloving 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (484) hide show
  1. package/README.md +329 -215
  2. package/dist/src/agent-harness-shell.d.ts +2 -1
  3. package/dist/src/agent-harness-shell.js +8 -5
  4. package/dist/src/authority/command-wait-checks.d.ts +8 -0
  5. package/dist/src/authority/command-wait-checks.js +88 -0
  6. package/dist/src/authority/command-wait-results.d.ts +15 -0
  7. package/dist/src/authority/command-wait-results.js +73 -0
  8. package/dist/src/authority/command-wait-view.d.ts +21 -0
  9. package/dist/src/authority/command-wait-view.js +34 -0
  10. package/dist/src/authority/command-waits.d.ts +39 -0
  11. package/dist/src/authority/command-waits.js +97 -0
  12. package/dist/src/authority/commands.js +22 -1
  13. package/dist/src/authority/dispatch-decision.d.ts +8 -0
  14. package/dist/src/authority/dispatch-decision.js +26 -1
  15. package/dist/src/authority/effect-requests.js +6 -3
  16. package/dist/src/authority/effect-results.js +4 -2
  17. package/dist/src/authority/history-state.d.ts +2 -0
  18. package/dist/src/authority/history-state.js +13 -1
  19. package/dist/src/authority/instants.d.ts +1 -0
  20. package/dist/src/authority/instants.js +21 -0
  21. package/dist/src/authority/reduction-state.d.ts +2 -0
  22. package/dist/src/authority/reduction-state.js +5 -0
  23. package/dist/src/authority/reduction.js +24 -0
  24. package/dist/src/authority/status-input.d.ts +2 -0
  25. package/dist/src/authority/status.d.ts +2 -0
  26. package/dist/src/authority/status.js +1 -0
  27. package/dist/src/authority/stop-sequence.d.ts +1 -0
  28. package/dist/src/authority/stop-sequence.js +2 -1
  29. package/dist/src/authority/transitions.d.ts +6 -4
  30. package/dist/src/authority/transitions.js +7 -0
  31. package/dist/src/broker/actor/authority-health.d.ts +9 -0
  32. package/dist/src/broker/actor/authority-health.js +24 -0
  33. package/dist/src/broker/actor/authority-queries.d.ts +2 -1
  34. package/dist/src/broker/actor/authority-queries.js +14 -5
  35. package/dist/src/broker/actor/authority-receipts.js +1 -1
  36. package/dist/src/broker/actor/authority-runtime.d.ts +4 -2
  37. package/dist/src/broker/actor/authority-runtime.js +29 -20
  38. package/dist/src/broker/actor/authority-session.d.ts +6 -19
  39. package/dist/src/broker/actor/authority-session.js +66 -88
  40. package/dist/src/broker/actor/authority-settings.d.ts +2 -1
  41. package/dist/src/broker/actor/authority-settings.js +6 -3
  42. package/dist/src/broker/actor/authority-upgrades.d.ts +23 -2
  43. package/dist/src/broker/actor/authority-upgrades.js +8 -2
  44. package/dist/src/broker/actor/authority-watchdog.d.ts +6 -2
  45. package/dist/src/broker/actor/authority-watchdog.js +31 -9
  46. package/dist/src/broker/actor/authority.js +3 -1
  47. package/dist/src/broker/actor/delivery-intents.js +2 -0
  48. package/dist/src/broker/actor/effect-delivery.d.ts +1 -1
  49. package/dist/src/broker/actor/effect-delivery.js +15 -2
  50. package/dist/src/broker/actor/effect-plan.js +11 -2
  51. package/dist/src/broker/actor/effect-queries.d.ts +4 -0
  52. package/dist/src/broker/actor/effect-queries.js +9 -1
  53. package/dist/src/broker/actor/effect-turn.js +2 -0
  54. package/dist/src/broker/actor/projection-memory.d.ts +43 -0
  55. package/dist/src/broker/actor/projection-memory.js +207 -0
  56. package/dist/src/broker/actor/runtime-parts.d.ts +5 -0
  57. package/dist/src/broker/actor/runtime-parts.js +8 -3
  58. package/dist/src/broker/actor/stop-plan.js +9 -3
  59. package/dist/src/broker/actor/stop-turn.d.ts +2 -0
  60. package/dist/src/broker/actor/stop-turn.js +24 -11
  61. package/dist/src/broker/actor/turn-draft.d.ts +1 -0
  62. package/dist/src/broker/actor/turn-draft.js +4 -0
  63. package/dist/src/broker/actor/turn-state.js +5 -1
  64. package/dist/src/broker/authority-admission.js +60 -0
  65. package/dist/src/broker/authority-restore.d.ts +2 -0
  66. package/dist/src/broker/authority-restore.js +35 -1
  67. package/dist/src/broker/command-wait-restore.d.ts +31 -0
  68. package/dist/src/broker/command-wait-restore.js +86 -0
  69. package/dist/src/broker/decision-restore.d.ts +1 -1
  70. package/dist/src/broker/decision-restore.js +1 -0
  71. package/dist/src/broker/effect-upgrade.d.ts +3 -0
  72. package/dist/src/broker/effect-upgrade.js +11 -2
  73. package/dist/src/cli/arguments.d.ts +13 -0
  74. package/dist/src/cli/arguments.js +43 -3
  75. package/dist/src/cli/chat-stores.d.ts +2 -0
  76. package/dist/src/cli/chat-stores.js +113 -0
  77. package/dist/src/cli/client.d.ts +7 -2
  78. package/dist/src/cli/client.js +13 -7
  79. package/dist/src/cli/command-requests.d.ts +46 -0
  80. package/dist/src/cli/command-requests.js +84 -0
  81. package/dist/src/cli/command-waits.d.ts +9 -0
  82. package/dist/src/cli/command-waits.js +51 -0
  83. package/dist/src/cli/commands.js +70 -88
  84. package/dist/src/cli/config-file.d.ts +2 -2
  85. package/dist/src/cli/config-file.js +4 -2
  86. package/dist/src/cli/config-notice.js +5 -2
  87. package/dist/src/cli/doctor-retention.d.ts +2 -0
  88. package/dist/src/cli/doctor-retention.js +93 -0
  89. package/dist/src/cli/doctor-workflows.d.ts +5 -2
  90. package/dist/src/cli/doctor-workflows.js +12 -7
  91. package/dist/src/cli/doctor.js +11 -9
  92. package/dist/src/cli/harness-probes.d.ts +2 -0
  93. package/dist/src/cli/harness-probes.js +1 -1
  94. package/dist/src/cli/harness-processes.d.ts +6 -0
  95. package/dist/src/cli/harness-processes.js +36 -0
  96. package/dist/src/cli/init-command.d.ts +9 -0
  97. package/dist/src/cli/init-command.js +52 -0
  98. package/dist/src/cli/init-prompt-command.d.ts +10 -0
  99. package/dist/src/cli/init-prompt-command.js +145 -0
  100. package/dist/src/cli/init-prompt.d.ts +35 -0
  101. package/dist/src/cli/init-prompt.js +74 -0
  102. package/dist/src/cli/init-selection.d.ts +13 -0
  103. package/dist/src/cli/init-selection.js +75 -0
  104. package/dist/src/cli/main.d.ts +2 -0
  105. package/dist/src/cli/main.js +37 -7
  106. package/dist/src/cli/mcp-server.d.ts +1 -0
  107. package/dist/src/cli/mcp-server.js +156 -0
  108. package/dist/src/cli/mcp-tools.d.ts +15 -0
  109. package/dist/src/cli/mcp-tools.js +242 -0
  110. package/dist/src/cli/queue-arguments.d.ts +15 -0
  111. package/dist/src/cli/queue-arguments.js +31 -0
  112. package/dist/src/cli/queue-render.d.ts +3 -0
  113. package/dist/src/cli/queue-render.js +26 -0
  114. package/dist/src/cli/reload-render.d.ts +2 -0
  115. package/dist/src/cli/reload-render.js +12 -0
  116. package/dist/src/cli/render.d.ts +1 -1
  117. package/dist/src/cli/render.js +54 -38
  118. package/dist/src/cli/report-ci-jobs.d.ts +23 -0
  119. package/dist/src/cli/report-ci-jobs.js +103 -0
  120. package/dist/src/cli/report-ci-usage.d.ts +9 -0
  121. package/dist/src/cli/report-ci-usage.js +185 -0
  122. package/dist/src/cli/report-ci.d.ts +13 -0
  123. package/dist/src/cli/report-ci.js +74 -0
  124. package/dist/src/cli/report-closures.d.ts +6 -0
  125. package/dist/src/cli/report-closures.js +97 -0
  126. package/dist/src/cli/report-flow.d.ts +7 -0
  127. package/dist/src/cli/report-flow.js +122 -0
  128. package/dist/src/cli/report-github-reader.d.ts +29 -0
  129. package/dist/src/cli/report-github-reader.js +157 -0
  130. package/dist/src/cli/report-github.d.ts +15 -8
  131. package/dist/src/cli/report-github.js +131 -150
  132. package/dist/src/cli/report-operator.d.ts +3 -0
  133. package/dist/src/cli/report-operator.js +40 -0
  134. package/dist/src/cli/report-ready.d.ts +3 -0
  135. package/dist/src/cli/report-ready.js +96 -0
  136. package/dist/src/cli/report-text.d.ts +9 -0
  137. package/dist/src/cli/report-text.js +33 -0
  138. package/dist/src/cli/report.d.ts +1 -0
  139. package/dist/src/cli/report.js +104 -27
  140. package/dist/src/cli/runtime-arguments.d.ts +18 -3
  141. package/dist/src/cli/runtime-arguments.js +29 -20
  142. package/dist/src/cli/schedule-arguments.d.ts +14 -0
  143. package/dist/src/cli/schedule-arguments.js +26 -0
  144. package/dist/src/cli/schedule-render.d.ts +22 -0
  145. package/dist/src/cli/schedule-render.js +73 -0
  146. package/dist/src/cli/terminal-text.d.ts +3 -0
  147. package/dist/src/cli/terminal-text.js +28 -0
  148. package/dist/src/cli/toolchain.d.ts +1 -0
  149. package/dist/src/cli/toolchain.js +1 -0
  150. package/dist/src/cli/usage-render.d.ts +1 -0
  151. package/dist/src/cli/usage-render.js +28 -1
  152. package/dist/src/cli/usage.d.ts +2 -2
  153. package/dist/src/cli/usage.js +89 -11
  154. package/dist/src/cli/watch-actions.js +2 -2
  155. package/dist/src/cli/watch-api-document.d.ts +430 -0
  156. package/dist/src/cli/watch-api-document.js +291 -0
  157. package/dist/src/cli/watch-api-run.d.ts +56 -0
  158. package/dist/src/cli/watch-api-run.js +112 -0
  159. package/dist/src/cli/watch-api.d.ts +17 -0
  160. package/dist/src/cli/watch-api.js +230 -0
  161. package/dist/src/cli/watch-board-view.js +19 -2
  162. package/dist/src/cli/watch-board.d.ts +4 -2
  163. package/dist/src/cli/watch-board.js +53 -43
  164. package/dist/src/cli/watch-card-forms.d.ts +1 -1
  165. package/dist/src/cli/watch-card-forms.js +11 -10
  166. package/dist/src/cli/watch-client.d.ts +1 -1
  167. package/dist/src/cli/watch-client.js +2 -11
  168. package/dist/src/cli/watch-header-view.d.ts +1 -5
  169. package/dist/src/cli/watch-header-view.js +17 -21
  170. package/dist/src/cli/watch-model.d.ts +5 -1
  171. package/dist/src/cli/watch-model.js +20 -11
  172. package/dist/src/cli/watch-page.js +15 -15
  173. package/dist/src/cli/watch-phases.d.ts +12 -3
  174. package/dist/src/cli/watch-phases.js +68 -11
  175. package/dist/src/cli/watch-pr-board.js +1 -1
  176. package/dist/src/cli/watch-pr-command.d.ts +1 -0
  177. package/dist/src/cli/watch-pull-request.js +18 -8
  178. package/dist/src/cli/watch-reads.d.ts +3 -0
  179. package/dist/src/cli/watch-reads.js +22 -20
  180. package/dist/src/cli/watch-render.d.ts +15 -0
  181. package/dist/src/cli/watch-run-input.d.ts +0 -1
  182. package/dist/src/cli/watch-run-input.js +0 -13
  183. package/dist/src/cli/watch-server.js +24 -10
  184. package/dist/src/cli/watch-view.d.ts +0 -3
  185. package/dist/src/cli/watch-view.js +13 -13
  186. package/dist/src/cli.js +73 -12
  187. package/dist/src/command-wait.d.ts +4 -0
  188. package/dist/src/command-wait.js +45 -0
  189. package/dist/src/configuration-change.d.ts +7 -0
  190. package/dist/src/configuration-change.js +14 -0
  191. package/dist/src/configuration-display.js +2 -0
  192. package/dist/src/configuration-schema.d.ts +14 -0
  193. package/dist/src/configuration-schema.js +6 -2
  194. package/dist/src/daemon/attachment-file.d.ts +6 -0
  195. package/dist/src/daemon/attachment-file.js +86 -0
  196. package/dist/src/daemon/attachments.d.ts +14 -0
  197. package/dist/src/daemon/attachments.js +17 -0
  198. package/dist/src/daemon/claude-recovery.d.ts +50 -0
  199. package/dist/src/daemon/claude-recovery.js +208 -0
  200. package/dist/src/daemon/claude-stream.d.ts +27 -0
  201. package/dist/src/daemon/claude-stream.js +63 -0
  202. package/dist/src/daemon/claude-turn.d.ts +11 -25
  203. package/dist/src/daemon/claude-turn.js +64 -81
  204. package/dist/src/daemon/claude-worker.d.ts +5 -4
  205. package/dist/src/daemon/claude-worker.js +127 -126
  206. package/dist/src/daemon/daemon-adapters.d.ts +9 -0
  207. package/dist/src/daemon/daemon-adapters.js +33 -5
  208. package/dist/src/daemon/daemon-loops.d.ts +5 -1
  209. package/dist/src/daemon/daemon-loops.js +18 -10
  210. package/dist/src/daemon/daemon.js +80 -61
  211. package/dist/src/daemon/github-attach.d.ts +2 -0
  212. package/dist/src/daemon/github-attach.js +222 -0
  213. package/dist/src/daemon/github-calls.js +1 -1
  214. package/dist/src/daemon/github-ci-filters.d.ts +6 -0
  215. package/dist/src/daemon/github-ci-filters.js +138 -0
  216. package/dist/src/daemon/github-ci-workflows.d.ts +10 -0
  217. package/dist/src/daemon/github-ci-workflows.js +148 -0
  218. package/dist/src/daemon/github-ci.js +22 -4
  219. package/dist/src/daemon/github-issue-methods.d.ts +2 -0
  220. package/dist/src/daemon/github-issue-methods.js +37 -2
  221. package/dist/src/daemon/github-merge-call.d.ts +2 -1
  222. package/dist/src/daemon/github-merge-call.js +10 -3
  223. package/dist/src/daemon/github-merge.js +52 -24
  224. package/dist/src/daemon/github-methods.js +18 -4
  225. package/dist/src/daemon/github-operation.d.ts +4 -0
  226. package/dist/src/daemon/github-operation.js +6 -0
  227. package/dist/src/daemon/github-worker.d.ts +4 -0
  228. package/dist/src/daemon/github-worker.js +6 -0
  229. package/dist/src/daemon/issue-queue.d.ts +4 -1
  230. package/dist/src/daemon/issue-queue.js +76 -78
  231. package/dist/src/daemon/merge-turns.d.ts +10 -0
  232. package/dist/src/daemon/merge-turns.js +37 -0
  233. package/dist/src/daemon/notify-events.d.ts +6 -0
  234. package/dist/src/daemon/notify-events.js +84 -0
  235. package/dist/src/daemon/notify-journal.js +1 -1
  236. package/dist/src/daemon/notify-message.d.ts +4 -1
  237. package/dist/src/daemon/notify-message.js +36 -0
  238. package/dist/src/daemon/notify.d.ts +1 -1
  239. package/dist/src/daemon/notify.js +5 -77
  240. package/dist/src/daemon/operation-journal.d.ts +1 -0
  241. package/dist/src/daemon/queue-control.d.ts +13 -0
  242. package/dist/src/daemon/queue-control.js +86 -0
  243. package/dist/src/daemon/queue-journal.d.ts +20 -0
  244. package/dist/src/daemon/queue-journal.js +89 -0
  245. package/dist/src/daemon/queue-status.d.ts +9 -3
  246. package/dist/src/daemon/queue-status.js +17 -4
  247. package/dist/src/daemon/record-archive.d.ts +19 -0
  248. package/dist/src/daemon/record-archive.js +82 -0
  249. package/dist/src/daemon/record-sweep.d.ts +24 -0
  250. package/dist/src/daemon/record-sweep.js +147 -0
  251. package/dist/src/daemon/resume-index-lock.d.ts +13 -0
  252. package/dist/src/daemon/resume-index-lock.js +160 -0
  253. package/dist/src/daemon/resume-worktree.d.ts +7 -0
  254. package/dist/src/daemon/resume-worktree.js +29 -0
  255. package/dist/src/daemon/retrying-turn.d.ts +2 -12
  256. package/dist/src/daemon/retrying-turn.js +98 -172
  257. package/dist/src/daemon/schedule-control.d.ts +26 -0
  258. package/dist/src/daemon/schedule-control.js +110 -0
  259. package/dist/src/daemon/schedule-journal.d.ts +2 -15
  260. package/dist/src/daemon/schedule-journal.js +67 -4
  261. package/dist/src/daemon/settings-reload.d.ts +26 -0
  262. package/dist/src/daemon/settings-reload.js +82 -0
  263. package/dist/src/daemon/ticket-registration.d.ts +2 -7
  264. package/dist/src/daemon/ticket-registration.js +15 -81
  265. package/dist/src/daemon/turn-attempt-journal.d.ts +38 -0
  266. package/dist/src/daemon/turn-attempt-journal.js +136 -0
  267. package/dist/src/daemon/turn-attempts.d.ts +47 -0
  268. package/dist/src/daemon/turn-attempts.js +166 -0
  269. package/dist/src/daemon/turn-details.d.ts +4 -0
  270. package/dist/src/daemon/turn-details.js +33 -0
  271. package/dist/src/daemon/turn-report.d.ts +8 -1
  272. package/dist/src/daemon/turn-report.js +39 -0
  273. package/dist/src/daemon/work-tree.d.ts +9 -0
  274. package/dist/src/daemon/work-tree.js +20 -0
  275. package/dist/src/daemon/worker-profile.d.ts +9 -0
  276. package/dist/src/daemon/worker-profile.js +44 -0
  277. package/dist/src/daemon/workflow-generations.d.ts +7 -4
  278. package/dist/src/daemon/workflow-generations.js +22 -14
  279. package/dist/src/daemon/workflow-reload.d.ts +41 -0
  280. package/dist/src/daemon/workflow-reload.js +244 -0
  281. package/dist/src/daemon/workflow-replay.d.ts +2 -1
  282. package/dist/src/daemon/workflow-replay.js +7 -3
  283. package/dist/src/daemon/workflow-schedules.d.ts +3 -0
  284. package/dist/src/daemon/workflow-schedules.js +98 -45
  285. package/dist/src/daemon/worktree-processes.d.ts +9 -0
  286. package/dist/src/daemon/worktree-processes.js +151 -0
  287. package/dist/src/doctor-report.d.ts +4 -6
  288. package/dist/src/doctor-report.js +8 -13
  289. package/dist/src/harness-start.d.ts +15 -0
  290. package/dist/src/harness-start.js +37 -0
  291. package/dist/src/host/command-wait.d.ts +38 -0
  292. package/dist/src/host/command-wait.js +115 -0
  293. package/dist/src/host/start-delivery.d.ts +5 -7
  294. package/dist/src/host/start-delivery.js +3 -15
  295. package/dist/src/host/step-bridge-host.d.ts +2 -0
  296. package/dist/src/host/step-bridge-host.js +21 -0
  297. package/dist/src/operation-identity.d.ts +1 -0
  298. package/dist/src/operation-identity.js +4 -0
  299. package/dist/src/private-config.schema.json +71 -0
  300. package/dist/src/project-config.schema.json +40 -0
  301. package/dist/src/project-settings.d.ts +16 -2
  302. package/dist/src/project-settings.js +35 -1
  303. package/dist/src/queue-spend.d.ts +4 -0
  304. package/dist/src/queue-spend.js +21 -0
  305. package/dist/src/queue-state.d.ts +26 -0
  306. package/dist/src/queue-state.js +34 -0
  307. package/dist/src/record-retention.d.ts +46 -0
  308. package/dist/src/record-retention.js +81 -0
  309. package/dist/src/relay/relay-service.d.ts +3 -0
  310. package/dist/src/relay/relay-service.js +5 -3
  311. package/dist/src/report-ci.d.ts +164 -0
  312. package/dist/src/report-ci.js +32 -0
  313. package/dist/src/report-effects.d.ts +15 -0
  314. package/dist/src/report-effects.js +212 -0
  315. package/dist/src/report-flow-types.d.ts +38 -0
  316. package/dist/src/report-flow-types.js +7 -0
  317. package/dist/src/report-flow.d.ts +43 -0
  318. package/dist/src/report-flow.js +193 -0
  319. package/dist/src/report-operator.d.ts +67 -0
  320. package/dist/src/report-operator.js +25 -0
  321. package/dist/src/report-quality.d.ts +221 -0
  322. package/dist/src/report-quality.js +94 -0
  323. package/dist/src/report-ready.d.ts +23 -0
  324. package/dist/src/report-ready.js +117 -0
  325. package/dist/src/report-statistics.d.ts +2 -1
  326. package/dist/src/report-statistics.js +40 -4
  327. package/dist/src/report.d.ts +588 -47
  328. package/dist/src/report.js +156 -41
  329. package/dist/src/schedule-progress.d.ts +33 -0
  330. package/dist/src/schedule-progress.js +45 -0
  331. package/dist/src/service/active-tickets.js +11 -6
  332. package/dist/src/service/command-waits.d.ts +34 -0
  333. package/dist/src/service/command-waits.js +86 -0
  334. package/dist/src/service/dispatcher.d.ts +4 -0
  335. package/dist/src/service/dispatcher.js +33 -0
  336. package/dist/src/service/expiry.js +2 -0
  337. package/dist/src/service/gateway.js +3 -1
  338. package/dist/src/service/queue-handlers.d.ts +4 -0
  339. package/dist/src/service/queue-handlers.js +32 -0
  340. package/dist/src/service/queue-spend.d.ts +6 -0
  341. package/dist/src/service/queue-spend.js +68 -0
  342. package/dist/src/service/registry.d.ts +28 -2
  343. package/dist/src/service/registry.js +48 -0
  344. package/dist/src/service/replies.d.ts +22 -8
  345. package/dist/src/service/replies.js +16 -2
  346. package/dist/src/service/run-handlers.js +37 -12
  347. package/dist/src/service/run-metadata.d.ts +15 -1
  348. package/dist/src/service/run-metadata.js +93 -8
  349. package/dist/src/service/service.d.ts +11 -3
  350. package/dist/src/service/service.js +22 -37
  351. package/dist/src/service/submission-handler.js +18 -4
  352. package/dist/src/service/worker-port.js +9 -1
  353. package/dist/src/service/worker-totals.d.ts +6 -0
  354. package/dist/src/service/worker-totals.js +8 -1
  355. package/dist/src/service/workflow-reload.d.ts +35 -0
  356. package/dist/src/service/workflow-reload.js +52 -0
  357. package/dist/src/step-bridge.d.ts +20 -0
  358. package/dist/src/steps/command-wait.d.ts +12 -0
  359. package/dist/src/steps/command-wait.js +26 -0
  360. package/dist/src/steps/open-decision-wait.d.ts +2 -0
  361. package/dist/src/steps/{decision-gate.js → open-decision-wait.js} +0 -7
  362. package/dist/src/steps/review-by-person.js +4 -1
  363. package/dist/src/steps/wait-for-command.d.ts +3 -0
  364. package/dist/src/steps/wait-for-command.js +17 -0
  365. package/dist/src/steps/wait-for-decision.js +1 -1
  366. package/dist/src/storage/command-wait-rows.d.ts +30 -0
  367. package/dist/src/storage/command-wait-rows.js +96 -0
  368. package/dist/src/storage/decision-snapshots.d.ts +8 -2
  369. package/dist/src/storage/decision-snapshots.js +16 -8
  370. package/dist/src/storage/domain-changes.d.ts +3 -1
  371. package/dist/src/storage/domain-changes.js +4 -0
  372. package/dist/src/storage/domain-schema.d.ts +16 -1
  373. package/dist/src/storage/domain-schema.js +35 -4
  374. package/dist/src/storage/effect-schema.d.ts +2 -0
  375. package/dist/src/storage/effect-schema.js +9 -0
  376. package/dist/src/storage/projection-changes.d.ts +12 -0
  377. package/dist/src/storage/projection-changes.js +194 -0
  378. package/dist/src/storage/projection-lookups.d.ts +7 -0
  379. package/dist/src/storage/projection-lookups.js +30 -0
  380. package/dist/src/testing-requests.d.ts +15 -0
  381. package/dist/src/testing-requests.js +93 -0
  382. package/dist/src/testing.d.ts +4 -10
  383. package/dist/src/testing.js +33 -86
  384. package/dist/src/worker-usage.d.ts +1 -0
  385. package/dist/src/worker-usage.js +3 -0
  386. package/dist/src/workflow-candidate.d.ts +1 -0
  387. package/dist/src/workflow-candidate.js +12 -1
  388. package/dist/src/workflow-contracts.d.ts +1 -0
  389. package/dist/src/workflow-contracts.js +9 -2
  390. package/dist/src/workflow-declaration.d.ts +1 -0
  391. package/dist/src/workflow-declaration.js +3 -0
  392. package/dist/src/workflow-discovery.d.ts +2 -13
  393. package/dist/src/workflow-discovery.js +1 -13
  394. package/dist/src/workflow-refusals.js +0 -1
  395. package/dist/src/workflows.d.ts +1 -1
  396. package/dist/src/workflows.js +1 -1
  397. package/dist/tools/compile-workflows.js +3 -0
  398. package/dist/tools/project-configuration.d.ts +7 -2
  399. package/dist/tools/project-configuration.js +30 -1
  400. package/dist/tools/red-green-command.d.ts +1 -0
  401. package/dist/tools/red-green-command.js +174 -0
  402. package/dist/tools/red-green-process.d.ts +10 -0
  403. package/dist/tools/red-green-process.js +59 -0
  404. package/dist/tools/self-host-processes.d.ts +2 -0
  405. package/dist/tools/self-host-processes.js +69 -26
  406. package/dist/tools/self-host-project.d.ts +2 -0
  407. package/dist/tools/self-host-project.js +30 -77
  408. package/dist/tools/self-host-runtime.js +1 -1
  409. package/dist/tools/self-host.js +76 -34
  410. package/dist/tools/template-command.d.ts +1 -0
  411. package/dist/tools/template-command.js +160 -0
  412. package/dist/tools/template-copy.d.ts +11 -0
  413. package/dist/tools/template-copy.js +130 -0
  414. package/dist/tools/template-files.d.ts +17 -0
  415. package/dist/tools/template-files.js +74 -0
  416. package/dist/tools/workflow-bundles.js +1 -0
  417. package/dist/tools/workflow-candidate-counts.js +2 -2
  418. package/dist/tools/workflow-candidate-program.d.ts +4 -2
  419. package/dist/tools/workflow-candidate-program.js +30 -11
  420. package/dist/tools/workflow-candidate-shape.d.ts +3 -0
  421. package/dist/tools/workflow-candidate-shape.js +90 -0
  422. package/dist/tools/workflow-candidate-source.d.ts +1 -0
  423. package/dist/tools/workflow-candidate-source.js +26 -4
  424. package/dist/tools/workflow-candidate-syntax.d.ts +2 -2
  425. package/dist/tools/workflow-candidate-syntax.js +24 -94
  426. package/dist/tools/workflow-command.js +1 -2
  427. package/dist/tools/workflow-folders.d.ts +2 -3
  428. package/dist/tools/workflow-folders.js +1 -1
  429. package/package.json +17 -9
  430. package/templates/develop/README.md +93 -4
  431. package/templates/develop/develop/flow-tests.ts +38 -1
  432. package/templates/develop/develop/interruption-tests.ts +157 -0
  433. package/templates/develop/develop/local.ts +1 -0
  434. package/templates/develop/develop/option-tests.ts +138 -9
  435. package/templates/develop/develop/pull.ts +5 -1
  436. package/templates/develop/develop/red-green.ts +55 -0
  437. package/templates/develop/develop/refusal-tests.ts +77 -0
  438. package/templates/develop/develop/report.ts +31 -11
  439. package/templates/develop/develop/round.ts +1 -0
  440. package/templates/develop/develop/scenarios.ts +27 -0
  441. package/templates/develop/develop/turn.ts +28 -7
  442. package/templates/develop/develop.declaration.json +1 -1
  443. package/templates/develop/develop.test.ts +4 -0
  444. package/templates/develop/template.json +29 -2
  445. package/templates/idea-to-issue/README.md +27 -0
  446. package/templates/idea-to-issue/idea-to-issue/effects.ts +52 -0
  447. package/templates/idea-to-issue/idea-to-issue/leave.ts +10 -0
  448. package/templates/idea-to-issue/idea-to-issue/next.ts +29 -0
  449. package/templates/idea-to-issue/idea-to-issue/post-person.ts +18 -0
  450. package/templates/idea-to-issue/idea-to-issue/post.ts +50 -0
  451. package/templates/idea-to-issue/idea-to-issue/queue.ts +27 -0
  452. package/templates/idea-to-issue/idea-to-issue/review.ts +42 -0
  453. package/templates/idea-to-issue/idea-to-issue/scenarios.ts +50 -0
  454. package/templates/idea-to-issue/idea-to-issue/turn.ts +40 -0
  455. package/templates/idea-to-issue/idea-to-issue.declaration.json +16 -0
  456. package/templates/idea-to-issue/idea-to-issue.test.ts +79 -0
  457. package/templates/idea-to-issue/idea-to-issue.ts +49 -0
  458. package/templates/idea-to-issue/template.json +81 -0
  459. package/templates/review-day/README.md +97 -0
  460. package/templates/review-day/review-day/critique.ts +58 -0
  461. package/templates/review-day/review-day/decision.ts +29 -0
  462. package/templates/review-day/review-day/facts.ts +69 -0
  463. package/templates/review-day/review-day/label.ts +29 -0
  464. package/templates/review-day/review-day/next.ts +28 -0
  465. package/templates/review-day/review-day/post.ts +27 -0
  466. package/templates/review-day/review-day/report.ts +98 -0
  467. package/templates/review-day/review-day/rules.ts +12 -0
  468. package/templates/review-day/review-day/scenarios.ts +76 -0
  469. package/templates/review-day/review-day/turn.ts +73 -0
  470. package/templates/review-day/review-day.declaration.json +16 -0
  471. package/templates/review-day/review-day.test.ts +362 -0
  472. package/templates/review-day/review-day.ts +37 -0
  473. package/templates/review-day/template.json +56 -0
  474. package/dist/src/cli/watch-start-view.d.ts +0 -18
  475. package/dist/src/cli/watch-start-view.js +0 -77
  476. package/dist/src/steps/decision-gate.d.ts +0 -3
  477. package/dist/workflows/develop-prd.d.ts +0 -7
  478. package/dist/workflows/develop-prd.js +0 -165
  479. package/dist/workflows/develop-ticket.d.ts +0 -9
  480. package/dist/workflows/develop-ticket.js +0 -207
  481. package/dist/workflows/issue-labels.d.ts +0 -16
  482. package/dist/workflows/issue-labels.js +0 -70
  483. package/dist/workflows/ticket-prompts.d.ts +0 -35
  484. package/dist/workflows/ticket-prompts.js +0 -147
@@ -1,94 +1,109 @@
1
- import { join } from "node:path";
2
1
  import { turnHarness } from "../harness-defaults.js";
3
- import { profileCommand, } from "../turn-profile.js";
4
- import { succeeded } from "./claude-turn.js";
5
- import { turnReport } from "./turn-report.js";
2
+ import { attachmentEnvironment } from "./attachments.js";
3
+ import { profileCommand } from "../turn-profile.js";
4
+ import {} from "./claude-turn.js";
5
+ import { turnOutcome } from "./turn-report.js";
6
6
  import { startRetriedTurn } from "./retrying-turn.js";
7
- import { interrupted, located, operationKey, readRecord as read, replied, reportOf, writeRecord as written, } from "./operation-journal.js";
8
- import { treeFailure, workTree } from "./work-tree.js";
7
+ import { located, readRecord as read, replied, reportOf, writeRecord as written, } from "./operation-journal.js";
8
+ import { firstTurn, treeFailure, workTree, } from "./work-tree.js";
9
+ import { recordedHarness, interruptedReply, processAlive, uncertainProcess, resumePlan, recordedField, resumableHarness, recoverTurn, turnIntent, } from "./claude-recovery.js";
10
+ import { checkedProfiles, selectedProfile } from "./worker-profile.js";
9
11
  export const claudeLimits = {
10
12
  summaryCharacters: 16_000,
11
13
  resultBytes: 48_000,
12
- stopMilliseconds: 2_000,
14
+ stopMilliseconds: 15_000,
13
15
  };
14
16
  const worker = "claude";
15
- async function recordedHarness(journal, operationId) {
16
- const { folder } = located(journal, operationId);
17
- const started = await read(folder, "started.json").catch(() => undefined);
18
- const harness = Reflect.get(Object(started), "harness");
19
- return typeof harness === "string" ? harness : undefined;
20
- }
21
- function alive(processId) {
22
- if (typeof processId !== "number")
23
- return false;
24
- try {
25
- process.kill(processId, 0);
26
- return true;
27
- }
28
- catch (error) {
29
- return Reflect.get(Object(error), "code") === "EPERM";
30
- }
17
+ function reconciled(parts, call) {
18
+ const { intent } = call;
19
+ const { key } = located(parts.settings.journal, intent.operationId);
20
+ const pending = parts.reconciling.get(key);
21
+ if (pending !== undefined)
22
+ return pending;
23
+ const reconciliation = reconcileOperation(parts, call).finally(() => {
24
+ if (parts.reconciling.get(key) === reconciliation)
25
+ parts.reconciling.delete(key);
26
+ });
27
+ parts.reconciling.set(key, reconciliation);
28
+ return reconciliation;
31
29
  }
32
- async function reconciled(parts, intent) {
30
+ async function reconcileOperation(parts, call) {
31
+ const { intent, signal } = call;
33
32
  const { key, folder } = located(parts.settings.journal, intent.operationId);
34
33
  const result = await read(folder, "result.json");
35
- if (result !== undefined)
34
+ if (result !== undefined &&
35
+ (recordedField(result, "stoppedBy") !== "daemon-shutdown" ||
36
+ parts.stopping.signal.aborted))
36
37
  return replied({ receipt: key, worker }, result);
37
38
  if (parts.active.has(key))
38
39
  return { kind: "accepted", receipt: key, worker };
39
40
  const started = await read(folder, "started.json");
40
41
  if (started === undefined)
41
42
  return { kind: "absent" };
42
- if (alive(Reflect.get(Object(started), "processId")))
43
+ if (await uncertainProcess(started))
43
44
  return { kind: "unknown", evidence: `claude-turn:${key}` };
44
- const ending = interrupted("claude-turn-interrupted");
45
- await written(folder, { name: "result.json", value: ending });
46
- return replied({ receipt: key, worker }, ending);
45
+ return resumed(parts, { intent, key, folder, started, signal });
47
46
  }
48
- async function outcome(running, end) {
49
- const endedAt = new Date().toISOString();
50
- const { result } = end;
51
- const report = result === undefined
52
- ? {}
53
- : await turnReport({
54
- tree: running.tree,
55
- harness: running.harness,
56
- limits: claudeLimits,
57
- }, result);
58
- const { text, reason } = report;
59
- if (succeeded(end) && reason === undefined && text !== undefined)
60
- return { outcome: "completed", result: text, endedAt };
61
- if (running.stopping.requested)
62
- return { outcome: "stopped", endedAt };
63
- return {
64
- outcome: "failed",
65
- reason: end.reason ?? reason ?? "claude-turn-failed",
66
- ...(end.detail === undefined ? {} : { detail: end.detail }),
67
- ...(text === undefined ? {} : { result: text }),
68
- endedAt,
69
- };
47
+ async function resumed(parts, request) {
48
+ const { intent, started, key, folder, signal } = request;
49
+ const aborted = () => signal.aborted;
50
+ if (!turnIntent(intent))
51
+ return interruptedReply(request, "claude-turn-interrupted");
52
+ if (aborted())
53
+ return failure("claude-start-aborted");
54
+ const current = parts.settings.turnSettings();
55
+ const plan = await resumePlan({ ...parts.settings, ...current }, { folder, started, intent, signal });
56
+ if (aborted())
57
+ return failure("claude-start-aborted");
58
+ if (typeof plan === "string")
59
+ return interruptedReply(request, plan);
60
+ const prompt = await parts.settings.document(intent.payload);
61
+ if (aborted())
62
+ return failure("claude-start-aborted");
63
+ if (prompt === undefined)
64
+ return interruptedReply(request, "claude-turn-interrupted");
65
+ await begun(parts, {
66
+ key,
67
+ folder,
68
+ intent,
69
+ ...plan,
70
+ signal,
71
+ prompt,
72
+ turnSettings: current,
73
+ });
74
+ return { kind: "accepted", receipt: key, worker };
70
75
  }
71
76
  async function concluded(parts, running) {
72
77
  const { intent, key } = running;
73
- const recorded = await outcome(running, await running.turn.ended);
78
+ const recorded = await turnOutcome({ ...running, limits: claudeLimits }, await running.turn.ended);
74
79
  await written(running.folder, { name: "result.json", value: recorded });
80
+ if (recorded.stoppedBy === "daemon-shutdown")
81
+ return;
75
82
  await parts.settings.report(reportOf({ intent, commandId: `claude-turn:${key}`, worker }, recorded));
76
83
  }
77
84
  async function begun(parts, start) {
78
85
  const { intent, key, folder, tree, prompt } = start;
79
86
  const { harness } = start;
80
87
  const stopping = { requested: false, controller: new AbortController() };
88
+ const cancel = () => {
89
+ stopping.controller.abort();
90
+ };
91
+ start.signal.addEventListener("abort", cancel, { once: true });
92
+ if (start.signal.aborted)
93
+ cancel();
81
94
  const turn = startRetriedTurn({
82
95
  ...harness,
83
96
  resultBytes: claudeLimits.resultBytes,
84
97
  command: profileCommand(harness.command, start.profile),
85
- environment: start.profile.env ?? {},
98
+ environment: await attachmentEnvironment(parts.settings, start),
86
99
  turnId: `${intent.runId}-${key}`,
87
100
  directory: tree.path,
88
101
  folder,
89
102
  prompt,
90
103
  }, {
91
104
  ...parts.settings,
105
+ ...start.turnSettings,
106
+ ...(start.resume === undefined ? {} : { resume: start.resume }),
92
107
  stopping: stopping.controller,
93
108
  metadata: {
94
109
  harness: harness.worker,
@@ -100,6 +115,7 @@ async function begun(parts, start) {
100
115
  },
101
116
  });
102
117
  parts.active.set(key, {
118
+ worker: harness.worker,
103
119
  turn,
104
120
  stopping,
105
121
  concluded: turn
@@ -107,74 +123,13 @@ async function begun(parts, start) {
107
123
  .catch(() => undefined)
108
124
  .finally(() => parts.active.delete(key)),
109
125
  });
110
- await turn;
111
- }
112
- async function firstTurn(settings, opening) {
113
- const { tree, intent } = opening;
114
- const { target, runId } = intent;
115
- const folder = target.startsWith("branch:")
116
- ? join(settings.journal, "runs", operationKey(runId), "targets")
117
- : join(settings.journal, "targets");
118
- const name = `${operationKey(target)}.json`;
119
- const startCommit = Reflect.get(Object(await read(folder, name)), "startCommit");
120
- if (typeof startCommit === "string")
121
- return { ...tree, startCommit };
122
- await written(folder, {
123
- name,
124
- value: { target, startCommit: tree.startCommit },
126
+ await turn.finally(() => {
127
+ start.signal.removeEventListener("abort", cancel);
125
128
  });
126
- return tree;
127
- }
128
- function turnIntent(intent) {
129
- return (intent.capability === worker &&
130
- (intent.method === "run-turn" ||
131
- /^run-turn:[A-Za-z0-9_-]{1,119}$/.test(intent.method ?? "")) &&
132
- intent.target !== undefined &&
133
- intent.payload !== undefined &&
134
- intent.leaseGeneration !== undefined);
135
129
  }
136
130
  function failure(reason) {
137
131
  return { kind: "failed", reason };
138
132
  }
139
- async function runWorkflow(settings, runId) {
140
- try {
141
- return await settings.workflowId?.(runId);
142
- }
143
- catch {
144
- return undefined;
145
- }
146
- }
147
- function unsupportedProfile(profile, harness) {
148
- if (harness.output === "text" && profile.model !== undefined)
149
- return "profile-model-not-supported";
150
- if (harness.worker === "claude")
151
- return undefined;
152
- return [
153
- profile.allowedTools,
154
- profile.permissionMode,
155
- profile.maxBudgetUsd,
156
- ].some((value) => value !== undefined)
157
- ? "profile-needs-claude"
158
- : undefined;
159
- }
160
- async function selectedProfile(settings, intent) {
161
- if (intent.method === "run-turn")
162
- return {};
163
- const name = intent.method.slice("run-turn:".length);
164
- const profiles = settings.profiles ?? {};
165
- const profile = Object.hasOwn(profiles, name) ? profiles[name] : undefined;
166
- if (profile === undefined)
167
- return "unknown-profile";
168
- const unsupported = unsupportedProfile(profile, turnHarness(settings, profile));
169
- if (unsupported !== undefined)
170
- return unsupported;
171
- if (profile.workflows === undefined)
172
- return profile;
173
- const workflowId = await runWorkflow(settings, intent.runId);
174
- if (workflowId === undefined || !profile.workflows.includes(workflowId))
175
- return "profile-not-allowed";
176
- return profile;
177
- }
178
133
  async function delivered(parts, call) {
179
134
  const { intent, signal } = call;
180
135
  const { settings } = parts;
@@ -183,10 +138,11 @@ async function delivered(parts, call) {
183
138
  return failure("unsupported-effect");
184
139
  if (aborted())
185
140
  return failure("claude-start-aborted");
186
- const known = await reconciled(parts, intent);
141
+ const known = await reconciled(parts, call);
187
142
  if (known.kind !== "absent")
188
143
  return known;
189
- const profile = await selectedProfile(settings, intent);
144
+ const current = settings.turnSettings();
145
+ const profile = await selectedProfile({ ...settings, ...current }, intent);
190
146
  if (typeof profile === "string")
191
147
  return failure(profile);
192
148
  const prompt = await settings.document(intent.payload);
@@ -213,6 +169,8 @@ async function delivered(parts, call) {
213
169
  prompt,
214
170
  profile,
215
171
  harness: turnHarness(settings, profile),
172
+ signal,
173
+ turnSettings: current,
216
174
  });
217
175
  return { receipt: place.key, worker };
218
176
  }
@@ -224,37 +182,80 @@ async function halted(parts, active) {
224
182
  await active.concluded;
225
183
  }
226
184
  async function stopped(parts, intent) {
227
- const { key } = located(parts.settings.journal, intent.operationId);
185
+ const { key, folder } = located(parts.settings.journal, intent.operationId);
228
186
  const active = parts.active.get(key);
229
- if (active !== undefined)
187
+ if (active !== undefined) {
188
+ delete active.stopping.stoppedBy;
230
189
  await halted(parts, active);
231
- return reconciled(parts, intent);
190
+ }
191
+ const result = await read(folder, "result.json");
192
+ if (result !== undefined &&
193
+ recordedField(result, "stoppedBy") !== "daemon-shutdown")
194
+ return replied({ receipt: key, worker }, result);
195
+ const started = await read(folder, "started.json");
196
+ if (started === undefined)
197
+ return { kind: "absent" };
198
+ if (!resumableHarness(recordedField(started, "harness")))
199
+ return reconcileOperation(parts, { intent, signal: parts.stopping.signal });
200
+ if (processAlive(recordedField(started, "processId")))
201
+ return { kind: "unknown", evidence: `claude-turn:${key}` };
202
+ if (!turnIntent(intent))
203
+ return failure("unsupported-effect");
204
+ const recorded = {
205
+ outcome: "stopped",
206
+ endedAt: new Date().toISOString(),
207
+ };
208
+ await written(folder, { name: "result.json", value: recorded });
209
+ await parts.settings.report(reportOf({ intent, commandId: `claude-turn:${key}`, worker }, recorded));
210
+ return replied({ receipt: key, worker }, recorded);
211
+ }
212
+ function stoppingOperation(parts, intent) {
213
+ const { key } = located(parts.settings.journal, intent.operationId);
214
+ const pending = parts.reconciling.get(key);
215
+ const stop = () => stopped(parts, intent);
216
+ const stopping = pending === undefined ? stop() : pending.then(stop, stop);
217
+ const settled = stopping.finally(() => {
218
+ if (parts.reconciling.get(key) === settled)
219
+ parts.reconciling.delete(key);
220
+ });
221
+ parts.reconciling.set(key, settled);
222
+ return settled;
232
223
  }
233
224
  export function claudeWorker(settings) {
234
225
  if (settings.command.length === 0)
235
226
  throw new Error("invalid-claude-command");
236
227
  turnHarness(settings);
237
- for (const profile of Object.values(settings.profiles ?? {}))
238
- turnHarness(settings, profile);
228
+ checkedProfiles(settings, settings.turnSettings().profiles);
239
229
  const parts = {
240
230
  settings,
241
231
  active: new Map(),
232
+ reconciling: new Map(),
242
233
  stopping: new AbortController(),
243
234
  };
244
235
  const guarded = (intent, run) => intent.method === "run-turn:analyze-chats"
245
236
  ? Promise.resolve(failure("unsupported-effect"))
246
237
  : run();
247
238
  return {
239
+ recover: (intent) => turnIntent(intent)
240
+ ? recoverTurn({ ...settings, intent, signal: parts.stopping.signal }, () => reconciled(parts, { intent, signal: parts.stopping.signal }))
241
+ : Promise.resolve(),
248
242
  harness: (operationId) => recordedHarness(settings.journal, operationId),
249
243
  deliver: (intent, signal) => guarded(intent, () => delivered(parts, {
250
244
  intent,
251
245
  signal: AbortSignal.any([signal, parts.stopping.signal]),
252
246
  })),
253
- reconcile: (intent) => guarded(intent, () => reconciled(parts, intent)),
254
- stop: (intent) => guarded(intent, () => stopped(parts, intent)),
247
+ reconcile: (intent, signal) => guarded(intent, () => reconciled(parts, {
248
+ intent,
249
+ signal: AbortSignal.any([signal, parts.stopping.signal]),
250
+ })),
251
+ stop: (intent) => guarded(intent, () => stoppingOperation(parts, intent)),
255
252
  close: async () => {
256
253
  parts.stopping.abort();
257
- await Promise.all([...parts.active.values()].map((active) => halted(parts, active)));
254
+ await Promise.all([...parts.active.values()].map((active) => {
255
+ if (resumableHarness(active.worker) && !active.stopping.requested)
256
+ active.stopping.stoppedBy = "daemon-shutdown";
257
+ return halted(parts, active);
258
+ }));
258
259
  },
259
260
  };
260
261
  }
@@ -12,12 +12,15 @@ import type { LocalCommands } from "../command-settings.ts";
12
12
  import type { DeclaredWorkflow } from "../workflow-declaration.ts";
13
13
  import type { WorkflowRefusal } from "../workflow-refusals.ts";
14
14
  import type { HarnessSettings } from "../harness-defaults.ts";
15
+ import type { RetentionSettings } from "../record-retention.ts";
16
+ import { type SettingDigests, type TurnSettingsSource } from "./settings-reload.ts";
15
17
  export interface DaemonSettings extends HarnessSettings {
16
18
  readonly commands?: LocalCommands;
17
19
  readonly commandSeconds?: number;
18
20
  readonly fallbackModels?: readonly string[];
19
21
  readonly tokenPrices?: TokenPrices;
20
22
  readonly profiles?: TurnProfiles;
23
+ readonly settingDigests?: SettingDigests;
21
24
  readonly directory: string;
22
25
  readonly runtimeDirectory: string;
23
26
  readonly repository: string;
@@ -28,6 +31,7 @@ export interface DaemonSettings extends HarnessSettings {
28
31
  readonly workflows: Readonly<Record<string, WorkflowFunction | undefined>>;
29
32
  readonly handler: WorkflowHandler;
30
33
  readonly loadBundle?: WorkflowBundleLoader;
34
+ readonly reloadCommand?: readonly string[];
31
35
  readonly command: readonly string[];
32
36
  readonly ticketCommand?: readonly string[];
33
37
  readonly nextCommand?: readonly string[];
@@ -35,8 +39,11 @@ export interface DaemonSettings extends HarnessSettings {
35
39
  readonly notifyMilliseconds?: number;
36
40
  readonly queueMilliseconds?: number;
37
41
  readonly scheduleClock?: () => number;
42
+ readonly retention?: RetentionSettings;
43
+ readonly retentionClock?: () => number;
38
44
  readonly schedules?: unknown;
39
45
  readonly queueLanes?: number;
46
+ readonly queueDailySpendLimitUsd?: number;
40
47
  readonly resetQueue?: boolean;
41
48
  readonly githubCommand?: readonly string[];
42
49
  readonly requiredChecks?: readonly string[] | null;
@@ -46,6 +53,7 @@ export interface DaemonSettings extends HarnessSettings {
46
53
  }
47
54
  export interface Adapters {
48
55
  readonly worker: ClaudeWorker;
56
+ readonly turnSettings: TurnSettingsSource;
49
57
  readonly github: GithubWorker;
50
58
  readonly runs: StartDelivery;
51
59
  readonly handoff: EffectDelivery;
@@ -56,3 +64,4 @@ export declare function adapters(settings: DaemonSettings, options: {
56
64
  readonly generations: ReturnType<typeof workflowGenerations>;
57
65
  }): Adapters;
58
66
  export declare function recoverCommands(commands: CommandWorker, ports: HostPorts): Promise<void>;
67
+ export declare function recoverClaude(worker: Pick<ClaudeWorker, "harness" | "recover">, ports: Pick<HostPorts, "state" | "operations">): Promise<void>;
@@ -6,11 +6,14 @@ import { claudeWorker } from "./claude-worker.js";
6
6
  import { githubWorker } from "./github-worker.js";
7
7
  import { commandWorker } from "./command-worker.js";
8
8
  import { handoffWorker } from "./handoff-worker.js";
9
+ import { resumableHarness } from "./claude-recovery.js";
10
+ import { turnSettingsSource, } from "./settings-reload.js";
9
11
  function githubOf(settings, given) {
10
12
  const { directory, repository, checkCommand } = settings;
11
13
  return githubWorker({
12
14
  document: async (digest) => (await given).document(digest),
13
15
  report: async (effect) => (await given).reportEffect(effect),
16
+ observe: async (observation) => (await given).submit({ kind: "report-observation", ...observation }),
14
17
  operationStatus: async (operationId) => (await (await given).operation(operationId))?.status,
15
18
  runStatus: async (runId) => (await (await given).state()).runs[runId]?.status,
16
19
  repository,
@@ -40,11 +43,14 @@ export function adapters(settings, options) {
40
43
  const { given, generations } = options;
41
44
  const document = async (digest) => (await given).document(digest);
42
45
  const report = async (effect) => (await given).reportEffect(effect);
43
- const worker = claudeWorker({
46
+ const turnSettings = turnSettingsSource({
47
+ profiles: settings.profiles ?? {},
44
48
  fallbackModels: settings.fallbackModels ?? [],
45
49
  tokenPrices: settings.tokenPrices ?? {},
50
+ });
51
+ const worker = claudeWorker({
46
52
  ...workerHarness(settings),
47
- profiles: settings.profiles ?? {},
53
+ turnSettings: turnSettings.current,
48
54
  workflowId: async (runId) => (await given).workflow.id(runId),
49
55
  repository,
50
56
  document,
@@ -70,7 +76,7 @@ export function adapters(settings, options) {
70
76
  document,
71
77
  report,
72
78
  });
73
- return { worker, github, runs, handoff, commands };
79
+ return { worker, github, runs, handoff, commands, turnSettings };
74
80
  }
75
81
  function handoffOf(settings, given) {
76
82
  return handoffWorker({
@@ -81,11 +87,33 @@ function handoffOf(settings, given) {
81
87
  });
82
88
  }
83
89
  export async function recoverCommands(commands, ports) {
90
+ await commands.recover(await recoveryCalls(ports, "command"));
91
+ }
92
+ export async function recoverClaude(worker, ports) {
93
+ for (const intent of await recoveryCalls(ports, "claude")) {
94
+ if (!resumableHarness(await worker.harness(intent.operationId)))
95
+ continue;
96
+ if (!(await stillRecoverable(ports, intent)))
97
+ continue;
98
+ await worker.recover(intent);
99
+ }
100
+ }
101
+ async function stillRecoverable(ports, intent) {
102
+ const operation = (await ports.operations(intent.runId)).find((current) => current.operationId === intent.operationId);
103
+ const run = (await ports.state()).runs[intent.runId];
104
+ return (run?.status === "running" &&
105
+ operation !== undefined &&
106
+ operation.leaseGeneration === intent.leaseGeneration &&
107
+ ["running", "recovering", "dispatch-pending"].includes(operation.status));
108
+ }
109
+ async function recoveryCalls(ports, capability) {
84
110
  const state = await ports.state();
85
111
  const calls = [];
86
112
  for (const run of Object.values(state.runs)) {
113
+ if (capability === "claude" && run.status !== "running")
114
+ continue;
87
115
  for (const operation of await ports.operations(run.runId)) {
88
- if (operation.capability !== "command" ||
116
+ if (operation.capability !== capability ||
89
117
  operation.leaseGeneration === null ||
90
118
  !["running", "recovering", "dispatch-pending"].includes(operation.status))
91
119
  continue;
@@ -98,5 +126,5 @@ export async function recoverCommands(commands, ports) {
98
126
  });
99
127
  }
100
128
  }
101
- await commands.recover(calls);
129
+ return calls;
102
130
  }
@@ -1,11 +1,15 @@
1
+ import type { scheduleConnection } from "./schedule-control.ts";
2
+ import type { queueConnection } from "./queue-control.ts";
1
3
  import { workflowSchedules } from "./workflow-schedules.ts";
2
4
  interface LoopSettings extends ParametersOfSchedules {
5
+ readonly scheduleConnection?: ReturnType<typeof scheduleConnection>;
6
+ readonly queueConnection?: ReturnType<typeof queueConnection>;
3
7
  readonly notifyCommand?: readonly string[];
4
8
  readonly notifyMilliseconds?: number;
5
9
  readonly queueMilliseconds?: number;
6
10
  readonly queueLanes?: number;
7
11
  readonly resetQueue?: boolean;
8
- readonly queueWorkflowId: string;
12
+ readonly queueWorkflowId: string | undefined;
9
13
  }
10
14
  type ParametersOfSchedules = Parameters<typeof workflowSchedules>[0];
11
15
  export declare function daemonLoops(settings: LoopSettings): Promise<{
@@ -1,8 +1,25 @@
1
1
  import { workflowSchedules } from "./workflow-schedules.js";
2
2
  import { issueQueue } from "./issue-queue.js";
3
3
  import { notifyRuns } from "./notify.js";
4
+ async function startedQueue(settings) {
5
+ if (settings.queueMilliseconds === undefined ||
6
+ settings.queueWorkflowId === undefined)
7
+ return undefined;
8
+ const queue = issueQueue({
9
+ directory: settings.directory,
10
+ runtimeDirectory: settings.runtimeDirectory,
11
+ intervalMilliseconds: settings.queueMilliseconds,
12
+ lanes: settings.queueLanes ?? 1,
13
+ resetQueue: settings.resetQueue ?? false,
14
+ workflowId: settings.queueWorkflowId,
15
+ });
16
+ settings.queueConnection?.connect(queue.port);
17
+ await queue.ready;
18
+ return queue;
19
+ }
4
20
  export async function daemonLoops(settings) {
5
21
  const schedules = await workflowSchedules(settings);
22
+ settings.scheduleConnection?.connect(schedules.request);
6
23
  try {
7
24
  const notifier = settings.notifyCommand === undefined
8
25
  ? undefined
@@ -14,16 +31,7 @@ export async function daemonLoops(settings) {
14
31
  ? {}
15
32
  : { intervalMilliseconds: settings.notifyMilliseconds }),
16
33
  });
17
- const queue = settings.queueMilliseconds === undefined
18
- ? undefined
19
- : issueQueue({
20
- directory: settings.directory,
21
- runtimeDirectory: settings.runtimeDirectory,
22
- intervalMilliseconds: settings.queueMilliseconds,
23
- lanes: settings.queueLanes ?? 1,
24
- resetQueue: settings.resetQueue ?? false,
25
- workflowId: settings.queueWorkflowId,
26
- });
34
+ const queue = await startedQueue(settings);
27
35
  return {
28
36
  stop: async () => {
29
37
  await schedules.stop();