cloving 1.1.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 (568) hide show
  1. package/README.md +584 -144
  2. package/assets/watch-fonts/fira-code-OFL.md +93 -0
  3. package/assets/watch-fonts/fira-code-latin-400-normal.woff2 +0 -0
  4. package/assets/watch-fonts/fira-code-latin-500-normal.woff2 +0 -0
  5. package/assets/watch-fonts/heebo-OFL.md +93 -0
  6. package/assets/watch-fonts/heebo-latin-500-normal.woff2 +0 -0
  7. package/assets/watch-fonts/heebo-latin-700-normal.woff2 +0 -0
  8. package/assets/watch-fonts/heebo-latin-800-normal.woff2 +0 -0
  9. package/assets/watch-fonts/manifest.json +112 -0
  10. package/assets/watch-fonts/space-grotesk-OFL.md +93 -0
  11. package/assets/watch-fonts/space-grotesk-latin-400-normal.woff2 +0 -0
  12. package/assets/watch-fonts/space-grotesk-latin-500-normal.woff2 +0 -0
  13. package/assets/watch-fonts/space-grotesk-latin-600-normal.woff2 +0 -0
  14. package/assets/watch-fonts/space-grotesk-latin-700-normal.woff2 +0 -0
  15. package/dist/src/agent-harness-shell.d.ts +12 -0
  16. package/dist/src/agent-harness-shell.js +90 -0
  17. package/dist/src/agent-harness-versions.d.ts +8 -0
  18. package/dist/src/agent-harness-versions.js +49 -0
  19. package/dist/src/agent-harnesses.d.ts +4 -0
  20. package/dist/src/agent-harnesses.js +13 -0
  21. package/dist/src/authority/commands.d.ts +2 -0
  22. package/dist/src/authority/commands.js +49 -8
  23. package/dist/src/authority/dispatch-decision.d.ts +1 -0
  24. package/dist/src/authority/dispatch-decision.js +7 -4
  25. package/dist/src/authority/events.js +2 -2
  26. package/dist/src/authority/gate-reduction.d.ts +1 -0
  27. package/dist/src/authority/gate-reduction.js +18 -3
  28. package/dist/src/authority/gates.d.ts +2 -1
  29. package/dist/src/authority/gates.js +5 -1
  30. package/dist/src/authority/handoff-chain.d.ts +24 -0
  31. package/dist/src/authority/handoff-chain.js +46 -0
  32. package/dist/src/authority/operations.js +1 -1
  33. package/dist/src/authority/reconciliation.d.ts +1 -0
  34. package/dist/src/authority/reconciliation.js +18 -11
  35. package/dist/src/authority/reduction.d.ts +1 -1
  36. package/dist/src/authority/reduction.js +6 -1
  37. package/dist/src/authority/status-input.d.ts +1 -1
  38. package/dist/src/authority/status.d.ts +1 -0
  39. package/dist/src/authority/status.js +27 -3
  40. package/dist/src/authority/transitions.d.ts +5 -5
  41. package/dist/src/authority/transitions.js +9 -0
  42. package/dist/src/broker/actor/authority-delivery.js +1 -0
  43. package/dist/src/broker/actor/authority-queries.d.ts +11 -1
  44. package/dist/src/broker/actor/authority-queries.js +67 -3
  45. package/dist/src/broker/actor/authority-receipts.js +11 -1
  46. package/dist/src/broker/actor/authority-session.js +2 -2
  47. package/dist/src/broker/actor/authority-settings.js +4 -0
  48. package/dist/src/broker/actor/delivery-intents.d.ts +3 -1
  49. package/dist/src/broker/actor/delivery-intents.js +4 -4
  50. package/dist/src/broker/actor/effect-delivery.js +13 -1
  51. package/dist/src/broker/actor/effect-queries.d.ts +1 -0
  52. package/dist/src/broker/actor/effect-queries.js +7 -0
  53. package/dist/src/broker/actor/pin-check.js +1 -1
  54. package/dist/src/broker/actor/stop-plan.js +1 -1
  55. package/dist/src/broker/actor/turn-state.js +1 -1
  56. package/dist/src/broker/authority-admission.js +26 -5
  57. package/dist/src/broker/authority-restore.js +1 -0
  58. package/dist/src/broker/decision-restore.js +4 -4
  59. package/dist/src/broker/socket-address.d.ts +3 -1
  60. package/dist/src/broker/socket-address.js +2 -2
  61. package/dist/src/cli/arguments.d.ts +11 -13
  62. package/dist/src/cli/arguments.js +37 -107
  63. package/dist/src/cli/command-effects.d.ts +7 -0
  64. package/dist/src/cli/command-effects.js +39 -0
  65. package/dist/src/cli/commands.js +11 -4
  66. package/dist/src/cli/config-arguments.d.ts +11 -0
  67. package/dist/src/cli/config-arguments.js +59 -0
  68. package/dist/src/cli/config-command.d.ts +2 -0
  69. package/dist/src/cli/config-command.js +105 -0
  70. package/dist/src/cli/config-file.d.ts +3 -0
  71. package/dist/src/cli/config-file.js +50 -0
  72. package/dist/src/cli/config-lock.d.ts +7 -0
  73. package/dist/src/cli/config-lock.js +61 -0
  74. package/dist/src/cli/config-notice.d.ts +5 -0
  75. package/dist/src/cli/config-notice.js +46 -0
  76. package/dist/src/cli/doctor-github.d.ts +9 -0
  77. package/dist/src/cli/doctor-github.js +138 -0
  78. package/dist/src/cli/doctor-harness.d.ts +13 -0
  79. package/dist/src/cli/doctor-harness.js +242 -0
  80. package/dist/src/cli/doctor-local.d.ts +18 -0
  81. package/dist/src/cli/doctor-local.js +77 -0
  82. package/dist/src/cli/doctor-runtime.d.ts +15 -0
  83. package/dist/src/cli/doctor-runtime.js +176 -0
  84. package/dist/src/cli/doctor-service.d.ts +1 -0
  85. package/dist/src/cli/doctor-service.js +11 -0
  86. package/dist/src/cli/doctor-workflows.d.ts +3 -0
  87. package/dist/src/cli/doctor-workflows.js +45 -0
  88. package/dist/src/cli/doctor.d.ts +15 -0
  89. package/dist/src/cli/doctor.js +190 -0
  90. package/dist/src/cli/github-ci-progress.d.ts +8 -0
  91. package/dist/src/cli/github-ci-progress.js +83 -0
  92. package/dist/src/cli/github-retry.d.ts +6 -0
  93. package/dist/src/cli/github-retry.js +47 -0
  94. package/dist/src/cli/harness-probes.d.ts +22 -0
  95. package/dist/src/cli/harness-probes.js +183 -0
  96. package/dist/src/cli/main.d.ts +7 -1
  97. package/dist/src/cli/main.js +39 -61
  98. package/dist/src/cli/phone-arguments.d.ts +14 -0
  99. package/dist/src/cli/phone-arguments.js +37 -0
  100. package/dist/src/cli/phone-client.d.ts +2 -0
  101. package/dist/src/cli/phone-client.js +32 -0
  102. package/dist/src/cli/phone-command.d.ts +13 -0
  103. package/dist/src/cli/phone-command.js +101 -0
  104. package/dist/src/cli/probe-command.d.ts +36 -0
  105. package/dist/src/cli/probe-command.js +59 -0
  106. package/dist/src/cli/project-settings.d.ts +4 -0
  107. package/dist/src/cli/project-settings.js +33 -0
  108. package/dist/src/cli/render.d.ts +3 -1
  109. package/dist/src/cli/render.js +102 -39
  110. package/dist/src/cli/report-github.d.ts +18 -0
  111. package/dist/src/cli/report-github.js +200 -0
  112. package/dist/src/cli/report.d.ts +17 -0
  113. package/dist/src/cli/report.js +192 -0
  114. package/dist/src/cli/repository-arguments.d.ts +5 -0
  115. package/dist/src/cli/repository-arguments.js +34 -0
  116. package/dist/src/cli/runtime-arguments.d.ts +4 -0
  117. package/dist/src/cli/runtime-arguments.js +15 -0
  118. package/dist/src/cli/runtime-directory.d.ts +6 -2
  119. package/dist/src/cli/runtime-directory.js +72 -14
  120. package/dist/src/cli/toolchain.d.ts +2 -0
  121. package/dist/src/cli/toolchain.js +22 -2
  122. package/dist/src/cli/usage-render.d.ts +5 -0
  123. package/dist/src/cli/usage-render.js +40 -1
  124. package/dist/src/cli/usage.d.ts +3 -3
  125. package/dist/src/cli/usage.js +74 -45
  126. package/dist/src/cli/watch-actions.d.ts +2 -0
  127. package/dist/src/cli/watch-actions.js +4 -4
  128. package/dist/src/cli/watch-board-view.d.ts +12 -1
  129. package/dist/src/cli/watch-board-view.js +64 -12
  130. package/dist/src/cli/watch-board.d.ts +7 -1
  131. package/dist/src/cli/watch-board.js +61 -16
  132. package/dist/src/cli/watch-card-forms.js +2 -2
  133. package/dist/src/cli/watch-client.d.ts +1 -1
  134. package/dist/src/cli/watch-client.js +12 -3
  135. package/dist/src/cli/watch-header-view.d.ts +27 -0
  136. package/dist/src/cli/watch-header-view.js +116 -0
  137. package/dist/src/cli/watch-model.d.ts +10 -4
  138. package/dist/src/cli/watch-model.js +49 -59
  139. package/dist/src/cli/watch-page.js +67 -14
  140. package/dist/src/cli/watch-phases.js +3 -3
  141. package/dist/src/cli/watch-phone-client.d.ts +1 -0
  142. package/dist/src/cli/watch-phone-client.js +84 -0
  143. package/dist/src/cli/watch-phone-view.d.ts +56 -0
  144. package/dist/src/cli/watch-phone-view.js +113 -0
  145. package/dist/src/cli/watch-phone.d.ts +5 -0
  146. package/dist/src/cli/watch-phone.js +53 -0
  147. package/dist/src/cli/watch-pr-command.d.ts +5 -2
  148. package/dist/src/cli/watch-pr-command.js +41 -4
  149. package/dist/src/cli/watch-pr-identity.d.ts +14 -2
  150. package/dist/src/cli/watch-pr-identity.js +25 -0
  151. package/dist/src/cli/watch-pr-observer.d.ts +1 -0
  152. package/dist/src/cli/watch-pr-observer.js +48 -6
  153. package/dist/src/cli/watch-pull-request.d.ts +12 -0
  154. package/dist/src/cli/watch-pull-request.js +134 -0
  155. package/dist/src/cli/watch-reads.d.ts +7 -1
  156. package/dist/src/cli/watch-reads.js +42 -20
  157. package/dist/src/cli/watch-render.d.ts +23 -2
  158. package/dist/src/cli/watch-render.js +2 -1
  159. package/dist/src/cli/watch-server.js +56 -7
  160. package/dist/src/cli/watch-turn.d.ts +4 -1
  161. package/dist/src/cli/watch-turn.js +38 -2
  162. package/dist/src/cli/watch-usage.js +5 -1
  163. package/dist/src/cli/watch-view.d.ts +10 -17
  164. package/dist/src/cli/watch-view.js +33 -77
  165. package/dist/src/cli.js +106 -23
  166. package/dist/src/command-settings.d.ts +16 -0
  167. package/dist/src/command-settings.js +42 -0
  168. package/dist/src/configuration-change.d.ts +11 -0
  169. package/dist/src/configuration-change.js +62 -0
  170. package/dist/src/configuration-display.d.ts +21 -0
  171. package/dist/src/configuration-display.js +69 -0
  172. package/dist/src/configuration-schema.d.ts +49 -0
  173. package/dist/src/configuration-schema.js +159 -0
  174. package/dist/src/daemon/claude-turn.d.ts +20 -5
  175. package/dist/src/daemon/claude-turn.js +116 -53
  176. package/dist/src/daemon/claude-worker.d.ts +3 -5
  177. package/dist/src/daemon/claude-worker.js +64 -80
  178. package/dist/src/daemon/command-journal.d.ts +5 -0
  179. package/dist/src/daemon/command-journal.js +50 -0
  180. package/dist/src/daemon/command-process.d.ts +28 -0
  181. package/dist/src/daemon/command-process.js +164 -0
  182. package/dist/src/daemon/command-worker.d.ts +19 -0
  183. package/dist/src/daemon/command-worker.js +182 -0
  184. package/dist/src/daemon/cursor-stream.d.ts +4 -0
  185. package/dist/src/daemon/cursor-stream.js +154 -0
  186. package/dist/src/daemon/daemon-adapters.d.ts +58 -0
  187. package/dist/src/daemon/daemon-adapters.js +102 -0
  188. package/dist/src/daemon/daemon-loops.d.ts +14 -0
  189. package/dist/src/daemon/daemon-loops.js +39 -0
  190. package/dist/src/daemon/daemon.d.ts +3 -30
  191. package/dist/src/daemon/daemon.js +132 -110
  192. package/dist/src/daemon/declared-input.d.ts +3 -0
  193. package/dist/src/daemon/declared-input.js +9 -0
  194. package/dist/src/daemon/delivery-router.js +7 -1
  195. package/dist/src/daemon/gemini-stream.d.ts +4 -0
  196. package/dist/src/daemon/gemini-stream.js +129 -0
  197. package/dist/src/daemon/github-calls.d.ts +4 -0
  198. package/dist/src/daemon/github-calls.js +16 -7
  199. package/dist/src/daemon/github-ci-rerun.d.ts +26 -0
  200. package/dist/src/daemon/github-ci-rerun.js +92 -0
  201. package/dist/src/daemon/github-ci.d.ts +6 -0
  202. package/dist/src/daemon/github-ci.js +251 -0
  203. package/dist/src/daemon/github-merge-call.d.ts +16 -0
  204. package/dist/src/daemon/github-merge-call.js +73 -0
  205. package/dist/src/daemon/github-merge.d.ts +3 -5
  206. package/dist/src/daemon/github-merge.js +59 -98
  207. package/dist/src/daemon/github-methods.d.ts +28 -0
  208. package/dist/src/daemon/github-methods.js +90 -16
  209. package/dist/src/daemon/github-operation.d.ts +3 -0
  210. package/dist/src/daemon/github-retry.d.ts +6 -0
  211. package/dist/src/daemon/github-retry.js +13 -0
  212. package/dist/src/daemon/github-ticket-status.js +27 -1
  213. package/dist/src/daemon/github-worker.js +2 -1
  214. package/dist/src/daemon/handoff-worker.d.ts +10 -0
  215. package/dist/src/daemon/handoff-worker.js +232 -0
  216. package/dist/src/daemon/issue-queue.d.ts +2 -0
  217. package/dist/src/daemon/issue-queue.js +92 -63
  218. package/dist/src/daemon/notify-journal.d.ts +18 -0
  219. package/dist/src/daemon/notify-journal.js +108 -0
  220. package/dist/src/daemon/notify-message.js +2 -1
  221. package/dist/src/daemon/notify.js +177 -37
  222. package/dist/src/daemon/opencode-stream.d.ts +5 -0
  223. package/dist/src/daemon/opencode-stream.js +87 -0
  224. package/dist/src/daemon/queue-status.d.ts +4 -0
  225. package/dist/src/daemon/queue-status.js +38 -0
  226. package/dist/src/daemon/retry-worktree.d.ts +18 -0
  227. package/dist/src/daemon/retry-worktree.js +139 -0
  228. package/dist/src/daemon/retrying-turn.d.ts +5 -0
  229. package/dist/src/daemon/retrying-turn.js +145 -21
  230. package/dist/src/daemon/schedule-journal.d.ts +19 -0
  231. package/dist/src/daemon/schedule-journal.js +57 -0
  232. package/dist/src/daemon/text-output.d.ts +18 -0
  233. package/dist/src/daemon/text-output.js +44 -0
  234. package/dist/src/daemon/ticket-dependency-waits.d.ts +18 -0
  235. package/dist/src/daemon/ticket-dependency-waits.js +60 -0
  236. package/dist/src/daemon/ticket-registration.d.ts +10 -8
  237. package/dist/src/daemon/ticket-registration.js +146 -47
  238. package/dist/src/daemon/ticket-source.d.ts +4 -1
  239. package/dist/src/daemon/ticket-source.js +8 -2
  240. package/dist/src/daemon/turn-command.d.ts +10 -0
  241. package/dist/src/daemon/turn-command.js +33 -0
  242. package/dist/src/daemon/turn-report.d.ts +18 -0
  243. package/dist/src/daemon/turn-report.js +79 -0
  244. package/dist/src/daemon/work-tree.d.ts +2 -1
  245. package/dist/src/daemon/work-tree.js +15 -12
  246. package/dist/src/daemon/workflow-generations.d.ts +32 -0
  247. package/dist/src/daemon/workflow-generations.js +57 -0
  248. package/dist/src/daemon/workflow-replay.d.ts +16 -0
  249. package/dist/src/daemon/workflow-replay.js +58 -0
  250. package/dist/src/daemon/workflow-schedules.d.ts +27 -0
  251. package/dist/src/daemon/workflow-schedules.js +185 -0
  252. package/dist/src/decision-visibility.d.ts +2 -0
  253. package/dist/src/decision-visibility.js +10 -0
  254. package/dist/src/decision-wait.d.ts +1 -0
  255. package/dist/src/decision-wait.js +3 -0
  256. package/dist/src/delivery-backoff.d.ts +1 -0
  257. package/dist/src/delivery-backoff.js +3 -0
  258. package/dist/src/doctor-report.d.ts +24 -0
  259. package/dist/src/doctor-report.js +70 -0
  260. package/dist/src/execution-pin.d.ts +9 -0
  261. package/dist/src/execution-pin.js +86 -2
  262. package/dist/src/grok-result.d.ts +12 -0
  263. package/dist/src/grok-result.js +61 -0
  264. package/dist/src/harness-defaults.d.ts +35 -0
  265. package/dist/src/harness-defaults.js +121 -0
  266. package/dist/src/host/decision-resume.d.ts +35 -0
  267. package/dist/src/host/decision-resume.js +86 -0
  268. package/dist/src/host/gate-bridge.d.ts +48 -0
  269. package/dist/src/host/gate-bridge.js +124 -0
  270. package/dist/src/host/run-wait.d.ts +26 -0
  271. package/dist/src/host/run-wait.js +37 -0
  272. package/dist/src/host/start-delivery.d.ts +3 -2
  273. package/dist/src/host/start-delivery.js +11 -4
  274. package/dist/src/host/step-bridge-host.d.ts +6 -19
  275. package/dist/src/host/step-bridge-host.js +57 -55
  276. package/dist/src/host/world-reconciliation.d.ts +1 -0
  277. package/dist/src/host/world-reconciliation.js +3 -0
  278. package/dist/src/host/world-runs.js +5 -0
  279. package/dist/src/issue-identity.d.ts +6 -0
  280. package/dist/src/issue-identity.js +23 -0
  281. package/dist/src/merge-request.d.ts +19 -0
  282. package/dist/src/merge-request.js +32 -0
  283. package/dist/src/phone/canonical-json.d.ts +1 -0
  284. package/dist/src/phone/canonical-json.js +16 -0
  285. package/dist/src/phone/phone-link.d.ts +7 -0
  286. package/dist/src/phone/phone-link.js +21 -0
  287. package/dist/src/phone/qr-data.d.ts +8 -0
  288. package/dist/src/phone/qr-data.js +133 -0
  289. package/dist/src/phone/qr-matrix.d.ts +6 -0
  290. package/dist/src/phone/qr-matrix.js +175 -0
  291. package/dist/src/phone/qr-penalty.d.ts +3 -0
  292. package/dist/src/phone/qr-penalty.js +67 -0
  293. package/dist/src/phone/qr-picture.d.ts +5 -0
  294. package/dist/src/phone/qr-picture.js +24 -0
  295. package/dist/src/private-config.schema.json +263 -0
  296. package/dist/src/project-config.schema.json +65 -0
  297. package/dist/src/project-settings.d.ts +19 -0
  298. package/dist/src/project-settings.js +131 -0
  299. package/dist/src/relay/answer-check.d.ts +24 -0
  300. package/dist/src/relay/answer-check.js +145 -0
  301. package/dist/src/relay/answer-inbox.d.ts +15 -0
  302. package/dist/src/relay/answer-inbox.js +173 -0
  303. package/dist/src/relay/daemon-keys.d.ts +16 -0
  304. package/dist/src/relay/daemon-keys.js +75 -0
  305. package/dist/src/relay/decision-check.d.ts +3 -0
  306. package/dist/src/relay/decision-check.js +77 -0
  307. package/dist/src/relay/decision-close.d.ts +6 -0
  308. package/dist/src/relay/decision-close.js +72 -0
  309. package/dist/src/relay/decision-envelopes.d.ts +29 -0
  310. package/dist/src/relay/decision-envelopes.js +93 -0
  311. package/dist/src/relay/decision-watch.d.ts +14 -0
  312. package/dist/src/relay/decision-watch.js +68 -0
  313. package/dist/src/relay/envelope-post.d.ts +8 -0
  314. package/dist/src/relay/envelope-post.js +71 -0
  315. package/dist/src/relay/envelope.d.ts +28 -0
  316. package/dist/src/relay/envelope.js +53 -0
  317. package/dist/src/relay/hpke.d.ts +25 -0
  318. package/dist/src/relay/hpke.js +108 -0
  319. package/dist/src/relay/pairing-checks.d.ts +42 -0
  320. package/dist/src/relay/pairing-checks.js +172 -0
  321. package/dist/src/relay/pairing-follow.d.ts +8 -0
  322. package/dist/src/relay/pairing-follow.js +95 -0
  323. package/dist/src/relay/pairing-session.d.ts +29 -0
  324. package/dist/src/relay/pairing-session.js +87 -0
  325. package/dist/src/relay/phone-delivery.d.ts +51 -0
  326. package/dist/src/relay/phone-delivery.js +139 -0
  327. package/dist/src/relay/phone-devices.d.ts +36 -0
  328. package/dist/src/relay/phone-devices.js +46 -0
  329. package/dist/src/relay/phone-inbox.d.ts +18 -0
  330. package/dist/src/relay/phone-inbox.js +17 -0
  331. package/dist/src/relay/phone-operations.d.ts +18 -0
  332. package/dist/src/relay/phone-operations.js +121 -0
  333. package/dist/src/relay/phone-outbox.d.ts +21 -0
  334. package/dist/src/relay/phone-outbox.js +25 -0
  335. package/dist/src/relay/phone-socket.d.ts +6 -0
  336. package/dist/src/relay/phone-socket.js +63 -0
  337. package/dist/src/relay/relay-control.d.ts +7 -0
  338. package/dist/src/relay/relay-control.js +24 -0
  339. package/dist/src/relay/relay-files.d.ts +2 -0
  340. package/dist/src/relay/relay-files.js +23 -0
  341. package/dist/src/relay/relay-heartbeat.d.ts +17 -0
  342. package/dist/src/relay/relay-heartbeat.js +81 -0
  343. package/dist/src/relay/relay-http.d.ts +14 -0
  344. package/dist/src/relay/relay-http.js +63 -0
  345. package/dist/src/relay/relay-registration.d.ts +15 -0
  346. package/dist/src/relay/relay-registration.js +63 -0
  347. package/dist/src/relay/relay-service.d.ts +25 -0
  348. package/dist/src/relay/relay-service.js +216 -0
  349. package/dist/src/relay/relay-store.d.ts +48 -0
  350. package/dist/src/relay/relay-store.js +131 -0
  351. package/dist/src/relay/sealed-post.d.ts +25 -0
  352. package/dist/src/relay/sealed-post.js +52 -0
  353. package/dist/src/relay.d.ts +1 -0
  354. package/dist/src/relay.js +8 -0
  355. package/dist/src/report-statistics.d.ts +50 -0
  356. package/dist/src/report-statistics.js +70 -0
  357. package/dist/src/report.d.ts +171 -0
  358. package/dist/src/report.js +119 -0
  359. package/dist/src/repository-identity.d.ts +4 -0
  360. package/dist/src/repository-identity.js +4 -0
  361. package/dist/src/review-subject.d.ts +41 -0
  362. package/dist/src/review-subject.js +91 -0
  363. package/dist/src/run-wait.d.ts +23 -0
  364. package/dist/src/run-wait.js +20 -0
  365. package/dist/src/service/active-tickets.d.ts +4 -0
  366. package/dist/src/service/active-tickets.js +49 -0
  367. package/dist/src/service/command-effects.d.ts +4 -0
  368. package/dist/src/service/command-effects.js +16 -0
  369. package/dist/src/service/decision-handler.d.ts +4 -0
  370. package/dist/src/service/decision-handler.js +39 -4
  371. package/dist/src/service/gateway.js +18 -3
  372. package/dist/src/service/queue-runs.d.ts +3 -0
  373. package/dist/src/service/queue-runs.js +39 -0
  374. package/dist/src/service/registry.d.ts +22 -3
  375. package/dist/src/service/registry.js +51 -8
  376. package/dist/src/service/replies.d.ts +10 -0
  377. package/dist/src/service/replies.js +12 -0
  378. package/dist/src/service/run-handlers.js +45 -54
  379. package/dist/src/service/run-metadata.d.ts +8 -0
  380. package/dist/src/service/run-metadata.js +53 -0
  381. package/dist/src/service/run-waits.d.ts +3 -0
  382. package/dist/src/service/run-waits.js +41 -0
  383. package/dist/src/service/service.d.ts +21 -2
  384. package/dist/src/service/service.js +23 -5
  385. package/dist/src/service/submission-handler.js +70 -19
  386. package/dist/src/service/worker-port.d.ts +1 -0
  387. package/dist/src/service/worker-totals.js +10 -1
  388. package/dist/src/step-bridge.d.ts +32 -0
  389. package/dist/src/steps/decision-gate.d.ts +2 -1
  390. package/dist/src/steps/decision-gate.js +7 -0
  391. package/dist/src/steps/handoff.d.ts +2 -0
  392. package/dist/src/steps/handoff.js +13 -0
  393. package/dist/src/steps/merge-by-person.d.ts +2 -0
  394. package/dist/src/steps/merge-by-person.js +18 -0
  395. package/dist/src/steps/merge-when-green.d.ts +2 -0
  396. package/dist/src/steps/merge-when-green.js +62 -0
  397. package/dist/src/steps/review-by-agent.d.ts +5 -0
  398. package/dist/src/steps/review-by-agent.js +124 -0
  399. package/dist/src/steps/review-by-person.d.ts +4 -0
  400. package/dist/src/steps/review-by-person.js +16 -0
  401. package/dist/src/steps/review-subject.d.ts +2 -0
  402. package/dist/src/steps/review-subject.js +11 -0
  403. package/dist/src/steps/run-command.d.ts +2 -0
  404. package/dist/src/steps/run-command.js +15 -0
  405. package/dist/src/steps/sleep.d.ts +3 -0
  406. package/dist/src/steps/sleep.js +19 -0
  407. package/dist/src/steps/wait-for-decision.d.ts +2 -0
  408. package/dist/src/steps/wait-for-decision.js +71 -0
  409. package/dist/src/steps/wait-for-run.d.ts +5 -0
  410. package/dist/src/steps/wait-for-run.js +9 -0
  411. package/dist/src/storage/decision-snapshots.d.ts +1 -0
  412. package/dist/src/storage/decision-snapshots.js +7 -1
  413. package/dist/src/submission.d.ts +4 -0
  414. package/dist/src/submission.js +6 -2
  415. package/dist/src/testing.d.ts +29 -0
  416. package/dist/src/testing.js +264 -0
  417. package/dist/src/ticket-dependencies.d.ts +1 -0
  418. package/dist/src/ticket-dependencies.js +15 -0
  419. package/dist/src/ticket-status-stream.d.ts +9 -0
  420. package/dist/src/ticket-status-stream.js +94 -0
  421. package/dist/src/ticket-status.js +7 -4
  422. package/dist/src/token-prices.d.ts +14 -4
  423. package/dist/src/token-prices.js +56 -11
  424. package/dist/src/turn-profile.d.ts +1 -0
  425. package/dist/src/turn-profile.js +8 -1
  426. package/dist/src/worker-usage.d.ts +25 -0
  427. package/dist/src/worker-usage.js +58 -1
  428. package/dist/src/workflow-admission.d.ts +6 -0
  429. package/dist/src/workflow-candidate.d.ts +7 -2
  430. package/dist/src/workflow-candidate.js +48 -5
  431. package/dist/src/workflow-contracts.d.ts +2 -0
  432. package/dist/src/workflow-contracts.js +8 -3
  433. package/dist/src/workflow-declaration.d.ts +31 -2
  434. package/dist/src/workflow-declaration.js +140 -16
  435. package/dist/src/workflow-discovery.d.ts +19 -0
  436. package/dist/src/workflow-discovery.js +36 -0
  437. package/dist/src/workflow-refusals.d.ts +6 -0
  438. package/dist/src/workflow-refusals.js +42 -0
  439. package/dist/src/workflow-schedule.d.ts +22 -0
  440. package/dist/src/workflow-schedule.js +53 -0
  441. package/dist/src/workflows.d.ts +12 -1
  442. package/dist/src/workflows.js +9 -0
  443. package/dist/tools/admit-workflow.d.ts +14 -0
  444. package/dist/tools/admit-workflow.js +107 -0
  445. package/dist/tools/doctor-adoption.d.ts +1 -0
  446. package/dist/tools/doctor-adoption.js +11 -0
  447. package/dist/tools/project-configuration.d.ts +4 -0
  448. package/dist/tools/project-configuration.js +47 -0
  449. package/dist/tools/self-host-processes.d.ts +1 -0
  450. package/dist/tools/self-host-processes.js +33 -22
  451. package/dist/tools/self-host-project.d.ts +21 -0
  452. package/dist/tools/self-host-project.js +224 -0
  453. package/dist/tools/self-host-runtime.d.ts +16 -0
  454. package/dist/tools/self-host-runtime.js +60 -0
  455. package/dist/tools/self-host-workflows.d.ts +1 -0
  456. package/dist/tools/self-host-workflows.js +36 -1
  457. package/dist/tools/self-host.js +106 -135
  458. package/dist/tools/workflow-bundle-dependencies.d.ts +5 -0
  459. package/dist/tools/workflow-bundle-dependencies.js +93 -0
  460. package/dist/tools/workflow-bundles.d.ts +20 -0
  461. package/dist/tools/workflow-bundles.js +173 -0
  462. package/dist/tools/workflow-candidate-counts.d.ts +12 -0
  463. package/dist/tools/workflow-candidate-counts.js +266 -0
  464. package/dist/tools/workflow-candidate-fields.d.ts +5 -0
  465. package/dist/tools/workflow-candidate-fields.js +24 -0
  466. package/dist/tools/workflow-candidate-helper-counts.d.ts +10 -0
  467. package/dist/tools/workflow-candidate-helper-counts.js +129 -0
  468. package/dist/tools/workflow-candidate-program.d.ts +13 -0
  469. package/dist/tools/workflow-candidate-program.js +106 -0
  470. package/dist/tools/workflow-candidate-source.d.ts +6 -0
  471. package/dist/tools/workflow-candidate-source.js +169 -0
  472. package/dist/tools/workflow-candidate-syntax.d.ts +21 -0
  473. package/dist/tools/workflow-candidate-syntax.js +263 -0
  474. package/dist/tools/workflow-command.d.ts +1 -0
  475. package/dist/tools/workflow-command.js +143 -0
  476. package/dist/tools/workflow-folder-capture.d.ts +18 -0
  477. package/dist/tools/workflow-folder-capture.js +261 -0
  478. package/dist/tools/workflow-folders.d.ts +49 -0
  479. package/dist/tools/workflow-folders.js +203 -0
  480. package/dist/tools/workflow-source-effects.d.ts +10 -0
  481. package/dist/tools/workflow-source-effects.js +213 -0
  482. package/dist/tools/workflow-test-hook.d.ts +7 -0
  483. package/dist/tools/workflow-test-hook.js +16 -0
  484. package/dist/tools/workflow-test-loader.d.ts +1 -0
  485. package/dist/tools/workflow-test-loader.js +10 -0
  486. package/dist/workflows/develop-prd.js +71 -3
  487. package/dist/workflows/develop-ticket.js +6 -1
  488. package/dist/workflows/ticket-prompts.js +17 -3
  489. package/package.json +66 -6
  490. package/templates/develop/README.md +78 -0
  491. package/templates/develop/develop/accept.ts +11 -0
  492. package/templates/develop/develop/flow-tests.ts +357 -0
  493. package/templates/develop/develop/local.ts +40 -0
  494. package/templates/develop/develop/option-tests.ts +174 -0
  495. package/templates/develop/develop/partial-choice.ts +29 -0
  496. package/templates/develop/develop/partial.ts +28 -0
  497. package/templates/develop/develop/pull.ts +152 -0
  498. package/templates/develop/develop/queue-partial.ts +39 -0
  499. package/templates/develop/develop/refusal-tests.ts +174 -0
  500. package/templates/develop/develop/report.ts +156 -0
  501. package/templates/develop/develop/round.ts +40 -0
  502. package/templates/develop/develop/scenarios.ts +87 -0
  503. package/templates/develop/develop/turn.ts +67 -0
  504. package/templates/develop/develop.declaration.json +24 -0
  505. package/templates/develop/develop.test.ts +287 -0
  506. package/templates/develop/develop.ts +30 -0
  507. package/templates/develop/template.json +153 -0
  508. package/dist/src/chats/analysis-batches.d.ts +0 -24
  509. package/dist/src/chats/analysis-batches.js +0 -83
  510. package/dist/src/chats/analysis-contract.d.ts +0 -80
  511. package/dist/src/chats/analysis-contract.js +0 -16
  512. package/dist/src/chats/analysis-data.d.ts +0 -3
  513. package/dist/src/chats/analysis-data.js +0 -85
  514. package/dist/src/chats/analysis-input.d.ts +0 -12
  515. package/dist/src/chats/analysis-input.js +0 -83
  516. package/dist/src/chats/analysis-links.d.ts +0 -2
  517. package/dist/src/chats/analysis-links.js +0 -25
  518. package/dist/src/chats/analysis-prompt.d.ts +0 -10
  519. package/dist/src/chats/analysis-prompt.js +0 -16
  520. package/dist/src/chats/analysis-proposal.d.ts +0 -2
  521. package/dist/src/chats/analysis-proposal.js +0 -32
  522. package/dist/src/chats/analysis-provenance.d.ts +0 -4
  523. package/dist/src/chats/analysis-provenance.js +0 -99
  524. package/dist/src/chats/analysis-shape.d.ts +0 -3
  525. package/dist/src/chats/analysis-shape.js +0 -228
  526. package/dist/src/chats/analysis.d.ts +0 -3
  527. package/dist/src/chats/analysis.js +0 -42
  528. package/dist/src/chats/corpus-input.d.ts +0 -5
  529. package/dist/src/chats/corpus-input.js +0 -288
  530. package/dist/src/chats/destination.d.ts +0 -4
  531. package/dist/src/chats/destination.js +0 -96
  532. package/dist/src/chats/import.d.ts +0 -15
  533. package/dist/src/chats/import.js +0 -243
  534. package/dist/src/chats/input-file.d.ts +0 -3
  535. package/dist/src/chats/input-file.js +0 -32
  536. package/dist/src/chats/normalize.d.ts +0 -29
  537. package/dist/src/chats/normalize.js +0 -155
  538. package/dist/src/chats/previous-import.d.ts +0 -5
  539. package/dist/src/chats/previous-import.js +0 -34
  540. package/dist/src/chats/reader.d.ts +0 -21
  541. package/dist/src/chats/reader.js +0 -118
  542. package/dist/src/chats/redact-import.d.ts +0 -14
  543. package/dist/src/chats/redact-import.js +0 -141
  544. package/dist/src/chats/redaction.d.ts +0 -41
  545. package/dist/src/chats/redaction.js +0 -161
  546. package/dist/src/chats/revision-input.d.ts +0 -3
  547. package/dist/src/chats/revision-input.js +0 -180
  548. package/dist/src/chats/revision.d.ts +0 -48
  549. package/dist/src/chats/revision.js +0 -94
  550. package/dist/src/chats/selection.d.ts +0 -25
  551. package/dist/src/chats/selection.js +0 -109
  552. package/dist/src/chats/source.d.ts +0 -23
  553. package/dist/src/chats/source.js +0 -135
  554. package/dist/src/chats/structure.d.ts +0 -57
  555. package/dist/src/chats/structure.js +0 -216
  556. package/dist/src/daemon/analysis-launch.d.ts +0 -5
  557. package/dist/src/daemon/analysis-launch.js +0 -81
  558. package/dist/src/daemon/analysis-token.d.ts +0 -6
  559. package/dist/src/daemon/analysis-token.js +0 -88
  560. package/dist/src/daemon/analysis-worker.d.ts +0 -22
  561. package/dist/src/daemon/analysis-worker.js +0 -219
  562. package/dist/src/daemon/chats-files.d.ts +0 -15
  563. package/dist/src/daemon/chats-files.js +0 -113
  564. package/dist/src/daemon/chats-worker.d.ts +0 -12
  565. package/dist/src/daemon/chats-worker.js +0 -200
  566. package/dist/workflows/analyze-chats.d.ts +0 -10
  567. package/dist/workflows/analyze-chats.declaration.json +0 -9
  568. package/dist/workflows/analyze-chats.js +0 -73
@@ -1,13 +1,19 @@
1
+ import { metadataOf, outcomeOf } from "./run-metadata.js";
2
+ import { linksOf } from "../authority/handoff-chain.js";
1
3
  import { runView, unresolvedEffects, } from "../authority/status.js";
2
4
  import { record } from "../protocol.js";
3
5
  import { committed, failed, invalidRequest, isIdentifier, publicReceipt, rejection, result, wholeNumber, } from "./replies.js";
4
6
  import { usageTotals } from "./worker-totals.js";
5
- import { feedbackOf } from "./decision-handler.js";
7
+ import { commandFields } from "./command-effects.js";
8
+ import { decidedOf, feedbackOf } from "./decision-handler.js";
9
+ import { queueOverview } from "./active-tickets.js";
10
+ import { queueRunStatuses } from "./queue-runs.js";
6
11
  async function snapshot(context) {
7
12
  const { authority } = context;
8
13
  const state = await authority.state();
9
14
  const sequences = await authority.queries.sequences();
10
15
  return {
16
+ links: await authority.queries.runLinks(),
11
17
  state,
12
18
  operations: await authority.operations(),
13
19
  sequences: sequences.runs,
@@ -39,9 +45,8 @@ async function effectInput(context, runId) {
39
45
  const budget = await effects.budget(runId);
40
46
  const stored = await effects.operations(runId);
41
47
  return {
42
- budget: budget === undefined
43
- ? null
44
- : { limit: budget.limit, spent: budget.spent },
48
+ commandOperations: stored.filter((operation) => operation.capability === "command"),
49
+ budget: budget ? { limit: budget.limit, spent: budget.spent } : null,
45
50
  effects: stored.map((operation) => ({
46
51
  operationId: operation.operationId,
47
52
  status: operation.status,
@@ -59,8 +64,9 @@ async function viewOf(context, scope) {
59
64
  if (run === undefined)
60
65
  return undefined;
61
66
  const details = state.details[run.runId];
67
+ const effects = await effectInput(context, run.runId);
62
68
  const input = {
63
- ...(await effectInput(context, run.runId)),
69
+ ...effects,
64
70
  closure: run.status === "cancelled"
65
71
  ? await context.authority.effects.closure(run.runId)
66
72
  : null,
@@ -78,6 +84,9 @@ async function viewOf(context, scope) {
78
84
  };
79
85
  return {
80
86
  ...runView(input),
87
+ commandOperations: effects.commandOperations,
88
+ ...linksOf({ runId: run.runId, ...scope.snapshot.links[run.runId] }),
89
+ input: await submittedInput(context, details?.submission),
81
90
  workflowId: scope.snapshot.workflowIds[run.runId] ?? run.workflow,
82
91
  latestAt: times[run.runId] ?? null,
83
92
  unresolvedEffects: unresolvedEffects(input),
@@ -87,9 +96,12 @@ async function viewOf(context, scope) {
87
96
  function summary(view) {
88
97
  return {
89
98
  runId: view.runId,
99
+ ...linksOf(view),
100
+ input: view.input,
90
101
  workflowId: view.workflowId,
91
102
  state: view.state,
92
103
  condition: view.condition,
104
+ awaitedRunId: view.awaitedRunId,
93
105
  revision: view.revision,
94
106
  latestSequence: view.latestSequence,
95
107
  latestAt: view.latestAt,
@@ -115,53 +127,12 @@ function full(view) {
115
127
  feedback: view.feedback,
116
128
  };
117
129
  }
118
- async function outcomeOf(context, view) {
119
- if (view.state !== "completed")
120
- return null;
121
- const event = await context.authority.queries.latestCompletion({
122
- runId: view.runId,
123
- atOrBefore: view.latestSequence,
124
- });
125
- const kind = event?.payload["outcome"];
126
- if (kind === undefined)
127
- return null;
128
- const ticketStatus = event?.payload["ticketStatus"];
129
- return {
130
- kind,
131
- reason: event?.payload["outcomeReason"] ?? null,
132
- ...(ticketStatus === undefined ? {} : { ticketStatus }),
133
- ...(event?.payload["issueUpdate"] === "failed"
134
- ? { issueUpdate: "failed" }
135
- : {}),
136
- };
137
- }
138
- function titleOf(input, workflowId) {
139
- const ticket = input?.["ticket"];
140
- if (typeof ticket !== "string")
141
- return null;
142
- const fallback = `Cloving task ${String(input?.["cycleId"])}`;
143
- const lines = ticket.split("\n");
144
- if (workflowId === "develop-prompt") {
145
- const first = lines.find((line) => /\S/.test(line));
146
- return first === undefined
147
- ? fallback
148
- : first.replace(/^# /, "").trim().slice(0, 200);
149
- }
150
- const first = lines[0] ?? "";
151
- return first.startsWith("# ")
152
- ? first.slice(2).trim().slice(0, 200)
153
- : fallback;
154
- }
155
- async function metadataOf(context, source) {
156
- const document = source.digest
157
- ? await context.authority.queries.document(source.digest)
130
+ async function submittedInput(context, digest) {
131
+ const document = digest
132
+ ? await context.authority.queries.document(digest)
158
133
  : undefined;
159
- const input = record(JSON.parse(document ?? "null"));
160
- const ticketId = input?.["ticketId"];
161
- return {
162
- ticketId: typeof ticketId === "string" && ticketId !== "" ? ticketId : null,
163
- title: titleOf(input, source.workflowId),
164
- };
134
+ const request = record(JSON.parse(document ?? "null"));
135
+ return record(request?.["submission"]) ?? null;
165
136
  }
166
137
  async function listed(context, page) {
167
138
  const identifiers = Object.keys(page.snapshot.state.runs)
@@ -173,21 +144,36 @@ async function listed(context, page) {
173
144
  views.push(await viewOf(context, { snapshot: page.snapshot, runId }));
174
145
  const runs = views.filter((view) => view !== undefined).map(summary);
175
146
  return result("run-list", {
147
+ ...(await queueOverview(context)),
176
148
  workflows: context.registry.workflowIds,
149
+ workflowRefusals: context.workflowRefusals ?? [],
150
+ ...(Object.keys(context.registry.workflowStages).length === 0
151
+ ? {}
152
+ : {
153
+ workflowStages: context.registry.workflowStages,
154
+ }),
177
155
  runs,
178
156
  next: identifiers.length > shown.length ? (shown.at(-1) ?? null) : null,
179
157
  worldReports: context.worldReports?.() ?? [],
180
158
  });
181
159
  }
182
- export async function status(context, parameters) {
183
- const { runId } = parameters;
160
+ function listParameters(parameters) {
184
161
  const after = parameters["after"] ?? "";
185
162
  const limit = parameters["limit"] ?? 50;
186
163
  if (typeof after !== "string" || !wholeNumber(limit, 1) || limit > 500)
164
+ return undefined;
165
+ return { after, limit };
166
+ }
167
+ export async function status(context, parameters) {
168
+ if (parameters["runIds"] !== undefined)
169
+ return queueRunStatuses(context, parameters["runIds"]);
170
+ const { runId } = parameters;
171
+ const page = listParameters(parameters);
172
+ if (page === undefined)
187
173
  return invalidRequest("The status request is not valid.");
188
174
  const current = await snapshot(context);
189
175
  if (runId === undefined)
190
- return listed(context, { snapshot: current, after, limit });
176
+ return listed(context, { snapshot: current, ...page });
191
177
  const named = typeof runId === "string" ? runId : "";
192
178
  const view = await viewOf(context, { snapshot: current, runId: named });
193
179
  if (view === undefined)
@@ -196,7 +182,12 @@ export async function status(context, parameters) {
196
182
  return result("run-status", {
197
183
  run: {
198
184
  ...full({ ...view, ...totals }),
185
+ ...(await commandFields(context, view.commandOperations)),
199
186
  outcome: await outcomeOf(context, view),
187
+ decisions: await decidedOf(context, {
188
+ state: current.state,
189
+ runId: view.runId,
190
+ }),
200
191
  ...(await metadataOf(context, {
201
192
  workflowId: view.workflowId,
202
193
  digest: current.state.details[view.runId]?.input,
@@ -0,0 +1,8 @@
1
+ import { type Fields } from "../protocol.ts";
2
+ import type { RunView } from "../authority/status.ts";
3
+ import type { ServiceContext } from "./replies.ts";
4
+ export declare function outcomeOf(context: ServiceContext, view: Pick<RunView, "state" | "runId" | "latestSequence">): Promise<Fields | null>;
5
+ export declare function metadataOf(context: ServiceContext, source: {
6
+ readonly workflowId: string;
7
+ readonly digest: string | null | undefined;
8
+ }): Promise<Fields>;
@@ -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,6 +1,10 @@
1
1
  import { type Authority, type AuthorityTiming, type Delivery, type EffectSettings, type Refusal } from "../broker/actor/authority.ts";
2
- import { type WorkflowRegistration } from "./registry.ts";
2
+ import { type WorkflowRefusal } from "../workflow-refusals.ts";
3
+ import { type Registry, type WorkflowRegistration, type WorkflowBundleStore } from "./registry.ts";
4
+ import { type ServiceContext } from "./replies.ts";
3
5
  import { type WorkerPort } from "./worker-port.ts";
6
+ import type { RunWaitTarget } from "../run-wait.ts";
7
+ import type { CommandEffects } from "../command-settings.ts";
4
8
  export type { WorkflowRegistration } from "./registry.ts";
5
9
  export type { EffectReply, EffectReport, EffectRequest, WorkerPort, } from "./worker-port.ts";
6
10
  export interface ServiceTiming {
@@ -23,21 +27,36 @@ export interface ServiceHost {
23
27
  readonly reports?: () => readonly unknown[];
24
28
  }
25
29
  export interface HostPorts {
30
+ readonly runWait?: {
31
+ readonly target: (runId: string) => Promise<RunWaitTarget | undefined>;
32
+ readonly observe: WorkerPort["observe"];
33
+ };
26
34
  readonly state: Authority["state"];
27
35
  readonly submit: WorkerPort["submit"];
28
36
  readonly input: (runId: string) => Promise<string | undefined>;
29
37
  readonly document: (digest: string) => Promise<string | undefined>;
30
- 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
+ };
31
43
  readonly requestEffect: WorkerPort["requestEffect"];
32
44
  readonly operation: Authority["effects"]["operation"];
45
+ readonly operations: Authority["effects"]["operations"];
33
46
  readonly reportEffect: WorkerPort["reportEffect"];
34
47
  readonly openGate: WorkerPort["openGate"];
35
48
  readonly registerWait: WorkerPort["registerWait"];
36
49
  }
37
50
  export interface ServiceOptions {
51
+ readonly workerHarness?: ServiceContext["workerHarness"];
52
+ readonly commandEffects?: CommandEffects;
38
53
  readonly stateDirectory: string;
39
54
  readonly runtimeDirectory: string;
40
55
  readonly workflows: readonly WorkflowRegistration[];
56
+ readonly retainedWorkflows?: readonly WorkflowRegistration[];
57
+ readonly workflowBundles?: WorkflowBundleStore;
58
+ readonly retainedWorkflow?: Registry["available"];
59
+ readonly workflowRefusals?: readonly WorkflowRefusal[];
41
60
  readonly delivery: Delivery;
42
61
  readonly host?: (ports: HostPorts) => Promise<ServiceHost>;
43
62
  readonly timing?: ServiceTiming;
@@ -2,17 +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 {} from "../workflow-refusals.js";
5
6
  import { changeSignal } from "./changes.js";
6
7
  import { decision, questions } from "./decision-handler.js";
7
8
  import { events } from "./event-handler.js";
8
9
  import { expiryScan } from "./expiry.js";
9
10
  import { commandGateway, workerCommandBound } from "./gateway.js";
10
11
  import { workflowRegistry, } from "./registry.js";
11
- import { failed } from "./replies.js";
12
+ import { failed, queryMetadata } from "./replies.js";
12
13
  import { runCommand, status } from "./run-handlers.js";
13
14
  import { submissionHandler } from "./submission-handler.js";
14
15
  import { connectionLimits, listen, reachable } from "./transport.js";
15
16
  import { workerPort } from "./worker-port.js";
17
+ import { runWaitTarget } from "./run-waits.js";
16
18
  export const serviceTiming = {
17
19
  authority: authorityTiming,
18
20
  expiryScanMilliseconds: 1_000,
@@ -87,6 +89,7 @@ async function started(authority, setup) {
87
89
  handle: dispatcher({
88
90
  authority,
89
91
  registry,
92
+ ...queryMetadata(options),
90
93
  gateway,
91
94
  clock,
92
95
  changed: changes.next,
@@ -133,7 +136,7 @@ export async function startService(options) {
133
136
  if (typeof path !== "string")
134
137
  return path;
135
138
  const timing = options.timing ?? serviceTiming;
136
- const registry = workflowRegistry(options.workflows);
139
+ const registry = workflowRegistry(options.workflows, options);
137
140
  const opening = await openAuthority(options.stateDirectory, {
138
141
  delivery: options.delivery,
139
142
  timing: timing.authority,
@@ -146,7 +149,7 @@ export async function startService(options) {
146
149
  const { authority } = opening;
147
150
  const gateway = serviceGateway(authority, { options, registry });
148
151
  const worker = workerPort({ gateway, authority });
149
- const host = await hosted(options, hostPorts(authority, worker));
152
+ const host = await hosted(options, hostPorts(authority, { worker, registry }));
150
153
  if (host.kind === "refused") {
151
154
  await authority.close();
152
155
  return host;
@@ -180,8 +183,13 @@ function serviceGateway(authority, parts) {
180
183
  pendingWorkerCommands: limits.pendingWorkerCommands,
181
184
  });
182
185
  }
183
- function hostPorts(authority, worker) {
186
+ function hostPorts(authority, parts) {
187
+ const { worker, registry } = parts;
184
188
  return {
189
+ runWait: {
190
+ target: (runId) => runWaitTarget(authority, runId),
191
+ observe: worker.observe,
192
+ },
185
193
  state: authority.state,
186
194
  submit: worker.submit,
187
195
  input: async (runId) => {
@@ -196,7 +204,17 @@ function hostPorts(authority, worker) {
196
204
  openGate: worker.openGate,
197
205
  registerWait: worker.registerWait,
198
206
  operation: authority.effects.operation,
199
- 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
+ },
200
218
  };
201
219
  }
202
220
  function message(error) {
@@ -1,10 +1,13 @@
1
1
  import { createHash } from "node:crypto";
2
+ import { handoffChain } from "../authority/handoff-chain.js";
3
+ import { executionCapabilities } from "../execution-pin.js";
2
4
  import { setTimeout as delay } from "node:timers/promises";
3
- import { isIdentifier as isWorkflowIdentifier } from "../authority/commands.js";
5
+ import { isCommandId, isIdentifier as isWorkflowIdentifier, } from "../authority/commands.js";
4
6
  import { documentDigest } from "../broker/decision-restore.js";
5
7
  import { record } from "../protocol.js";
6
- import { checkResolution, checkSubmission, normalizedRequest, } from "../submission.js";
7
- import { committed, failed, invalidRequest, isIdentifier, publicReceipt, rejection, result, } from "./replies.js";
8
+ import { checkResolution, checkSubmission, hasTicketField, normalizedRequest, } from "../submission.js";
9
+ import { activeWorkflow } from "./active-tickets.js";
10
+ import { committed, failed, invalidRequest, publicReceipt, rejection, result, } from "./replies.js";
8
11
  export function runIdentity(commandId) {
9
12
  return `run-${createHash("sha256").update(commandId).digest("hex").slice(0, 32)}`;
10
13
  }
@@ -49,7 +52,7 @@ function effectBudget(workflow) {
49
52
  return {};
50
53
  return {
51
54
  effectLimit: workflow.effectLimit,
52
- capabilities: JSON.stringify([...workflow.manifest.capabilities].sort()),
55
+ capabilities: executionCapabilities(workflow.manifest),
53
56
  };
54
57
  }
55
58
  function usable(workflow, workflowId) {
@@ -73,7 +76,13 @@ async function resolved(context, admission) {
73
76
  const { workflow, workflowId, commandId, submission } = admission;
74
77
  const limit = new AbortController();
75
78
  const timer = new AbortController();
76
- const request = { workflowId, submission, commandId, signal: limit.signal };
79
+ const request = {
80
+ workflowId,
81
+ submission,
82
+ commandId,
83
+ signal: limit.signal,
84
+ activeTickets: admission.activeTickets,
85
+ };
77
86
  const call = Promise.resolve(request)
78
87
  .then((given) => workflow.resolver.resolve(given))
79
88
  .then((value) => checkResolution(value) ?? "failure")
@@ -110,6 +119,9 @@ async function admit(context, admission) {
110
119
  return unresolved(context, { kind: resolution, commandId });
111
120
  if (resolution.kind === "rejected")
112
121
  return failed(resolution.code, { commandId, detail: resolution.detail });
122
+ const limited = capacityRefusal(workflow, admission);
123
+ if (limited !== undefined)
124
+ return limited;
113
125
  const { input } = resolution;
114
126
  if (Buffer.byteLength(input) > context.documentBytes)
115
127
  return unresolved(context, { kind: "failure", commandId });
@@ -124,6 +136,12 @@ async function admit(context, admission) {
124
136
  input: documentDigest(input),
125
137
  resolver: `${workflow.resolver.id}:${workflow.resolver.version}`,
126
138
  ...effectBudget(workflow),
139
+ ...(admission.chain.kind === "handoff"
140
+ ? {
141
+ parentRunId: admission.chain.parentRunId,
142
+ chainId: admission.chain.chainId,
143
+ }
144
+ : {}),
127
145
  },
128
146
  documents: [normalized, input],
129
147
  });
@@ -137,9 +155,33 @@ async function admit(context, admission) {
137
155
  replayed: receipt.kind === "duplicate",
138
156
  });
139
157
  }
158
+ function admissionRefusal(workflow, request) {
159
+ const { workflowId, commandId, submission, activeTickets } = request;
160
+ const tickets = workflowId === "develop-issue" || hasTicketField(workflow.submission);
161
+ if (tickets &&
162
+ typeof submission["ticket"] === "string" &&
163
+ activeTickets.some((input) => input["ticketId"] === submission["ticket"]))
164
+ return failed("ticket-active", {
165
+ commandId,
166
+ detail: "An active run already works on this ticket.",
167
+ });
168
+ if (tickets && submission["ticket"] !== "next")
169
+ return undefined;
170
+ return capacityRefusal(workflow, request);
171
+ }
172
+ function capacityRefusal(workflow, request) {
173
+ if (workflow.admission !== undefined &&
174
+ request.activeTickets.length >=
175
+ (workflow.admission === "when-idle" ? 1 : workflow.admission))
176
+ return failed("workflow-active", {
177
+ commandId: request.commandId,
178
+ detail: `The workflow ${request.workflowId} already has an active run.`,
179
+ });
180
+ return undefined;
181
+ }
140
182
  async function submitted(context, parameters) {
141
183
  const { workflowId, commandId } = parameters;
142
- if (!isWorkflowIdentifier(workflowId) || !isIdentifier(commandId))
184
+ if (!isWorkflowIdentifier(workflowId) || !isCommandId(commandId))
143
185
  return invalidRequest("The workflow ID or the command ID is not valid.");
144
186
  const existing = await context.authority.queries.receipt(commandId);
145
187
  if (existing !== undefined)
@@ -147,6 +189,14 @@ async function submitted(context, parameters) {
147
189
  workflowId,
148
190
  submission: parameters["submission"],
149
191
  });
192
+ const chain = handoffChain(commandId, commandId.startsWith("handoff:")
193
+ ? await context.authority.queries.runOrigins()
194
+ : {});
195
+ if (chain.kind === "refused")
196
+ return failed(chain.reason, {
197
+ commandId,
198
+ detail: "A hand-off chain permits at most five runs and requires a recorded parent.",
199
+ });
150
200
  const found = usable(context.registry.byId(workflowId), workflowId);
151
201
  if (found.kind === "unusable")
152
202
  return found.reply;
@@ -161,32 +211,33 @@ async function submitted(context, parameters) {
161
211
  });
162
212
  if (check.kind === "rejected")
163
213
  return failed(check.code, { commandId, detail: check.detail });
164
- if (found.workflow.admission === "when-idle" &&
165
- (await activeWorkflow(context, workflowId)))
166
- return failed("workflow-active", {
167
- commandId,
168
- detail: `The workflow ${workflowId} already has an active run.`,
169
- });
214
+ const activeTickets = await activeWorkflow(context, workflowId);
215
+ const refusal = admissionRefusal(found.workflow, {
216
+ workflowId,
217
+ commandId,
218
+ submission: check.submission,
219
+ activeTickets,
220
+ });
221
+ if (refusal !== undefined)
222
+ return refusal;
170
223
  return admit(context, {
224
+ chain,
171
225
  workflow: found.workflow,
172
226
  workflowId,
173
227
  commandId,
174
228
  submission: check.submission,
175
229
  normalized: check.normalized,
230
+ activeTickets,
176
231
  });
177
232
  }
178
- async function activeWorkflow(context, workflowId) {
179
- const workflows = await context.authority.queries.workflowIds();
180
- const state = await context.authority.state();
181
- return Object.values(state.runs).some((run) => workflows[run.runId] === workflowId &&
182
- !["completed", "failed", "cancelled"].includes(run.status));
183
- }
184
233
  export function submissionHandler(context) {
185
234
  const pending = new Map();
186
235
  return (parameters) => {
187
236
  const keys = [`command:${String(parameters["commandId"])}`];
188
237
  const workflowId = String(parameters["workflowId"]);
189
- if (context.registry.byId(workflowId)?.admission === "when-idle")
238
+ if (workflowId === "develop-issue" ||
239
+ hasTicketField(context.registry.byId(workflowId)?.submission) ||
240
+ context.registry.byId(workflowId)?.admission !== undefined)
190
241
  keys.push(`workflow:${workflowId}`);
191
242
  const next = () => submitted(context, parameters);
192
243
  const previous = keys
@@ -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, 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")) ?? {};
@@ -17,7 +17,16 @@ export async function usageTotals(context, runId) {
17
17
  const report = reportFields(operation.result === null
18
18
  ? undefined
19
19
  : await queries.document(operation.result));
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));
20
25
  turns.push({
26
+ ...(typeof model === "string" ? { model } : {}),
27
+ ...(typeof summary === "string" ? { summary } : {}),
28
+ ...(typeof harness === "string" ? { harness } : {}),
29
+ ...(attempts === undefined ? {} : { attempts }),
21
30
  operationId: operation.operationId,
22
31
  usage: usageOf(report["usage"]),
23
32
  costUsd: priceOf(report["costUsd"]),
@@ -39,6 +39,35 @@ export interface GateRequest {
39
39
  readonly gateId: string;
40
40
  readonly kind: "question" | "approval";
41
41
  readonly prompt: string;
42
+ readonly expiresAt?: string;
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;
51
+ export type HandoffValue = string | number | boolean | null | readonly HandoffValue[] | {
52
+ readonly [key: string]: HandoffValue;
53
+ };
54
+ export interface HandoffRequest {
55
+ readonly workflowId: string;
56
+ readonly input: Readonly<Record<string, HandoffValue>>;
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;
42
71
  }
43
72
  export type GateResult = {
44
73
  readonly kind: "opened";
@@ -53,5 +82,8 @@ export type GateResult = {
53
82
  export interface StepBridge {
54
83
  readonly effect: (request: ProtectedRequest) => Promise<ProtectedResult>;
55
84
  readonly gate: (request: GateRequest) => Promise<GateResult>;
85
+ readonly waitForDecision?: (request: GateRequest) => Promise<DecisionWait>;
86
+ readonly handoff?: (request: HandoffRequest) => Promise<ProtectedResult>;
87
+ readonly waitForRun?: (request: RunWaitRequest) => Promise<RunWaitOutcome>;
56
88
  }
57
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>;