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
@@ -0,0 +1,264 @@
1
+ import { spawn } from "node:child_process";
2
+ import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
3
+ import { tmpdir } from "node:os";
4
+ import { join, resolve } from "node:path";
5
+ import { pathToFileURL } from "node:url";
6
+ import { workflowTestLoader } from "../tools/workflow-test-loader.js";
7
+ import { authorizeEffect } from "./effect-authorization.js";
8
+ import { record } from "./protocol.js";
9
+ import { stepBridgeKey, } from "./step-bridge.js";
10
+ export function fakeStepBridge(scenario) {
11
+ const { bridge, requests, budget } = scenarioBridge(scenario);
12
+ const key = Symbol.for(stepBridgeKey);
13
+ const sleepKey = Symbol.for("WORKFLOW_SLEEP");
14
+ const previous = Object.getOwnPropertyDescriptor(globalThis, key);
15
+ const previousSleep = Object.getOwnPropertyDescriptor(globalThis, sleepKey);
16
+ if (Reflect.get(globalThis, key) !== undefined ||
17
+ Reflect.get(globalThis, sleepKey) !== undefined)
18
+ throw new Error("workflow-testing-host-active");
19
+ if (previous?.configurable === false || previousSleep?.configurable === false)
20
+ throw new Error("workflow-testing-host-locked");
21
+ Object.defineProperty(globalThis, key, { configurable: true, value: bridge });
22
+ Object.defineProperty(globalThis, sleepKey, {
23
+ configurable: true,
24
+ value: (milliseconds) => {
25
+ requests.push(["sleep", { seconds: milliseconds / 1000 }]);
26
+ return Promise.resolve();
27
+ },
28
+ });
29
+ return {
30
+ requests,
31
+ get spent() {
32
+ return budget.spent;
33
+ },
34
+ [Symbol.dispose]() {
35
+ if (previous === undefined)
36
+ Reflect.deleteProperty(globalThis, key);
37
+ else
38
+ Object.defineProperty(globalThis, key, previous);
39
+ if (previousSleep === undefined)
40
+ Reflect.deleteProperty(globalThis, sleepKey);
41
+ else
42
+ Object.defineProperty(globalThis, sleepKey, previousSleep);
43
+ },
44
+ };
45
+ }
46
+ function scenarioBridge(scenario) {
47
+ const requests = [];
48
+ const waits = [...(scenario.waits ?? [])];
49
+ const decisions = [...(scenario.decisions ?? [])];
50
+ const budget = { spent: 0 };
51
+ const bridge = {
52
+ ...scenarioEffects(scenario, { requests, budget }),
53
+ gate: (request) => {
54
+ requests.push(["gate", request]);
55
+ return Promise.resolve(scenario.gate ?? {
56
+ kind: "unavailable",
57
+ reason: "no-scenario-result",
58
+ });
59
+ },
60
+ waitForDecision: (request) => {
61
+ requests.push(["waitForDecision", request]);
62
+ const decision = decisions.shift();
63
+ if (decision === undefined)
64
+ return Promise.reject(new Error("no-scenario-result"));
65
+ return Promise.resolve(decision);
66
+ },
67
+ waitForRun: (request) => {
68
+ requests.push(["waitForRun", request]);
69
+ return Promise.resolve(waits.shift() ?? {
70
+ kind: "unavailable",
71
+ reason: "no-scenario-result",
72
+ promotionId: null,
73
+ });
74
+ },
75
+ };
76
+ return { bridge, requests, budget };
77
+ }
78
+ function scenarioEffects(scenario, state) {
79
+ const { requests, budget } = state;
80
+ const effects = new Map(Object.entries(scenario.effects ?? {}).map(([key, values]) => [
81
+ key,
82
+ [...values],
83
+ ]));
84
+ return {
85
+ effect: (request) => {
86
+ requests.push(["effect", request]);
87
+ const refusal = spend(scenario, { budget, request });
88
+ if (refusal !== undefined)
89
+ return Promise.resolve(refusal);
90
+ const result = scenario.effects === undefined
91
+ ? scenario.turn
92
+ : effects.get(request.capability + " " + request.method)?.shift();
93
+ return Promise.resolve(result ?? { kind: "unavailable", reason: "no-scenario-result" });
94
+ },
95
+ handoff: (request) => {
96
+ requests.push(["handoff", request]);
97
+ const refusal = spend(scenario, {
98
+ budget,
99
+ request: { capability: "handoff", units: 1 },
100
+ });
101
+ if (refusal !== undefined)
102
+ return Promise.resolve(refusal);
103
+ return Promise.resolve(effects.get("handoff")?.shift() ?? {
104
+ kind: "completed",
105
+ operationId: "handoff",
106
+ receipt: null,
107
+ result: "target-run",
108
+ });
109
+ },
110
+ };
111
+ }
112
+ function spend(scenario, effect) {
113
+ const { budget, request } = effect;
114
+ if (scenario.effectLimit === undefined)
115
+ return undefined;
116
+ const allowed = authorizeEffect({ capabilities: ["claude", "github", "command", "handoff"] }, {
117
+ budget: { limit: scenario.effectLimit, spent: budget.spent },
118
+ request,
119
+ });
120
+ if (allowed.kind === "rejected")
121
+ return { kind: "refused", reason: allowed.reason };
122
+ budget.spent = allowed.spent;
123
+ return undefined;
124
+ }
125
+ function scenarioScript(scenario) {
126
+ const workflow = scenario.workflow.startsWith("file:")
127
+ ? scenario.workflow
128
+ : pathToFileURL(resolve(scenario.workflow)).href;
129
+ return `import { writeFile } from "node:fs/promises";
130
+ import { fakeStepBridge } from ${JSON.stringify(import.meta.url)};
131
+ import * as workflows from ${JSON.stringify(workflow)};
132
+ const given = ${JSON.stringify(scenario)};
133
+ const workflow = workflows[given.exportName];
134
+ if (typeof workflow !== "function") throw new Error("workflow-test-export-missing");
135
+ using bridge = fakeStepBridge(given);
136
+ const outcome = await workflow(given.input, given.decision);
137
+ await writeFile(process.argv[2], JSON.stringify({ outcome, requests: bridge.requests,
138
+ ...(given.effectLimit === undefined ? {} : { spent: bridge.spent }) }));`;
139
+ }
140
+ function scenarioResult(value) {
141
+ const result = record(value);
142
+ return (result !== undefined &&
143
+ Object.hasOwn(result, "outcome") &&
144
+ Array.isArray(result["requests"]) &&
145
+ result["requests"].every(scenarioRequest) &&
146
+ (result["spent"] === undefined || typeof result["spent"] === "number"));
147
+ }
148
+ function scenarioRequest(value) {
149
+ if (!Array.isArray(value) || value.length !== 2)
150
+ return false;
151
+ const request = record(value[1]);
152
+ if (request === undefined)
153
+ return false;
154
+ switch (value[0]) {
155
+ case "effect":
156
+ return protectedRequest(request);
157
+ case "gate":
158
+ case "waitForDecision":
159
+ return gateRequest(request);
160
+ case "handoff":
161
+ return handoffRequest(request);
162
+ case "waitForRun":
163
+ return runWaitRequest(request);
164
+ case "sleep":
165
+ return sleepRequest(request);
166
+ default:
167
+ return false;
168
+ }
169
+ }
170
+ function runWaitRequest(request) {
171
+ return (typeof request["runId"] === "string" &&
172
+ typeof request["maximumWaitSeconds"] === "number");
173
+ }
174
+ function sleepRequest(request) {
175
+ const seconds = request["seconds"];
176
+ return (typeof seconds === "number" &&
177
+ Number.isInteger(seconds) &&
178
+ seconds >= 1 &&
179
+ seconds <= 86400);
180
+ }
181
+ function gateRequest(request) {
182
+ return (typeof request["gateId"] === "string" &&
183
+ (request["kind"] === "question" || request["kind"] === "approval") &&
184
+ typeof request["prompt"] === "string" &&
185
+ optionalText(request["expiresAt"]));
186
+ }
187
+ function handoffRequest(request) {
188
+ const input = record(request["input"]);
189
+ return (typeof request["workflowId"] === "string" &&
190
+ input !== undefined &&
191
+ Object.values(input).every(handoffValue));
192
+ }
193
+ function protectedRequest(request) {
194
+ return (protectedScope(request["scope"]) &&
195
+ ["capability", "method", "target", "payload"].every((key) => typeof request[key] === "string") &&
196
+ typeof request["units"] === "number" &&
197
+ optionalText(request["resource"]));
198
+ }
199
+ function protectedScope(value) {
200
+ const scope = record(value);
201
+ if (scope === undefined)
202
+ return false;
203
+ const stage = record(scope["stage"]);
204
+ return (typeof scope["phase"] === "string" &&
205
+ typeof scope["operation"] === "string" &&
206
+ typeof scope["round"] === "number" &&
207
+ optionalText(scope["key"]) &&
208
+ (scope["stage"] === undefined ||
209
+ (stage !== undefined &&
210
+ ["id", "visit", "branch"].every((key) => typeof stage[key] === "string"))));
211
+ }
212
+ function optionalText(value) {
213
+ return value === undefined || typeof value === "string";
214
+ }
215
+ function handoffValue(value) {
216
+ if (value === null || ["string", "boolean", "number"].includes(typeof value))
217
+ return true;
218
+ if (Array.isArray(value))
219
+ return value.every(handoffValue);
220
+ const fields = record(value);
221
+ return fields !== undefined && Object.values(fields).every(handoffValue);
222
+ }
223
+ export async function runScenario(scenario) {
224
+ const temporary = await mkdtemp(join(tmpdir(), "cloving-scenario-"));
225
+ try {
226
+ const script = join(temporary, "scenario.mjs");
227
+ const resultFile = join(temporary, "result.json");
228
+ await writeFile(script, scenarioScript(scenario));
229
+ await executeScenario(script, resultFile);
230
+ const value = JSON.parse(await readFile(resultFile, "utf8"));
231
+ if (!scenarioResult(value))
232
+ throw new Error("invalid-workflow-scenario-result");
233
+ return value;
234
+ }
235
+ finally {
236
+ await rm(temporary, { recursive: true, force: true });
237
+ }
238
+ }
239
+ function executeScenario(script, resultFile) {
240
+ return new Promise((settle, reject) => {
241
+ const child = spawn(process.execPath, [
242
+ "--experimental-strip-types",
243
+ "--import",
244
+ workflowTestLoader(),
245
+ script,
246
+ resultFile,
247
+ ], {
248
+ env: { ...process.env, NODE_TEST_CONTEXT: undefined },
249
+ stdio: ["ignore", "ignore", "pipe"],
250
+ });
251
+ let diagnostics = "";
252
+ child.stderr.setEncoding("utf8");
253
+ child.stderr.on("data", (text) => {
254
+ diagnostics = (diagnostics + text).slice(-65536);
255
+ });
256
+ child.once("error", reject);
257
+ child.once("close", (code, signal) => {
258
+ if (code === 0)
259
+ settle();
260
+ else
261
+ reject(new Error(`workflow-scenario-failed: ${String(code ?? signal)}\n${diagnostics}`));
262
+ });
263
+ });
264
+ }
@@ -0,0 +1 @@
1
+ export declare function hardDependencies(ticket: string): readonly string[];
@@ -0,0 +1,15 @@
1
+ export function hardDependencies(ticket) {
2
+ const lines = ticket.split(/\r?\n/);
3
+ const start = lines.findIndex((line) => /^## Dependencies\s*$/.test(line));
4
+ if (start === -1)
5
+ return [];
6
+ const following = lines.slice(start + 1);
7
+ const end = following.findIndex((line) => /^#{1,2} /.test(line));
8
+ const section = (end === -1 ? following : following.slice(0, end)).join("\n");
9
+ const sentences = section
10
+ .replace(/\b(?:e\.g|i\.e)\./g, "example")
11
+ .matchAll(/(?:^|[.!?]\s+|\n)\s*(?:[-*+]\s+|\d+\.\s+)?Needs\b([\s\S]*?)(?=[.!?](?:\s|$)|$)/g);
12
+ return [
13
+ ...new Set([...sentences].flatMap((sentence) => [...String(sentence[1]).matchAll(/#([1-9]\d*)\b/g)].map((match) => String(match[1])))),
14
+ ];
15
+ }
@@ -0,0 +1,9 @@
1
+ import { type TicketStatus } from "./ticket-status.ts";
2
+ export interface StreamedTicketStatus {
3
+ readonly ticketStatus: TicketStatus;
4
+ readonly ticketStatusTooLarge?: true;
5
+ }
6
+ export declare function ticketStatusStream(limit: number): {
7
+ write: (chunk: string) => void;
8
+ result: () => StreamedTicketStatus;
9
+ };
@@ -0,0 +1,94 @@
1
+ import { ticketStatus } from "./ticket-status.js";
2
+ function emptyLine() {
3
+ return {
4
+ text: "",
5
+ length: 0,
6
+ contentLength: 0,
7
+ breaks: 0,
8
+ trailingCarriage: false,
9
+ };
10
+ }
11
+ function remainingLine(stream, line) {
12
+ if (line.length <= stream.limit && line.text === "Remaining:") {
13
+ stream.remaining = [];
14
+ stream.characters = 0;
15
+ stream.valid = true;
16
+ return;
17
+ }
18
+ if (!stream.valid)
19
+ return;
20
+ if (line.breaks > 0 || !/^- \S.*$/.test(line.text)) {
21
+ stream.valid = false;
22
+ return;
23
+ }
24
+ stream.characters = Math.min(stream.limit + 1, stream.characters + line.length + 1);
25
+ if (stream.characters <= stream.limit)
26
+ stream.remaining.push(line.text.slice(2));
27
+ }
28
+ function receivedLine(stream) {
29
+ const line = stream.line;
30
+ stream.line = emptyLine();
31
+ if (line.contentLength === 0)
32
+ return;
33
+ if (line.trailingCarriage)
34
+ line.breaks--;
35
+ if (line.length <= stream.limit + 1 && line.trailingCarriage) {
36
+ line.text = line.text.slice(0, -1);
37
+ line.length--;
38
+ }
39
+ if (stream.last !== undefined)
40
+ remainingLine(stream, stream.last);
41
+ if (/^Ticket status:/i.test(line.text))
42
+ stream.statuses = Math.min(2, stream.statuses + 1);
43
+ stream.last = line;
44
+ }
45
+ function writeStatus(stream, chunk) {
46
+ const parts = chunk.split("\n");
47
+ for (const [index, part] of parts.entries()) {
48
+ const { line, limit } = stream;
49
+ const content = part.trimEnd();
50
+ line.breaks = Math.min(2, line.breaks + (part.match(/[\r\u2028\u2029]/g)?.length ?? 0));
51
+ if (part !== "")
52
+ line.trailingCarriage = part.endsWith("\r");
53
+ if (content !== "")
54
+ line.contentLength = Math.min(limit + 1, line.length + content.length);
55
+ line.text = (line.text + part).slice(0, limit + 1);
56
+ line.length = Math.min(limit + 2, line.length + part.length);
57
+ if (index < parts.length - 1)
58
+ receivedLine(stream);
59
+ }
60
+ }
61
+ function statusResult(stream) {
62
+ receivedLine(stream);
63
+ const last = stream.last;
64
+ if (stream.statuses !== 1 || last === undefined)
65
+ return { ticketStatus: ticketStatus("") };
66
+ const status = last.contentLength > stream.limit ? "" : last.text.trimEnd();
67
+ if (status !== "Ticket status: partial" || !stream.valid)
68
+ return { ticketStatus: ticketStatus(status) };
69
+ if (stream.characters > stream.limit)
70
+ return {
71
+ ticketStatus: ticketStatus(status),
72
+ ticketStatusTooLarge: true,
73
+ };
74
+ return {
75
+ ticketStatus: ticketStatus(`Remaining:\n${stream.remaining.map((item) => `- ${item}`).join("\n")}\n${status}`),
76
+ };
77
+ }
78
+ export function ticketStatusStream(limit) {
79
+ const stream = {
80
+ limit,
81
+ line: emptyLine(),
82
+ last: undefined,
83
+ statuses: 0,
84
+ remaining: [],
85
+ characters: 0,
86
+ valid: false,
87
+ };
88
+ return {
89
+ write: (chunk) => {
90
+ writeStatus(stream, chunk);
91
+ },
92
+ result: () => statusResult(stream),
93
+ };
94
+ }
@@ -8,11 +8,14 @@ function parsedStatus(summary) {
8
8
  if (status !== "Ticket status: partial")
9
9
  return undefined;
10
10
  const heading = lines.lastIndexOf("Remaining:");
11
- if (heading === -1)
12
- return undefined;
13
- const items = lines.slice(heading + 1);
11
+ const items = heading === -1
12
+ ? []
13
+ : lines.slice(heading + 1).filter((line) => line.trim() !== "");
14
14
  if (items.length === 0 || items.some((line) => !/^- \S.*$/.test(line)))
15
- return undefined;
15
+ return {
16
+ kind: "partial",
17
+ remaining: ["The worker report has an unreadable Remaining: list."],
18
+ };
16
19
  return { kind: "partial", remaining: items.map((line) => line.slice(2)) };
17
20
  }
18
21
  function preservedStatus(value) {
@@ -1,4 +1,5 @@
1
- import { type WorkerUsage } from "./worker-usage.ts";
1
+ import { type WorkerUsage, type WorkerModelUsage } from "./worker-usage.ts";
2
+ import type { NativeHarness } from "./harness-defaults.ts";
2
3
  export interface TokenPrice {
3
4
  readonly input: number;
4
5
  readonly cachedInput: number;
@@ -11,9 +12,18 @@ export declare const builtInPriceTable: {
11
12
  readonly prices: TokenPrices;
12
13
  };
13
14
  export declare function parseTokenPrices(value: string | undefined): TokenPrices;
15
+ export declare function parseFallbackModels(value: string | undefined): readonly string[];
14
16
  export declare function priceForModel(prices: TokenPrices, model: string | null): TokenPrice | undefined;
15
17
  export declare function commandModel(command: readonly string[]): string | null;
16
- export declare function estimatedCostUsd(usage: WorkerUsage, pricing: {
17
- readonly worker: "claude" | "codex";
18
+ export declare function replaceCommandModel(command: readonly string[], model: string): readonly string[];
19
+ interface SinglePricing {
20
+ readonly worker: NativeHarness;
18
21
  readonly price: TokenPrice | undefined;
19
- }): number | null;
22
+ }
23
+ interface ModelPricing {
24
+ readonly worker: "gemini";
25
+ readonly models: readonly WorkerModelUsage[];
26
+ readonly prices: TokenPrices;
27
+ }
28
+ export declare function estimatedCostUsd(usage: WorkerUsage, pricing: SinglePricing | ModelPricing): number | null;
29
+ export {};
@@ -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",
@@ -36,38 +36,83 @@ export function parseTokenPrices(value) {
36
36
  throw new Error("Invalid CLOVING_TOKEN_PRICES");
37
37
  }
38
38
  }
39
+ export function parseFallbackModels(value) {
40
+ if (value === undefined)
41
+ return [];
42
+ try {
43
+ const models = JSON.parse(value);
44
+ if (Array.isArray(models) &&
45
+ models.length <= 3 &&
46
+ models.every((model) => typeof model === "string" && model.trim().length > 0))
47
+ return models.map(String);
48
+ }
49
+ catch {
50
+ throw new Error("The daemon did not start: invalid-fallback-models");
51
+ }
52
+ throw new Error("The daemon did not start: invalid-fallback-models");
53
+ }
39
54
  export function priceForModel(prices, model) {
40
55
  return model !== null && Object.hasOwn(prices, model)
41
56
  ? prices[model]
42
57
  : undefined;
43
58
  }
44
- export function commandModel(command) {
45
- let model = null;
46
- for (let index = 1; index < command.length; index += 1) {
59
+ function modelIndex(command) {
60
+ let selected;
61
+ const separator = command.indexOf("--", 1);
62
+ const end = separator === -1 ? command.length : separator;
63
+ for (let index = 1; index < end; index += 1) {
47
64
  const argument = command[index] ?? "";
48
- if (argument === "--")
49
- break;
50
65
  if (argument.startsWith("--model="))
51
- model = argument.slice(8) || null;
52
- if (argument === "--model" || argument === "-m") {
66
+ selected = argument.slice(8) ? index : undefined;
67
+ if (["--model", "-m"].includes(argument)) {
53
68
  const next = command[index + 1];
54
- model = next && !next.startsWith("-") ? next : null;
69
+ selected = next && !next.startsWith("-") ? index + 1 : undefined;
55
70
  index += 1;
56
71
  }
57
72
  }
58
- return model;
73
+ return selected;
74
+ }
75
+ export function commandModel(command) {
76
+ const index = modelIndex(command);
77
+ if (index === undefined)
78
+ return null;
79
+ const argument = command[index] ?? "";
80
+ return argument.startsWith("--model=") ? argument.slice(8) : argument;
81
+ }
82
+ export function replaceCommandModel(command, model) {
83
+ const index = modelIndex(command);
84
+ if (index === undefined)
85
+ return command;
86
+ return command.map((argument, position) => {
87
+ if (position !== index)
88
+ return argument;
89
+ return argument.startsWith("--model=") ? `--model=${model}` : model;
90
+ });
59
91
  }
60
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) {
61
104
  const { worker, price } = pricing;
62
105
  const counts = usageOf(usage);
63
106
  const cached = counts.cache_read_input_tokens;
64
107
  const output = counts.output_tokens;
65
108
  if (price === undefined ||
109
+ (worker === "cursor-agent" && counts.cache_creation_input_tokens !== 0) ||
66
110
  counts.input_tokens === null ||
67
111
  cached === null ||
68
112
  output === null)
69
113
  return null;
70
- const input = counts.input_tokens - (worker === "codex" ? cached : 0);
114
+ const input = counts.input_tokens -
115
+ (worker === "codex" || worker === "gemini" ? cached : 0);
71
116
  if (input < 0)
72
117
  return null;
73
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,14 +1,34 @@
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;
12
+ readonly attempts?: readonly WorkerAttemptUsage[];
7
13
  readonly estimatedCostUsd: number | null;
8
14
  readonly operationId: string;
9
15
  readonly usage: WorkerUsage;
10
16
  readonly costUsd: number | null;
11
17
  }
18
+ export interface WorkerAttemptUsage {
19
+ readonly models?: readonly WorkerModelUsage[];
20
+ readonly retryKind?: RetryKind | null;
21
+ readonly attempt: number;
22
+ readonly model: string | null;
23
+ readonly usage: WorkerUsage;
24
+ readonly costUsd: number | null;
25
+ readonly estimatedCostUsd: number | null;
26
+ }
27
+ export interface WorkerModelUsage {
28
+ readonly model: string;
29
+ readonly usage: WorkerUsage;
30
+ }
31
+ export declare function modelUsageOf(value: unknown): readonly WorkerModelUsage[] | undefined;
12
32
  export interface WorkerTotals {
13
33
  readonly estimatedCostUsd: number | null;
14
34
  readonly workerTurns: readonly WorkerTurnUsage[];
@@ -19,4 +39,9 @@ export declare function priceOf(value: unknown): number | null;
19
39
  export declare function tokenCount(value: unknown): number | null;
20
40
  export declare function usageOf(value: unknown): WorkerUsage;
21
41
  export declare function sumUsage(values: readonly WorkerUsage[]): WorkerUsage;
42
+ export declare function sumPrices(values: readonly (number | null)[]): number | null;
22
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
+ };