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
@@ -1,4 +1,4 @@
1
- import { priceOf, usageOf } from "./worker-usage.js";
1
+ import { priceOf, sumPrices, usageOf, } from "./worker-usage.js";
2
2
  import { record } from "./protocol.js";
3
3
  export const builtInPriceTable = {
4
4
  date: "2026-10-18",
@@ -90,16 +90,29 @@ export function replaceCommandModel(command, model) {
90
90
  });
91
91
  }
92
92
  export function estimatedCostUsd(usage, pricing) {
93
+ return "models" in pricing
94
+ ? modelCostUsd(pricing)
95
+ : singleCostUsd(usage, pricing);
96
+ }
97
+ function modelCostUsd(pricing) {
98
+ return sumPrices(pricing.models.map(({ model, usage: counts }) => singleCostUsd(counts, {
99
+ worker: "gemini",
100
+ price: priceForModel(pricing.prices, model),
101
+ })));
102
+ }
103
+ function singleCostUsd(usage, pricing) {
93
104
  const { worker, price } = pricing;
94
105
  const counts = usageOf(usage);
95
106
  const cached = counts.cache_read_input_tokens;
96
107
  const output = counts.output_tokens;
97
108
  if (price === undefined ||
109
+ (worker === "cursor-agent" && counts.cache_creation_input_tokens !== 0) ||
98
110
  counts.input_tokens === null ||
99
111
  cached === null ||
100
112
  output === null)
101
113
  return null;
102
- const input = counts.input_tokens - (worker === "codex" ? cached : 0);
114
+ const input = counts.input_tokens -
115
+ (worker === "codex" || worker === "gemini" ? cached : 0);
103
116
  if (input < 0)
104
117
  return null;
105
118
  return priceOf((input / 1_000_000) * price.input +
@@ -1,4 +1,5 @@
1
1
  export interface TurnProfile {
2
+ readonly harness?: string;
2
3
  readonly env?: Readonly<Record<string, string>>;
3
4
  readonly allowedTools?: readonly string[];
4
5
  readonly model?: string;
@@ -1,4 +1,5 @@
1
1
  const fields = [
2
+ "harness",
2
3
  "env",
3
4
  "allowedTools",
4
5
  "model",
@@ -29,6 +30,8 @@ function environment(value) {
29
30
  text(item)));
30
31
  }
31
32
  function validField(name, value) {
33
+ if (name === "harness")
34
+ return typeof value === "string" && /^[a-z][a-z0-9-]{0,63}$/.test(value);
32
35
  if (name === "env")
33
36
  return environment(value);
34
37
  if (name === "allowedTools" || name === "workflows")
@@ -71,7 +74,11 @@ function retained(argumentsList, values) {
71
74
  for (let index = 0; index < argumentsList.length;) {
72
75
  const argument = argumentsList[index] ?? "";
73
76
  const name = argument.split("=")[0] ?? "";
74
- const flag = name === "--allowed-tools" ? "--allowedTools" : name;
77
+ const aliases = {
78
+ "--allowed-tools": "--allowedTools",
79
+ "-m": "--model",
80
+ };
81
+ const flag = aliases[name] ?? name;
75
82
  if (!values.has(flag)) {
76
83
  kept.push(argument);
77
84
  index += 1;
@@ -1,9 +1,14 @@
1
+ export type RetryKind = "capacity" | "network";
1
2
  export interface WorkerUsage {
3
+ readonly cache_creation_input_tokens?: number | null;
2
4
  readonly input_tokens: number | null;
3
5
  readonly cache_read_input_tokens: number | null;
4
6
  readonly output_tokens: number | null;
5
7
  }
6
8
  export interface WorkerTurnUsage {
9
+ readonly model?: string;
10
+ readonly summary?: string;
11
+ readonly harness?: string;
7
12
  readonly attempts?: readonly WorkerAttemptUsage[];
8
13
  readonly estimatedCostUsd: number | null;
9
14
  readonly operationId: string;
@@ -11,12 +16,19 @@ export interface WorkerTurnUsage {
11
16
  readonly costUsd: number | null;
12
17
  }
13
18
  export interface WorkerAttemptUsage {
19
+ readonly models?: readonly WorkerModelUsage[];
20
+ readonly retryKind?: RetryKind | null;
14
21
  readonly attempt: number;
15
22
  readonly model: string | null;
16
23
  readonly usage: WorkerUsage;
17
24
  readonly costUsd: number | null;
18
25
  readonly estimatedCostUsd: number | null;
19
26
  }
27
+ export interface WorkerModelUsage {
28
+ readonly model: string;
29
+ readonly usage: WorkerUsage;
30
+ }
31
+ export declare function modelUsageOf(value: unknown): readonly WorkerModelUsage[] | undefined;
20
32
  export interface WorkerTotals {
21
33
  readonly estimatedCostUsd: number | null;
22
34
  readonly workerTurns: readonly WorkerTurnUsage[];
@@ -29,3 +41,7 @@ export declare function usageOf(value: unknown): WorkerUsage;
29
41
  export declare function sumUsage(values: readonly WorkerUsage[]): WorkerUsage;
30
42
  export declare function sumPrices(values: readonly (number | null)[]): number | null;
31
43
  export declare function workerTotals(workerTurns: readonly WorkerTurnUsage[]): WorkerTotals;
44
+ export declare function attemptsOf(value: unknown): readonly WorkerAttemptUsage[] | undefined;
45
+ export declare function attemptFields(value: unknown): {
46
+ readonly attempts?: readonly WorkerAttemptUsage[];
47
+ };
@@ -1,3 +1,15 @@
1
+ export function modelUsageOf(value) {
2
+ if (!Array.isArray(value))
3
+ return undefined;
4
+ return value.flatMap((entry) => {
5
+ if (typeof entry !== "object" || entry === null)
6
+ return [];
7
+ const model = Reflect.get(entry, "model");
8
+ if (typeof model !== "string")
9
+ return [];
10
+ return [{ model, usage: usageOf(Reflect.get(entry, "usage")) }];
11
+ });
12
+ }
1
13
  export function priceOf(value) {
2
14
  return typeof value === "number" && Number.isFinite(value) && value >= 0
3
15
  ? value
@@ -11,6 +23,11 @@ export function tokenCount(value) {
11
23
  export function usageOf(value) {
12
24
  const fields = typeof value === "object" && value !== null ? value : {};
13
25
  return {
26
+ ...(Object.hasOwn(fields, "cache_creation_input_tokens")
27
+ ? {
28
+ cache_creation_input_tokens: tokenCount(Reflect.get(fields, "cache_creation_input_tokens")),
29
+ }
30
+ : {}),
14
31
  input_tokens: tokenCount(Reflect.get(fields, "input_tokens")),
15
32
  cache_read_input_tokens: tokenCount(Reflect.get(fields, "cache_read_input_tokens")),
16
33
  output_tokens: tokenCount(Reflect.get(fields, "output_tokens")),
@@ -23,6 +40,11 @@ function total(values) {
23
40
  }
24
41
  export function sumUsage(values) {
25
42
  return {
43
+ ...(values.some((value) => Object.hasOwn(value, "cache_creation_input_tokens"))
44
+ ? {
45
+ cache_creation_input_tokens: total(values.map((value) => value.cache_creation_input_tokens ?? null)),
46
+ }
47
+ : {}),
26
48
  input_tokens: total(values.map((value) => value.input_tokens)),
27
49
  cache_read_input_tokens: total(values.map((value) => value.cache_read_input_tokens)),
28
50
  output_tokens: total(values.map((value) => value.output_tokens)),
@@ -42,3 +64,38 @@ export function workerTotals(workerTurns) {
42
64
  estimatedCostUsd: sumPrices(workerTurns.map((turn) => turn.estimatedCostUsd)),
43
65
  };
44
66
  }
67
+ function retryKindField(value) {
68
+ return value === null || value === "capacity" || value === "network"
69
+ ? { retryKind: value }
70
+ : {};
71
+ }
72
+ export function attemptsOf(value) {
73
+ if (!Array.isArray(value))
74
+ return undefined;
75
+ return value.flatMap((entry) => {
76
+ const fields = typeof entry === "object" && entry !== null ? entry : {};
77
+ const field = (name) => Reflect.get(fields, name);
78
+ const attempt = tokenCount(field("attempt"));
79
+ const model = field("model");
80
+ const models = modelUsageOf(field("models"));
81
+ if (attempt === null ||
82
+ attempt === 0 ||
83
+ (model !== null && typeof model !== "string"))
84
+ return [];
85
+ return [
86
+ {
87
+ ...retryKindField(field("retryKind")),
88
+ attempt,
89
+ model,
90
+ ...(models === undefined ? {} : { models }),
91
+ usage: usageOf(field("usage")),
92
+ costUsd: priceOf(field("costUsd")),
93
+ estimatedCostUsd: priceOf(field("estimatedCostUsd")),
94
+ },
95
+ ];
96
+ });
97
+ }
98
+ export function attemptFields(value) {
99
+ const attempts = attemptsOf(value);
100
+ return attempts === undefined ? {} : { attempts };
101
+ }
@@ -1,3 +1,4 @@
1
+ import type { CommandWaits } from "./workflow-declaration.ts";
1
2
  export interface ToolchainIdentity {
2
3
  readonly sdk: string;
3
4
  readonly world: string;
@@ -23,11 +24,15 @@ export interface AdmissionPolicy {
23
24
  readonly capabilities: readonly string[];
24
25
  }
25
26
  export interface ExecutionManifest {
27
+ readonly queue?: boolean;
26
28
  readonly name: string;
27
29
  readonly workflowId: string;
28
30
  readonly steps: readonly string[];
29
31
  readonly capabilities: readonly string[];
30
32
  readonly handoffs?: readonly string[];
33
+ readonly commands?: readonly string[];
34
+ readonly commandWaits?: CommandWaits;
35
+ readonly bundleDigest?: string;
31
36
  readonly artifacts: Readonly<Record<string, string>>;
32
37
  readonly resources: Readonly<Record<string, string>>;
33
38
  readonly toolchain: ToolchainIdentity;
@@ -1,4 +1,4 @@
1
- import { type WorkflowDeclaration } from "./workflow-declaration.ts";
1
+ import { type WorkflowQueueCode, type WorkflowDeclaration } from "./workflow-declaration.ts";
2
2
  export interface CandidateDeclaration {
3
3
  readonly workflow: WorkflowDeclaration;
4
4
  readonly methods: Readonly<Record<string, readonly string[]>>;
@@ -6,12 +6,14 @@ export interface CandidateDeclaration {
6
6
  export interface CandidateImport {
7
7
  readonly module: string;
8
8
  readonly names: readonly string[];
9
+ readonly source?: string;
9
10
  }
10
11
  export interface CandidateEffect {
11
12
  readonly capability: string | null;
12
13
  readonly method: string | null;
13
14
  }
14
15
  export interface CandidateAnalysis {
16
+ readonly localSources?: readonly string[];
15
17
  readonly imports: readonly CandidateImport[];
16
18
  readonly effects: readonly CandidateEffect[];
17
19
  readonly directEffects: readonly string[];
@@ -20,10 +22,13 @@ export interface CandidateAnalysis {
20
22
  readonly knownUnitTotal: number;
21
23
  }
22
24
  export type InstalledWorkflowExports = Readonly<Record<string, readonly string[]>>;
23
- export type WorkflowCandidateCode = "invalid-declaration" | "forbidden-import" | "missing-export" | "unsupported-source" | "dynamic-effect" | "undeclared-effect" | "effect-limit" | "direct-effect";
25
+ export type WorkflowCandidateCode = WorkflowQueueCode | "invalid-declaration" | "forbidden-import" | "missing-export" | "unsupported-source" | "dynamic-effect" | "undeclared-effect" | "effect-limit" | "direct-effect";
24
26
  export interface WorkflowCandidateInput {
25
27
  readonly declaration: unknown;
26
28
  readonly analysis: CandidateAnalysis;
27
29
  readonly installedExports: InstalledWorkflowExports;
28
30
  }
31
+ export declare function workflowHelperPath(source: string, imported: string): string | undefined;
32
+ export declare function isCandidateDeclaration(value: unknown): value is CandidateDeclaration;
29
33
  export declare function checkWorkflowCandidate(input: WorkflowCandidateInput): readonly WorkflowCandidateCode[];
34
+ export declare function candidateDeclarationRefusals(value: unknown): readonly WorkflowCandidateCode[];
@@ -1,22 +1,58 @@
1
1
  import { record } from "./protocol.js";
2
- import { isWorkflowDeclaration, } from "./workflow-declaration.js";
2
+ import { isWorkflowDeclaration, workflowQueueRefusals, } from "./workflow-declaration.js";
3
3
  const workflowModules = [
4
4
  "cloving/workflows",
5
5
  "cloving/workflows/steps/decision-gate",
6
+ "cloving/workflows/steps/wait-for-decision",
7
+ "cloving/workflows/steps/review-by-person",
8
+ "cloving/workflows/steps/review-by-agent",
9
+ "cloving/workflows/steps/merge-by-person",
10
+ "cloving/workflows/steps/merge-when-green",
11
+ "cloving/workflows/steps/review-subject",
6
12
  "cloving/workflows/steps/load-cycle",
7
13
  "cloving/workflows/steps/protected-effect",
8
14
  "cloving/workflows/steps/handoff",
15
+ "cloving/workflows/steps/wait-for-run",
16
+ "cloving/workflows/steps/run-command",
17
+ "cloving/workflows/steps/sleep",
9
18
  ];
19
+ export function workflowHelperPath(source, imported) {
20
+ if (!imported.startsWith("./"))
21
+ return undefined;
22
+ const parts = [
23
+ ...source.split("/").slice(0, -1),
24
+ ...imported.slice(2).split("/"),
25
+ ];
26
+ if (parts.length < 2 ||
27
+ parts.some((part) => part.length === 0 ||
28
+ part === "." ||
29
+ part === ".." ||
30
+ part.toUpperCase() === "NODE_MODULES" ||
31
+ /[\\:\0]/.test(part) ||
32
+ part.startsWith("~")))
33
+ return undefined;
34
+ const path = parts.join("/");
35
+ return path.endsWith(".ts") && !path.endsWith(".d.ts") ? path : undefined;
36
+ }
37
+ function allowedImport(entry, analysis) {
38
+ if (workflowModules.includes(entry.module))
39
+ return true;
40
+ const path = workflowHelperPath(entry.source ?? "candidate.ts", entry.module);
41
+ return path !== undefined && (analysis.localSources ?? []).includes(path);
42
+ }
10
43
  function isMethodList(value) {
11
44
  return (Array.isArray(value) &&
12
45
  value.length > 0 &&
13
46
  Array.from(value).every((method) => typeof method === "string" && method.trim().length > 0) &&
14
47
  new Set(value).size === value.length);
15
48
  }
16
- function isCandidateDeclaration(value) {
49
+ export function isCandidateDeclaration(value) {
17
50
  const fields = record(value);
18
51
  if (!fields ||
19
- Object.keys(fields).some((key) => key !== "workflow" && key !== "methods"))
52
+ Object.keys(fields).some((key) => !["workflow", "methods", "template"].includes(key)) ||
53
+ (Object.hasOwn(fields, "template") &&
54
+ (typeof fields["template"] !== "string" ||
55
+ !/^[a-z][a-z0-9-]{0,63}$/.test(fields["template"]))))
20
56
  return false;
21
57
  const workflow = fields["workflow"];
22
58
  const methods = record(fields["methods"]);
@@ -28,10 +64,10 @@ function isCandidateDeclaration(value) {
28
64
  }
29
65
  export function checkWorkflowCandidate(input) {
30
66
  if (!isCandidateDeclaration(input.declaration))
31
- return ["invalid-declaration"];
67
+ return candidateDeclarationRefusals(input.declaration);
32
68
  const { analysis, declaration, installedExports } = input;
33
69
  const codes = [];
34
- if (analysis.imports.some((entry) => !workflowModules.includes(entry.module)))
70
+ if (analysis.imports.some((entry) => !allowedImport(entry, analysis)))
35
71
  codes.push("forbidden-import");
36
72
  if (analysis.imports.some((entry) => {
37
73
  if (!workflowModules.includes(entry.module))
@@ -58,3 +94,9 @@ export function checkWorkflowCandidate(input) {
58
94
  codes.push("unsupported-source");
59
95
  return [...new Set(codes)].sort();
60
96
  }
97
+ export function candidateDeclarationRefusals(value) {
98
+ if (isCandidateDeclaration(value))
99
+ return [];
100
+ const codes = workflowQueueRefusals(record(value)?.["workflow"]);
101
+ return codes.length > 0 ? codes : ["invalid-declaration"];
102
+ }
@@ -1,22 +1,40 @@
1
- import type { SubmissionContract } from "./submission.ts";
1
+ import { type SubmissionContract } from "./submission.ts";
2
+ import { type WorkflowSchedule } from "./workflow-schedule.ts";
2
3
  export interface WorkflowStage {
3
4
  readonly name: string;
4
5
  readonly label: string;
5
6
  readonly operations?: readonly string[];
6
7
  readonly gateKinds?: readonly ("approval" | "question")[];
8
+ readonly gateIds?: readonly string[];
7
9
  }
8
10
  export type WorkflowStages = Readonly<Record<string, readonly WorkflowStage[]>>;
11
+ export interface CommandWaitDeclaration {
12
+ readonly command: string;
13
+ readonly maximumWaitSeconds: number;
14
+ readonly pollEverySeconds: number;
15
+ }
16
+ export type CommandWaits = Readonly<Record<string, CommandWaitDeclaration>>;
9
17
  export interface WorkflowDeclaration {
10
18
  readonly workflowId: string;
11
19
  readonly effectLimit: number;
12
- readonly capabilities: readonly ("claude" | "github" | "chats")[];
20
+ readonly capabilities: readonly ("claude" | "github" | "command")[];
13
21
  readonly input: SubmissionContract;
14
22
  readonly stages?: readonly WorkflowStage[];
15
23
  readonly handoffs?: readonly string[];
24
+ readonly commands?: readonly string[];
25
+ readonly commandWaits?: CommandWaits;
26
+ readonly queue?: boolean;
27
+ readonly schedule?: WorkflowSchedule;
16
28
  }
17
29
  export interface DeclaredWorkflow extends WorkflowDeclaration {
18
30
  readonly functionName: string;
19
31
  }
32
+ export type WorkflowQueueCode = "queue-needs-ticket-field" | "queue-input-incomplete";
33
+ export declare function workflowQueueRefusals(value: unknown): readonly WorkflowQueueCode[];
20
34
  export declare function isWorkflowStages(value: unknown): value is readonly WorkflowStage[];
21
- export declare function isWorkflowHandoffs(value: unknown): value is readonly string[];
35
+ export declare function isWorkflowNames(value: unknown): value is readonly string[];
36
+ export declare function isCommandWaits(value: unknown, permissions: {
37
+ readonly capabilities: readonly string[];
38
+ readonly commands: readonly string[];
39
+ }): value is CommandWaits;
22
40
  export declare function isWorkflowDeclaration(value: unknown): value is WorkflowDeclaration;
@@ -1,4 +1,17 @@
1
1
  import { record } from "./protocol.js";
2
+ import { hasTicketField, } from "./submission.js";
3
+ import { checkWorkflowSchedule, } from "./workflow-schedule.js";
4
+ export function workflowQueueRefusals(value) {
5
+ const declaration = record(value);
6
+ if (declaration?.["queue"] !== true || !isInput(declaration["input"]))
7
+ return [];
8
+ const input = declaration["input"];
9
+ if (!hasTicketField(input))
10
+ return ["queue-needs-ticket-field"];
11
+ return Object.entries(input.fields).some(([name, rule]) => name !== "ticket" && (rule === "string" || rule.optional !== true))
12
+ ? ["queue-input-incomplete"]
13
+ : [];
14
+ }
2
15
  function keys(fields, allowed) {
3
16
  return (fields !== undefined &&
4
17
  Object.keys(fields).every((key) => allowed.includes(key)));
@@ -28,7 +41,9 @@ function isField(value) {
28
41
  return false;
29
42
  if (fields["type"] === "integer")
30
43
  return integerBounds(fields);
31
- return ((fields["type"] === "string" || fields["type"] === "boolean") &&
44
+ return ((fields["type"] === "string" ||
45
+ fields["type"] === "boolean" ||
46
+ fields["type"] === "ticket") &&
32
47
  !Object.hasOwn(fields, "minimum") &&
33
48
  !Object.hasOwn(fields, "maximum"));
34
49
  }
@@ -39,7 +54,7 @@ function isInput(value) {
39
54
  const fields = record(input["fields"]);
40
55
  return (integer(input["maximumBytes"], { minimum: 1, maximum: 1_048_576 }) &&
41
56
  fields !== undefined &&
42
- Object.values(fields).every(isField));
57
+ Object.entries(fields).every(([name, rule]) => isField(rule) && (rule.type !== "ticket" || name === "ticket")));
43
58
  }
44
59
  function matches(value, pattern) {
45
60
  return typeof value === "string" && pattern.test(value);
@@ -56,18 +71,20 @@ function isStageLabel(label) {
56
71
  }
57
72
  function isStage(value) {
58
73
  const stage = record(value);
59
- if (!keys(stage, ["name", "label", "operations", "gateKinds"]))
74
+ if (!keys(stage, ["name", "label", "operations", "gateKinds", "gateIds"]))
60
75
  return false;
61
76
  const { name, label } = stage;
62
77
  const operations = Object.hasOwn(stage, "operations")
63
78
  ? stage["operations"]
64
79
  : [];
65
80
  const gateKinds = Object.hasOwn(stage, "gateKinds") ? stage["gateKinds"] : [];
81
+ const gateIds = Object.hasOwn(stage, "gateIds") ? stage["gateIds"] : [];
66
82
  return (matches(name, /^[A-Za-z0-9-]{1,64}$/) &&
67
83
  isStageLabel(label) &&
68
84
  selectors(operations, /^[A-Za-z0-9._:/-]{1,128}$/) &&
69
85
  selectors(gateKinds, /^(approval|question)$/) &&
70
- operations.length + gateKinds.length > 0);
86
+ selectors(gateIds, /^[A-Za-z0-9._:/-]{1,128}$/) &&
87
+ operations.length + gateKinds.length + gateIds.length > 0);
71
88
  }
72
89
  function unique(values) {
73
90
  return new Set(values).size === values.length;
@@ -81,18 +98,55 @@ export function isWorkflowStages(value) {
81
98
  return (unique(stages.map((stage) => stage.name)) &&
82
99
  unique(stages.map((stage) => stage.label)) &&
83
100
  unique(stages.flatMap((stage) => stage.operations ?? [])) &&
84
- unique(stages.flatMap((stage) => stage.gateKinds ?? [])));
101
+ unique(stages.flatMap((stage) => stage.gateKinds ?? [])) &&
102
+ unique(stages.flatMap((stage) => stage.gateIds ?? [])));
85
103
  }
86
104
  function isCapabilities(value) {
87
105
  return (Array.isArray(value) &&
88
106
  value.length > 0 &&
89
107
  value.every((capability) => capability === "claude" ||
90
108
  capability === "github" ||
91
- capability === "chats"));
109
+ capability === "command"));
92
110
  }
93
- export function isWorkflowHandoffs(value) {
111
+ export function isWorkflowNames(value) {
94
112
  return selectors(value, /^[A-Za-z0-9-]{1,64}$/) && unique(value);
95
113
  }
114
+ function declaredCommands(declaration, capabilities) {
115
+ const commands = declaration["commands"];
116
+ if (Object.hasOwn(declaration, "commands") && !isWorkflowNames(commands))
117
+ return false;
118
+ return ((!capabilities.includes("command") ||
119
+ (Array.isArray(commands) && commands.length > 0)) &&
120
+ declaredCommandWaits(declaration, capabilities));
121
+ }
122
+ function isCommandWait(value) {
123
+ const wait = record(value);
124
+ if (!keys(wait, ["command", "maximumWaitSeconds", "pollEverySeconds"]))
125
+ return false;
126
+ return (typeof wait["command"] === "string" &&
127
+ integer(wait["maximumWaitSeconds"], { minimum: 60, maximum: 2_592_000 }) &&
128
+ integer(wait["pollEverySeconds"], { minimum: 60, maximum: 86_400 }) &&
129
+ Number(wait["pollEverySeconds"]) <= Number(wait["maximumWaitSeconds"]));
130
+ }
131
+ export function isCommandWaits(value, permissions) {
132
+ const waits = record(value);
133
+ if (waits === undefined)
134
+ return false;
135
+ return Object.entries(waits).every(([name, wait]) => matches(name, /^[A-Za-z0-9-]{1,64}$/) &&
136
+ name.trim() === name &&
137
+ isCommandWait(wait) &&
138
+ permissions.capabilities.includes("command") &&
139
+ permissions.commands.includes(wait.command));
140
+ }
141
+ function declaredCommandWaits(declaration, capabilities) {
142
+ if (!Object.hasOwn(declaration, "commandWaits"))
143
+ return true;
144
+ const commands = declaration["commands"];
145
+ return isCommandWaits(declaration["commandWaits"], {
146
+ capabilities,
147
+ commands: isWorkflowNames(commands) ? commands : [],
148
+ });
149
+ }
96
150
  export function isWorkflowDeclaration(value) {
97
151
  const declaration = record(value);
98
152
  if (!keys(declaration, [
@@ -102,14 +156,28 @@ export function isWorkflowDeclaration(value) {
102
156
  "input",
103
157
  "stages",
104
158
  "handoffs",
159
+ "commands",
160
+ "commandWaits",
161
+ "queue",
162
+ "schedule",
105
163
  ]))
106
164
  return false;
107
- const { workflowId, effectLimit, capabilities, input, handoffs } = declaration;
165
+ const { workflowId, effectLimit, capabilities, input } = declaration;
108
166
  return (matches(workflowId, /^[A-Za-z0-9-]{1,64}$/) &&
109
167
  integer(effectLimit, { minimum: 1, maximum: 100 }) &&
110
168
  isCapabilities(capabilities) &&
169
+ declaredCommands(declaration, capabilities) &&
111
170
  isInput(input) &&
171
+ declaredOptions(declaration, input));
172
+ }
173
+ function declaredOptions(declaration, input) {
174
+ return ((!Object.hasOwn(declaration, "queue") ||
175
+ typeof declaration["queue"] === "boolean") &&
176
+ workflowQueueRefusals(declaration).length === 0 &&
112
177
  (!Object.hasOwn(declaration, "stages") ||
113
178
  isWorkflowStages(declaration["stages"])) &&
114
- (!Object.hasOwn(declaration, "handoffs") || isWorkflowHandoffs(handoffs)));
179
+ (!Object.hasOwn(declaration, "handoffs") ||
180
+ isWorkflowNames(declaration["handoffs"])) &&
181
+ (!Object.hasOwn(declaration, "schedule") ||
182
+ checkWorkflowSchedule(input, declaration["schedule"]).kind === "valid"));
115
183
  }
@@ -4,11 +4,12 @@ export interface WorkflowReservation {
4
4
  readonly functionName?: string;
5
5
  }
6
6
  export interface WorkflowDiscoveryIdentity {
7
+ readonly queue?: boolean;
7
8
  readonly baseName: string;
8
9
  readonly workflowId: string | undefined;
9
10
  readonly functionNames: readonly string[];
10
11
  }
11
- export type WorkflowConflictCode = "workflow-conflict" | "bundled-name-reserved";
12
+ export type WorkflowConflictCode = "workflow-conflict" | "bundled-name-reserved" | "queue-workflow-conflict";
12
13
  export declare function workflowConflicts(candidates: readonly WorkflowDiscoveryIdentity[], bundled: readonly WorkflowReservation[]): readonly (readonly WorkflowConflictCode[])[];
13
14
  export declare const bundledWorkflowIds: {
14
15
  readonly ticket: "develop-ticket";
@@ -16,8 +16,11 @@ export function workflowConflicts(candidates, bundled) {
16
16
  ...entry,
17
17
  functionNames: entry.functionName === undefined ? [] : [entry.functionName],
18
18
  })));
19
- return keys.map((names) => {
19
+ const queued = candidates.filter((candidate) => candidate.queue === true);
20
+ return keys.map((names, index) => {
20
21
  const codes = [];
22
+ if (queued.length > 1 && candidates[index]?.queue === true)
23
+ codes.push("queue-workflow-conflict");
21
24
  if (names.some((name) => reserved.has(name)))
22
25
  codes.push("bundled-name-reserved");
23
26
  if (names.some((name) => (counts.get(name) ?? 0) > 1))
@@ -1,6 +1,9 @@
1
1
  import { record } from "./protocol.js";
2
2
  const refusalCodes = new Set([
3
3
  "invalid-declaration",
4
+ "queue-needs-ticket-field",
5
+ "queue-input-incomplete",
6
+ "queue-workflow-conflict",
4
7
  "forbidden-import",
5
8
  "missing-export",
6
9
  "unsupported-source",
@@ -0,0 +1,22 @@
1
+ import { type Fields } from "./protocol.ts";
2
+ import { type SubmissionContract } from "./submission.ts";
3
+ export interface WorkflowSchedule {
4
+ readonly everySeconds: number;
5
+ readonly input: Fields;
6
+ }
7
+ export type ScheduleCheck = {
8
+ readonly kind: "valid";
9
+ readonly schedule: WorkflowSchedule;
10
+ } | {
11
+ readonly kind: "rejected";
12
+ readonly code: string;
13
+ };
14
+ interface ScheduleSource {
15
+ readonly workflowId: string;
16
+ readonly input: SubmissionContract;
17
+ readonly schedule?: WorkflowSchedule;
18
+ }
19
+ export declare function parseSchedulesSetting(value: string | undefined): unknown;
20
+ export declare function configuredSchedules(declarations: readonly ScheduleSource[], overrides: unknown): Readonly<Record<string, WorkflowSchedule>>;
21
+ export declare function checkWorkflowSchedule(contract: SubmissionContract, value: unknown): ScheduleCheck;
22
+ export {};
@@ -0,0 +1,53 @@
1
+ import { record } from "./protocol.js";
2
+ import { checkSubmission } from "./submission.js";
3
+ export function parseSchedulesSetting(value) {
4
+ try {
5
+ return JSON.parse(value ?? "{}");
6
+ }
7
+ catch {
8
+ throw new Error("invalid-schedules");
9
+ }
10
+ }
11
+ export function configuredSchedules(declarations, overrides) {
12
+ const settings = record(overrides);
13
+ if (settings === undefined)
14
+ throw new Error("invalid-schedules");
15
+ if (Object.keys(settings).some((id) => !declarations.some((entry) => entry.workflowId === id)))
16
+ throw new Error("unknown-schedule-workflow");
17
+ const schedules = [];
18
+ for (const declaration of declarations) {
19
+ const { workflowId } = declaration;
20
+ const selected = Object.hasOwn(settings, workflowId)
21
+ ? settings[workflowId]
22
+ : declaration.schedule;
23
+ if (selected === undefined && !Object.hasOwn(settings, workflowId))
24
+ continue;
25
+ const checked = checkWorkflowSchedule(declaration.input, selected);
26
+ if (checked.kind === "rejected")
27
+ throw new Error(checked.code);
28
+ schedules.push([workflowId, checked.schedule]);
29
+ }
30
+ return Object.fromEntries(schedules);
31
+ }
32
+ export function checkWorkflowSchedule(contract, value) {
33
+ const fields = record(value);
34
+ const seconds = fields?.["everySeconds"];
35
+ if (fields === undefined ||
36
+ Object.keys(fields).some((key) => !["everySeconds", "input"].includes(key)) ||
37
+ typeof seconds !== "number" ||
38
+ !Number.isInteger(seconds) ||
39
+ seconds < 60 ||
40
+ seconds > 86400)
41
+ return { kind: "rejected", code: "invalid-schedule-interval" };
42
+ const checked = checkSubmission(contract, {
43
+ workflowId: "schedule",
44
+ source: "declared",
45
+ submission: fields["input"],
46
+ });
47
+ if (checked.kind === "rejected")
48
+ return { kind: "rejected", code: "invalid-schedule-input" };
49
+ return {
50
+ kind: "valid",
51
+ schedule: { everySeconds: seconds, input: checked.submission },
52
+ };
53
+ }