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,11 @@
1
+ import { send } from "./client.js";
2
+ async function main() {
3
+ const runtime = process.argv[2];
4
+ if (runtime === undefined) {
5
+ process.exitCode = 1;
6
+ return;
7
+ }
8
+ process.stdout.write(JSON.stringify(await send(runtime, { operation: "status", parameters: { limit: 1 } })) + "\n");
9
+ }
10
+ if (process.argv[1] === import.meta.filename)
11
+ await main();
@@ -0,0 +1,3 @@
1
+ import type { DoctorWorkflow } from "../doctor-report.ts";
2
+ export declare const bundledDoctorWorkflows: DoctorWorkflow[];
3
+ export declare function doctorWorkflows(repository: string, environment: Readonly<NodeJS.ProcessEnv>): Promise<readonly DoctorWorkflow[]>;
@@ -0,0 +1,45 @@
1
+ import { readdir, readFile } from "node:fs/promises";
2
+ import { homedir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { configurationRoot, absoluteWorkflowFolder, } from "../project-settings.js";
5
+ import { isCandidateDeclaration } from "../workflow-candidate.js";
6
+ import { bundledWorkflowIds } from "../workflow-discovery.js";
7
+ export const bundledDoctorWorkflows = Object.values(bundledWorkflowIds).map((workflowId) => ({
8
+ scope: "bundled",
9
+ workflowId,
10
+ capabilities: ["claude", "github"],
11
+ }));
12
+ export async function doctorWorkflows(repository, environment) {
13
+ const discovered = [];
14
+ for (const [scope, folder] of [
15
+ ["project", join(repository, ".cloving/workflows")],
16
+ [
17
+ "user",
18
+ absoluteWorkflowFolder(environment["CLOVING_WORKFLOW_FOLDER"]) ??
19
+ join(configurationRoot(environment, homedir()), "cloving/workflows"),
20
+ ],
21
+ ]) {
22
+ const files = await readdir(folder).catch((error) => {
23
+ if (error instanceof Error && "code" in error && error.code === "ENOENT")
24
+ return [];
25
+ throw error;
26
+ });
27
+ for (const file of files.filter((file) => file.endsWith(".ts") &&
28
+ !file.endsWith(".d.ts") &&
29
+ !file.endsWith(".test.ts"))) {
30
+ const text = await readFile(join(folder, file.slice(0, -3) + ".declaration.json"), "utf8").catch(() => undefined);
31
+ if (text === undefined)
32
+ continue;
33
+ let declaration;
34
+ try {
35
+ declaration = JSON.parse(text);
36
+ }
37
+ catch {
38
+ continue;
39
+ }
40
+ if (isCandidateDeclaration(declaration))
41
+ discovered.push({ scope, ...declaration.workflow });
42
+ }
43
+ }
44
+ return [...bundledDoctorWorkflows, ...discovered];
45
+ }
@@ -0,0 +1,15 @@
1
+ import { type DoctorCheck } from "../doctor-report.ts";
2
+ import type { ProbeRunner } from "./probe-command.ts";
3
+ interface DoctorOptions {
4
+ readonly repository: string | undefined;
5
+ readonly environment: Readonly<NodeJS.ProcessEnv>;
6
+ readonly probe: ProbeRunner;
7
+ }
8
+ export declare function doctorReport(options: DoctorOptions): Promise<{
9
+ readonly version: 1;
10
+ readonly checks: readonly DoctorCheck[];
11
+ }>;
12
+ export declare function doctorCommand(options: DoctorOptions & {
13
+ readonly json: boolean;
14
+ }): Promise<number>;
15
+ export {};
@@ -0,0 +1,190 @@
1
+ import { shellArgument } from "./runtime-directory.js";
2
+ import { dirname, delimiter, join } from "node:path";
3
+ import { doctorCodes, doctorExitCode, doctorFixes, requiredDoctorCodes, } from "../doctor-report.js";
4
+ import { privateSettingsPath, projectSettings } from "./project-settings.js";
5
+ import { githubObservations } from "./doctor-github.js";
6
+ import { bundledDoctorWorkflows, doctorWorkflows } from "./doctor-workflows.js";
7
+ import { runtimeObservation, serviceObservation } from "./doctor-runtime.js";
8
+ import { harnessObservations } from "./doctor-harness.js";
9
+ import { commandObservation, nodeObservation, privateTextsObservation, queueObservation, } from "./doctor-local.js";
10
+ function settings(repository, environment) {
11
+ try {
12
+ const resolved = projectSettings(environment, repository);
13
+ return {
14
+ environment: resolved.environment,
15
+ harness: resolved.harness,
16
+ observation: {
17
+ result: "ok",
18
+ detail: "Settings files are valid",
19
+ },
20
+ };
21
+ }
22
+ catch (error) {
23
+ const detail = error instanceof Error ? error.message : "Invalid settings files";
24
+ const files = [
25
+ join(repository, ".cloving/config.json"),
26
+ privateSettingsPath(environment, repository),
27
+ ];
28
+ return {
29
+ environment,
30
+ observation: {
31
+ result: "fail",
32
+ detail,
33
+ fix: `Edit the invalid settings: \${EDITOR:-vi} ${files.map(shellArgument).join(" ")}`,
34
+ },
35
+ };
36
+ }
37
+ }
38
+ export async function doctorReport(options) {
39
+ const repository = options.repository;
40
+ const found = repository === undefined
41
+ ? {
42
+ observations: {},
43
+ required: requiredDoctorCodes([], { queueSeconds: undefined }),
44
+ }
45
+ : await repositoryObservations({ ...options, repository });
46
+ const git = repository === undefined
47
+ ? { result: "fail", detail: "No git repository" }
48
+ : await gitObservation({ ...options, repository });
49
+ const observations = {
50
+ ...found.observations,
51
+ "node-version": nodeObservation(process.version),
52
+ "git-repository": git,
53
+ };
54
+ const checks = doctorCodes.map((code) => ({
55
+ code,
56
+ required: found.required.includes(code),
57
+ fix: doctorFixes[code],
58
+ ...(observations[code] ?? {
59
+ result: "skip",
60
+ detail: "Repository prerequisite unavailable",
61
+ }),
62
+ }));
63
+ return { version: 1, checks };
64
+ }
65
+ async function repositoryObservations(options) {
66
+ const { repository, probe } = options;
67
+ const configured = settings(repository, options.environment);
68
+ const { environment } = configured;
69
+ const observations = {
70
+ "settings-files": configured.observation,
71
+ };
72
+ const settingsValid = configured.observation.result === "ok";
73
+ const location = await runtimeObservation(repository, { environment, probe });
74
+ observations["runtime-directory"] = location.observation;
75
+ observations["service"] = await serviceObservation(location, {
76
+ environment,
77
+ probe,
78
+ });
79
+ const project = location.project;
80
+ const serviceEnvironment = {
81
+ ...environment,
82
+ PATH: [dirname(process.execPath), environment["PATH"]].join(delimiter),
83
+ };
84
+ const harnesses = await harnessObservations(environment, {
85
+ directory: repository,
86
+ settingsValid,
87
+ probe,
88
+ commandEnvironment: serviceEnvironment,
89
+ harness: "harness" in configured ? configured.harness : undefined,
90
+ });
91
+ observations["harnesses"] = harnesses.harnesses;
92
+ observations["default-harness"] = harnesses.selected;
93
+ const workflowContext = await workflowRequirements(repository, {
94
+ settingsValid,
95
+ environment,
96
+ });
97
+ const required = requiredDoctorCodes(workflowContext.workflows, {
98
+ queueSeconds: settingsValid
99
+ ? environment["CLOVING_QUEUE_SECONDS"]
100
+ : undefined,
101
+ });
102
+ const dependent = await configuredObservations({ ...options, environment }, { prerequisite: workflowContext.prerequisite, project, serviceEnvironment });
103
+ return { observations: { ...observations, ...dependent }, required };
104
+ }
105
+ async function workflowRequirements(repository, context) {
106
+ if (!context.settingsValid)
107
+ return {
108
+ workflows: bundledDoctorWorkflows,
109
+ prerequisite: "Settings files are invalid",
110
+ };
111
+ try {
112
+ return {
113
+ workflows: await doctorWorkflows(repository, context.environment),
114
+ prerequisite: undefined,
115
+ };
116
+ }
117
+ catch (error) {
118
+ return {
119
+ workflows: bundledDoctorWorkflows,
120
+ prerequisite: `Workflow requirements unavailable: ${error instanceof Error ? error.message : "discovery failed"}`,
121
+ };
122
+ }
123
+ }
124
+ async function configuredObservations(options, location) {
125
+ const { environment, repository, probe } = options;
126
+ const observations = {};
127
+ if (location.prerequisite !== undefined) {
128
+ for (const code of [
129
+ "gh-login",
130
+ "github-origin",
131
+ "greptile-review",
132
+ "ticket-command",
133
+ "next-command",
134
+ "check-command",
135
+ "queue-interval",
136
+ "private-texts",
137
+ ])
138
+ observations[code] = {
139
+ result: "skip",
140
+ detail: location.prerequisite,
141
+ };
142
+ return observations;
143
+ }
144
+ for (const [code, variable, directory] of [
145
+ ["ticket-command", "CLOVING_TICKET_COMMAND", location.project],
146
+ ["next-command", "CLOVING_NEXT_COMMAND", location.project],
147
+ ["check-command", "CLOVING_CHECK_COMMAND", repository],
148
+ ])
149
+ observations[code] =
150
+ directory === undefined
151
+ ? { result: "skip", detail: "Runtime project prerequisite unavailable" }
152
+ : await commandObservation(environment[variable], {
153
+ directory,
154
+ environment: location.serviceEnvironment,
155
+ });
156
+ const github = await githubObservations(repository, { environment, probe });
157
+ Object.assign(observations, github.observations);
158
+ const login = observations["gh-login"];
159
+ if (login !== undefined)
160
+ observations["gh-login"] = { ...login, fix: github.loginFix };
161
+ observations["queue-interval"] = queueObservation(environment["CLOVING_QUEUE_SECONDS"]);
162
+ observations["private-texts"] = privateTextsObservation(environment["CLOVING_PRIVATE_TEXTS"]);
163
+ return observations;
164
+ }
165
+ async function gitObservation(options) {
166
+ const given = { env: options.environment, directory: options.repository };
167
+ const branch = await options.probe("git", {
168
+ ...given,
169
+ arguments: ["symbolic-ref", "--short", "HEAD"],
170
+ });
171
+ const detached = branch.reason === null
172
+ ? branch
173
+ : await options.probe("git", {
174
+ ...given,
175
+ arguments: ["rev-parse", "--short", "HEAD"],
176
+ });
177
+ return {
178
+ result: detached.reason === null ? "ok" : "fail",
179
+ detail: `git repository ${options.repository}, branch ${detached.stdout.trim() || "unavailable"}`,
180
+ };
181
+ }
182
+ export async function doctorCommand(options) {
183
+ const report = await doctorReport(options);
184
+ process.stdout.write(options.json
185
+ ? JSON.stringify(report) + "\n"
186
+ : report.checks
187
+ .map((check) => `${check.result.padEnd(6)}${check.code} ${check.detail}${check.result === "ok" ? "" : ". " + check.fix}${check.required ? " (required)" : ""}\n`)
188
+ .join(""));
189
+ return doctorExitCode(report.checks);
190
+ }
@@ -0,0 +1,8 @@
1
+ import { type Reply } from "../protocol.ts";
2
+ export interface CiRerunNotice {
3
+ readonly commit: string;
4
+ readonly run: string;
5
+ readonly requestedAt: number;
6
+ }
7
+ export declare function ciRerunNotices(folder: string): Promise<CiRerunNotice[]>;
8
+ export declare function withCiReruns(runtimeDirectory: string, reply: Reply): Promise<Reply>;
@@ -0,0 +1,83 @@
1
+ import { readdir, readFile } from "node:fs/promises";
2
+ import { dirname, join } from "node:path";
3
+ import { record } from "../protocol.js";
4
+ async function stored(file) {
5
+ try {
6
+ return record(JSON.parse(await readFile(file, "utf8")));
7
+ }
8
+ catch {
9
+ return undefined;
10
+ }
11
+ }
12
+ function noticeOf(value, commit) {
13
+ const rerun = record(value);
14
+ const run = rerun?.["run"];
15
+ const requestedAt = rerun?.["requestedAt"];
16
+ if (typeof run !== "string" ||
17
+ !/^\d+$/.test(run) ||
18
+ typeof requestedAt !== "number" ||
19
+ !Number.isFinite(requestedAt))
20
+ return [];
21
+ return [{ commit, run, requestedAt }];
22
+ }
23
+ export async function ciRerunNotices(folder) {
24
+ const notices = [];
25
+ for (const file of await readdir(folder).catch(() => [])) {
26
+ if (!/^ci-[a-f0-9]{32}\.json$/.test(file))
27
+ continue;
28
+ const wait = await stored(join(folder, file));
29
+ const commit = wait?.["commit"];
30
+ if (typeof commit !== "string" || !/^[a-f0-9]{40,64}$/.test(commit))
31
+ continue;
32
+ const reruns = Array.isArray(wait?.["reruns"])
33
+ ? wait["reruns"]
34
+ : [];
35
+ notices.push(...reruns.flatMap((value) => noticeOf(value, commit)));
36
+ }
37
+ return notices.toSorted((first, second) => first.requestedAt - second.requestedAt);
38
+ }
39
+ function requestedRunIds(result) {
40
+ const runs = Array.isArray(result["runs"])
41
+ ? result["runs"]
42
+ : [];
43
+ return new Set([result["run"], ...runs].flatMap((value) => {
44
+ const runId = record(value)?.["runId"];
45
+ return typeof runId === "string" ? [runId] : [];
46
+ }));
47
+ }
48
+ export async function withCiReruns(runtimeDirectory, reply) {
49
+ if (reply.kind !== "result")
50
+ return reply;
51
+ const { result } = reply;
52
+ const requested = requestedRunIds(result);
53
+ const journal = join(dirname(runtimeDirectory), "github");
54
+ const notices = new Map();
55
+ for (const key of await readdir(journal).catch(() => [])) {
56
+ const folder = join(journal, key);
57
+ const started = (await stored(join(folder, "started.json"))) ?? {};
58
+ const runId = started["runId"];
59
+ if (started["method"] !== "merge" ||
60
+ typeof runId !== "string" ||
61
+ !requested.has(runId))
62
+ continue;
63
+ notices.set(runId, [
64
+ ...(notices.get(runId) ?? []),
65
+ ...(await ciRerunNotices(folder)),
66
+ ]);
67
+ }
68
+ const shown = (value) => {
69
+ const run = record(value);
70
+ const found = notices.get(String(run?.["runId"])) ?? [];
71
+ return found.length === 0 ? value : { ...run, ciReruns: found };
72
+ };
73
+ return {
74
+ kind: "result",
75
+ result: {
76
+ ...result,
77
+ ...(result["run"] === undefined ? {} : { run: shown(result["run"]) }),
78
+ ...(Array.isArray(result["runs"])
79
+ ? { runs: result["runs"].map(shown) }
80
+ : {}),
81
+ },
82
+ };
83
+ }
@@ -0,0 +1,6 @@
1
+ export declare function githubRetry<Result>(retry: {
2
+ readonly signal: AbortSignal;
3
+ readonly pollMilliseconds: number;
4
+ readonly action: (attempt: number) => Promise<Result>;
5
+ readonly statuses?: readonly number[];
6
+ }): Promise<Result>;
@@ -0,0 +1,47 @@
1
+ import { setTimeout as delay } from "node:timers/promises";
2
+ function field(value, name) {
3
+ return Reflect.get(Object(value), name);
4
+ }
5
+ function transient(error) {
6
+ if (!(error instanceof Error) || error.message !== "github-call-failed")
7
+ return false;
8
+ const detail = field(error, "detail");
9
+ if (typeof detail !== "string")
10
+ return false;
11
+ const status = field(error, "status");
12
+ if ([500, 502, 503, 504].includes(Number(status)))
13
+ return true;
14
+ return ((status === undefined ||
15
+ (typeof status === "number" && Number.isNaN(status))) &&
16
+ /TLS handshake timeout|connection reset|i\/o timeout|\bEOF\b|error connecting to/i.test(detail));
17
+ }
18
+ function retryFactor(error, retry) {
19
+ const network = transient(error);
20
+ if (!network && !retry.statuses.includes(Number(field(error, "status"))))
21
+ throw error;
22
+ if (retry.attempt < 2)
23
+ return network ? retry.attempt + 1 : 1;
24
+ if (!network)
25
+ throw error;
26
+ throw Object.assign(new Error("github-network-failed", { cause: error }), {
27
+ detail: field(error, "detail"),
28
+ });
29
+ }
30
+ export async function githubRetry(retry) {
31
+ for (let attempt = 0;; attempt += 1) {
32
+ retry.signal.throwIfAborted();
33
+ try {
34
+ return await retry.action(attempt);
35
+ }
36
+ catch (error) {
37
+ retry.signal.throwIfAborted();
38
+ const factor = retryFactor(error, {
39
+ attempt,
40
+ statuses: retry.statuses ?? [],
41
+ });
42
+ await delay(retry.pollMilliseconds * factor, undefined, {
43
+ signal: retry.signal,
44
+ });
45
+ }
46
+ }
47
+ }
@@ -0,0 +1,22 @@
1
+ import type { ProbeRunner } from "./probe-command.ts";
2
+ export interface HarnessEntry {
3
+ readonly name: string;
4
+ readonly kind: "file" | "shell";
5
+ readonly path: string;
6
+ readonly version: string | null;
7
+ readonly working: boolean;
8
+ readonly reason: string | null;
9
+ }
10
+ export interface HarnessDiscovery {
11
+ readonly entries: HarnessEntry[];
12
+ readonly shellReason: string | null;
13
+ }
14
+ export interface HarnessOptions {
15
+ readonly env?: Readonly<Record<string, string | undefined>>;
16
+ }
17
+ export declare function discoverHarnesses(options: HarnessOptions & {
18
+ readonly probe: ProbeRunner;
19
+ }): Promise<HarnessDiscovery>;
20
+ export declare function probeHarness(target: string, options: HarnessOptions & {
21
+ readonly probe: ProbeRunner;
22
+ }): Promise<HarnessDiscovery>;
@@ -0,0 +1,183 @@
1
+ import { access, constants, stat } from "node:fs/promises";
2
+ import { basename, delimiter, resolve } from "node:path";
3
+ import { harnessDefinition, harnessVersion, knownHarnesses, } from "../agent-harness-versions.js";
4
+ import { shellArguments, shellBlock, shellDiscoveryScript, shellEntries, shellProbeScript, } from "../agent-harness-shell.js";
5
+ async function executableFile(path) {
6
+ try {
7
+ await access(path, constants.X_OK);
8
+ return (await stat(path)).isFile();
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ async function findFile(name, env) {
15
+ if (name.includes("/")) {
16
+ const path = resolve(name);
17
+ return (await executableFile(path)) ? path : null;
18
+ }
19
+ for (const directory of (env["PATH"] ?? "").split(delimiter)) {
20
+ const path = resolve(directory, name);
21
+ if (await executableFile(path))
22
+ return path;
23
+ }
24
+ return null;
25
+ }
26
+ function probeEntry(entry, output) {
27
+ const version = harnessVersion(output.stdout, harnessDefinition(entry.name).versionPattern);
28
+ const reason = output.reason ?? (version === null ? "no-version" : null);
29
+ return {
30
+ ...entry,
31
+ version: reason === null ? version : null,
32
+ working: reason === null,
33
+ reason,
34
+ };
35
+ }
36
+ async function probeFile(entry, context) {
37
+ const { env, probe } = context;
38
+ const { name, path } = entry;
39
+ const output = await probe(path, {
40
+ arguments: [harnessDefinition(name).versionOption],
41
+ env,
42
+ });
43
+ return probeEntry({ name, kind: "file", path }, output);
44
+ }
45
+ async function discoverFiles(definitions, context) {
46
+ const { env } = context;
47
+ const entries = await Promise.all(definitions.map(async ({ name }) => {
48
+ const path = await findFile(name, env);
49
+ return path === null ? [] : [await probeFile({ name, path }, context)];
50
+ }));
51
+ return entries.flat();
52
+ }
53
+ async function inspectShell(names, options) {
54
+ const { env, mode, probe } = options;
55
+ const shell = env["SHELL"];
56
+ if (!shell)
57
+ return { entries: [], reason: "shell-unavailable", bash: false };
58
+ const output = await probe(shell, {
59
+ arguments: [
60
+ ...shellArguments(mode),
61
+ shellDiscoveryScript,
62
+ "cloving-harnesses",
63
+ ...names,
64
+ ],
65
+ env,
66
+ });
67
+ const found = shellEntries(output.stdout, names);
68
+ const reason = output.exitCode === 64 ? "unsupported-shell" : output.reason;
69
+ return {
70
+ entries: reason === null ? (found ?? []) : [],
71
+ reason: reason ?? (found === null ? "shell-protocol" : null),
72
+ bash: shellBlock(output.stdout, -1)?.trim() === "bash",
73
+ };
74
+ }
75
+ async function probeShell(candidate, context) {
76
+ const { env, probe } = context;
77
+ const { entry, mode } = candidate;
78
+ const { name, kind, path } = entry;
79
+ const output = await probe(env["SHELL"] ?? "", {
80
+ arguments: [
81
+ ...shellArguments(mode),
82
+ shellProbeScript,
83
+ "cloving-harness-probe",
84
+ path,
85
+ kind,
86
+ ],
87
+ env,
88
+ });
89
+ const stdout = shellBlock(output.stdout, 0);
90
+ return probeEntry({ name, kind, path }, {
91
+ stdout: stdout ?? "",
92
+ reason: output.reason ?? (stdout === null ? "shell-protocol" : null),
93
+ });
94
+ }
95
+ function entryKey(entry) {
96
+ return JSON.stringify([entry.name, entry.kind, entry.path]);
97
+ }
98
+ async function probeCandidates(candidates, options) {
99
+ const { files, env, probe } = options;
100
+ const settled = new Set(files.filter((file) => file.working).map(entryKey));
101
+ const groups = new Map();
102
+ for (const candidate of candidates) {
103
+ const key = entryKey(candidate.entry);
104
+ if (settled.has(key))
105
+ continue;
106
+ const group = groups.get(key) ?? [];
107
+ group.push(candidate);
108
+ groups.set(key, group);
109
+ }
110
+ const entries = await Promise.all([...groups.values()].map(async (group) => {
111
+ let result = [];
112
+ for (const { entry, mode } of group) {
113
+ const output = await probeShell({ entry, mode }, { env, probe });
114
+ result = [output];
115
+ if (output.working)
116
+ break;
117
+ }
118
+ return result;
119
+ }));
120
+ return entries.flat();
121
+ }
122
+ async function discoverShell(names, options) {
123
+ const { env, files, probe } = options;
124
+ const login = await inspectShell(names, { env, mode: "login", probe });
125
+ const interactive = login.bash ||
126
+ (login.reason !== null && basename(env["SHELL"] ?? "") !== "zsh")
127
+ ? await inspectShell(names, { env, mode: "interactive", probe })
128
+ : null;
129
+ const found = [
130
+ ...login.entries.map((entry) => ({ entry, mode: "login" })),
131
+ ...(interactive?.bash ? interactive.entries : []).map((entry) => ({
132
+ entry,
133
+ mode: "interactive",
134
+ })),
135
+ ];
136
+ const entries = await probeCandidates(found, { files, env, probe });
137
+ return { entries, shellReason: login.reason ?? interactive?.reason ?? null };
138
+ }
139
+ async function discoverNames(definitions, context) {
140
+ const { env, probe } = context;
141
+ const files = await discoverFiles(definitions, context);
142
+ const shell = await discoverShell(definitions.map(({ name }) => name), { env, files, probe });
143
+ return {
144
+ entries: [
145
+ ...new Map([...files, ...shell.entries].map((entry) => [entryKey(entry), entry])).values(),
146
+ ],
147
+ shellReason: shell.shellReason,
148
+ };
149
+ }
150
+ export function discoverHarnesses(options) {
151
+ return discoverNames(knownHarnesses, {
152
+ env: options.env ?? process.env,
153
+ probe: options.probe,
154
+ });
155
+ }
156
+ export async function probeHarness(target, options) {
157
+ const env = options.env ?? process.env;
158
+ const probe = options.probe;
159
+ if (target.includes("/")) {
160
+ const path = await findFile(target, env);
161
+ const entry = {
162
+ name: basename(target),
163
+ kind: "file",
164
+ path: path ?? target,
165
+ };
166
+ const output = path === null
167
+ ? { stdout: "", reason: "not-found" }
168
+ : await probe(path, { arguments: ["--version"], env });
169
+ return { entries: [probeEntry(entry, output)], shellReason: null };
170
+ }
171
+ const found = await discoverNames([harnessDefinition(target)], {
172
+ env,
173
+ probe,
174
+ });
175
+ if (found.entries.length > 0)
176
+ return found;
177
+ return {
178
+ ...found,
179
+ entries: [
180
+ probeEntry({ name: target, kind: "file", path: target }, { stdout: "", reason: "not-found" }),
181
+ ],
182
+ };
183
+ }
@@ -1,2 +1,8 @@
1
1
  import type { WatchPrSettings } from "./watch-pr-settings.ts";
2
- export declare function main(argumentsList: readonly string[], watchPr?: WatchPrSettings): Promise<void>;
2
+ import type { ProbeRunner } from "./probe-command.ts";
3
+ export declare function main(argumentsList: readonly string[], context?: {
4
+ readonly watchPr?: WatchPrSettings;
5
+ readonly doctorProbe?: ProbeRunner;
6
+ readonly environment?: Readonly<NodeJS.ProcessEnv>;
7
+ readonly repository: string | undefined;
8
+ }): Promise<void>;