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
package/dist/src/cli.js CHANGED
@@ -1,11 +1,27 @@
1
1
  #!/usr/bin/env node
2
+ import { createProbeRunner } from "./cli/probe-command.js";
3
+ import { settingsEnvironment } from "./cli/project-settings.js";
2
4
  import { addAbortListener } from "node:events";
3
- import { execFile, spawn } from "node:child_process";
4
- import { delimiter, dirname, extname, join } from "node:path";
5
+ import { execFile, execFileSync, spawn } from "node:child_process";
6
+ import { existsSync, realpathSync } from "node:fs";
7
+ import { parseArgs } from "node:util";
8
+ import { delimiter, dirname, extname, join, resolve } from "node:path";
5
9
  import { main } from "./cli/main.js";
6
- import { clientCommand, runtimeDirectory } from "./cli/runtime-directory.js";
10
+ import { parseInvocation } from "./cli/arguments.js";
11
+ import { adoptionRecordPath, clientCommand, legacyRuntimeDirectory, runtimeDirectory, } from "./cli/runtime-directory.js";
7
12
  import { commandUsage } from "./cli/usage.js";
8
13
  const [command, ...options] = process.argv.slice(2);
14
+ function repositoryDirectory(directory) {
15
+ try {
16
+ return realpathSync(execFileSync("git", ["-C", resolve(directory), "rev-parse", "--show-toplevel"], {
17
+ encoding: "utf8",
18
+ stdio: ["ignore", "pipe", "ignore"],
19
+ }).trim());
20
+ }
21
+ catch {
22
+ return undefined;
23
+ }
24
+ }
9
25
  const watchCommand = async (request) => {
10
26
  const [command = "", ...argumentsList] = request.command;
11
27
  const completed = Promise.withResolvers();
@@ -42,17 +58,30 @@ const watchCommand = async (request) => {
42
58
  listener[Symbol.dispose]();
43
59
  }
44
60
  };
45
- function started(runtime, argumentsList) {
46
- const program = join(import.meta.dirname, "..", "tools", `self-host${extname(import.meta.filename)}`);
61
+ function startArguments(input) {
62
+ const { runtime, repository, argumentsList } = input;
47
63
  const located = [
48
64
  "--runtime",
49
- runtime,
65
+ runtimeDirectory(process.env, repository) ?? runtime,
50
66
  "--repository",
51
- process.cwd(),
67
+ repository ?? process.cwd(),
52
68
  "--client",
53
- clientCommand(process.env),
69
+ clientCommand(process.env, repository),
54
70
  ];
55
- const child = spawn(process.execPath, [program, ...located, ...argumentsList], {
71
+ const record = repository === undefined
72
+ ? undefined
73
+ : adoptionRecordPath(process.env, repository);
74
+ const legacy = legacyRuntimeDirectory(process.env);
75
+ if (!process.env["CLOVING_RUNTIME_DIR"] &&
76
+ record !== undefined &&
77
+ !existsSync(record) &&
78
+ legacy !== undefined)
79
+ located.push("--legacy-runtime", resolve(legacy), "--adoption-record", resolve(record));
80
+ return [...located, ...argumentsList];
81
+ }
82
+ function toolProcess(input) {
83
+ const program = join(import.meta.dirname, "..", "tools", `${input.tool}${extname(import.meta.filename)}`);
84
+ const child = spawn(process.execPath, [program, ...input.argumentsList], {
56
85
  stdio: "inherit",
57
86
  env: {
58
87
  ...process.env,
@@ -78,27 +107,81 @@ function started(runtime, argumentsList) {
78
107
  });
79
108
  });
80
109
  }
110
+ function started(input) {
111
+ return toolProcess({
112
+ tool: "self-host",
113
+ argumentsList: startArguments(input),
114
+ });
115
+ }
81
116
  async function start() {
82
117
  if (options.includes("--help")) {
83
118
  process.stdout.write(String(commandUsage["start"]));
84
119
  return 0;
85
120
  }
86
- const runtime = runtimeDirectory(process.env);
87
- if (runtime !== undefined) {
88
- let status = await started(runtime, options);
89
- const restarting = options.filter((option) => option !== "--reset-queue");
90
- while (status === 75)
91
- status = await started(runtime, restarting);
92
- return status === 0 ? 0 : 1;
121
+ const parsed = parseArgs({
122
+ args: options,
123
+ options: { repository: { type: "string" } },
124
+ strict: false,
125
+ allowPositionals: true,
126
+ });
127
+ const selected = parsed.values["repository"];
128
+ if (Object.hasOwn(parsed.values, "repository") &&
129
+ (typeof selected !== "string" || selected === "")) {
130
+ process.stderr.write("missing-value: --repository needs a directory.\n");
131
+ return 1;
93
132
  }
94
- process.stderr.write("runtime-directory-unknown: Set CLOVING_RUNTIME_DIR to the runtime directory of the service.\n");
95
- return 1;
133
+ if (parsed.positionals.length > 0) {
134
+ process.stderr.write("unexpected-argument: run cloving start --help for usage.\n");
135
+ return 1;
136
+ }
137
+ const repository = repositoryDirectory(typeof selected === "string" ? selected : process.cwd());
138
+ const runtime = runtimeDirectory(process.env, repository);
139
+ if (runtime === undefined) {
140
+ process.stderr.write("repository-unknown: Change to the service repository, use --repository <directory>, or set CLOVING_RUNTIME_DIR.\n");
141
+ return 1;
142
+ }
143
+ let status = await started({ runtime, argumentsList: options, repository });
144
+ const restarting = options.filter((option) => option !== "--reset-queue");
145
+ while (status === 75)
146
+ status = await started({
147
+ runtime,
148
+ argumentsList: restarting,
149
+ repository,
150
+ });
151
+ return status === 0 ? 0 : 1;
96
152
  }
97
- if (command === "start")
153
+ if (command === "workflows" && ["list", "test"].includes(options[0] ?? ""))
154
+ process.exitCode = await toolProcess({
155
+ tool: "workflow-command",
156
+ argumentsList: options,
157
+ });
158
+ else if (command === "templates")
159
+ process.exitCode = await toolProcess({
160
+ tool: "template-command",
161
+ argumentsList: options,
162
+ });
163
+ else if (command === "start")
98
164
  process.exitCode = await start();
99
- else
165
+ else {
166
+ const invocation = parseInvocation(process.argv.slice(2));
167
+ const repository = repositoryDirectory("repository" in invocation
168
+ ? (invocation.repository ?? process.cwd())
169
+ : process.cwd());
170
+ const settingsRepository = process.env["CLOVING_WATCH_REPOSITORY"] ?? repository;
171
+ const environment = invocation.kind === "watch" && settingsRepository !== undefined
172
+ ? settingsEnvironment(process.env, settingsRepository)
173
+ : process.env;
100
174
  await main(process.argv.slice(2), {
101
- repository: process.env["CLOVING_WATCH_REPOSITORY"],
102
- githubCommand: process.env["CLOVING_GH_COMMAND"],
103
- execute: watchCommand,
175
+ repository,
176
+ environment,
177
+ doctorProbe: createProbeRunner({
178
+ spawn: (input) => spawn(input.executable, input.arguments, input.options),
179
+ kill: (identifier, signal) => process.kill(identifier, signal),
180
+ }),
181
+ watchPr: {
182
+ repository: process.env["CLOVING_WATCH_REPOSITORY"],
183
+ githubCommand: environment["CLOVING_GH_COMMAND"],
184
+ execute: watchCommand,
185
+ },
104
186
  });
187
+ }
@@ -0,0 +1,16 @@
1
+ export type LocalCommands = Readonly<Record<string, readonly string[]>>;
2
+ export declare const commandLimits: {
3
+ stdoutBytes: number;
4
+ stderrBytes: number;
5
+ resultBytes: number;
6
+ };
7
+ export interface CommandEffect {
8
+ readonly operationId: string;
9
+ readonly name: string;
10
+ readonly state: string;
11
+ readonly exitCode: number | null;
12
+ readonly durationMilliseconds: number | null;
13
+ }
14
+ export type CommandEffects = (effects: readonly CommandEffect[]) => Promise<readonly CommandEffect[]>;
15
+ export declare function parseCommands(text: string | undefined): LocalCommands;
16
+ export declare function parseCommandSeconds(text: string | undefined): number;
@@ -0,0 +1,42 @@
1
+ import { record } from "./protocol.js";
2
+ export const commandLimits = {
3
+ stdoutBytes: 1_048_576,
4
+ stderrBytes: 65_536,
5
+ resultBytes: 3_145_728,
6
+ };
7
+ function argumentsList(value) {
8
+ return (Array.isArray(value) &&
9
+ typeof value[0] === "string" &&
10
+ value[0].startsWith("/") &&
11
+ Array.from(value).every((argument) => typeof argument === "string" && !argument.includes("\u0000")));
12
+ }
13
+ export function parseCommands(text) {
14
+ if (text === undefined)
15
+ return {};
16
+ try {
17
+ const fields = record(JSON.parse(text));
18
+ if (fields === undefined)
19
+ throw new Error("invalid-commands");
20
+ const commands = {};
21
+ for (const [name, argumentList] of Object.entries(fields)) {
22
+ if (!/^[A-Za-z0-9-]{1,64}$/.test(name) || !argumentsList(argumentList))
23
+ throw new Error("invalid-commands");
24
+ commands[name] = [...argumentList];
25
+ }
26
+ return commands;
27
+ }
28
+ catch {
29
+ throw new Error("invalid-commands");
30
+ }
31
+ }
32
+ export function parseCommandSeconds(text) {
33
+ if (text === undefined)
34
+ return 60;
35
+ const seconds = Number(text);
36
+ if (!/^\d+$/.test(text) ||
37
+ !Number.isInteger(seconds) ||
38
+ seconds < 1 ||
39
+ seconds > 3600)
40
+ throw new Error("invalid-command-seconds");
41
+ return seconds;
42
+ }
@@ -0,0 +1,11 @@
1
+ export interface SettingChange {
2
+ readonly field: string;
3
+ readonly action: "set" | "unset";
4
+ readonly value?: string;
5
+ readonly scope: "project" | "private";
6
+ }
7
+ export type JsonValue = null | boolean | number | string | readonly JsonValue[] | {
8
+ readonly [name: string]: JsonValue;
9
+ };
10
+ export declare function settingValue(text: string): JsonValue;
11
+ export declare function changedConfiguration(contents: string | undefined, change: SettingChange): string;
@@ -0,0 +1,62 @@
1
+ import { configuration, settingScope, validateSetting, } from "./configuration-schema.js";
2
+ import { configurationValues, parseConfiguration } from "./project-settings.js";
3
+ import { record } from "./protocol.js";
4
+ function isJsonValue(value) {
5
+ if (value === null || typeof value === "boolean" || typeof value === "string")
6
+ return true;
7
+ if (typeof value === "number")
8
+ return Number.isFinite(value);
9
+ if (Array.isArray(value))
10
+ return value.every(isJsonValue);
11
+ const object = record(value);
12
+ return object !== undefined && Object.values(object).every(isJsonValue);
13
+ }
14
+ export function settingValue(text) {
15
+ let value;
16
+ try {
17
+ value = JSON.parse(text);
18
+ }
19
+ catch {
20
+ return text;
21
+ }
22
+ if (!isJsonValue(value))
23
+ throw new Error("invalid-setting-value");
24
+ return value;
25
+ }
26
+ function trimHarness(root, field) {
27
+ const order = ["harness.name", "harness.kind", "harness.path"];
28
+ const index = order.indexOf(field);
29
+ const harness = record(root["harness"]);
30
+ if (index < 0 || harness === undefined)
31
+ return;
32
+ const names = ["name", "kind", "path"].slice(0, index + 1);
33
+ root["harness"] = Object.fromEntries(Object.entries(harness).filter(([name]) => names.includes(name)));
34
+ }
35
+ function assign(root, change) {
36
+ const [name = "", ...tail] = change.field.split(".");
37
+ if (tail.length === 0 && change.action === "unset")
38
+ return Object.fromEntries(Object.entries(root).filter(([key]) => key !== name));
39
+ if (tail.length === 0)
40
+ return { ...root, [name]: settingValue(change.value ?? "") };
41
+ const child = assign({ ...record(root[name]) }, { ...change, field: tail.join(".") });
42
+ if (Object.keys(child).length === 0)
43
+ return Object.fromEntries(Object.entries(root).filter(([key]) => key !== name));
44
+ return { ...root, [name]: child };
45
+ }
46
+ export function changedConfiguration(contents, change) {
47
+ settingScope(change.field);
48
+ if (change.action === "set")
49
+ validateSetting(change.field, settingValue(change.value ?? ""));
50
+ const previous = parseConfiguration(contents, change.scope);
51
+ const root = {
52
+ version: 1,
53
+ ...previous,
54
+ };
55
+ if (change.action === "unset" ||
56
+ configurationValues(previous)[change.field] !==
57
+ settingValue(change.value ?? ""))
58
+ trimHarness(root, change.field);
59
+ const next = assign(root, change);
60
+ configuration(next, change.scope);
61
+ return JSON.stringify(next, null, 2) + "\n";
62
+ }
@@ -0,0 +1,21 @@
1
+ import { type SettingValue } from "./project-settings.ts";
2
+ import { type JsonValue } from "./configuration-change.ts";
3
+ import type { TurnProfiles } from "./turn-profile.ts";
4
+ type Source = "environment" | "private" | "project" | "default";
5
+ type DisplayValue = SettingValue | JsonValue;
6
+ interface ValueSource {
7
+ readonly value: DisplayValue;
8
+ readonly source: Source;
9
+ }
10
+ export interface SettingEntry extends ValueSource {
11
+ readonly field: string;
12
+ readonly hidden: readonly ValueSource[];
13
+ }
14
+ export declare function configurationEntries(input: {
15
+ readonly project: string | undefined;
16
+ readonly private: string | undefined;
17
+ readonly environment: Readonly<NodeJS.ProcessEnv>;
18
+ readonly field?: string;
19
+ readonly profiles?: TurnProfiles;
20
+ }): readonly SettingEntry[];
21
+ export {};
@@ -0,0 +1,69 @@
1
+ import { settingFields, settingScope } from "./configuration-schema.js";
2
+ import { configurationValues, parseConfiguration, settingVariables, } from "./project-settings.js";
3
+ import { settingValue } from "./configuration-change.js";
4
+ import { harnessDefaults, nativeHarness } from "./harness-defaults.js";
5
+ import { builtInPriceTable, parseTokenPrices } from "./token-prices.js";
6
+ const defaults = {
7
+ "queue.lanes": 1,
8
+ "harness.name": "claude",
9
+ "harness.output": "text",
10
+ tokenPrices: builtInPriceTable.prices,
11
+ fallbackModels: [],
12
+ profiles: {},
13
+ "watch.port": 3663,
14
+ "watch.actions": "on",
15
+ "github.command": ["gh"],
16
+ };
17
+ function effectiveValue(setting) {
18
+ const { field, value } = setting;
19
+ if (field === "tokenPrices")
20
+ return parseTokenPrices(JSON.stringify(value));
21
+ return value;
22
+ }
23
+ export function configurationEntries(input) {
24
+ const project = configurationValues(parseConfiguration(input.project, "project"));
25
+ const privateFile = configurationValues(parseConfiguration(input.private, "private"));
26
+ const name = input.environment["CLOVING_WORKER"] ?? privateFile["harness.name"];
27
+ const harness = typeof name === "string" && !nativeHarness(name)
28
+ ? undefined
29
+ : harnessDefaults(name);
30
+ const environment = Object.fromEntries(Object.entries({
31
+ ...settingVariables,
32
+ profiles: "CLOVING_PROFILES",
33
+ ...(harness?.variable === undefined
34
+ ? {}
35
+ : { "harness.command": harness.variable }),
36
+ }).flatMap(([field, variable]) => {
37
+ const value = input.environment[variable];
38
+ return value === undefined ? [] : [[field, settingValue(value)]];
39
+ }));
40
+ if (input.profiles !== undefined)
41
+ environment["profiles"] = input.profiles;
42
+ const effectiveDefaults = {
43
+ ...defaults,
44
+ ...(harness === undefined ? {} : { "harness.command": harness.command }),
45
+ };
46
+ const fields = input.field === undefined ? settingFields() : [input.field];
47
+ const layers = [
48
+ ["environment", environment],
49
+ ["private", privateFile],
50
+ ["project", project],
51
+ ];
52
+ return fields.map((field) => {
53
+ settingScope(field);
54
+ const [effective, ...hidden] = layers.flatMap(([source, values]) => {
55
+ const value = values[field];
56
+ return value === undefined ? [] : [{ source, value }];
57
+ });
58
+ const selected = effective ?? {
59
+ source: "default",
60
+ value: effectiveDefaults[field] ?? null,
61
+ };
62
+ return {
63
+ field,
64
+ ...selected,
65
+ value: effectiveValue({ field, value: selected.value }),
66
+ hidden,
67
+ };
68
+ });
69
+ }
@@ -0,0 +1,49 @@
1
+ import type { TurnProfiles } from "./turn-profile.ts";
2
+ import type { TokenPrices } from "./token-prices.ts";
3
+ export interface Configuration {
4
+ readonly version: 1;
5
+ readonly checks?: {
6
+ readonly beforeMerge?: readonly string[];
7
+ readonly required?: readonly string[];
8
+ };
9
+ readonly tickets?: {
10
+ readonly command?: readonly string[];
11
+ readonly nextCommand?: readonly string[];
12
+ };
13
+ readonly queue?: {
14
+ readonly everySeconds?: number;
15
+ readonly lanes?: number;
16
+ };
17
+ readonly harness?: {
18
+ readonly name?: string;
19
+ readonly turn?: readonly string[];
20
+ readonly output?: "text";
21
+ readonly kind?: "file" | "shell";
22
+ readonly path?: string;
23
+ readonly command?: readonly string[];
24
+ };
25
+ readonly profiles?: TurnProfiles;
26
+ readonly fallbackModels?: readonly string[];
27
+ readonly tokenPrices?: TokenPrices;
28
+ readonly privateTexts?: readonly string[];
29
+ readonly notify?: {
30
+ readonly command?: readonly string[];
31
+ };
32
+ readonly watch?: {
33
+ readonly port?: number | "off";
34
+ readonly actions?: "on" | "off";
35
+ };
36
+ readonly selfUpdate?: {
37
+ readonly everySeconds?: number;
38
+ };
39
+ readonly github?: {
40
+ readonly command?: readonly string[];
41
+ };
42
+ readonly workflows?: {
43
+ readonly folder?: string;
44
+ };
45
+ }
46
+ export declare function configuration(value: unknown, scope: "project" | "private"): Configuration;
47
+ export declare function settingScope(field: string): "project" | "private";
48
+ export declare function validateSetting(field: string, value: unknown): void;
49
+ export declare function settingFields(): readonly string[];
@@ -0,0 +1,159 @@
1
+ import project from "./project-config.schema.json" with { type: "json" };
2
+ import privateConfig from "./private-config.schema.json" with { type: "json" };
3
+ import { record } from "./protocol.js";
4
+ import { isTurnCommand } from "./harness-defaults.js";
5
+ const schemas = {
6
+ project,
7
+ private: privateConfig,
8
+ };
9
+ function invalid(field) {
10
+ throw new Error(`invalid-setting: ${field}`);
11
+ }
12
+ function text(value, { schema, field }) {
13
+ if (typeof value !== "string")
14
+ invalid(field);
15
+ if (schema.pattern !== undefined && !new RegExp(schema.pattern).test(value))
16
+ invalid(field);
17
+ }
18
+ function number(value, { schema, field }) {
19
+ if (typeof value !== "number" || !Number.isFinite(value))
20
+ invalid(field);
21
+ if (schema.type === "integer" && !Number.isInteger(value))
22
+ invalid(field);
23
+ bounds(value, { schema, field });
24
+ }
25
+ function bounds(value, { schema, field }) {
26
+ if (schema.minimum !== undefined && value < schema.minimum)
27
+ invalid(field);
28
+ if (schema.maximum !== undefined && value > schema.maximum)
29
+ invalid(field);
30
+ if (schema.exclusiveMinimum !== undefined && value <= schema.exclusiveMinimum)
31
+ invalid(field);
32
+ }
33
+ function scalar(value, checked) {
34
+ const { schema, field } = checked;
35
+ if (field === "harness.turn" && !isTurnCommand(value))
36
+ invalid(field);
37
+ if ("const" in schema && value !== schema.const)
38
+ invalid(field);
39
+ if (schema.enum !== undefined && !schema.enum.includes(value))
40
+ invalid(field);
41
+ if (schema.type === "string")
42
+ text(value, checked);
43
+ if (schema.type === "number" || schema.type === "integer")
44
+ number(value, checked);
45
+ }
46
+ function childSchema(name, { schema, field }) {
47
+ const properties = schema.properties ?? {};
48
+ const child = Object.hasOwn(properties, name)
49
+ ? properties[name]
50
+ : schema.additionalProperties;
51
+ if (child === false || child === undefined)
52
+ throw new Error(`unknown-setting: ${field}`);
53
+ if (schema.propertyNames !== undefined &&
54
+ !new RegExp(schema.propertyNames.pattern).test(name))
55
+ invalid(field);
56
+ return child;
57
+ }
58
+ function validateObject(value, { schema, field }) {
59
+ const object = record(value);
60
+ if (object === undefined)
61
+ invalid(field);
62
+ for (const required of schema.required ?? [])
63
+ if (!Object.hasOwn(object, required))
64
+ invalid(`${field}.${required}`);
65
+ for (const [name, item] of Object.entries(object)) {
66
+ const path = field === "" ? name : `${field}.${name}`;
67
+ const child = childSchema(name, { schema, field: path });
68
+ if (typeof child === "object")
69
+ validate(item, { schema: child, field: path });
70
+ }
71
+ }
72
+ function matches(value, schema) {
73
+ try {
74
+ validate(value, { schema, field: "" });
75
+ return true;
76
+ }
77
+ catch {
78
+ return false;
79
+ }
80
+ }
81
+ function validate(value, checked) {
82
+ const { schema, field } = checked;
83
+ if (schema.anyOf !== undefined) {
84
+ if (!schema.anyOf.some((option) => matches(value, option)))
85
+ invalid(field);
86
+ return;
87
+ }
88
+ scalar(value, checked);
89
+ if (schema.type === "object")
90
+ validateObject(value, checked);
91
+ if (schema.type !== "array")
92
+ return;
93
+ if (!Array.isArray(value))
94
+ invalid(field);
95
+ if (schema.maxItems !== undefined && value.length > schema.maxItems)
96
+ invalid(field);
97
+ if (schema.items === undefined)
98
+ return;
99
+ for (const [index, item] of value.entries())
100
+ validate(item, {
101
+ schema: schema.items,
102
+ field: `${field}.${String(index)}`,
103
+ });
104
+ }
105
+ function validateConfiguration(value, scope) {
106
+ const object = record(value);
107
+ if (object === undefined)
108
+ invalid("$");
109
+ if (object["version"] !== 1)
110
+ throw new Error("unsupported-config-version: version");
111
+ if (scope === "project") {
112
+ for (const field of Object.keys(object))
113
+ if (Object.hasOwn(privateConfig.properties, field) &&
114
+ !Object.hasOwn(project.properties, field))
115
+ throw new Error(`private-setting-in-project-file: ${field}`);
116
+ }
117
+ validate(object, { schema: schemas[scope] ?? {}, field: "" });
118
+ }
119
+ export function configuration(value, scope) {
120
+ validateConfiguration(value, scope);
121
+ return value;
122
+ }
123
+ export function settingScope(field) {
124
+ fieldSchema(field);
125
+ const root = field.split(".")[0] ?? "";
126
+ return Object.hasOwn(project.properties, root) ? "project" : "private";
127
+ }
128
+ function fieldSchema(field) {
129
+ if (!settingFields().includes(field))
130
+ throw new Error(`unknown-setting: ${field}`);
131
+ let schema = privateConfig;
132
+ for (const name of field.split(".")) {
133
+ if (schema.type !== "object")
134
+ throw new Error(`unknown-setting: ${field}`);
135
+ const child = childSchema(name, { schema, field });
136
+ if (typeof child !== "object")
137
+ throw new Error(`unknown-setting: ${field}`);
138
+ schema = child;
139
+ }
140
+ return schema;
141
+ }
142
+ export function validateSetting(field, value) {
143
+ const schema = fieldSchema(field);
144
+ if (schema.minimum !== undefined &&
145
+ schema.maximum !== undefined &&
146
+ typeof value === "number" &&
147
+ (value < schema.minimum || value > schema.maximum))
148
+ throw new Error(`invalid-setting: ${field} must be from ${String(schema.minimum)} to ${String(schema.maximum)}`);
149
+ validate(value, { schema, field });
150
+ }
151
+ export function settingFields() {
152
+ return Object.entries(privateConfig.properties).flatMap(([name, schema]) => {
153
+ if (name === "version")
154
+ return [];
155
+ return "properties" in schema
156
+ ? Object.keys(schema.properties).map((child) => `${name}.${child}`)
157
+ : [name];
158
+ });
159
+ }
@@ -1,6 +1,15 @@
1
- import { type WorkerUsage } from "../worker-usage.ts";
2
- export type Worker = "claude" | "codex";
1
+ import type { ReviewVerdict } from "../review-subject.ts";
2
+ import type { TicketStatus } from "../ticket-status.ts";
3
+ import { type WorkerUsage, type WorkerAttemptUsage, type WorkerModelUsage, type RetryKind } from "../worker-usage.ts";
4
+ export type Worker = string;
3
5
  export interface StreamResult {
6
+ readonly reviewFeedback?: string;
7
+ readonly reviewVerdict?: ReviewVerdict | null;
8
+ readonly models?: readonly WorkerModelUsage[];
9
+ readonly ticketStatusTooLarge?: true;
10
+ readonly ticketStatus?: TicketStatus;
11
+ readonly attempts?: readonly WorkerAttemptUsage[];
12
+ readonly pricingModel?: string | null;
4
13
  readonly subtype?: string;
5
14
  readonly errorType?: string;
6
15
  readonly model: string | null;
@@ -12,13 +21,16 @@ export interface StreamResult {
12
21
  readonly turns: number | null;
13
22
  }
14
23
  export interface TurnEnd {
24
+ readonly reason?: string;
25
+ readonly detail?: string;
15
26
  readonly stopped?: boolean;
16
27
  readonly exitCode: number | null;
17
28
  readonly result: StreamResult | undefined;
18
29
  }
19
30
  export interface TurnStart {
20
- readonly mode?: "analysis";
21
- readonly analysisToken?: string;
31
+ readonly resultBytes?: number;
32
+ readonly output?: "text";
33
+ readonly shell?: string;
22
34
  readonly worker?: Worker;
23
35
  readonly turnId?: string;
24
36
  readonly environment?: Readonly<Record<string, string>>;
@@ -34,5 +46,8 @@ export interface RunningTurn {
34
46
  readonly stop: (graceMilliseconds: number) => void;
35
47
  }
36
48
  export declare function capacityRefusal(result: StreamResult | undefined): boolean;
37
- export declare function streamResult(line: string): StreamResult | undefined;
49
+ export declare function retryKind(result: StreamResult | undefined): RetryKind | null;
50
+ export declare function succeeded(end: TurnEnd): boolean;
51
+ export declare function streamResult(line: string, worker?: Worker): StreamResult | undefined;
52
+ export declare function turnEnvironment(configuration: string, start: TurnStart): NodeJS.ProcessEnv;
38
53
  export declare function startTurn(start: TurnStart): RunningTurn;