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,53 @@
1
+ import { issueIdentity } from "../issue-identity.js";
2
+ import { record } from "../protocol.js";
3
+ export async function outcomeOf(context, view) {
4
+ if (view.state !== "completed")
5
+ return null;
6
+ const event = await context.authority.queries.latestCompletion({
7
+ runId: view.runId,
8
+ atOrBefore: view.latestSequence,
9
+ });
10
+ const payload = event?.payload ?? {};
11
+ const kind = payload["outcome"];
12
+ if (kind === undefined)
13
+ return null;
14
+ const { ticketStatus, promotionId, outcomeReason, issueUpdate } = payload;
15
+ return {
16
+ kind,
17
+ reason: outcomeReason ?? null,
18
+ ...(promotionId === undefined ? {} : { promotionId }),
19
+ ...(ticketStatus === undefined ? {} : { ticketStatus }),
20
+ ...(issueUpdate === "failed" ? { issueUpdate } : {}),
21
+ };
22
+ }
23
+ function titleOf(input, workflowId) {
24
+ const ticket = input?.["ticket"];
25
+ if (typeof ticket !== "string")
26
+ return null;
27
+ const fallback = `Cloving task ${String(input?.["cycleId"])}`;
28
+ const lines = ticket.split("\n");
29
+ if (workflowId === "develop-prompt") {
30
+ const first = lines.find((line) => /\S/.test(line));
31
+ return first === undefined
32
+ ? fallback
33
+ : first.replace(/^# /, "").trim().slice(0, 200);
34
+ }
35
+ const first = lines[0] ?? "";
36
+ return first.startsWith("# ")
37
+ ? first.slice(2).trim().slice(0, 200)
38
+ : fallback;
39
+ }
40
+ export async function metadataOf(context, source) {
41
+ const document = source.digest
42
+ ? await context.authority.queries.document(source.digest)
43
+ : undefined;
44
+ const input = record(JSON.parse(document ?? "null"));
45
+ const ticketId = input?.["ticketId"];
46
+ return {
47
+ ticketId: typeof ticketId === "string" && ticketId !== "" ? ticketId : null,
48
+ title: titleOf(input, source.workflowId),
49
+ ...(source.workflowId === "develop-issue"
50
+ ? { issueIdentity: issueIdentity(input?.["ticket"]) }
51
+ : {}),
52
+ };
53
+ }
@@ -0,0 +1,3 @@
1
+ import type { Authority } from "../broker/actor/authority.ts";
2
+ import type { RunWaitTarget } from "../run-wait.ts";
3
+ export declare function runWaitTarget(authority: Authority, runId: string): Promise<RunWaitTarget | undefined>;
@@ -0,0 +1,41 @@
1
+ function outcomeOf(event, status) {
2
+ if (event === undefined)
3
+ return null;
4
+ return {
5
+ kind: event.payload["outcome"] ?? status,
6
+ reason: event.payload["outcomeReason"] ?? null,
7
+ promotionId: event.payload["promotionId"] ?? null,
8
+ };
9
+ }
10
+ async function settled(authority, run) {
11
+ if (run.status !== "cancelled")
12
+ return ["completed", "failed"].includes(run.status);
13
+ const closure = await authority.effects.closure(run.runId);
14
+ return (!closure.open &&
15
+ closure.closure === "cancelled" &&
16
+ closure.unresolved.length === 0);
17
+ }
18
+ export async function runWaitTarget(authority, runId) {
19
+ const run = await authority.queries.run(runId);
20
+ const origin = (await authority.queries.runOrigins())[runId];
21
+ if (run === undefined || origin === undefined)
22
+ return undefined;
23
+ const terminal = await settled(authority, run);
24
+ const event = terminal
25
+ ? await authority.queries.latestCompletion({
26
+ runId,
27
+ atOrBefore: run.sequence,
28
+ terminal: true,
29
+ })
30
+ : undefined;
31
+ const endedAt = event === undefined ? null : Date.parse(event.recordedAt);
32
+ const stoppedAt = run.status === "cancelled" && terminal
33
+ ? await authority.effects.settledAt(runId)
34
+ : null;
35
+ return {
36
+ parentRunId: origin.parentRunId,
37
+ status: run.status,
38
+ endedAt: endedAt === null ? null : Math.max(endedAt, stoppedAt ?? endedAt),
39
+ outcome: outcomeOf(event, run.status),
40
+ };
41
+ }
@@ -1,7 +1,10 @@
1
1
  import { type Authority, type AuthorityTiming, type Delivery, type EffectSettings, type Refusal } from "../broker/actor/authority.ts";
2
2
  import { type WorkflowRefusal } from "../workflow-refusals.ts";
3
- import { type WorkflowRegistration } from "./registry.ts";
3
+ import { type Registry, type WorkflowRegistration, type WorkflowBundleStore } from "./registry.ts";
4
+ import { type ServiceContext } from "./replies.ts";
4
5
  import { type WorkerPort } from "./worker-port.ts";
6
+ import type { RunWaitTarget } from "../run-wait.ts";
7
+ import type { CommandEffects } from "../command-settings.ts";
5
8
  export type { WorkflowRegistration } from "./registry.ts";
6
9
  export type { EffectReply, EffectReport, EffectRequest, WorkerPort, } from "./worker-port.ts";
7
10
  export interface ServiceTiming {
@@ -24,22 +27,35 @@ export interface ServiceHost {
24
27
  readonly reports?: () => readonly unknown[];
25
28
  }
26
29
  export interface HostPorts {
30
+ readonly runWait?: {
31
+ readonly target: (runId: string) => Promise<RunWaitTarget | undefined>;
32
+ readonly observe: WorkerPort["observe"];
33
+ };
27
34
  readonly state: Authority["state"];
28
35
  readonly submit: WorkerPort["submit"];
29
36
  readonly input: (runId: string) => Promise<string | undefined>;
30
37
  readonly document: (digest: string) => Promise<string | undefined>;
31
- readonly workflowId: (runId: string) => Promise<string | undefined>;
38
+ readonly workflow: {
39
+ readonly id: (runId: string) => Promise<string | undefined>;
40
+ readonly manifest: Authority["queries"]["manifest"];
41
+ readonly available: (runId: string, workflowId?: string) => Promise<boolean>;
42
+ };
32
43
  readonly requestEffect: WorkerPort["requestEffect"];
33
44
  readonly operation: Authority["effects"]["operation"];
45
+ readonly operations: Authority["effects"]["operations"];
34
46
  readonly reportEffect: WorkerPort["reportEffect"];
35
47
  readonly openGate: WorkerPort["openGate"];
36
48
  readonly registerWait: WorkerPort["registerWait"];
37
49
  }
38
50
  export interface ServiceOptions {
51
+ readonly workerHarness?: ServiceContext["workerHarness"];
52
+ readonly commandEffects?: CommandEffects;
39
53
  readonly stateDirectory: string;
40
54
  readonly runtimeDirectory: string;
41
55
  readonly workflows: readonly WorkflowRegistration[];
42
56
  readonly retainedWorkflows?: readonly WorkflowRegistration[];
57
+ readonly workflowBundles?: WorkflowBundleStore;
58
+ readonly retainedWorkflow?: Registry["available"];
43
59
  readonly workflowRefusals?: readonly WorkflowRefusal[];
44
60
  readonly delivery: Delivery;
45
61
  readonly host?: (ports: HostPorts) => Promise<ServiceHost>;
@@ -2,18 +2,19 @@ import { lstat, rm } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
  import { authorityTiming, openAuthority, } from "../broker/actor/authority.js";
4
4
  import { socketAddress } from "../broker/socket-address.js";
5
- import { workflowRefusals, } from "../workflow-refusals.js";
5
+ import {} from "../workflow-refusals.js";
6
6
  import { changeSignal } from "./changes.js";
7
7
  import { decision, questions } from "./decision-handler.js";
8
8
  import { events } from "./event-handler.js";
9
9
  import { expiryScan } from "./expiry.js";
10
10
  import { commandGateway, workerCommandBound } from "./gateway.js";
11
11
  import { workflowRegistry, } from "./registry.js";
12
- import { failed } from "./replies.js";
12
+ import { failed, queryMetadata } from "./replies.js";
13
13
  import { runCommand, status } from "./run-handlers.js";
14
14
  import { submissionHandler } from "./submission-handler.js";
15
15
  import { connectionLimits, listen, reachable } from "./transport.js";
16
16
  import { workerPort } from "./worker-port.js";
17
+ import { runWaitTarget } from "./run-waits.js";
17
18
  export const serviceTiming = {
18
19
  authority: authorityTiming,
19
20
  expiryScanMilliseconds: 1_000,
@@ -88,7 +89,7 @@ async function started(authority, setup) {
88
89
  handle: dispatcher({
89
90
  authority,
90
91
  registry,
91
- workflowRefusals: workflowRefusals(options.workflowRefusals),
92
+ ...queryMetadata(options),
92
93
  gateway,
93
94
  clock,
94
95
  changed: changes.next,
@@ -135,7 +136,7 @@ export async function startService(options) {
135
136
  if (typeof path !== "string")
136
137
  return path;
137
138
  const timing = options.timing ?? serviceTiming;
138
- const registry = workflowRegistry(options.workflows, options.retainedWorkflows);
139
+ const registry = workflowRegistry(options.workflows, options);
139
140
  const opening = await openAuthority(options.stateDirectory, {
140
141
  delivery: options.delivery,
141
142
  timing: timing.authority,
@@ -148,7 +149,7 @@ export async function startService(options) {
148
149
  const { authority } = opening;
149
150
  const gateway = serviceGateway(authority, { options, registry });
150
151
  const worker = workerPort({ gateway, authority });
151
- const host = await hosted(options, hostPorts(authority, worker));
152
+ const host = await hosted(options, hostPorts(authority, { worker, registry }));
152
153
  if (host.kind === "refused") {
153
154
  await authority.close();
154
155
  return host;
@@ -182,8 +183,13 @@ function serviceGateway(authority, parts) {
182
183
  pendingWorkerCommands: limits.pendingWorkerCommands,
183
184
  });
184
185
  }
185
- function hostPorts(authority, worker) {
186
+ function hostPorts(authority, parts) {
187
+ const { worker, registry } = parts;
186
188
  return {
189
+ runWait: {
190
+ target: (runId) => runWaitTarget(authority, runId),
191
+ observe: worker.observe,
192
+ },
187
193
  state: authority.state,
188
194
  submit: worker.submit,
189
195
  input: async (runId) => {
@@ -198,7 +204,17 @@ function hostPorts(authority, worker) {
198
204
  openGate: worker.openGate,
199
205
  registerWait: worker.registerWait,
200
206
  operation: authority.effects.operation,
201
- workflowId: async (runId) => (await authority.queries.workflowIds())[runId],
207
+ operations: authority.effects.operations,
208
+ workflow: {
209
+ id: async (runId) => (await authority.queries.workflowIds())[runId],
210
+ manifest: authority.queries.manifest,
211
+ available: async (runId, workflowId) => {
212
+ const manifest = await authority.queries.manifest(runId);
213
+ return (manifest !== undefined &&
214
+ (workflowId === undefined || manifest.workflowId === workflowId) &&
215
+ (await registry.available(manifest)) !== undefined);
216
+ },
217
+ },
202
218
  };
203
219
  }
204
220
  function message(error) {
@@ -1,5 +1,4 @@
1
1
  import { type Fields, type Reply } from "../protocol.ts";
2
2
  import { type ServiceContext } from "./replies.ts";
3
3
  export declare function runIdentity(commandId: string): string;
4
- export declare function queueOverview(context: ServiceContext): Promise<Fields>;
5
4
  export declare function submissionHandler(context: ServiceContext): (parameters: Fields) => Promise<Reply>;
@@ -5,7 +5,8 @@ import { setTimeout as delay } from "node:timers/promises";
5
5
  import { isCommandId, isIdentifier as isWorkflowIdentifier, } from "../authority/commands.js";
6
6
  import { documentDigest } from "../broker/decision-restore.js";
7
7
  import { record } from "../protocol.js";
8
- import { checkResolution, checkSubmission, normalizedRequest, } from "../submission.js";
8
+ import { checkResolution, checkSubmission, hasTicketField, normalizedRequest, } from "../submission.js";
9
+ import { activeWorkflow } from "./active-tickets.js";
9
10
  import { committed, failed, invalidRequest, publicReceipt, rejection, result, } from "./replies.js";
10
11
  export function runIdentity(commandId) {
11
12
  return `run-${createHash("sha256").update(commandId).digest("hex").slice(0, 32)}`;
@@ -156,14 +157,15 @@ async function admit(context, admission) {
156
157
  }
157
158
  function admissionRefusal(workflow, request) {
158
159
  const { workflowId, commandId, submission, activeTickets } = request;
159
- if (workflowId === "develop-issue" &&
160
+ const tickets = workflowId === "develop-issue" || hasTicketField(workflow.submission);
161
+ if (tickets &&
160
162
  typeof submission["ticket"] === "string" &&
161
163
  activeTickets.some((input) => input["ticketId"] === submission["ticket"]))
162
164
  return failed("ticket-active", {
163
165
  commandId,
164
166
  detail: "An active run already works on this ticket.",
165
167
  });
166
- if (workflowId === "develop-issue" && submission["ticket"] !== "next")
168
+ if (tickets && submission["ticket"] !== "next")
167
169
  return undefined;
168
170
  return capacityRefusal(workflow, request);
169
171
  }
@@ -228,43 +230,13 @@ async function submitted(context, parameters) {
228
230
  activeTickets,
229
231
  });
230
232
  }
231
- async function activeWorkflow(context, workflowId) {
232
- const workflows = await context.authority.queries.workflowIds();
233
- const state = await context.authority.state();
234
- const runs = Object.values(state.runs).filter((run) => workflows[run.runId] === workflowId &&
235
- !["completed", "failed", "cancelled"].includes(run.status));
236
- return Promise.all(runs.map(async (run) => {
237
- const digest = state.details[run.runId]?.input;
238
- const text = digest
239
- ? await context.authority.queries.document(digest)
240
- : undefined;
241
- return record(JSON.parse(text ?? "null")) ?? {};
242
- }));
243
- }
244
- export async function queueOverview(context) {
245
- const workflow = context.registry.byId("develop-issue");
246
- if (workflow?.admission === undefined)
247
- return {};
248
- const active = await activeWorkflow(context, "develop-issue");
249
- return {
250
- queue: {
251
- lanes: workflow.admission === "when-idle" ? 1 : workflow.admission,
252
- busy: active.length,
253
- skipped: [
254
- ...active.flatMap((input) => typeof input["ticketId"] === "string"
255
- ? [{ ticketId: input["ticketId"], reason: "ticket-active" }]
256
- : []),
257
- ...(workflow.resolver.skippedTickets?.() ?? []),
258
- ],
259
- },
260
- };
261
- }
262
233
  export function submissionHandler(context) {
263
234
  const pending = new Map();
264
235
  return (parameters) => {
265
236
  const keys = [`command:${String(parameters["commandId"])}`];
266
237
  const workflowId = String(parameters["workflowId"]);
267
238
  if (workflowId === "develop-issue" ||
239
+ hasTicketField(context.registry.byId(workflowId)?.submission) ||
268
240
  context.registry.byId(workflowId)?.admission !== undefined)
269
241
  keys.push(`workflow:${workflowId}`);
270
242
  const next = () => submitted(context, parameters);
@@ -8,6 +8,7 @@ interface Revised extends Identified {
8
8
  readonly expectedRevision: number;
9
9
  }
10
10
  export interface GateOpening extends Revised {
11
+ readonly waitMode?: "hook";
11
12
  readonly gateId: string;
12
13
  readonly kind: "question" | "approval";
13
14
  readonly prompt: string;
@@ -1,5 +1,5 @@
1
1
  import { record } from "../protocol.js";
2
- import { priceOf, usageOf, tokenCount, workerTotals, } from "../worker-usage.js";
2
+ import { priceOf, usageOf, attemptsOf, workerTotals, } from "../worker-usage.js";
3
3
  function reportFields(text) {
4
4
  try {
5
5
  return record(JSON.parse(text ?? "null")) ?? {};
@@ -8,28 +8,6 @@ function reportFields(text) {
8
8
  return {};
9
9
  }
10
10
  }
11
- function attemptsOf(value) {
12
- if (!Array.isArray(value))
13
- return undefined;
14
- return value.flatMap((entry) => {
15
- const fields = record(entry) ?? {};
16
- const attempt = tokenCount(fields["attempt"]);
17
- const model = fields["model"];
18
- if (attempt === null ||
19
- attempt === 0 ||
20
- (model !== null && typeof model !== "string"))
21
- return [];
22
- return [
23
- {
24
- attempt,
25
- model,
26
- usage: usageOf(fields["usage"]),
27
- costUsd: priceOf(fields["costUsd"]),
28
- estimatedCostUsd: priceOf(fields["estimatedCostUsd"]),
29
- },
30
- ];
31
- });
32
- }
33
11
  export async function usageTotals(context, runId) {
34
12
  const { effects, queries } = context.authority;
35
13
  const operations = (await effects.operations(runId)).filter((operation) => operation.capability === "claude" &&
@@ -40,7 +18,14 @@ export async function usageTotals(context, runId) {
40
18
  ? undefined
41
19
  : await queries.document(operation.result));
42
20
  const attempts = attemptsOf(report["attempts"]);
21
+ const model = report["model"];
22
+ const summary = report["summary"];
23
+ const harness = report["harness"] ??
24
+ (await context.workerHarness?.(operation.operationId));
43
25
  turns.push({
26
+ ...(typeof model === "string" ? { model } : {}),
27
+ ...(typeof summary === "string" ? { summary } : {}),
28
+ ...(typeof harness === "string" ? { harness } : {}),
44
29
  ...(attempts === undefined ? {} : { attempts }),
45
30
  operationId: operation.operationId,
46
31
  usage: usageOf(report["usage"]),
@@ -41,6 +41,13 @@ export interface GateRequest {
41
41
  readonly prompt: string;
42
42
  readonly expiresAt?: string;
43
43
  }
44
+ export interface DecisionResult {
45
+ readonly decision: "approved" | "denied" | "answered" | "expired";
46
+ readonly answer: string | null;
47
+ }
48
+ export type DecisionWait = {
49
+ readonly token: string;
50
+ } | DecisionResult;
44
51
  export type HandoffValue = string | number | boolean | null | readonly HandoffValue[] | {
45
52
  readonly [key: string]: HandoffValue;
46
53
  };
@@ -48,6 +55,20 @@ export interface HandoffRequest {
48
55
  readonly workflowId: string;
49
56
  readonly input: Readonly<Record<string, HandoffValue>>;
50
57
  }
58
+ export interface RunWaitRequest {
59
+ readonly runId: string;
60
+ readonly maximumWaitSeconds: number;
61
+ }
62
+ export interface RunWaitOutcome {
63
+ readonly kind: string;
64
+ readonly reason: string | null;
65
+ readonly promotionId: string | null;
66
+ }
67
+ export interface CommandRequest {
68
+ readonly scope: ProtectedScope;
69
+ readonly name: string;
70
+ readonly input: HandoffValue;
71
+ }
51
72
  export type GateResult = {
52
73
  readonly kind: "opened";
53
74
  readonly decisionId: string;
@@ -61,6 +82,8 @@ export type GateResult = {
61
82
  export interface StepBridge {
62
83
  readonly effect: (request: ProtectedRequest) => Promise<ProtectedResult>;
63
84
  readonly gate: (request: GateRequest) => Promise<GateResult>;
85
+ readonly waitForDecision?: (request: GateRequest) => Promise<DecisionWait>;
64
86
  readonly handoff?: (request: HandoffRequest) => Promise<ProtectedResult>;
87
+ readonly waitForRun?: (request: RunWaitRequest) => Promise<RunWaitOutcome>;
65
88
  }
66
89
  export declare function isStepBridge(value: unknown): value is StepBridge;
@@ -1,2 +1,3 @@
1
- import { type GateRequest, type GateResult } from "../step-bridge.ts";
1
+ import { type GateRequest, type GateResult, type DecisionWait } from "../step-bridge.ts";
2
2
  export declare function decisionGate(request: GateRequest): Promise<GateResult>;
3
+ export declare function openDecisionWait(request: GateRequest): Promise<DecisionWait>;
@@ -6,3 +6,10 @@ export async function decisionGate(request) {
6
6
  return { kind: "unavailable", reason: "cloving-host-unavailable" };
7
7
  return await bridge.gate(request);
8
8
  }
9
+ export async function openDecisionWait(request) {
10
+ "use step";
11
+ const bridge = Reflect.get(globalThis, Symbol.for(stepBridgeKey));
12
+ if (!isStepBridge(bridge) || bridge.waitForDecision === undefined)
13
+ throw new Error("cloving-host-unavailable");
14
+ return await bridge.waitForDecision(request);
15
+ }
@@ -0,0 +1,2 @@
1
+ import { type MergeRequest, type MergeResult } from "../merge-request.ts";
2
+ export declare function mergeByPerson(request: MergeRequest): Promise<MergeResult>;
@@ -0,0 +1,18 @@
1
+ import { mergeRequest, } from "../merge-request.js";
2
+ import { mergeWhenGreen } from "./merge-when-green.js";
3
+ import { waitForDecision } from "./wait-for-decision.js";
4
+ export async function mergeByPerson(request) {
5
+ const { pull, check, round } = mergeRequest(request);
6
+ const decision = await waitForDecision({
7
+ gateId: `merge:${String(pull.number)}:${pull.commit}`,
8
+ kind: "approval",
9
+ prompt: `Merge pull request #${String(pull.number)} (${pull.url}) at commit ${pull.commit} ${check === null ? "with no local check" : `after the local check ${check}`}.`,
10
+ });
11
+ if (decision.decision !== "approved")
12
+ return {
13
+ merged: false,
14
+ reason: "not-approved",
15
+ output: decision.answer ?? "",
16
+ };
17
+ return await mergeWhenGreen({ pull, check, round });
18
+ }
@@ -0,0 +1,2 @@
1
+ import { type MergeRequest, type MergeResult } from "../merge-request.ts";
2
+ export declare function mergeWhenGreen(request: MergeRequest): Promise<MergeResult>;
@@ -0,0 +1,62 @@
1
+ import { mergeRequest, } from "../merge-request.js";
2
+ import { record } from "../protocol.js";
3
+ import { protectedEffect } from "./protected-effect.js";
4
+ const repairReasons = [
5
+ "check-failed",
6
+ "merge-conflict",
7
+ "ci-failed",
8
+ "ci-pending",
9
+ ];
10
+ export async function mergeWhenGreen(request) {
11
+ const { pull, check, round } = mergeRequest(request);
12
+ const effect = await protectedEffect({
13
+ capability: "github",
14
+ method: "merge",
15
+ target: pull.target,
16
+ payload: JSON.stringify({
17
+ number: pull.number,
18
+ commit: pull.commit,
19
+ check,
20
+ }),
21
+ scope: {
22
+ phase: "merge",
23
+ operation: "merge",
24
+ round,
25
+ key: `${String(pull.number)}:${pull.commit}`,
26
+ },
27
+ units: 1,
28
+ });
29
+ return mergeOutcome(effect, pull);
30
+ }
31
+ function mergeOutcome(effect, pull) {
32
+ if (effect.kind !== "completed")
33
+ return notMerged(effect);
34
+ const result = parsedResult(effect.result);
35
+ const reason = repairReasons.find((name) => name === result["reason"]);
36
+ if (reason !== undefined && typeof result["output"] === "string")
37
+ return { merged: false, reason, output: result["output"] };
38
+ if (result["reason"] !== undefined ||
39
+ result["number"] !== pull.number ||
40
+ result["commit"] !== pull.commit ||
41
+ typeof result["merged"] !== "string")
42
+ throw new Error("invalid-merge-result");
43
+ return { merged: true, reason: null, output: "" };
44
+ }
45
+ function notMerged(effect) {
46
+ if (effect.kind === "failed" && effect.reason === "check-not-configured")
47
+ return { merged: false, reason: "check-not-configured", output: "" };
48
+ throw new Error(effect.reason ?? effect.kind);
49
+ }
50
+ function parsedResult(text) {
51
+ let parsed;
52
+ try {
53
+ parsed = JSON.parse(text ?? "null");
54
+ }
55
+ catch {
56
+ throw new Error("invalid-merge-result");
57
+ }
58
+ const result = record(parsed);
59
+ if (result === undefined)
60
+ throw new Error("invalid-merge-result");
61
+ return result;
62
+ }
@@ -0,0 +1,5 @@
1
+ import type { ReviewResult, ReviewSubject, Reviewer } from "../review-subject.ts";
2
+ export declare function reviewByAgent(request: {
3
+ readonly subject: ReviewSubject;
4
+ readonly reviewer: Reviewer;
5
+ }): Promise<ReviewResult>;
@@ -0,0 +1,124 @@
1
+ import { record } from "../protocol.js";
2
+ import { protectedEffect } from "./protected-effect.js";
3
+ import { snapshotReviewSubject } from "./review-subject.js";
4
+ export async function reviewByAgent(request) {
5
+ const reviewer = selectedReviewer(request.reviewer);
6
+ const subject = { ...request.subject };
7
+ const snapshot = await snapshotReviewSubject(subject);
8
+ const effect = await protectedEffect({
9
+ ...reviewEffect({ subject, snapshot, reviewer }),
10
+ scope: {
11
+ phase: "review",
12
+ operation: reviewer.kind === "greptile" ? "greptile" : `turn:${reviewer.profile}`,
13
+ round: 1,
14
+ key: snapshot.subjectDigest,
15
+ },
16
+ units: 1,
17
+ });
18
+ if (effect.kind !== "completed")
19
+ throw new Error(effect.reason ?? effect.kind);
20
+ let parsed;
21
+ try {
22
+ parsed = JSON.parse(effect.result ?? "null");
23
+ }
24
+ catch {
25
+ throw new Error("invalid-review-result");
26
+ }
27
+ return {
28
+ ...(reviewer.kind === "turn"
29
+ ? turnResult(parsed)
30
+ : greptileFeedback(parsed, subject)),
31
+ commit: snapshot.commit,
32
+ subjectDigest: snapshot.subjectDigest,
33
+ };
34
+ }
35
+ function selectedReviewer(value) {
36
+ const reviewer = record(value);
37
+ if (reviewer?.["kind"] === "greptile")
38
+ return { kind: "greptile" };
39
+ if (reviewer?.["kind"] === "turn" &&
40
+ typeof reviewer["profile"] === "string" &&
41
+ /^[A-Za-z0-9_-]{1,119}$/.test(reviewer["profile"]))
42
+ return { kind: "turn", profile: reviewer["profile"] };
43
+ throw new Error("invalid-reviewer");
44
+ }
45
+ function reviewEffect(input) {
46
+ const { subject, snapshot, reviewer } = input;
47
+ if (reviewer.kind === "turn")
48
+ return {
49
+ capability: "claude",
50
+ method: `run-turn:${reviewer.profile}`,
51
+ target: "draft" in subject ? snapshot.subjectDigest : subject.target,
52
+ payload: `Review only this immutable subject. Do not change it. For a commit, inspect that exact commit, not the current branch head.\n${snapshot.prompt}\nEnd your report with exactly one of these lines:\nReview verdict: accept\nReview verdict: change`,
53
+ };
54
+ if ("draft" in subject ||
55
+ !Number.isSafeInteger(subject.number) ||
56
+ Number(subject.number) < 1)
57
+ throw new Error("invalid-greptile-subject");
58
+ return {
59
+ capability: "github",
60
+ method: "wait-review",
61
+ target: subject.target,
62
+ payload: JSON.stringify({ number: subject.number, commit: subject.commit }),
63
+ };
64
+ }
65
+ function turnResult(parsed) {
66
+ const result = record(parsed);
67
+ if (result &&
68
+ (result["reviewVerdict"] === null || result["reviewVerdict"] === undefined))
69
+ return {
70
+ accepted: false,
71
+ feedback: "The review turn has no verdict line.",
72
+ };
73
+ if (!result ||
74
+ typeof result["summary"] !== "string" ||
75
+ (result["reviewVerdict"] !== "accept" &&
76
+ result["reviewVerdict"] !== "change"))
77
+ throw new Error("invalid-review-result");
78
+ return {
79
+ accepted: result["reviewVerdict"] === "accept",
80
+ feedback: result["summary"],
81
+ };
82
+ }
83
+ function greptileFeedback(parsed, subject) {
84
+ if ("draft" in subject)
85
+ throw new Error("invalid-greptile-subject");
86
+ const result = greptileResult(parsed, subject);
87
+ return {
88
+ accepted: result.score === 5,
89
+ feedback: [result.summary, ...result.findings].filter(Boolean).join("\n\n"),
90
+ };
91
+ }
92
+ function greptileResult(parsed, subject) {
93
+ const result = record(parsed);
94
+ if (!result)
95
+ throw new Error("invalid-review-result");
96
+ const score = result["score"];
97
+ const summary = result["summary"];
98
+ const findings = result["findings"];
99
+ if (result["number"] !== subject.number ||
100
+ result["commit"] !== subject.commit ||
101
+ typeof score !== "number" ||
102
+ !Number.isInteger(score) ||
103
+ score < 0 ||
104
+ score > 5 ||
105
+ typeof summary !== "string" ||
106
+ !Array.isArray(findings))
107
+ throw new Error("invalid-review-result");
108
+ return {
109
+ score,
110
+ summary,
111
+ findings: findings.map((value) => {
112
+ const finding = record(value);
113
+ if (!finding)
114
+ throw new Error("invalid-review-result");
115
+ const { path, line, body } = finding;
116
+ if (typeof path !== "string" ||
117
+ typeof body !== "string" ||
118
+ !(line === null ||
119
+ (typeof line === "number" && Number.isSafeInteger(line) && line > 0)))
120
+ throw new Error("invalid-review-result");
121
+ return `${path}${line === null ? "" : `:${String(line)}`}\n${body}`;
122
+ }),
123
+ };
124
+ }
@@ -0,0 +1,4 @@
1
+ import type { ReviewResult, ReviewSubject } from "../review-subject.ts";
2
+ export declare function reviewByPerson(request: {
3
+ readonly subject: ReviewSubject;
4
+ }): Promise<ReviewResult>;