cloving 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (518) hide show
  1. package/README.md +525 -185
  2. package/dist/src/agent-harness-shell.d.ts +12 -0
  3. package/dist/src/agent-harness-shell.js +90 -0
  4. package/dist/src/agent-harness-versions.d.ts +8 -0
  5. package/dist/src/agent-harness-versions.js +49 -0
  6. package/dist/src/agent-harnesses.d.ts +4 -0
  7. package/dist/src/agent-harnesses.js +13 -0
  8. package/dist/src/authority/commands.d.ts +1 -0
  9. package/dist/src/authority/commands.js +24 -4
  10. package/dist/src/authority/gate-reduction.d.ts +1 -0
  11. package/dist/src/authority/gate-reduction.js +18 -3
  12. package/dist/src/authority/gates.d.ts +2 -1
  13. package/dist/src/authority/gates.js +5 -1
  14. package/dist/src/authority/operations.js +1 -1
  15. package/dist/src/authority/reduction.d.ts +1 -1
  16. package/dist/src/authority/reduction.js +6 -1
  17. package/dist/src/authority/status-input.d.ts +1 -1
  18. package/dist/src/authority/status.d.ts +1 -0
  19. package/dist/src/authority/status.js +27 -3
  20. package/dist/src/authority/transitions.d.ts +5 -5
  21. package/dist/src/authority/transitions.js +6 -0
  22. package/dist/src/broker/actor/authority-delivery.js +1 -0
  23. package/dist/src/broker/actor/authority-queries.d.ts +7 -1
  24. package/dist/src/broker/actor/authority-queries.js +17 -2
  25. package/dist/src/broker/actor/authority-receipts.js +11 -1
  26. package/dist/src/broker/actor/authority-session.js +2 -2
  27. package/dist/src/broker/actor/authority-settings.js +4 -0
  28. package/dist/src/broker/actor/delivery-intents.d.ts +2 -1
  29. package/dist/src/broker/actor/delivery-intents.js +4 -4
  30. package/dist/src/broker/actor/effect-delivery.js +4 -1
  31. package/dist/src/broker/actor/effect-queries.d.ts +1 -0
  32. package/dist/src/broker/actor/effect-queries.js +7 -0
  33. package/dist/src/broker/actor/pin-check.js +1 -1
  34. package/dist/src/broker/actor/stop-plan.js +1 -1
  35. package/dist/src/broker/actor/turn-state.js +1 -1
  36. package/dist/src/broker/authority-admission.js +22 -9
  37. package/dist/src/broker/authority-restore.js +1 -0
  38. package/dist/src/broker/decision-restore.js +4 -4
  39. package/dist/src/broker/socket-address.d.ts +3 -1
  40. package/dist/src/broker/socket-address.js +2 -2
  41. package/dist/src/cli/arguments.d.ts +11 -13
  42. package/dist/src/cli/arguments.js +37 -107
  43. package/dist/src/cli/command-effects.d.ts +7 -0
  44. package/dist/src/cli/command-effects.js +39 -0
  45. package/dist/src/cli/commands.js +11 -4
  46. package/dist/src/cli/config-arguments.d.ts +11 -0
  47. package/dist/src/cli/config-arguments.js +59 -0
  48. package/dist/src/cli/config-command.d.ts +2 -0
  49. package/dist/src/cli/config-command.js +105 -0
  50. package/dist/src/cli/config-file.d.ts +3 -0
  51. package/dist/src/cli/config-file.js +50 -0
  52. package/dist/src/cli/config-lock.d.ts +7 -0
  53. package/dist/src/cli/config-lock.js +61 -0
  54. package/dist/src/cli/config-notice.d.ts +5 -0
  55. package/dist/src/cli/config-notice.js +46 -0
  56. package/dist/src/cli/doctor-github.d.ts +9 -0
  57. package/dist/src/cli/doctor-github.js +138 -0
  58. package/dist/src/cli/doctor-harness.d.ts +13 -0
  59. package/dist/src/cli/doctor-harness.js +242 -0
  60. package/dist/src/cli/doctor-local.d.ts +18 -0
  61. package/dist/src/cli/doctor-local.js +77 -0
  62. package/dist/src/cli/doctor-runtime.d.ts +15 -0
  63. package/dist/src/cli/doctor-runtime.js +176 -0
  64. package/dist/src/cli/doctor-service.d.ts +1 -0
  65. package/dist/src/cli/doctor-service.js +11 -0
  66. package/dist/src/cli/doctor-workflows.d.ts +3 -0
  67. package/dist/src/cli/doctor-workflows.js +45 -0
  68. package/dist/src/cli/doctor.d.ts +15 -0
  69. package/dist/src/cli/doctor.js +190 -0
  70. package/dist/src/cli/github-ci-progress.d.ts +8 -0
  71. package/dist/src/cli/github-ci-progress.js +83 -0
  72. package/dist/src/cli/github-retry.d.ts +6 -0
  73. package/dist/src/cli/github-retry.js +47 -0
  74. package/dist/src/cli/harness-probes.d.ts +22 -0
  75. package/dist/src/cli/harness-probes.js +183 -0
  76. package/dist/src/cli/main.d.ts +7 -1
  77. package/dist/src/cli/main.js +39 -61
  78. package/dist/src/cli/phone-arguments.d.ts +14 -0
  79. package/dist/src/cli/phone-arguments.js +37 -0
  80. package/dist/src/cli/phone-client.d.ts +2 -0
  81. package/dist/src/cli/phone-client.js +32 -0
  82. package/dist/src/cli/phone-command.d.ts +13 -0
  83. package/dist/src/cli/phone-command.js +101 -0
  84. package/dist/src/cli/probe-command.d.ts +36 -0
  85. package/dist/src/cli/probe-command.js +59 -0
  86. package/dist/src/cli/project-settings.d.ts +4 -0
  87. package/dist/src/cli/project-settings.js +33 -0
  88. package/dist/src/cli/render.d.ts +2 -1
  89. package/dist/src/cli/render.js +44 -28
  90. package/dist/src/cli/report-github.d.ts +18 -0
  91. package/dist/src/cli/report-github.js +200 -0
  92. package/dist/src/cli/report.d.ts +17 -0
  93. package/dist/src/cli/report.js +192 -0
  94. package/dist/src/cli/repository-arguments.d.ts +5 -0
  95. package/dist/src/cli/repository-arguments.js +34 -0
  96. package/dist/src/cli/runtime-arguments.d.ts +4 -0
  97. package/dist/src/cli/runtime-arguments.js +15 -0
  98. package/dist/src/cli/runtime-directory.d.ts +6 -2
  99. package/dist/src/cli/runtime-directory.js +72 -14
  100. package/dist/src/cli/toolchain.d.ts +2 -0
  101. package/dist/src/cli/toolchain.js +22 -2
  102. package/dist/src/cli/usage-render.d.ts +5 -0
  103. package/dist/src/cli/usage-render.js +40 -1
  104. package/dist/src/cli/usage.d.ts +3 -3
  105. package/dist/src/cli/usage.js +70 -44
  106. package/dist/src/cli/watch-actions.d.ts +2 -0
  107. package/dist/src/cli/watch-actions.js +4 -4
  108. package/dist/src/cli/watch-board-view.d.ts +1 -1
  109. package/dist/src/cli/watch-board-view.js +8 -2
  110. package/dist/src/cli/watch-board.js +23 -10
  111. package/dist/src/cli/watch-card-forms.js +2 -2
  112. package/dist/src/cli/watch-client.d.ts +1 -1
  113. package/dist/src/cli/watch-client.js +7 -2
  114. package/dist/src/cli/watch-header-view.d.ts +27 -0
  115. package/dist/src/cli/watch-header-view.js +116 -0
  116. package/dist/src/cli/watch-model.js +17 -4
  117. package/dist/src/cli/watch-page.js +48 -12
  118. package/dist/src/cli/watch-phone-client.d.ts +1 -0
  119. package/dist/src/cli/watch-phone-client.js +84 -0
  120. package/dist/src/cli/watch-phone-view.d.ts +56 -0
  121. package/dist/src/cli/watch-phone-view.js +113 -0
  122. package/dist/src/cli/watch-phone.d.ts +5 -0
  123. package/dist/src/cli/watch-phone.js +53 -0
  124. package/dist/src/cli/watch-pull-request.d.ts +3 -1
  125. package/dist/src/cli/watch-pull-request.js +4 -0
  126. package/dist/src/cli/watch-render.d.ts +9 -1
  127. package/dist/src/cli/watch-server.js +23 -5
  128. package/dist/src/cli/watch-turn.d.ts +4 -1
  129. package/dist/src/cli/watch-turn.js +37 -1
  130. package/dist/src/cli/watch-usage.js +5 -1
  131. package/dist/src/cli/watch-view.d.ts +6 -20
  132. package/dist/src/cli/watch-view.js +14 -106
  133. package/dist/src/cli.js +106 -23
  134. package/dist/src/command-settings.d.ts +16 -0
  135. package/dist/src/command-settings.js +42 -0
  136. package/dist/src/configuration-change.d.ts +11 -0
  137. package/dist/src/configuration-change.js +62 -0
  138. package/dist/src/configuration-display.d.ts +21 -0
  139. package/dist/src/configuration-display.js +69 -0
  140. package/dist/src/configuration-schema.d.ts +49 -0
  141. package/dist/src/configuration-schema.js +159 -0
  142. package/dist/src/daemon/claude-turn.d.ts +19 -5
  143. package/dist/src/daemon/claude-turn.js +116 -53
  144. package/dist/src/daemon/claude-worker.d.ts +3 -3
  145. package/dist/src/daemon/claude-worker.js +65 -76
  146. package/dist/src/daemon/command-journal.d.ts +5 -0
  147. package/dist/src/daemon/command-journal.js +50 -0
  148. package/dist/src/daemon/command-process.d.ts +28 -0
  149. package/dist/src/daemon/command-process.js +164 -0
  150. package/dist/src/daemon/command-worker.d.ts +19 -0
  151. package/dist/src/daemon/command-worker.js +182 -0
  152. package/dist/src/daemon/cursor-stream.d.ts +4 -0
  153. package/dist/src/daemon/cursor-stream.js +154 -0
  154. package/dist/src/daemon/daemon-adapters.d.ts +58 -0
  155. package/dist/src/daemon/daemon-adapters.js +102 -0
  156. package/dist/src/daemon/daemon-loops.d.ts +14 -0
  157. package/dist/src/daemon/daemon-loops.js +39 -0
  158. package/dist/src/daemon/daemon.d.ts +2 -33
  159. package/dist/src/daemon/daemon.js +126 -132
  160. package/dist/src/daemon/declared-input.d.ts +3 -0
  161. package/dist/src/daemon/declared-input.js +9 -0
  162. package/dist/src/daemon/delivery-router.js +1 -1
  163. package/dist/src/daemon/gemini-stream.d.ts +4 -0
  164. package/dist/src/daemon/gemini-stream.js +129 -0
  165. package/dist/src/daemon/github-ci-rerun.d.ts +26 -0
  166. package/dist/src/daemon/github-ci-rerun.js +92 -0
  167. package/dist/src/daemon/github-ci.js +89 -8
  168. package/dist/src/daemon/github-merge-call.d.ts +2 -0
  169. package/dist/src/daemon/github-merge.js +7 -3
  170. package/dist/src/daemon/github-methods.js +10 -0
  171. package/dist/src/daemon/github-operation.d.ts +1 -0
  172. package/dist/src/daemon/github-retry.js +8 -44
  173. package/dist/src/daemon/issue-queue.d.ts +1 -0
  174. package/dist/src/daemon/issue-queue.js +3 -26
  175. package/dist/src/daemon/notify.js +2 -1
  176. package/dist/src/daemon/opencode-stream.d.ts +5 -0
  177. package/dist/src/daemon/opencode-stream.js +87 -0
  178. package/dist/src/daemon/queue-status.d.ts +4 -0
  179. package/dist/src/daemon/queue-status.js +38 -0
  180. package/dist/src/daemon/retry-worktree.d.ts +18 -0
  181. package/dist/src/daemon/retry-worktree.js +139 -0
  182. package/dist/src/daemon/retrying-turn.d.ts +2 -0
  183. package/dist/src/daemon/retrying-turn.js +108 -30
  184. package/dist/src/daemon/schedule-journal.d.ts +19 -0
  185. package/dist/src/daemon/schedule-journal.js +57 -0
  186. package/dist/src/daemon/text-output.d.ts +18 -0
  187. package/dist/src/daemon/text-output.js +44 -0
  188. package/dist/src/daemon/ticket-registration.d.ts +5 -7
  189. package/dist/src/daemon/ticket-registration.js +85 -40
  190. package/dist/src/daemon/turn-command.d.ts +10 -0
  191. package/dist/src/daemon/turn-command.js +33 -0
  192. package/dist/src/daemon/turn-report.d.ts +18 -0
  193. package/dist/src/daemon/turn-report.js +79 -0
  194. package/dist/src/daemon/work-tree.d.ts +2 -1
  195. package/dist/src/daemon/work-tree.js +15 -12
  196. package/dist/src/daemon/workflow-generations.d.ts +32 -0
  197. package/dist/src/daemon/workflow-generations.js +57 -0
  198. package/dist/src/daemon/workflow-replay.d.ts +16 -0
  199. package/dist/src/daemon/workflow-replay.js +58 -0
  200. package/dist/src/daemon/workflow-schedules.d.ts +27 -0
  201. package/dist/src/daemon/workflow-schedules.js +185 -0
  202. package/dist/src/decision-wait.d.ts +1 -0
  203. package/dist/src/decision-wait.js +3 -0
  204. package/dist/src/delivery-backoff.d.ts +1 -0
  205. package/dist/src/delivery-backoff.js +3 -0
  206. package/dist/src/doctor-report.d.ts +24 -0
  207. package/dist/src/doctor-report.js +70 -0
  208. package/dist/src/execution-pin.d.ts +5 -0
  209. package/dist/src/execution-pin.js +67 -4
  210. package/dist/src/grok-result.d.ts +12 -0
  211. package/dist/src/grok-result.js +61 -0
  212. package/dist/src/harness-defaults.d.ts +35 -0
  213. package/dist/src/harness-defaults.js +121 -0
  214. package/dist/src/host/decision-resume.d.ts +35 -0
  215. package/dist/src/host/decision-resume.js +86 -0
  216. package/dist/src/host/gate-bridge.d.ts +48 -0
  217. package/dist/src/host/gate-bridge.js +124 -0
  218. package/dist/src/host/run-wait.d.ts +26 -0
  219. package/dist/src/host/run-wait.js +37 -0
  220. package/dist/src/host/start-delivery.d.ts +1 -1
  221. package/dist/src/host/start-delivery.js +10 -3
  222. package/dist/src/host/step-bridge-host.d.ts +6 -20
  223. package/dist/src/host/step-bridge-host.js +44 -58
  224. package/dist/src/merge-request.d.ts +19 -0
  225. package/dist/src/merge-request.js +32 -0
  226. package/dist/src/phone/canonical-json.d.ts +1 -0
  227. package/dist/src/phone/canonical-json.js +16 -0
  228. package/dist/src/phone/phone-link.d.ts +7 -0
  229. package/dist/src/phone/phone-link.js +21 -0
  230. package/dist/src/phone/qr-data.d.ts +8 -0
  231. package/dist/src/phone/qr-data.js +133 -0
  232. package/dist/src/phone/qr-matrix.d.ts +6 -0
  233. package/dist/src/phone/qr-matrix.js +175 -0
  234. package/dist/src/phone/qr-penalty.d.ts +3 -0
  235. package/dist/src/phone/qr-penalty.js +67 -0
  236. package/dist/src/phone/qr-picture.d.ts +5 -0
  237. package/dist/src/phone/qr-picture.js +24 -0
  238. package/dist/src/private-config.schema.json +263 -0
  239. package/dist/src/project-config.schema.json +65 -0
  240. package/dist/src/project-settings.d.ts +19 -0
  241. package/dist/src/project-settings.js +131 -0
  242. package/dist/src/relay/answer-check.d.ts +24 -0
  243. package/dist/src/relay/answer-check.js +145 -0
  244. package/dist/src/relay/answer-inbox.d.ts +15 -0
  245. package/dist/src/relay/answer-inbox.js +173 -0
  246. package/dist/src/relay/daemon-keys.d.ts +16 -0
  247. package/dist/src/relay/daemon-keys.js +75 -0
  248. package/dist/src/relay/decision-check.d.ts +3 -0
  249. package/dist/src/relay/decision-check.js +77 -0
  250. package/dist/src/relay/decision-close.d.ts +6 -0
  251. package/dist/src/relay/decision-close.js +72 -0
  252. package/dist/src/relay/decision-envelopes.d.ts +29 -0
  253. package/dist/src/relay/decision-envelopes.js +93 -0
  254. package/dist/src/relay/decision-watch.d.ts +14 -0
  255. package/dist/src/relay/decision-watch.js +68 -0
  256. package/dist/src/relay/envelope-post.d.ts +8 -0
  257. package/dist/src/relay/envelope-post.js +71 -0
  258. package/dist/src/relay/envelope.d.ts +28 -0
  259. package/dist/src/relay/envelope.js +53 -0
  260. package/dist/src/relay/hpke.d.ts +25 -0
  261. package/dist/src/relay/hpke.js +108 -0
  262. package/dist/src/relay/pairing-checks.d.ts +42 -0
  263. package/dist/src/relay/pairing-checks.js +172 -0
  264. package/dist/src/relay/pairing-follow.d.ts +8 -0
  265. package/dist/src/relay/pairing-follow.js +95 -0
  266. package/dist/src/relay/pairing-session.d.ts +29 -0
  267. package/dist/src/relay/pairing-session.js +87 -0
  268. package/dist/src/relay/phone-delivery.d.ts +51 -0
  269. package/dist/src/relay/phone-delivery.js +139 -0
  270. package/dist/src/relay/phone-devices.d.ts +36 -0
  271. package/dist/src/relay/phone-devices.js +46 -0
  272. package/dist/src/relay/phone-inbox.d.ts +18 -0
  273. package/dist/src/relay/phone-inbox.js +17 -0
  274. package/dist/src/relay/phone-operations.d.ts +18 -0
  275. package/dist/src/relay/phone-operations.js +121 -0
  276. package/dist/src/relay/phone-outbox.d.ts +21 -0
  277. package/dist/src/relay/phone-outbox.js +25 -0
  278. package/dist/src/relay/phone-socket.d.ts +6 -0
  279. package/dist/src/relay/phone-socket.js +63 -0
  280. package/dist/src/relay/relay-control.d.ts +7 -0
  281. package/dist/src/relay/relay-control.js +24 -0
  282. package/dist/src/relay/relay-files.d.ts +2 -0
  283. package/dist/src/relay/relay-files.js +23 -0
  284. package/dist/src/relay/relay-heartbeat.d.ts +17 -0
  285. package/dist/src/relay/relay-heartbeat.js +81 -0
  286. package/dist/src/relay/relay-http.d.ts +14 -0
  287. package/dist/src/relay/relay-http.js +63 -0
  288. package/dist/src/relay/relay-registration.d.ts +15 -0
  289. package/dist/src/relay/relay-registration.js +63 -0
  290. package/dist/src/relay/relay-service.d.ts +25 -0
  291. package/dist/src/relay/relay-service.js +216 -0
  292. package/dist/src/relay/relay-store.d.ts +48 -0
  293. package/dist/src/relay/relay-store.js +131 -0
  294. package/dist/src/relay/sealed-post.d.ts +25 -0
  295. package/dist/src/relay/sealed-post.js +52 -0
  296. package/dist/src/relay.d.ts +1 -0
  297. package/dist/src/relay.js +8 -0
  298. package/dist/src/report-statistics.d.ts +50 -0
  299. package/dist/src/report-statistics.js +70 -0
  300. package/dist/src/report.d.ts +171 -0
  301. package/dist/src/report.js +119 -0
  302. package/dist/src/repository-identity.d.ts +4 -0
  303. package/dist/src/repository-identity.js +4 -0
  304. package/dist/src/review-subject.d.ts +41 -0
  305. package/dist/src/review-subject.js +91 -0
  306. package/dist/src/run-wait.d.ts +23 -0
  307. package/dist/src/run-wait.js +20 -0
  308. package/dist/src/service/active-tickets.d.ts +4 -0
  309. package/dist/src/service/active-tickets.js +49 -0
  310. package/dist/src/service/command-effects.d.ts +4 -0
  311. package/dist/src/service/command-effects.js +16 -0
  312. package/dist/src/service/decision-handler.d.ts +4 -0
  313. package/dist/src/service/decision-handler.js +39 -4
  314. package/dist/src/service/gateway.js +18 -3
  315. package/dist/src/service/registry.d.ts +16 -3
  316. package/dist/src/service/registry.js +34 -3
  317. package/dist/src/service/replies.d.ts +9 -1
  318. package/dist/src/service/replies.js +12 -0
  319. package/dist/src/service/run-handlers.js +14 -55
  320. package/dist/src/service/run-metadata.d.ts +8 -0
  321. package/dist/src/service/run-metadata.js +53 -0
  322. package/dist/src/service/run-waits.d.ts +3 -0
  323. package/dist/src/service/run-waits.js +41 -0
  324. package/dist/src/service/service.d.ts +18 -2
  325. package/dist/src/service/service.js +23 -7
  326. package/dist/src/service/submission-handler.d.ts +0 -1
  327. package/dist/src/service/submission-handler.js +6 -34
  328. package/dist/src/service/worker-port.d.ts +1 -0
  329. package/dist/src/service/worker-totals.js +8 -23
  330. package/dist/src/step-bridge.d.ts +23 -0
  331. package/dist/src/steps/decision-gate.d.ts +2 -1
  332. package/dist/src/steps/decision-gate.js +7 -0
  333. package/dist/src/steps/merge-by-person.d.ts +2 -0
  334. package/dist/src/steps/merge-by-person.js +18 -0
  335. package/dist/src/steps/merge-when-green.d.ts +2 -0
  336. package/dist/src/steps/merge-when-green.js +62 -0
  337. package/dist/src/steps/review-by-agent.d.ts +5 -0
  338. package/dist/src/steps/review-by-agent.js +124 -0
  339. package/dist/src/steps/review-by-person.d.ts +4 -0
  340. package/dist/src/steps/review-by-person.js +16 -0
  341. package/dist/src/steps/review-subject.d.ts +2 -0
  342. package/dist/src/steps/review-subject.js +11 -0
  343. package/dist/src/steps/run-command.d.ts +2 -0
  344. package/dist/src/steps/run-command.js +15 -0
  345. package/dist/src/steps/sleep.d.ts +3 -0
  346. package/dist/src/steps/sleep.js +19 -0
  347. package/dist/src/steps/wait-for-decision.d.ts +2 -0
  348. package/dist/src/steps/wait-for-decision.js +71 -0
  349. package/dist/src/steps/wait-for-run.d.ts +5 -0
  350. package/dist/src/steps/wait-for-run.js +9 -0
  351. package/dist/src/storage/decision-snapshots.d.ts +1 -0
  352. package/dist/src/storage/decision-snapshots.js +7 -1
  353. package/dist/src/submission.d.ts +4 -0
  354. package/dist/src/submission.js +6 -2
  355. package/dist/src/testing.d.ts +29 -0
  356. package/dist/src/testing.js +264 -0
  357. package/dist/src/ticket-status-stream.d.ts +9 -0
  358. package/dist/src/ticket-status-stream.js +94 -0
  359. package/dist/src/token-prices.d.ts +12 -4
  360. package/dist/src/token-prices.js +15 -2
  361. package/dist/src/turn-profile.d.ts +1 -0
  362. package/dist/src/turn-profile.js +8 -1
  363. package/dist/src/worker-usage.d.ts +16 -0
  364. package/dist/src/worker-usage.js +57 -0
  365. package/dist/src/workflow-admission.d.ts +5 -0
  366. package/dist/src/workflow-candidate.d.ts +7 -2
  367. package/dist/src/workflow-candidate.js +47 -5
  368. package/dist/src/workflow-declaration.d.ts +21 -3
  369. package/dist/src/workflow-declaration.js +77 -9
  370. package/dist/src/workflow-discovery.d.ts +2 -1
  371. package/dist/src/workflow-discovery.js +4 -1
  372. package/dist/src/workflow-refusals.js +3 -0
  373. package/dist/src/workflow-schedule.d.ts +22 -0
  374. package/dist/src/workflow-schedule.js +53 -0
  375. package/dist/src/workflows.d.ts +11 -1
  376. package/dist/src/workflows.js +8 -0
  377. package/dist/tools/admit-workflow.d.ts +1 -0
  378. package/dist/tools/admit-workflow.js +18 -5
  379. package/dist/tools/doctor-adoption.d.ts +1 -0
  380. package/dist/tools/doctor-adoption.js +11 -0
  381. package/dist/tools/project-configuration.d.ts +4 -0
  382. package/dist/tools/project-configuration.js +47 -0
  383. package/dist/tools/self-host-processes.d.ts +1 -0
  384. package/dist/tools/self-host-processes.js +33 -22
  385. package/dist/tools/self-host-project.d.ts +4 -0
  386. package/dist/tools/self-host-project.js +61 -14
  387. package/dist/tools/self-host-runtime.d.ts +16 -0
  388. package/dist/tools/self-host-runtime.js +60 -0
  389. package/dist/tools/self-host-workflows.d.ts +1 -0
  390. package/dist/tools/self-host-workflows.js +36 -1
  391. package/dist/tools/self-host.js +86 -61
  392. package/dist/tools/workflow-candidate-counts.d.ts +6 -2
  393. package/dist/tools/workflow-candidate-counts.js +31 -16
  394. package/dist/tools/workflow-candidate-fields.d.ts +5 -0
  395. package/dist/tools/workflow-candidate-fields.js +24 -0
  396. package/dist/tools/workflow-candidate-helper-counts.d.ts +10 -0
  397. package/dist/tools/workflow-candidate-helper-counts.js +129 -0
  398. package/dist/tools/workflow-candidate-program.d.ts +2 -0
  399. package/dist/tools/workflow-candidate-program.js +36 -8
  400. package/dist/tools/workflow-candidate-source.js +77 -15
  401. package/dist/tools/workflow-candidate-syntax.d.ts +8 -2
  402. package/dist/tools/workflow-candidate-syntax.js +70 -26
  403. package/dist/tools/workflow-command.d.ts +1 -0
  404. package/dist/tools/workflow-command.js +143 -0
  405. package/dist/tools/workflow-folder-capture.d.ts +1 -0
  406. package/dist/tools/workflow-folder-capture.js +47 -2
  407. package/dist/tools/workflow-folders.d.ts +17 -1
  408. package/dist/tools/workflow-folders.js +59 -6
  409. package/dist/tools/workflow-test-hook.d.ts +7 -0
  410. package/dist/tools/workflow-test-hook.js +16 -0
  411. package/dist/tools/workflow-test-loader.d.ts +1 -0
  412. package/dist/tools/workflow-test-loader.js +10 -0
  413. package/dist/workflows/develop-ticket.js +1 -1
  414. package/dist/workflows/ticket-prompts.js +5 -1
  415. package/package.json +46 -4
  416. package/templates/develop/README.md +78 -0
  417. package/templates/develop/develop/accept.ts +11 -0
  418. package/templates/develop/develop/flow-tests.ts +357 -0
  419. package/templates/develop/develop/local.ts +40 -0
  420. package/templates/develop/develop/option-tests.ts +174 -0
  421. package/templates/develop/develop/partial-choice.ts +29 -0
  422. package/templates/develop/develop/partial.ts +28 -0
  423. package/templates/develop/develop/pull.ts +152 -0
  424. package/templates/develop/develop/queue-partial.ts +39 -0
  425. package/templates/develop/develop/refusal-tests.ts +174 -0
  426. package/templates/develop/develop/report.ts +156 -0
  427. package/templates/develop/develop/round.ts +40 -0
  428. package/templates/develop/develop/scenarios.ts +87 -0
  429. package/templates/develop/develop/turn.ts +67 -0
  430. package/templates/develop/develop.declaration.json +24 -0
  431. package/templates/develop/develop.test.ts +287 -0
  432. package/templates/develop/develop.ts +30 -0
  433. package/templates/develop/template.json +153 -0
  434. package/dist/src/chats/analysis-batches.d.ts +0 -42
  435. package/dist/src/chats/analysis-batches.js +0 -97
  436. package/dist/src/chats/analysis-checkpoint.d.ts +0 -29
  437. package/dist/src/chats/analysis-checkpoint.js +0 -31
  438. package/dist/src/chats/analysis-contract.d.ts +0 -80
  439. package/dist/src/chats/analysis-contract.js +0 -16
  440. package/dist/src/chats/analysis-data.d.ts +0 -3
  441. package/dist/src/chats/analysis-data.js +0 -85
  442. package/dist/src/chats/analysis-input.d.ts +0 -18
  443. package/dist/src/chats/analysis-input.js +0 -97
  444. package/dist/src/chats/analysis-links.d.ts +0 -2
  445. package/dist/src/chats/analysis-links.js +0 -25
  446. package/dist/src/chats/analysis-merge.d.ts +0 -16
  447. package/dist/src/chats/analysis-merge.js +0 -134
  448. package/dist/src/chats/analysis-prompt.d.ts +0 -18
  449. package/dist/src/chats/analysis-prompt.js +0 -42
  450. package/dist/src/chats/analysis-proposal.d.ts +0 -4
  451. package/dist/src/chats/analysis-proposal.js +0 -41
  452. package/dist/src/chats/analysis-provenance.d.ts +0 -4
  453. package/dist/src/chats/analysis-provenance.js +0 -99
  454. package/dist/src/chats/analysis-shape.d.ts +0 -4
  455. package/dist/src/chats/analysis-shape.js +0 -235
  456. package/dist/src/chats/analysis.d.ts +0 -3
  457. package/dist/src/chats/analysis.js +0 -42
  458. package/dist/src/chats/corpus-input.d.ts +0 -5
  459. package/dist/src/chats/corpus-input.js +0 -288
  460. package/dist/src/chats/destination.d.ts +0 -4
  461. package/dist/src/chats/destination.js +0 -96
  462. package/dist/src/chats/import.d.ts +0 -15
  463. package/dist/src/chats/import.js +0 -243
  464. package/dist/src/chats/input-file.d.ts +0 -3
  465. package/dist/src/chats/input-file.js +0 -32
  466. package/dist/src/chats/normalize.d.ts +0 -29
  467. package/dist/src/chats/normalize.js +0 -155
  468. package/dist/src/chats/previous-import.d.ts +0 -5
  469. package/dist/src/chats/previous-import.js +0 -34
  470. package/dist/src/chats/reader.d.ts +0 -21
  471. package/dist/src/chats/reader.js +0 -118
  472. package/dist/src/chats/redact-import.d.ts +0 -14
  473. package/dist/src/chats/redact-import.js +0 -141
  474. package/dist/src/chats/redaction.d.ts +0 -41
  475. package/dist/src/chats/redaction.js +0 -161
  476. package/dist/src/chats/reference-mapping.d.ts +0 -16
  477. package/dist/src/chats/reference-mapping.js +0 -153
  478. package/dist/src/chats/revision-input.d.ts +0 -3
  479. package/dist/src/chats/revision-input.js +0 -180
  480. package/dist/src/chats/revision.d.ts +0 -48
  481. package/dist/src/chats/revision.js +0 -94
  482. package/dist/src/chats/selection.d.ts +0 -25
  483. package/dist/src/chats/selection.js +0 -109
  484. package/dist/src/chats/source.d.ts +0 -23
  485. package/dist/src/chats/source.js +0 -135
  486. package/dist/src/chats/structure.d.ts +0 -57
  487. package/dist/src/chats/structure.js +0 -216
  488. package/dist/src/chats/workflow-generation-projection.d.ts +0 -8
  489. package/dist/src/chats/workflow-generation-projection.js +0 -75
  490. package/dist/src/chats/workflow-generation-source.d.ts +0 -25
  491. package/dist/src/chats/workflow-generation-source.js +0 -124
  492. package/dist/src/chats/workflow-generation-text.d.ts +0 -23
  493. package/dist/src/chats/workflow-generation-text.js +0 -74
  494. package/dist/src/chats/workflow-generation.d.ts +0 -69
  495. package/dist/src/chats/workflow-generation.js +0 -142
  496. package/dist/src/daemon/analysis-launch.d.ts +0 -5
  497. package/dist/src/daemon/analysis-launch.js +0 -81
  498. package/dist/src/daemon/analysis-token.d.ts +0 -6
  499. package/dist/src/daemon/analysis-token.js +0 -88
  500. package/dist/src/daemon/analysis-worker.d.ts +0 -20
  501. package/dist/src/daemon/analysis-worker.js +0 -271
  502. package/dist/src/daemon/chats-batch-binding.d.ts +0 -23
  503. package/dist/src/daemon/chats-batch-binding.js +0 -99
  504. package/dist/src/daemon/chats-capture.d.ts +0 -18
  505. package/dist/src/daemon/chats-capture.js +0 -194
  506. package/dist/src/daemon/chats-checkpoints.d.ts +0 -41
  507. package/dist/src/daemon/chats-checkpoints.js +0 -186
  508. package/dist/src/daemon/chats-files.d.ts +0 -42
  509. package/dist/src/daemon/chats-files.js +0 -252
  510. package/dist/src/daemon/chats-follow-up.d.ts +0 -38
  511. package/dist/src/daemon/chats-follow-up.js +0 -180
  512. package/dist/src/daemon/chats-question.d.ts +0 -15
  513. package/dist/src/daemon/chats-question.js +0 -93
  514. package/dist/src/daemon/chats-worker.d.ts +0 -13
  515. package/dist/src/daemon/chats-worker.js +0 -201
  516. package/dist/workflows/analyze-chats.d.ts +0 -15
  517. package/dist/workflows/analyze-chats.declaration.json +0 -22
  518. package/dist/workflows/analyze-chats.js +0 -250
@@ -0,0 +1,200 @@
1
+ export async function readReportGithub(input) {
2
+ const reader = await repositoryReader(input).catch(() => null);
3
+ if (reader === null)
4
+ return {
5
+ observedSince: null,
6
+ issues: null,
7
+ pulls: null,
8
+ sources: {
9
+ issues: { status: "unavailable", reason: "configuration-or-identity" },
10
+ pulls: { status: "unavailable", reason: "configuration-or-identity" },
11
+ history: { status: "unavailable", reason: "configuration-or-identity" },
12
+ },
13
+ };
14
+ const [issues, pulls, history] = await Promise.allSettled([
15
+ issuesOf(reader, input.since),
16
+ pullsOf(reader, input.since),
17
+ repositoryCreatedAt(reader),
18
+ ]);
19
+ return {
20
+ observedSince: history.status === "fulfilled" ? history.value : null,
21
+ issues: issues.status === "fulfilled" ? issues.value : null,
22
+ pulls: pulls.status === "fulfilled" ? pulls.value : null,
23
+ sources: {
24
+ issues: source(issues),
25
+ pulls: source(pulls),
26
+ history: source(history),
27
+ },
28
+ };
29
+ }
30
+ import { record } from "../protocol.js";
31
+ import { githubRetry } from "./github-retry.js";
32
+ import { prRepository } from "./watch-pr-identity.js";
33
+ function commandOf(value) {
34
+ const command = JSON.parse(value ?? '["gh"]');
35
+ if (!Array.isArray(command) ||
36
+ command.length === 0 ||
37
+ !command.every((part) => typeof part === "string" && part !== "" && !part.includes("\0")))
38
+ throw new Error("configuration");
39
+ return command.map(String);
40
+ }
41
+ function rows(value) {
42
+ if (!Array.isArray(value))
43
+ throw new Error("response");
44
+ return value.map((item) => {
45
+ const row = record(item);
46
+ if (row === undefined)
47
+ throw new Error("response");
48
+ return row;
49
+ });
50
+ }
51
+ function identity(row, context) {
52
+ const { repository, kind } = context;
53
+ const number = row["number"];
54
+ const url = row["html_url"];
55
+ if (typeof number !== "number" ||
56
+ !Number.isSafeInteger(number) ||
57
+ number <= 0 ||
58
+ typeof url !== "string" ||
59
+ url.toLowerCase() !==
60
+ `https://${repository.host}/${repository.owner}/${repository.repository}/${kind}/${String(number)}`)
61
+ throw new Error("identity");
62
+ return number;
63
+ }
64
+ function timestamp(value) {
65
+ if (typeof value !== "string" || !Number.isFinite(Date.parse(value)))
66
+ throw new Error("response");
67
+ return Date.parse(value);
68
+ }
69
+ async function issuesOf(reader, since) {
70
+ const result = [];
71
+ const seen = new Set();
72
+ for (let page = 1;; page += 1) {
73
+ const values = rows(await reader.read(`issues?state=closed&since=${encodeURIComponent(since)}&per_page=100&page=${String(page)}`, [
74
+ "--jq",
75
+ 'map({number, html_url, closed_at, state, state_reason} + (if has("pull_request") then {pull_request: {}} else {} end))',
76
+ ]));
77
+ for (const row of values) {
78
+ if (Object.hasOwn(row, "pull_request"))
79
+ continue;
80
+ const number = identity(row, {
81
+ repository: reader.repository,
82
+ kind: "issues",
83
+ });
84
+ if (seen.has(number))
85
+ throw new Error("response");
86
+ seen.add(number);
87
+ if (!completedIssue(row))
88
+ continue;
89
+ result.push({
90
+ at: timestamp(row["closed_at"]),
91
+ value: 1,
92
+ evidence: { issue: number },
93
+ });
94
+ }
95
+ if (values.length < 100)
96
+ return result;
97
+ }
98
+ }
99
+ async function pullsOf(reader, since) {
100
+ const result = [];
101
+ const seen = new Set();
102
+ for (let page = 1;; page += 1) {
103
+ const values = rows(await reader.read(`pulls?state=closed&sort=updated&direction=desc&per_page=100&page=${String(page)}`));
104
+ for (const row of values) {
105
+ const number = identity(row, {
106
+ repository: reader.repository,
107
+ kind: "pull",
108
+ });
109
+ if (seen.has(number))
110
+ throw new Error("response");
111
+ seen.add(number);
112
+ timestamp(row["updated_at"]);
113
+ if (row["merged_at"] === null)
114
+ continue;
115
+ result.push({
116
+ at: timestamp(row["merged_at"]),
117
+ value: 1,
118
+ evidence: { pullRequest: number },
119
+ });
120
+ }
121
+ if (values.length < 100 ||
122
+ values.some((row) => Date.parse(String(row["updated_at"])) < Date.parse(since)))
123
+ return result;
124
+ }
125
+ }
126
+ async function repositoryReader(input) {
127
+ const settings = input.settings;
128
+ if (settings?.repository === undefined)
129
+ throw new Error("configuration");
130
+ const command = commandOf(settings.githubCommand);
131
+ const signal = AbortSignal.timeout(120_000);
132
+ const origin = await settings.execute({
133
+ command: ["git", "config", "--local", "--get-all", "remote.origin.url"],
134
+ directory: settings.repository,
135
+ signal,
136
+ });
137
+ const repository = origin.status === 0 && origin.errorCode === null
138
+ ? prRepository(origin.stdout)
139
+ : null;
140
+ if (repository === null)
141
+ throw new Error("identity");
142
+ const directory = settings.repository;
143
+ return {
144
+ repository,
145
+ read: async (endpoint, flags = []) => {
146
+ const output = await githubRetry({
147
+ signal,
148
+ pollMilliseconds: input.retryMilliseconds ?? 30_000,
149
+ action: async () => {
150
+ const output = await settings.execute({
151
+ directory,
152
+ signal,
153
+ command: [
154
+ ...command,
155
+ "api",
156
+ "--method",
157
+ "GET",
158
+ "--hostname",
159
+ repository.host,
160
+ `repos/${repository.owner}/${repository.repository}${endpoint === "" ? "" : `/${endpoint}`}`,
161
+ ...flags,
162
+ ],
163
+ });
164
+ if (output.status !== 0 || output.errorCode !== null)
165
+ throw Object.assign(new Error("github-call-failed"), {
166
+ status: Number(/\(HTTP (\d{3})\)/.exec(output.stderr)?.[1]),
167
+ detail: output.stderr,
168
+ });
169
+ return output.stdout;
170
+ },
171
+ });
172
+ const parsed = JSON.parse(output);
173
+ return parsed;
174
+ },
175
+ };
176
+ }
177
+ function source(result) {
178
+ if (result.status === "fulfilled")
179
+ return { status: "available" };
180
+ const reason = result.reason instanceof Error &&
181
+ result.reason.message === "github-network-failed"
182
+ ? "github-network-failed"
183
+ : "read-failed";
184
+ return { status: "unavailable", reason };
185
+ }
186
+ async function repositoryCreatedAt(reader) {
187
+ const repository = record(await reader.read(""));
188
+ const name = repository?.["full_name"];
189
+ if (typeof name !== "string" ||
190
+ name.toLowerCase() !==
191
+ `${reader.repository.owner}/${reader.repository.repository}`)
192
+ throw new Error("identity");
193
+ return timestamp(repository?.["created_at"]);
194
+ }
195
+ function completedIssue(row) {
196
+ if (row["state"] !== "closed" ||
197
+ !["completed", "not_planned", "duplicate"].includes(String(row["state_reason"])))
198
+ throw new Error("response");
199
+ return row["state_reason"] === "completed";
200
+ }
@@ -0,0 +1,17 @@
1
+ import { type Fields } from "../protocol.ts";
2
+ import { type ReportCompletion } from "../report.ts";
3
+ import type { WatchPrSettings } from "./watch-pr-settings.ts";
4
+ interface ReportEnvironment {
5
+ readonly runtimeDirectory: string;
6
+ readonly workingDirectory: string;
7
+ readonly watchPr?: WatchPrSettings;
8
+ readonly terminal: {
9
+ readonly out: (text: string) => void;
10
+ };
11
+ }
12
+ export declare function reportCommand(invocation: {
13
+ readonly since: number;
14
+ readonly json: boolean;
15
+ }, environment: ReportEnvironment): Promise<number>;
16
+ export declare function reportCompletion(event: Fields): ReportCompletion | null;
17
+ export {};
@@ -0,0 +1,192 @@
1
+ import { record } from "../protocol.js";
2
+ import { loopReport, } from "../report.js";
3
+ import { send } from "./client.js";
4
+ import { readReportGithub } from "./report-github.js";
5
+ function reportRecord(value, after) {
6
+ const event = record(value) ?? {};
7
+ const sequence = event["sequence"];
8
+ const at = event["recordedAt"];
9
+ if (typeof sequence !== "number" ||
10
+ !Number.isSafeInteger(sequence) ||
11
+ sequence <= after ||
12
+ typeof at !== "string" ||
13
+ !Number.isFinite(Date.parse(at)))
14
+ throw new Error("invalid-report-cursor");
15
+ return { event, sequence, at: Date.parse(at) };
16
+ }
17
+ function appendEvents(snapshot, values) {
18
+ for (const value of values) {
19
+ const parsed = reportRecord(value, snapshot.after);
20
+ if (snapshot.latest !== null && parsed.sequence > snapshot.latest)
21
+ break;
22
+ snapshot.after = parsed.sequence;
23
+ if (snapshot.observedSince === null || parsed.at < snapshot.observedSince)
24
+ snapshot.observedSince = parsed.at;
25
+ const completion = reportCompletion(parsed.event);
26
+ if (completion === null)
27
+ continue;
28
+ if (snapshot.completions.has(completion.runId))
29
+ throw new Error("duplicate-report-completion");
30
+ snapshot.completions.set(completion.runId, completion);
31
+ }
32
+ }
33
+ async function daemonReport(runtime) {
34
+ const snapshot = {
35
+ after: 0,
36
+ latest: null,
37
+ observedSince: null,
38
+ completions: new Map(),
39
+ };
40
+ for (;;) {
41
+ const reply = await send(runtime, {
42
+ operation: "events",
43
+ parameters: { after: snapshot.after, limit: 1000 },
44
+ });
45
+ if (reply.kind === "error")
46
+ throw new Error(reply.error.code);
47
+ const latest = reply.result["latestSequence"];
48
+ if (typeof latest !== "number" ||
49
+ !Number.isSafeInteger(latest) ||
50
+ latest < snapshot.after)
51
+ throw new Error("invalid-report-snapshot");
52
+ snapshot.latest ??= latest;
53
+ const events = reply.result["events"];
54
+ if (!Array.isArray(events))
55
+ throw new Error("invalid-report-events");
56
+ appendEvents(snapshot, events);
57
+ if (snapshot.after >= snapshot.latest)
58
+ return {
59
+ completions: [...snapshot.completions.values()],
60
+ observedSince: snapshot.observedSince,
61
+ };
62
+ if (events.length < 1000)
63
+ throw new Error("incomplete-report-snapshot");
64
+ }
65
+ }
66
+ function settledSpending(run) {
67
+ const condition = run["condition"];
68
+ const effects = run["effects"];
69
+ return (["completed", "failed", "cancelled"].includes(String(condition)) &&
70
+ Array.isArray(effects) &&
71
+ effects.every((value) => ["completed", "failed", "stopped", "cancelled", "refused"].includes(String(record(value)?.["state"]))));
72
+ }
73
+ async function runCost(runtime, runId) {
74
+ const reply = await send(runtime, {
75
+ operation: "status",
76
+ parameters: { runId },
77
+ });
78
+ if (reply.kind === "error")
79
+ return { runId, turns: null };
80
+ const run = record(reply.result["run"]);
81
+ const turns = run?.["workerTurns"];
82
+ if (run?.["runId"] !== runId ||
83
+ !Array.isArray(turns) ||
84
+ !settledSpending(run))
85
+ return { runId, turns: null };
86
+ const parsed = turns.map((value) => {
87
+ const turn = record(value);
88
+ const operationId = turn?.["operationId"];
89
+ const costUsd = turn?.["costUsd"];
90
+ return typeof operationId === "string" &&
91
+ (costUsd === null ||
92
+ (typeof costUsd === "number" &&
93
+ Number.isFinite(costUsd) &&
94
+ costUsd >= 0))
95
+ ? { operationId, costUsd }
96
+ : null;
97
+ });
98
+ return {
99
+ runId,
100
+ turns: parsed.some((turn) => turn === null)
101
+ ? null
102
+ : parsed.filter((turn) => turn !== null),
103
+ };
104
+ }
105
+ function textReport(report) {
106
+ const lines = [`Loop report ${JSON.stringify(report["window"])}`];
107
+ for (const [name, value] of Object.entries(record(report["metrics"]) ?? {})) {
108
+ const metric = record(value) ?? {};
109
+ lines.push(`${name}: ${metric["status"] === "unavailable" ? "unavailable" : String(metric["value"])}`);
110
+ const baseline = record(metric["baseline"]) ?? {};
111
+ lines.push(` history: ${String(baseline["history"])}; median: ${String(baseline["median"])}; band: ${JSON.stringify(baseline["band"])}${metric["mark"] === "outside" ? "; outside" : ""}`);
112
+ lines.push(` comparison value: ${String(metric["comparisonValue"])}`);
113
+ lines.push(` evidence: ${JSON.stringify(metric["evidence"])}`);
114
+ lines.push(` baseline evidence: ${JSON.stringify(baseline["evidence"])}`);
115
+ }
116
+ lines.push(`Run costs (USD): ${JSON.stringify(report["runCosts"])}`);
117
+ lines.push(`Sources: ${JSON.stringify(report["sources"])}`);
118
+ lines.push(`Coverage: ${JSON.stringify(report["coverage"])}`);
119
+ return lines.join("\n") + "\n";
120
+ }
121
+ export async function reportCommand(invocation, environment) {
122
+ const now = Date.now();
123
+ const since = new Date(now - (invocation.since + 168) * 3_600_000).toISOString();
124
+ const settings = environment.watchPr === undefined ? {} : { settings: environment.watchPr };
125
+ const [daemonRead, githubRead] = await Promise.allSettled([
126
+ daemonReport(environment.runtimeDirectory),
127
+ readReportGithub({ since, ...settings }),
128
+ ]);
129
+ const daemon = daemonRead.status === "fulfilled"
130
+ ? daemonRead.value
131
+ : { completions: null, observedSince: null };
132
+ const github = githubRead.status === "fulfilled" ? { github: githubRead.value } : {};
133
+ const costs = [];
134
+ for (const event of daemon.completions ?? [])
135
+ if (event.at >= now - (invocation.since + 168) * 3_600_000 &&
136
+ event.at < now)
137
+ costs.push(await runCost(environment.runtimeDirectory, event.runId));
138
+ const calculated = loopReport({
139
+ since: invocation.since,
140
+ now,
141
+ ...daemon,
142
+ costs,
143
+ ...github,
144
+ });
145
+ const report = {
146
+ ...calculated,
147
+ window: {
148
+ ...calculated.window,
149
+ start: new Date(calculated.window.start).toISOString(),
150
+ end: new Date(now).toISOString(),
151
+ },
152
+ runCosts: calculated.runCosts.map((cost) => ({
153
+ ...cost,
154
+ completedAt: new Date(cost.completedAt).toISOString(),
155
+ })),
156
+ };
157
+ environment.terminal.out(invocation.json ? `${JSON.stringify(report)}\n` : textReport(report));
158
+ return 0;
159
+ }
160
+ function outcomeOf(event) {
161
+ if (event["type"] === "run.failed")
162
+ return "failed";
163
+ if (event["type"] === "run.cancelled")
164
+ return "cancelled";
165
+ if (event["type"] !== "run.completed")
166
+ return null;
167
+ const payload = record(event["payload"]) ?? {};
168
+ if (payload["outcome"] === "handoff_requested" &&
169
+ payload["ticketStatus"] === "partial")
170
+ return "partial";
171
+ const outcome = payload["outcome"];
172
+ if (outcome === undefined || outcome === "handoff_requested")
173
+ return "completed";
174
+ return outcome === "blocked" ? "blocked" : null;
175
+ }
176
+ export function reportCompletion(event) {
177
+ const terminal = ["run.completed", "run.failed", "run.cancelled"].includes(String(event["type"]));
178
+ if (!terminal)
179
+ return null;
180
+ const outcome = outcomeOf(event);
181
+ if (outcome === null)
182
+ throw new Error("invalid-report-event");
183
+ const runId = event["runId"];
184
+ const sequence = event["sequence"];
185
+ const at = event["recordedAt"];
186
+ if (typeof runId !== "string" ||
187
+ typeof sequence !== "number" ||
188
+ typeof at !== "string" ||
189
+ !Number.isFinite(Date.parse(at)))
190
+ throw new Error("invalid-report-event");
191
+ return { runId, sequence, at: Date.parse(at), outcome };
192
+ }
@@ -0,0 +1,5 @@
1
+ import { type ParseArgsConfig } from "node:util";
2
+ export declare function repositoryArguments(argumentsList: readonly string[], options: NonNullable<ParseArgsConfig["options"]>): {
3
+ readonly argumentsList: readonly string[];
4
+ readonly repository: string | undefined;
5
+ } | string;
@@ -0,0 +1,34 @@
1
+ import { parseArgs } from "node:util";
2
+ export function repositoryArguments(argumentsList, options) {
3
+ if (!argumentsList.some((argument) => argument === "--repository" || argument.startsWith("--repository=")))
4
+ return { argumentsList, repository: undefined };
5
+ try {
6
+ const parsed = parseArgs({
7
+ args: [...argumentsList],
8
+ options: {
9
+ ...options,
10
+ repository: { type: "string" },
11
+ },
12
+ tokens: true,
13
+ allowPositionals: true,
14
+ strict: false,
15
+ });
16
+ const selectors = parsed.tokens.filter((token) => token.kind === "option" && token.name === "repository");
17
+ if (selectors.length > 1)
18
+ return "repeated-option";
19
+ const removed = new Set(selectors.flatMap((token) => token.kind === "option" && !token.inlineValue
20
+ ? [token.index, token.index + 1]
21
+ : [token.index]));
22
+ const repository = parsed.values["repository"];
23
+ if (selectors.length > 0 &&
24
+ (typeof repository !== "string" || repository === ""))
25
+ return "missing-value";
26
+ return {
27
+ argumentsList: argumentsList.filter((_, index) => !removed.has(index)),
28
+ repository: typeof repository === "string" ? repository : undefined,
29
+ };
30
+ }
31
+ catch {
32
+ return "missing-value";
33
+ }
34
+ }
@@ -11,6 +11,10 @@ export type RunSource = {
11
11
  type DecisionCommand = "answer" | "approve" | "deny";
12
12
  type RunCommand = "pause" | "resume" | "drop";
13
13
  export type RuntimeInvocation = {
14
+ readonly kind: "report";
15
+ readonly since: number;
16
+ readonly json: boolean;
17
+ } | {
14
18
  readonly kind: "command-help";
15
19
  readonly command: string;
16
20
  } | {
@@ -51,6 +51,15 @@ const shapes = new Map([
51
51
  build: events,
52
52
  },
53
53
  ],
54
+ [
55
+ "report",
56
+ {
57
+ subject: "none",
58
+ required: [],
59
+ allowed: () => ["since", "json"],
60
+ build: report,
61
+ },
62
+ ],
54
63
  [
55
64
  "watch",
56
65
  {
@@ -246,3 +255,9 @@ function events(request) {
246
255
  const json = given(request, "json");
247
256
  return { kind: "events", runId, after: after ?? 0, limit, follow, json };
248
257
  }
258
+ function report(request) {
259
+ const since = whole(valueOf(request, "since"), { minimum: 1, maximum: 168 });
260
+ if (since === invalid)
261
+ return "invalid-option-value";
262
+ return { kind: "report", since: since ?? 24, json: given(request, "json") };
263
+ }
@@ -1,4 +1,8 @@
1
1
  type Environment = Readonly<Record<string, string | undefined>>;
2
- export declare function clientCommand(environment: Environment): string;
3
- export declare function runtimeDirectory(environment: Environment): string | undefined;
2
+ export declare function shellArgument(value: string): string;
3
+ export declare function clientCommand(environment: Environment, repository?: string): string;
4
+ export declare function repositoryRuntimeName(repository: string): string;
5
+ export declare function adoptionRecordPath(environment: Environment, repository: string): string | undefined;
6
+ export declare function legacyRuntimeDirectory(environment: Environment): string | undefined;
7
+ export declare function runtimeDirectory(environment: Environment, repository?: string): string | undefined;
4
8
  export {};
@@ -1,25 +1,83 @@
1
- import { join } from "node:path";
1
+ import { repositoryFileName } from "../repository-identity.js";
2
+ import { createHash } from "node:crypto";
3
+ import { readFileSync, realpathSync } from "node:fs";
4
+ import { basename, isAbsolute, join } from "node:path";
5
+ import { record } from "../protocol.js";
2
6
  function given(value) {
3
7
  return value !== undefined && value.length > 0;
4
8
  }
5
- export function clientCommand(environment) {
9
+ export function shellArgument(value) {
10
+ return /^[A-Za-z0-9_./-]+$/.test(value)
11
+ ? value
12
+ : `'${value.replaceAll("'", "'\\''")}'`;
13
+ }
14
+ export function clientCommand(environment, repository) {
6
15
  const explicit = environment["CLOVING_RUNTIME_DIR"];
7
16
  return given(explicit)
8
- ? `CLOVING_RUNTIME_DIR=${explicit} cloving`
9
- : "cloving";
17
+ ? `CLOVING_RUNTIME_DIR=${shellArgument(explicit)} cloving`
18
+ : `cloving${repository === undefined ? "" : ` --repository ${shellArgument(repository)}`}`;
19
+ }
20
+ function stateRoot(environment) {
21
+ const state = environment["XDG_STATE_HOME"];
22
+ if (given(state))
23
+ return state;
24
+ const home = environment["HOME"];
25
+ return given(home) ? join(home, ".local", "state") : undefined;
26
+ }
27
+ export function repositoryRuntimeName(repository) {
28
+ const canonical = realpathSync(repository);
29
+ return repositoryFileName({
30
+ name: basename(canonical),
31
+ sha256: createHash("sha256").update(canonical).digest("hex"),
32
+ });
33
+ }
34
+ export function adoptionRecordPath(environment, repository) {
35
+ const state = stateRoot(environment);
36
+ return state === undefined
37
+ ? undefined
38
+ : join(state, "cloving", "adopted-runtime", `${repositoryRuntimeName(repository)}.json`);
39
+ }
40
+ export function legacyRuntimeDirectory(environment) {
41
+ const runtime = environment["XDG_RUNTIME_DIR"];
42
+ if (given(runtime))
43
+ return join(runtime, "cloving");
44
+ const state = stateRoot(environment);
45
+ return state === undefined ? undefined : join(state, "cloving", "run");
46
+ }
47
+ function adoptedRuntime(environment, repository) {
48
+ const path = adoptionRecordPath(environment, repository);
49
+ if (path === undefined)
50
+ return undefined;
51
+ try {
52
+ return runtimeRecord(path, repository);
53
+ }
54
+ catch (error) {
55
+ if (error instanceof Error && "code" in error && error.code === "ENOENT")
56
+ return undefined;
57
+ throw error;
58
+ }
10
59
  }
11
- export function runtimeDirectory(environment) {
60
+ function runtimeRecord(path, repository) {
61
+ const value = record(JSON.parse(readFileSync(path, "utf8")));
62
+ if (value?.["schemaVersion"] === 1 &&
63
+ value["repository"] === realpathSync(repository) &&
64
+ typeof value["runtimeDirectory"] === "string" &&
65
+ isAbsolute(value["runtimeDirectory"]))
66
+ return value["runtimeDirectory"];
67
+ throw new Error("invalid-runtime-record");
68
+ }
69
+ export function runtimeDirectory(environment, repository) {
12
70
  const explicit = environment["CLOVING_RUNTIME_DIR"];
13
71
  if (given(explicit))
14
72
  return explicit;
73
+ if (repository === undefined)
74
+ return undefined;
75
+ const adopted = adoptedRuntime(environment, repository);
76
+ if (adopted !== undefined)
77
+ return adopted;
15
78
  const runtime = environment["XDG_RUNTIME_DIR"];
16
- if (given(runtime))
17
- return join(runtime, "cloving");
18
- const state = environment["XDG_STATE_HOME"];
19
- if (given(state))
20
- return join(state, "cloving", "run");
21
- const home = environment["HOME"];
22
- return given(home)
23
- ? join(home, ".local", "state", "cloving", "run")
24
- : undefined;
79
+ const root = given(runtime) ? runtime : stateRoot(environment);
80
+ return root === undefined
81
+ ? undefined
82
+ : join(root, "cloving", repositoryRuntimeName(repository), "run");
25
83
  }
@@ -1,3 +1,5 @@
1
1
  import type { ToolchainIdentity } from "../workflow-admission.ts";
2
+ export declare const supportedNodes: string;
3
+ export declare function supportedNode(version: string): boolean;
2
4
  export declare function observedToolchain(start: string): Promise<ToolchainIdentity>;
3
5
  export declare function qualifiedToolchain(observed: ToolchainIdentity, start: string): Promise<ToolchainIdentity>;
@@ -3,7 +3,27 @@ import { createHash } from "node:crypto";
3
3
  import { access, readFile, realpath } from "node:fs/promises";
4
4
  import { dirname, join } from "node:path";
5
5
  import packageMetadata from "#package" with { type: "json" };
6
- const qualifiedNode = "v26.9.0";
6
+ export const supportedNodes = packageMetadata.engines.node;
7
+ export function supportedNode(version) {
8
+ const release = /^v(\d+)\.(\d+)\.(\d+)$/.exec(version);
9
+ if (release === null)
10
+ return false;
11
+ const observed = release.slice(1).map(Number);
12
+ return supportedNodes.split(" || ").some((range) => {
13
+ const bounds = /^>=(\d+)\.(\d+)\.(\d+) <(\d+)$/
14
+ .exec(range)
15
+ ?.slice(1)
16
+ .map(Number);
17
+ if (bounds === undefined)
18
+ return false;
19
+ return (atLeast(observed, bounds.slice(0, 3)) &&
20
+ (observed[0] ?? 0) < (bounds[3] ?? 0));
21
+ });
22
+ }
23
+ function atLeast(observed, minimum) {
24
+ const index = observed.findIndex((part, position) => part !== minimum[position]);
25
+ return index === -1 || (observed[index] ?? 0) > (minimum[index] ?? 0);
26
+ }
7
27
  export async function observedToolchain(start) {
8
28
  const root = await projectRoot(start);
9
29
  const sdk = await packageDirectory(start, "workflow");
@@ -29,7 +49,7 @@ export async function qualifiedToolchain(observed, start) {
29
49
  sdk: `workflow@${packageMetadata.dependencies.workflow}`,
30
50
  world: `@workflow/world-local@${typeof declared === "string" ? declared : "undeclared"}`,
31
51
  builder: `@workflow/builders@${packageMetadata.dependencies["@workflow/builders"]}`,
32
- node: qualifiedNode,
52
+ node: supportedNode(observed.node) ? observed.node : supportedNodes,
33
53
  dependencies: observed.dependencies,
34
54
  };
35
55
  }
@@ -1,3 +1,8 @@
1
+ import { type WorkerAttemptUsage } from "../worker-usage.ts";
1
2
  export declare function priceText(value: unknown, estimate?: unknown): string;
2
3
  export declare function usageText(value: unknown): string;
3
4
  export declare function totalsSuffix(state: unknown): string;
5
+ export declare function statusJson(result: Fields): Fields;
6
+ import { type Fields } from "../protocol.ts";
7
+ export declare function attemptText(attempt: WorkerAttemptUsage): string;
8
+ export declare function attemptTexts(value: unknown): readonly string[];