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,3 +1,5 @@
1
+ import { scheduledText } from "./schedule-render.js";
2
+ import { CommandWaits, effectBudgetText } from "./command-waits.js";
1
3
  import { Header, Queue } from "./watch-header-view.js";
2
4
  export { clove, Header } from "./watch-header-view.js";
3
5
  import { priceText, usageText, totalsSuffix } from "./usage-render.js";
@@ -8,7 +10,6 @@ import { boardWorkflow, watchHash, watchLocation } from "./watch-navigation.js";
8
10
  import { Decision, Events, Turn, PullRequest } from "./watch-turn.js";
9
11
  import { Commands } from "./command-effects.js";
10
12
  export { PullRequest } from "./watch-turn.js";
11
- import { StartRun } from "./watch-start-view.js";
12
13
  export function BannerDetail(props) {
13
14
  const { run, now } = props;
14
15
  const turn = run.turns.at(-1);
@@ -88,9 +89,7 @@ export function Review(props) {
88
89
  export function Run(props) {
89
90
  const { run, now, copying } = props;
90
91
  const turn = run.turns.at(-1);
91
- const budget = run.spent === null || run.limit === null
92
- ? ""
93
- : ` · ${String(run.spent)} of ${String(run.limit)} effect units`;
92
+ const budget = effectBudgetText(run.spent, run.limit);
94
93
  const none = "No agent turn for this run.";
95
94
  const turns = run.turns.length === 0
96
95
  ? element("p", { class: "meta", children: none })
@@ -103,13 +102,17 @@ export function Run(props) {
103
102
  }),
104
103
  ]);
105
104
  const foot = [
106
- `${run.workflowId} · ${run.runId}${budget}`,
105
+ `${run.workflowId} · ${run.runId}${budget === "" ? "" : ` · ${budget}`}`,
107
106
  element("br", {}),
108
107
  `${run.code}: ${run.detail}`,
109
108
  ];
110
109
  return [
111
110
  component(Banner, { run, now }),
111
+ run.scheduled === undefined
112
+ ? null
113
+ : element("p", { class: "meta", children: scheduledText(run.scheduled) }),
112
114
  component(HandoffLinks, { run }),
115
+ component(CommandWaits, { waits: run.commandWaits ?? [] }),
113
116
  element("section", {
114
117
  class: "run-usage",
115
118
  children: [
@@ -181,21 +184,18 @@ export function Page(props) {
181
184
  return component(BoardPage, { ...props, model, workflowId, down });
182
185
  }
183
186
  export function BoardPage(props) {
184
- const { model, workflowId, down, now, stale, copying } = props;
187
+ const { model, workflowId, down, now, stale } = props;
185
188
  const workflow = model.workflows.find((item) => item.workflowId === workflowId);
186
- const start = props.start ?? { shown: false, onToggle: () => undefined };
187
189
  return element("div", {
188
190
  class: "board-page",
189
191
  children: [
190
- component(Header, { model, stale, start, phone: props.phone, now }),
192
+ component(Header, { model, stale, phone: props.phone, now }),
191
193
  component(Queue, { model }),
192
194
  down,
195
+ model.schedules !== undefined && "status" in model.schedules
196
+ ? element("p", { class: "meta", children: "Schedules: unavailable" })
197
+ : null,
193
198
  component(RefusedWorkflows, { model }),
194
- component(StartRun, {
195
- workflows: model.workflows,
196
- copying,
197
- shown: start.shown,
198
- }),
199
199
  component(WorkflowList, {
200
200
  workflows: model.workflows,
201
201
  selected: workflowId,
package/dist/src/cli.js CHANGED
@@ -1,8 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import { createProbeRunner } from "./cli/probe-command.js";
3
+ import { terminateHarness } from "./cli/harness-processes.js";
3
4
  import { settingsEnvironment } from "./cli/project-settings.js";
5
+ import { constants as systemConstants } from "node:os";
4
6
  import { addAbortListener } from "node:events";
5
- import { execFile, execFileSync, spawn } from "node:child_process";
7
+ import { execFile, execFileSync, spawn, } from "node:child_process";
6
8
  import { existsSync, realpathSync } from "node:fs";
7
9
  import { parseArgs } from "node:util";
8
10
  import { delimiter, dirname, extname, join, resolve } from "node:path";
@@ -30,7 +32,7 @@ const watchCommand = async (request) => {
30
32
  cwd: request.directory,
31
33
  signal: request.signal,
32
34
  killSignal: "SIGKILL",
33
- maxBuffer: 1024 * 1024,
35
+ maxBuffer: request.outputBytes ?? 1024 * 1024,
34
36
  encoding: "utf8",
35
37
  }, (error, stdout) => {
36
38
  const code = error === null ? 0 : error.code;
@@ -58,6 +60,52 @@ const watchCommand = async (request) => {
58
60
  listener[Symbol.dispose]();
59
61
  }
60
62
  };
63
+ function spawnedHarness(request) {
64
+ try {
65
+ return spawn(request.executable, request.arguments, {
66
+ cwd: request.directory,
67
+ env: request.environment,
68
+ stdio: "inherit",
69
+ });
70
+ }
71
+ catch {
72
+ return undefined;
73
+ }
74
+ }
75
+ function startHarness(request) {
76
+ return new Promise((settle) => {
77
+ const interrupt = () => undefined;
78
+ const terminate = () => {
79
+ terminateHarness(child?.pid, {
80
+ snapshot: () => execFileSync("/bin/ps", ["-axo", "pid=,ppid="], {
81
+ encoding: "utf8",
82
+ timeout: 1000,
83
+ }),
84
+ kill: (identifier, signal) => process.kill(identifier, signal),
85
+ });
86
+ };
87
+ const cleanup = () => {
88
+ process.off("SIGINT", interrupt);
89
+ process.off("SIGTERM", terminate);
90
+ };
91
+ process.on("SIGINT", interrupt);
92
+ process.on("SIGTERM", terminate);
93
+ const child = spawnedHarness(request);
94
+ if (child === undefined) {
95
+ cleanup();
96
+ settle(null);
97
+ return;
98
+ }
99
+ child.once("error", () => {
100
+ cleanup();
101
+ settle(null);
102
+ });
103
+ child.once("close", (status, signal) => {
104
+ cleanup();
105
+ settle(status ?? (signal === null ? 1 : 128 + systemConstants.signals[signal]));
106
+ });
107
+ });
108
+ }
61
109
  function startArguments(input) {
62
110
  const { runtime, repository, argumentsList } = input;
63
111
  const located = [
@@ -81,13 +129,6 @@ function startArguments(input) {
81
129
  }
82
130
  function toolProcess(input) {
83
131
  const program = join(import.meta.dirname, "..", "tools", `${input.tool}${extname(import.meta.filename)}`);
84
- const child = spawn(process.execPath, [program, ...input.argumentsList], {
85
- stdio: "inherit",
86
- env: {
87
- ...process.env,
88
- PATH: [dirname(process.execPath), process.env["PATH"]].join(delimiter),
89
- },
90
- });
91
132
  let stopping = false;
92
133
  const interrupt = () => {
93
134
  stopping = true;
@@ -99,11 +140,25 @@ function toolProcess(input) {
99
140
  };
100
141
  process.on("SIGINT", interrupt);
101
142
  process.on("SIGTERM", terminate);
143
+ const child = spawn(process.execPath, [program, ...input.argumentsList], {
144
+ detached: input.tool === "red-green-command",
145
+ stdio: input.tool === "red-green-command"
146
+ ? ["inherit", "inherit", "inherit", "ipc"]
147
+ : "inherit",
148
+ env: {
149
+ ...process.env,
150
+ PATH: [dirname(process.execPath), process.env["PATH"]].join(delimiter),
151
+ },
152
+ });
102
153
  return new Promise((settle) => {
103
154
  child.once("close", (status) => {
104
- process.off("SIGINT", interrupt);
105
- process.off("SIGTERM", terminate);
106
- settle(stopping && status === 75 ? 0 : (status ?? 1));
155
+ setImmediate(() => {
156
+ setImmediate(() => {
157
+ process.off("SIGINT", interrupt);
158
+ process.off("SIGTERM", terminate);
159
+ settle(stopping && status === 75 ? 0 : (status ?? 1));
160
+ });
161
+ });
107
162
  });
108
163
  });
109
164
  }
@@ -160,6 +215,11 @@ else if (command === "templates")
160
215
  tool: "template-command",
161
216
  argumentsList: options,
162
217
  });
218
+ else if (command === "red-green")
219
+ process.exitCode = await toolProcess({
220
+ tool: "red-green-command",
221
+ argumentsList: options,
222
+ });
163
223
  else if (command === "start")
164
224
  process.exitCode = await start();
165
225
  else {
@@ -174,6 +234,7 @@ else {
174
234
  await main(process.argv.slice(2), {
175
235
  repository,
176
236
  environment,
237
+ startHarness,
177
238
  doctorProbe: createProbeRunner({
178
239
  spawn: (input) => spawn(input.executable, input.arguments, input.options),
179
240
  kill: (identifier, signal) => process.kill(identifier, signal),
@@ -0,0 +1,4 @@
1
+ import type { HandoffValue, CommandWaitRequest } from "./step-bridge.ts";
2
+ export type { CommandWaitRequest, CommandWaitOutcome, CommandWaitProgress, } from "./step-bridge.ts";
3
+ export declare function isCommandWaitRequest(value: unknown): value is CommandWaitRequest;
4
+ export declare function commandWaitValue(value: unknown, ancestors?: ReadonlySet<unknown>): value is HandoffValue;
@@ -0,0 +1,45 @@
1
+ export function isCommandWaitRequest(value) {
2
+ if (!dataFields(value, ["name", "input"]))
3
+ return false;
4
+ const name = Reflect.get(value, "name");
5
+ return (typeof name === "string" &&
6
+ name.length > 0 &&
7
+ commandWaitValue(Reflect.get(value, "input")));
8
+ }
9
+ function dataFields(value, keys) {
10
+ if (value === null || typeof value !== "object" || Array.isArray(value))
11
+ return false;
12
+ return (Reflect.ownKeys(value).length === keys.length &&
13
+ keys.every((key) => {
14
+ const field = Object.getOwnPropertyDescriptor(value, key);
15
+ return field?.enumerable === true && Object.hasOwn(field, "value");
16
+ }));
17
+ }
18
+ export function commandWaitValue(value, ancestors = new Set()) {
19
+ if (value === null || typeof value === "string" || typeof value === "boolean")
20
+ return true;
21
+ if (typeof value === "number")
22
+ return Number.isFinite(value);
23
+ if (typeof value !== "object" || ancestors.has(value))
24
+ return false;
25
+ return commandWaitObject(value, ancestors);
26
+ }
27
+ function commandWaitObject(value, ancestors) {
28
+ const prototype = Object.getPrototypeOf(value);
29
+ const expectedPrototype = Object.getPrototypeOf(Array.isArray(value) ? [] : {});
30
+ if (prototype !== expectedPrototype && prototype !== null)
31
+ return false;
32
+ const keys = Array.isArray(value)
33
+ ? Array.from({ length: value.length }, (_, index) => String(index))
34
+ : Object.keys(value);
35
+ const ownKeys = Reflect.ownKeys(value).filter((key) => !Array.isArray(value) || key !== "length");
36
+ if (keys.length !== ownKeys.length)
37
+ return false;
38
+ const seen = new Set([...ancestors, value]);
39
+ return keys.every((key) => {
40
+ const field = Object.getOwnPropertyDescriptor(value, key);
41
+ return (field?.enumerable === true &&
42
+ Object.hasOwn(field, "value") &&
43
+ commandWaitValue(field.value, seen));
44
+ });
45
+ }
@@ -1,9 +1,16 @@
1
+ import { type Configuration } from "./configuration-schema.ts";
1
2
  export interface SettingChange {
2
3
  readonly field: string;
3
4
  readonly action: "set" | "unset";
4
5
  readonly value?: string;
5
6
  readonly scope: "project" | "private";
6
7
  }
8
+ export type HarnessSelection = Required<Pick<NonNullable<Configuration["harness"]>, "name" | "kind" | "path">>;
9
+ export interface HarnessChange {
10
+ readonly harness: HarnessSelection;
11
+ readonly scope: "private";
12
+ }
13
+ export declare function selectedHarnessConfiguration(contents: string | undefined, selection: HarnessSelection): string;
7
14
  export type JsonValue = null | boolean | number | string | readonly JsonValue[] | {
8
15
  readonly [name: string]: JsonValue;
9
16
  };
@@ -1,6 +1,20 @@
1
1
  import { configuration, settingScope, validateSetting, } from "./configuration-schema.js";
2
2
  import { configurationValues, parseConfiguration } from "./project-settings.js";
3
3
  import { record } from "./protocol.js";
4
+ export function selectedHarnessConfiguration(contents, selection) {
5
+ const previous = parseConfiguration(contents, "private");
6
+ const harness = previous.harness;
7
+ const same = harness?.name === selection.name &&
8
+ harness.kind === selection.kind &&
9
+ harness.path === selection.path;
10
+ const next = {
11
+ version: 1,
12
+ ...previous,
13
+ harness: { ...(same ? harness : {}), ...selection },
14
+ };
15
+ configuration(next, "private");
16
+ return JSON.stringify(next, null, 2) + "\n";
17
+ }
4
18
  function isJsonValue(value) {
5
19
  if (value === null || typeof value === "boolean" || typeof value === "string")
6
20
  return true;
@@ -13,6 +13,8 @@ const defaults = {
13
13
  "watch.port": 3663,
14
14
  "watch.actions": "on",
15
15
  "github.command": ["gh"],
16
+ "retention.days": 30,
17
+ "retention.action": "archive",
16
18
  };
17
19
  function effectiveValue(setting) {
18
20
  const { field, value } = setting;
@@ -1,10 +1,18 @@
1
1
  import type { TurnProfiles } from "./turn-profile.ts";
2
2
  import type { TokenPrices } from "./token-prices.ts";
3
+ export interface RedGreenSettings {
4
+ readonly test: readonly string[];
5
+ readonly testFiles: readonly string[];
6
+ readonly prepare?: readonly string[];
7
+ readonly assertionPattern?: string;
8
+ readonly skipPattern?: string;
9
+ }
3
10
  export interface Configuration {
4
11
  readonly version: 1;
5
12
  readonly checks?: {
6
13
  readonly beforeMerge?: readonly string[];
7
14
  readonly required?: readonly string[];
15
+ readonly redGreen?: RedGreenSettings;
8
16
  };
9
17
  readonly tickets?: {
10
18
  readonly command?: readonly string[];
@@ -13,6 +21,7 @@ export interface Configuration {
13
21
  readonly queue?: {
14
22
  readonly everySeconds?: number;
15
23
  readonly lanes?: number;
24
+ readonly dailySpendLimitUsd?: number;
16
25
  };
17
26
  readonly harness?: {
18
27
  readonly name?: string;
@@ -42,6 +51,11 @@ export interface Configuration {
42
51
  readonly workflows?: {
43
52
  readonly folder?: string;
44
53
  };
54
+ readonly retention?: {
55
+ readonly days?: number | null;
56
+ readonly action?: "archive" | "delete";
57
+ readonly archiveFolder?: string | null;
58
+ };
45
59
  }
46
60
  export declare function configuration(value: unknown, scope: "project" | "private"): Configuration;
47
61
  export declare function settingScope(field: string): "project" | "private";
@@ -88,12 +88,16 @@ function validate(value, checked) {
88
88
  scalar(value, checked);
89
89
  if (schema.type === "object")
90
90
  validateObject(value, checked);
91
- if (schema.type !== "array")
92
- return;
91
+ if (schema.type === "array")
92
+ validateArray(value, checked);
93
+ }
94
+ function validateArray(value, { schema, field }) {
93
95
  if (!Array.isArray(value))
94
96
  invalid(field);
95
97
  if (schema.maxItems !== undefined && value.length > schema.maxItems)
96
98
  invalid(field);
99
+ if (schema.minItems !== undefined && value.length < schema.minItems)
100
+ invalid(field);
97
101
  if (schema.items === undefined)
98
102
  return;
99
103
  for (const [index, item] of value.entries())
@@ -0,0 +1,6 @@
1
+ import { type FileHandle } from "node:fs/promises";
2
+ export declare function openedAttachment(place: {
3
+ readonly folder: string;
4
+ readonly name: string;
5
+ }): Promise<FileHandle>;
6
+ export declare function copiedAttachment(handle: FileHandle, copy: string): Promise<void>;
@@ -0,0 +1,86 @@
1
+ import { constants } from "node:fs";
2
+ import { lstat, open, rm } from "node:fs/promises";
3
+ import { dirname, join } from "node:path";
4
+ const maximumBytes = 104_857_600;
5
+ const chunkBytes = 1_048_576;
6
+ const pngSignature = Buffer.from([
7
+ 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a,
8
+ ]);
9
+ const webmSignature = Buffer.from([0x1a, 0x45, 0xdf, 0xa3]);
10
+ const signatures = new Map([
11
+ ["mp4", (head) => head.subarray(4, 8).toString("latin1") === "ftyp"],
12
+ ["webm", (head) => head.subarray(0, 4).equals(webmSignature)],
13
+ ["png", (head) => head.subarray(0, 8).equals(pngSignature)],
14
+ ]);
15
+ function listedStatus(path) {
16
+ return lstat(path).catch(() => undefined);
17
+ }
18
+ async function realFolder(path) {
19
+ const status = await listedStatus(path);
20
+ return (status !== undefined && status.isDirectory() && !status.isSymbolicLink());
21
+ }
22
+ async function realFolders(folder) {
23
+ return (await realFolder(dirname(folder))) && (await realFolder(folder));
24
+ }
25
+ function sameFile(opened, listed) {
26
+ return (listed !== undefined &&
27
+ listed.isFile() &&
28
+ listed.ino === opened.ino &&
29
+ listed.dev === opened.dev);
30
+ }
31
+ async function signed(handle, name) {
32
+ const head = Buffer.alloc(8);
33
+ const { bytesRead } = await handle.read(head, 0, 8, 0);
34
+ const check = signatures.get(name.slice(name.lastIndexOf(".") + 1));
35
+ return bytesRead === 8 && check !== undefined && check(head);
36
+ }
37
+ async function checkedHandle(handle, place) {
38
+ const opened = await handle.stat();
39
+ const listed = await listedStatus(join(place.folder, place.name));
40
+ if (!opened.isFile() || opened.nlink !== 1 || !sameFile(opened, listed))
41
+ throw new Error("attachment-not-available");
42
+ if (!(await realFolders(place.folder)))
43
+ throw new Error("attachment-not-available");
44
+ if (opened.size > maximumBytes)
45
+ throw new Error("attachment-too-large");
46
+ if (!(await signed(handle, place.name)))
47
+ throw new Error("attachment-not-available");
48
+ }
49
+ export async function openedAttachment(place) {
50
+ if (!(await realFolders(place.folder)))
51
+ throw new Error("attachment-not-available");
52
+ const handle = await open(join(place.folder, place.name), constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK).catch(() => undefined);
53
+ if (handle === undefined)
54
+ throw new Error("attachment-not-available");
55
+ try {
56
+ await checkedHandle(handle, place);
57
+ return handle;
58
+ }
59
+ catch (error) {
60
+ await handle.close();
61
+ throw error;
62
+ }
63
+ }
64
+ async function copiedChunks(source, target) {
65
+ const chunk = Buffer.alloc(chunkBytes);
66
+ let position = 0;
67
+ for (;;) {
68
+ const { bytesRead } = await source.read(chunk, 0, chunkBytes, position);
69
+ if (bytesRead === 0)
70
+ return;
71
+ position += bytesRead;
72
+ if (position > maximumBytes)
73
+ throw new Error("attachment-too-large");
74
+ await target.write(chunk, 0, bytesRead);
75
+ }
76
+ }
77
+ export async function copiedAttachment(handle, copy) {
78
+ await rm(copy, { force: true });
79
+ const target = await open(copy, "wx");
80
+ try {
81
+ await copiedChunks(handle, target);
82
+ }
83
+ finally {
84
+ await target.close();
85
+ }
86
+ }
@@ -0,0 +1,14 @@
1
+ export declare function attachmentFolder(place: {
2
+ readonly worktrees: string;
3
+ readonly target: string;
4
+ }): string;
5
+ export declare function attachmentEnvironment(settings: {
6
+ readonly worktrees: string;
7
+ }, start: {
8
+ readonly intent: {
9
+ readonly target: string;
10
+ };
11
+ readonly profile: {
12
+ readonly env?: Readonly<Record<string, string>>;
13
+ };
14
+ }): Promise<Readonly<Record<string, string>>>;
@@ -0,0 +1,17 @@
1
+ import { mkdir } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
+ import { treeName } from "./work-tree.js";
4
+ export function attachmentFolder(place) {
5
+ return join(dirname(place.worktrees), "attachments", treeName(place.target));
6
+ }
7
+ export async function attachmentEnvironment(settings, start) {
8
+ const attachments = attachmentFolder({
9
+ worktrees: settings.worktrees,
10
+ target: start.intent.target,
11
+ });
12
+ await mkdir(attachments, { recursive: true });
13
+ return {
14
+ ...(start.profile.env ?? {}),
15
+ CLOVING_ATTACHMENTS_DIRECTORY: attachments,
16
+ };
17
+ }
@@ -0,0 +1,50 @@
1
+ import type { TurnEnd } from "./claude-turn.ts";
2
+ import { type Located, type WorkerReport } from "./operation-journal.ts";
3
+ import type { WorkTree } from "./work-tree.ts";
4
+ import { type WorkerProfiles } from "./worker-profile.ts";
5
+ import type { AdapterOutcome, DeliveryIntent, ProtectedIntent } from "../broker/actor/delivery-intents.ts";
6
+ export interface TurnResume {
7
+ readonly startedAt: string;
8
+ readonly turnStartCommit: string | null;
9
+ readonly sessionId: string;
10
+ readonly ends: readonly TurnEnd[];
11
+ }
12
+ export declare const resumePrompt = "This turn stopped because the Cloving daemon restarted. Continue the task from the point where it stopped. Run again each command or subagent that did not end. End with the result line that the task asks for.";
13
+ export declare function turnIntent(intent: DeliveryIntent): intent is ProtectedIntent;
14
+ export declare function resumableHarness(harness: unknown): boolean;
15
+ export declare function resumedCommand(request: {
16
+ readonly worker: string | undefined;
17
+ readonly command: readonly string[];
18
+ readonly sessionId: string;
19
+ }): readonly string[] | undefined;
20
+ export declare function recordedField(value: unknown, name: string): unknown;
21
+ export declare function processAlive(processId: unknown): boolean;
22
+ export declare function uncertainProcess(started: unknown): Promise<boolean>;
23
+ export declare function recordedTree(started: unknown): WorkTree | undefined;
24
+ export declare function resumePlan(settings: WorkerProfiles & {
25
+ readonly stopMilliseconds?: number;
26
+ }, request: {
27
+ readonly folder: string;
28
+ readonly started: unknown;
29
+ readonly intent: ProtectedIntent;
30
+ readonly signal: AbortSignal;
31
+ }): Promise<"worktree-index-unknown" | "worktree-index-locked" | "claude-turn-interrupted" | {
32
+ resume: TurnResume;
33
+ tree: WorkTree;
34
+ profile: import("../turn-profile.ts").TurnProfile;
35
+ harness: {
36
+ readonly worker: string;
37
+ readonly command: readonly string[];
38
+ readonly shell?: string;
39
+ readonly output?: "text";
40
+ };
41
+ }>;
42
+ export declare function readResume(folder: string, started: unknown): Promise<TurnResume | undefined>;
43
+ export declare function recordedHarness(journal: string, operationId: string): Promise<string | undefined>;
44
+ export declare function interruptedReply(place: Located, reason: string): Promise<AdapterOutcome>;
45
+ export declare function recoverTurn(operation: {
46
+ readonly intent: ProtectedIntent;
47
+ readonly journal: string;
48
+ readonly report: (report: WorkerReport) => Promise<unknown>;
49
+ readonly signal: AbortSignal;
50
+ }, reconcile: () => Promise<AdapterOutcome>): Promise<void>;