cloving 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (518) hide show
  1. package/README.md +525 -185
  2. package/dist/src/agent-harness-shell.d.ts +12 -0
  3. package/dist/src/agent-harness-shell.js +90 -0
  4. package/dist/src/agent-harness-versions.d.ts +8 -0
  5. package/dist/src/agent-harness-versions.js +49 -0
  6. package/dist/src/agent-harnesses.d.ts +4 -0
  7. package/dist/src/agent-harnesses.js +13 -0
  8. package/dist/src/authority/commands.d.ts +1 -0
  9. package/dist/src/authority/commands.js +24 -4
  10. package/dist/src/authority/gate-reduction.d.ts +1 -0
  11. package/dist/src/authority/gate-reduction.js +18 -3
  12. package/dist/src/authority/gates.d.ts +2 -1
  13. package/dist/src/authority/gates.js +5 -1
  14. package/dist/src/authority/operations.js +1 -1
  15. package/dist/src/authority/reduction.d.ts +1 -1
  16. package/dist/src/authority/reduction.js +6 -1
  17. package/dist/src/authority/status-input.d.ts +1 -1
  18. package/dist/src/authority/status.d.ts +1 -0
  19. package/dist/src/authority/status.js +27 -3
  20. package/dist/src/authority/transitions.d.ts +5 -5
  21. package/dist/src/authority/transitions.js +6 -0
  22. package/dist/src/broker/actor/authority-delivery.js +1 -0
  23. package/dist/src/broker/actor/authority-queries.d.ts +7 -1
  24. package/dist/src/broker/actor/authority-queries.js +17 -2
  25. package/dist/src/broker/actor/authority-receipts.js +11 -1
  26. package/dist/src/broker/actor/authority-session.js +2 -2
  27. package/dist/src/broker/actor/authority-settings.js +4 -0
  28. package/dist/src/broker/actor/delivery-intents.d.ts +2 -1
  29. package/dist/src/broker/actor/delivery-intents.js +4 -4
  30. package/dist/src/broker/actor/effect-delivery.js +4 -1
  31. package/dist/src/broker/actor/effect-queries.d.ts +1 -0
  32. package/dist/src/broker/actor/effect-queries.js +7 -0
  33. package/dist/src/broker/actor/pin-check.js +1 -1
  34. package/dist/src/broker/actor/stop-plan.js +1 -1
  35. package/dist/src/broker/actor/turn-state.js +1 -1
  36. package/dist/src/broker/authority-admission.js +22 -9
  37. package/dist/src/broker/authority-restore.js +1 -0
  38. package/dist/src/broker/decision-restore.js +4 -4
  39. package/dist/src/broker/socket-address.d.ts +3 -1
  40. package/dist/src/broker/socket-address.js +2 -2
  41. package/dist/src/cli/arguments.d.ts +11 -13
  42. package/dist/src/cli/arguments.js +37 -107
  43. package/dist/src/cli/command-effects.d.ts +7 -0
  44. package/dist/src/cli/command-effects.js +39 -0
  45. package/dist/src/cli/commands.js +11 -4
  46. package/dist/src/cli/config-arguments.d.ts +11 -0
  47. package/dist/src/cli/config-arguments.js +59 -0
  48. package/dist/src/cli/config-command.d.ts +2 -0
  49. package/dist/src/cli/config-command.js +105 -0
  50. package/dist/src/cli/config-file.d.ts +3 -0
  51. package/dist/src/cli/config-file.js +50 -0
  52. package/dist/src/cli/config-lock.d.ts +7 -0
  53. package/dist/src/cli/config-lock.js +61 -0
  54. package/dist/src/cli/config-notice.d.ts +5 -0
  55. package/dist/src/cli/config-notice.js +46 -0
  56. package/dist/src/cli/doctor-github.d.ts +9 -0
  57. package/dist/src/cli/doctor-github.js +138 -0
  58. package/dist/src/cli/doctor-harness.d.ts +13 -0
  59. package/dist/src/cli/doctor-harness.js +242 -0
  60. package/dist/src/cli/doctor-local.d.ts +18 -0
  61. package/dist/src/cli/doctor-local.js +77 -0
  62. package/dist/src/cli/doctor-runtime.d.ts +15 -0
  63. package/dist/src/cli/doctor-runtime.js +176 -0
  64. package/dist/src/cli/doctor-service.d.ts +1 -0
  65. package/dist/src/cli/doctor-service.js +11 -0
  66. package/dist/src/cli/doctor-workflows.d.ts +3 -0
  67. package/dist/src/cli/doctor-workflows.js +45 -0
  68. package/dist/src/cli/doctor.d.ts +15 -0
  69. package/dist/src/cli/doctor.js +190 -0
  70. package/dist/src/cli/github-ci-progress.d.ts +8 -0
  71. package/dist/src/cli/github-ci-progress.js +83 -0
  72. package/dist/src/cli/github-retry.d.ts +6 -0
  73. package/dist/src/cli/github-retry.js +47 -0
  74. package/dist/src/cli/harness-probes.d.ts +22 -0
  75. package/dist/src/cli/harness-probes.js +183 -0
  76. package/dist/src/cli/main.d.ts +7 -1
  77. package/dist/src/cli/main.js +39 -61
  78. package/dist/src/cli/phone-arguments.d.ts +14 -0
  79. package/dist/src/cli/phone-arguments.js +37 -0
  80. package/dist/src/cli/phone-client.d.ts +2 -0
  81. package/dist/src/cli/phone-client.js +32 -0
  82. package/dist/src/cli/phone-command.d.ts +13 -0
  83. package/dist/src/cli/phone-command.js +101 -0
  84. package/dist/src/cli/probe-command.d.ts +36 -0
  85. package/dist/src/cli/probe-command.js +59 -0
  86. package/dist/src/cli/project-settings.d.ts +4 -0
  87. package/dist/src/cli/project-settings.js +33 -0
  88. package/dist/src/cli/render.d.ts +2 -1
  89. package/dist/src/cli/render.js +44 -28
  90. package/dist/src/cli/report-github.d.ts +18 -0
  91. package/dist/src/cli/report-github.js +200 -0
  92. package/dist/src/cli/report.d.ts +17 -0
  93. package/dist/src/cli/report.js +192 -0
  94. package/dist/src/cli/repository-arguments.d.ts +5 -0
  95. package/dist/src/cli/repository-arguments.js +34 -0
  96. package/dist/src/cli/runtime-arguments.d.ts +4 -0
  97. package/dist/src/cli/runtime-arguments.js +15 -0
  98. package/dist/src/cli/runtime-directory.d.ts +6 -2
  99. package/dist/src/cli/runtime-directory.js +72 -14
  100. package/dist/src/cli/toolchain.d.ts +2 -0
  101. package/dist/src/cli/toolchain.js +22 -2
  102. package/dist/src/cli/usage-render.d.ts +5 -0
  103. package/dist/src/cli/usage-render.js +40 -1
  104. package/dist/src/cli/usage.d.ts +3 -3
  105. package/dist/src/cli/usage.js +70 -44
  106. package/dist/src/cli/watch-actions.d.ts +2 -0
  107. package/dist/src/cli/watch-actions.js +4 -4
  108. package/dist/src/cli/watch-board-view.d.ts +1 -1
  109. package/dist/src/cli/watch-board-view.js +8 -2
  110. package/dist/src/cli/watch-board.js +23 -10
  111. package/dist/src/cli/watch-card-forms.js +2 -2
  112. package/dist/src/cli/watch-client.d.ts +1 -1
  113. package/dist/src/cli/watch-client.js +7 -2
  114. package/dist/src/cli/watch-header-view.d.ts +27 -0
  115. package/dist/src/cli/watch-header-view.js +116 -0
  116. package/dist/src/cli/watch-model.js +17 -4
  117. package/dist/src/cli/watch-page.js +48 -12
  118. package/dist/src/cli/watch-phone-client.d.ts +1 -0
  119. package/dist/src/cli/watch-phone-client.js +84 -0
  120. package/dist/src/cli/watch-phone-view.d.ts +56 -0
  121. package/dist/src/cli/watch-phone-view.js +113 -0
  122. package/dist/src/cli/watch-phone.d.ts +5 -0
  123. package/dist/src/cli/watch-phone.js +53 -0
  124. package/dist/src/cli/watch-pull-request.d.ts +3 -1
  125. package/dist/src/cli/watch-pull-request.js +4 -0
  126. package/dist/src/cli/watch-render.d.ts +9 -1
  127. package/dist/src/cli/watch-server.js +23 -5
  128. package/dist/src/cli/watch-turn.d.ts +4 -1
  129. package/dist/src/cli/watch-turn.js +37 -1
  130. package/dist/src/cli/watch-usage.js +5 -1
  131. package/dist/src/cli/watch-view.d.ts +6 -20
  132. package/dist/src/cli/watch-view.js +14 -106
  133. package/dist/src/cli.js +106 -23
  134. package/dist/src/command-settings.d.ts +16 -0
  135. package/dist/src/command-settings.js +42 -0
  136. package/dist/src/configuration-change.d.ts +11 -0
  137. package/dist/src/configuration-change.js +62 -0
  138. package/dist/src/configuration-display.d.ts +21 -0
  139. package/dist/src/configuration-display.js +69 -0
  140. package/dist/src/configuration-schema.d.ts +49 -0
  141. package/dist/src/configuration-schema.js +159 -0
  142. package/dist/src/daemon/claude-turn.d.ts +19 -5
  143. package/dist/src/daemon/claude-turn.js +116 -53
  144. package/dist/src/daemon/claude-worker.d.ts +3 -3
  145. package/dist/src/daemon/claude-worker.js +65 -76
  146. package/dist/src/daemon/command-journal.d.ts +5 -0
  147. package/dist/src/daemon/command-journal.js +50 -0
  148. package/dist/src/daemon/command-process.d.ts +28 -0
  149. package/dist/src/daemon/command-process.js +164 -0
  150. package/dist/src/daemon/command-worker.d.ts +19 -0
  151. package/dist/src/daemon/command-worker.js +182 -0
  152. package/dist/src/daemon/cursor-stream.d.ts +4 -0
  153. package/dist/src/daemon/cursor-stream.js +154 -0
  154. package/dist/src/daemon/daemon-adapters.d.ts +58 -0
  155. package/dist/src/daemon/daemon-adapters.js +102 -0
  156. package/dist/src/daemon/daemon-loops.d.ts +14 -0
  157. package/dist/src/daemon/daemon-loops.js +39 -0
  158. package/dist/src/daemon/daemon.d.ts +2 -33
  159. package/dist/src/daemon/daemon.js +126 -132
  160. package/dist/src/daemon/declared-input.d.ts +3 -0
  161. package/dist/src/daemon/declared-input.js +9 -0
  162. package/dist/src/daemon/delivery-router.js +1 -1
  163. package/dist/src/daemon/gemini-stream.d.ts +4 -0
  164. package/dist/src/daemon/gemini-stream.js +129 -0
  165. package/dist/src/daemon/github-ci-rerun.d.ts +26 -0
  166. package/dist/src/daemon/github-ci-rerun.js +92 -0
  167. package/dist/src/daemon/github-ci.js +89 -8
  168. package/dist/src/daemon/github-merge-call.d.ts +2 -0
  169. package/dist/src/daemon/github-merge.js +7 -3
  170. package/dist/src/daemon/github-methods.js +10 -0
  171. package/dist/src/daemon/github-operation.d.ts +1 -0
  172. package/dist/src/daemon/github-retry.js +8 -44
  173. package/dist/src/daemon/issue-queue.d.ts +1 -0
  174. package/dist/src/daemon/issue-queue.js +3 -26
  175. package/dist/src/daemon/notify.js +2 -1
  176. package/dist/src/daemon/opencode-stream.d.ts +5 -0
  177. package/dist/src/daemon/opencode-stream.js +87 -0
  178. package/dist/src/daemon/queue-status.d.ts +4 -0
  179. package/dist/src/daemon/queue-status.js +38 -0
  180. package/dist/src/daemon/retry-worktree.d.ts +18 -0
  181. package/dist/src/daemon/retry-worktree.js +139 -0
  182. package/dist/src/daemon/retrying-turn.d.ts +2 -0
  183. package/dist/src/daemon/retrying-turn.js +108 -30
  184. package/dist/src/daemon/schedule-journal.d.ts +19 -0
  185. package/dist/src/daemon/schedule-journal.js +57 -0
  186. package/dist/src/daemon/text-output.d.ts +18 -0
  187. package/dist/src/daemon/text-output.js +44 -0
  188. package/dist/src/daemon/ticket-registration.d.ts +5 -7
  189. package/dist/src/daemon/ticket-registration.js +85 -40
  190. package/dist/src/daemon/turn-command.d.ts +10 -0
  191. package/dist/src/daemon/turn-command.js +33 -0
  192. package/dist/src/daemon/turn-report.d.ts +18 -0
  193. package/dist/src/daemon/turn-report.js +79 -0
  194. package/dist/src/daemon/work-tree.d.ts +2 -1
  195. package/dist/src/daemon/work-tree.js +15 -12
  196. package/dist/src/daemon/workflow-generations.d.ts +32 -0
  197. package/dist/src/daemon/workflow-generations.js +57 -0
  198. package/dist/src/daemon/workflow-replay.d.ts +16 -0
  199. package/dist/src/daemon/workflow-replay.js +58 -0
  200. package/dist/src/daemon/workflow-schedules.d.ts +27 -0
  201. package/dist/src/daemon/workflow-schedules.js +185 -0
  202. package/dist/src/decision-wait.d.ts +1 -0
  203. package/dist/src/decision-wait.js +3 -0
  204. package/dist/src/delivery-backoff.d.ts +1 -0
  205. package/dist/src/delivery-backoff.js +3 -0
  206. package/dist/src/doctor-report.d.ts +24 -0
  207. package/dist/src/doctor-report.js +70 -0
  208. package/dist/src/execution-pin.d.ts +5 -0
  209. package/dist/src/execution-pin.js +67 -4
  210. package/dist/src/grok-result.d.ts +12 -0
  211. package/dist/src/grok-result.js +61 -0
  212. package/dist/src/harness-defaults.d.ts +35 -0
  213. package/dist/src/harness-defaults.js +121 -0
  214. package/dist/src/host/decision-resume.d.ts +35 -0
  215. package/dist/src/host/decision-resume.js +86 -0
  216. package/dist/src/host/gate-bridge.d.ts +48 -0
  217. package/dist/src/host/gate-bridge.js +124 -0
  218. package/dist/src/host/run-wait.d.ts +26 -0
  219. package/dist/src/host/run-wait.js +37 -0
  220. package/dist/src/host/start-delivery.d.ts +1 -1
  221. package/dist/src/host/start-delivery.js +10 -3
  222. package/dist/src/host/step-bridge-host.d.ts +6 -20
  223. package/dist/src/host/step-bridge-host.js +44 -58
  224. package/dist/src/merge-request.d.ts +19 -0
  225. package/dist/src/merge-request.js +32 -0
  226. package/dist/src/phone/canonical-json.d.ts +1 -0
  227. package/dist/src/phone/canonical-json.js +16 -0
  228. package/dist/src/phone/phone-link.d.ts +7 -0
  229. package/dist/src/phone/phone-link.js +21 -0
  230. package/dist/src/phone/qr-data.d.ts +8 -0
  231. package/dist/src/phone/qr-data.js +133 -0
  232. package/dist/src/phone/qr-matrix.d.ts +6 -0
  233. package/dist/src/phone/qr-matrix.js +175 -0
  234. package/dist/src/phone/qr-penalty.d.ts +3 -0
  235. package/dist/src/phone/qr-penalty.js +67 -0
  236. package/dist/src/phone/qr-picture.d.ts +5 -0
  237. package/dist/src/phone/qr-picture.js +24 -0
  238. package/dist/src/private-config.schema.json +263 -0
  239. package/dist/src/project-config.schema.json +65 -0
  240. package/dist/src/project-settings.d.ts +19 -0
  241. package/dist/src/project-settings.js +131 -0
  242. package/dist/src/relay/answer-check.d.ts +24 -0
  243. package/dist/src/relay/answer-check.js +145 -0
  244. package/dist/src/relay/answer-inbox.d.ts +15 -0
  245. package/dist/src/relay/answer-inbox.js +173 -0
  246. package/dist/src/relay/daemon-keys.d.ts +16 -0
  247. package/dist/src/relay/daemon-keys.js +75 -0
  248. package/dist/src/relay/decision-check.d.ts +3 -0
  249. package/dist/src/relay/decision-check.js +77 -0
  250. package/dist/src/relay/decision-close.d.ts +6 -0
  251. package/dist/src/relay/decision-close.js +72 -0
  252. package/dist/src/relay/decision-envelopes.d.ts +29 -0
  253. package/dist/src/relay/decision-envelopes.js +93 -0
  254. package/dist/src/relay/decision-watch.d.ts +14 -0
  255. package/dist/src/relay/decision-watch.js +68 -0
  256. package/dist/src/relay/envelope-post.d.ts +8 -0
  257. package/dist/src/relay/envelope-post.js +71 -0
  258. package/dist/src/relay/envelope.d.ts +28 -0
  259. package/dist/src/relay/envelope.js +53 -0
  260. package/dist/src/relay/hpke.d.ts +25 -0
  261. package/dist/src/relay/hpke.js +108 -0
  262. package/dist/src/relay/pairing-checks.d.ts +42 -0
  263. package/dist/src/relay/pairing-checks.js +172 -0
  264. package/dist/src/relay/pairing-follow.d.ts +8 -0
  265. package/dist/src/relay/pairing-follow.js +95 -0
  266. package/dist/src/relay/pairing-session.d.ts +29 -0
  267. package/dist/src/relay/pairing-session.js +87 -0
  268. package/dist/src/relay/phone-delivery.d.ts +51 -0
  269. package/dist/src/relay/phone-delivery.js +139 -0
  270. package/dist/src/relay/phone-devices.d.ts +36 -0
  271. package/dist/src/relay/phone-devices.js +46 -0
  272. package/dist/src/relay/phone-inbox.d.ts +18 -0
  273. package/dist/src/relay/phone-inbox.js +17 -0
  274. package/dist/src/relay/phone-operations.d.ts +18 -0
  275. package/dist/src/relay/phone-operations.js +121 -0
  276. package/dist/src/relay/phone-outbox.d.ts +21 -0
  277. package/dist/src/relay/phone-outbox.js +25 -0
  278. package/dist/src/relay/phone-socket.d.ts +6 -0
  279. package/dist/src/relay/phone-socket.js +63 -0
  280. package/dist/src/relay/relay-control.d.ts +7 -0
  281. package/dist/src/relay/relay-control.js +24 -0
  282. package/dist/src/relay/relay-files.d.ts +2 -0
  283. package/dist/src/relay/relay-files.js +23 -0
  284. package/dist/src/relay/relay-heartbeat.d.ts +17 -0
  285. package/dist/src/relay/relay-heartbeat.js +81 -0
  286. package/dist/src/relay/relay-http.d.ts +14 -0
  287. package/dist/src/relay/relay-http.js +63 -0
  288. package/dist/src/relay/relay-registration.d.ts +15 -0
  289. package/dist/src/relay/relay-registration.js +63 -0
  290. package/dist/src/relay/relay-service.d.ts +25 -0
  291. package/dist/src/relay/relay-service.js +216 -0
  292. package/dist/src/relay/relay-store.d.ts +48 -0
  293. package/dist/src/relay/relay-store.js +131 -0
  294. package/dist/src/relay/sealed-post.d.ts +25 -0
  295. package/dist/src/relay/sealed-post.js +52 -0
  296. package/dist/src/relay.d.ts +1 -0
  297. package/dist/src/relay.js +8 -0
  298. package/dist/src/report-statistics.d.ts +50 -0
  299. package/dist/src/report-statistics.js +70 -0
  300. package/dist/src/report.d.ts +171 -0
  301. package/dist/src/report.js +119 -0
  302. package/dist/src/repository-identity.d.ts +4 -0
  303. package/dist/src/repository-identity.js +4 -0
  304. package/dist/src/review-subject.d.ts +41 -0
  305. package/dist/src/review-subject.js +91 -0
  306. package/dist/src/run-wait.d.ts +23 -0
  307. package/dist/src/run-wait.js +20 -0
  308. package/dist/src/service/active-tickets.d.ts +4 -0
  309. package/dist/src/service/active-tickets.js +49 -0
  310. package/dist/src/service/command-effects.d.ts +4 -0
  311. package/dist/src/service/command-effects.js +16 -0
  312. package/dist/src/service/decision-handler.d.ts +4 -0
  313. package/dist/src/service/decision-handler.js +39 -4
  314. package/dist/src/service/gateway.js +18 -3
  315. package/dist/src/service/registry.d.ts +16 -3
  316. package/dist/src/service/registry.js +34 -3
  317. package/dist/src/service/replies.d.ts +9 -1
  318. package/dist/src/service/replies.js +12 -0
  319. package/dist/src/service/run-handlers.js +14 -55
  320. package/dist/src/service/run-metadata.d.ts +8 -0
  321. package/dist/src/service/run-metadata.js +53 -0
  322. package/dist/src/service/run-waits.d.ts +3 -0
  323. package/dist/src/service/run-waits.js +41 -0
  324. package/dist/src/service/service.d.ts +18 -2
  325. package/dist/src/service/service.js +23 -7
  326. package/dist/src/service/submission-handler.d.ts +0 -1
  327. package/dist/src/service/submission-handler.js +6 -34
  328. package/dist/src/service/worker-port.d.ts +1 -0
  329. package/dist/src/service/worker-totals.js +8 -23
  330. package/dist/src/step-bridge.d.ts +23 -0
  331. package/dist/src/steps/decision-gate.d.ts +2 -1
  332. package/dist/src/steps/decision-gate.js +7 -0
  333. package/dist/src/steps/merge-by-person.d.ts +2 -0
  334. package/dist/src/steps/merge-by-person.js +18 -0
  335. package/dist/src/steps/merge-when-green.d.ts +2 -0
  336. package/dist/src/steps/merge-when-green.js +62 -0
  337. package/dist/src/steps/review-by-agent.d.ts +5 -0
  338. package/dist/src/steps/review-by-agent.js +124 -0
  339. package/dist/src/steps/review-by-person.d.ts +4 -0
  340. package/dist/src/steps/review-by-person.js +16 -0
  341. package/dist/src/steps/review-subject.d.ts +2 -0
  342. package/dist/src/steps/review-subject.js +11 -0
  343. package/dist/src/steps/run-command.d.ts +2 -0
  344. package/dist/src/steps/run-command.js +15 -0
  345. package/dist/src/steps/sleep.d.ts +3 -0
  346. package/dist/src/steps/sleep.js +19 -0
  347. package/dist/src/steps/wait-for-decision.d.ts +2 -0
  348. package/dist/src/steps/wait-for-decision.js +71 -0
  349. package/dist/src/steps/wait-for-run.d.ts +5 -0
  350. package/dist/src/steps/wait-for-run.js +9 -0
  351. package/dist/src/storage/decision-snapshots.d.ts +1 -0
  352. package/dist/src/storage/decision-snapshots.js +7 -1
  353. package/dist/src/submission.d.ts +4 -0
  354. package/dist/src/submission.js +6 -2
  355. package/dist/src/testing.d.ts +29 -0
  356. package/dist/src/testing.js +264 -0
  357. package/dist/src/ticket-status-stream.d.ts +9 -0
  358. package/dist/src/ticket-status-stream.js +94 -0
  359. package/dist/src/token-prices.d.ts +12 -4
  360. package/dist/src/token-prices.js +15 -2
  361. package/dist/src/turn-profile.d.ts +1 -0
  362. package/dist/src/turn-profile.js +8 -1
  363. package/dist/src/worker-usage.d.ts +16 -0
  364. package/dist/src/worker-usage.js +57 -0
  365. package/dist/src/workflow-admission.d.ts +5 -0
  366. package/dist/src/workflow-candidate.d.ts +7 -2
  367. package/dist/src/workflow-candidate.js +47 -5
  368. package/dist/src/workflow-declaration.d.ts +21 -3
  369. package/dist/src/workflow-declaration.js +77 -9
  370. package/dist/src/workflow-discovery.d.ts +2 -1
  371. package/dist/src/workflow-discovery.js +4 -1
  372. package/dist/src/workflow-refusals.js +3 -0
  373. package/dist/src/workflow-schedule.d.ts +22 -0
  374. package/dist/src/workflow-schedule.js +53 -0
  375. package/dist/src/workflows.d.ts +11 -1
  376. package/dist/src/workflows.js +8 -0
  377. package/dist/tools/admit-workflow.d.ts +1 -0
  378. package/dist/tools/admit-workflow.js +18 -5
  379. package/dist/tools/doctor-adoption.d.ts +1 -0
  380. package/dist/tools/doctor-adoption.js +11 -0
  381. package/dist/tools/project-configuration.d.ts +4 -0
  382. package/dist/tools/project-configuration.js +47 -0
  383. package/dist/tools/self-host-processes.d.ts +1 -0
  384. package/dist/tools/self-host-processes.js +33 -22
  385. package/dist/tools/self-host-project.d.ts +4 -0
  386. package/dist/tools/self-host-project.js +61 -14
  387. package/dist/tools/self-host-runtime.d.ts +16 -0
  388. package/dist/tools/self-host-runtime.js +60 -0
  389. package/dist/tools/self-host-workflows.d.ts +1 -0
  390. package/dist/tools/self-host-workflows.js +36 -1
  391. package/dist/tools/self-host.js +86 -61
  392. package/dist/tools/workflow-candidate-counts.d.ts +6 -2
  393. package/dist/tools/workflow-candidate-counts.js +31 -16
  394. package/dist/tools/workflow-candidate-fields.d.ts +5 -0
  395. package/dist/tools/workflow-candidate-fields.js +24 -0
  396. package/dist/tools/workflow-candidate-helper-counts.d.ts +10 -0
  397. package/dist/tools/workflow-candidate-helper-counts.js +129 -0
  398. package/dist/tools/workflow-candidate-program.d.ts +2 -0
  399. package/dist/tools/workflow-candidate-program.js +36 -8
  400. package/dist/tools/workflow-candidate-source.js +77 -15
  401. package/dist/tools/workflow-candidate-syntax.d.ts +8 -2
  402. package/dist/tools/workflow-candidate-syntax.js +70 -26
  403. package/dist/tools/workflow-command.d.ts +1 -0
  404. package/dist/tools/workflow-command.js +143 -0
  405. package/dist/tools/workflow-folder-capture.d.ts +1 -0
  406. package/dist/tools/workflow-folder-capture.js +47 -2
  407. package/dist/tools/workflow-folders.d.ts +17 -1
  408. package/dist/tools/workflow-folders.js +59 -6
  409. package/dist/tools/workflow-test-hook.d.ts +7 -0
  410. package/dist/tools/workflow-test-hook.js +16 -0
  411. package/dist/tools/workflow-test-loader.d.ts +1 -0
  412. package/dist/tools/workflow-test-loader.js +10 -0
  413. package/dist/workflows/develop-ticket.js +1 -1
  414. package/dist/workflows/ticket-prompts.js +5 -1
  415. package/package.json +46 -4
  416. package/templates/develop/README.md +78 -0
  417. package/templates/develop/develop/accept.ts +11 -0
  418. package/templates/develop/develop/flow-tests.ts +357 -0
  419. package/templates/develop/develop/local.ts +40 -0
  420. package/templates/develop/develop/option-tests.ts +174 -0
  421. package/templates/develop/develop/partial-choice.ts +29 -0
  422. package/templates/develop/develop/partial.ts +28 -0
  423. package/templates/develop/develop/pull.ts +152 -0
  424. package/templates/develop/develop/queue-partial.ts +39 -0
  425. package/templates/develop/develop/refusal-tests.ts +174 -0
  426. package/templates/develop/develop/report.ts +156 -0
  427. package/templates/develop/develop/round.ts +40 -0
  428. package/templates/develop/develop/scenarios.ts +87 -0
  429. package/templates/develop/develop/turn.ts +67 -0
  430. package/templates/develop/develop.declaration.json +24 -0
  431. package/templates/develop/develop.test.ts +287 -0
  432. package/templates/develop/develop.ts +30 -0
  433. package/templates/develop/template.json +153 -0
  434. package/dist/src/chats/analysis-batches.d.ts +0 -42
  435. package/dist/src/chats/analysis-batches.js +0 -97
  436. package/dist/src/chats/analysis-checkpoint.d.ts +0 -29
  437. package/dist/src/chats/analysis-checkpoint.js +0 -31
  438. package/dist/src/chats/analysis-contract.d.ts +0 -80
  439. package/dist/src/chats/analysis-contract.js +0 -16
  440. package/dist/src/chats/analysis-data.d.ts +0 -3
  441. package/dist/src/chats/analysis-data.js +0 -85
  442. package/dist/src/chats/analysis-input.d.ts +0 -18
  443. package/dist/src/chats/analysis-input.js +0 -97
  444. package/dist/src/chats/analysis-links.d.ts +0 -2
  445. package/dist/src/chats/analysis-links.js +0 -25
  446. package/dist/src/chats/analysis-merge.d.ts +0 -16
  447. package/dist/src/chats/analysis-merge.js +0 -134
  448. package/dist/src/chats/analysis-prompt.d.ts +0 -18
  449. package/dist/src/chats/analysis-prompt.js +0 -42
  450. package/dist/src/chats/analysis-proposal.d.ts +0 -4
  451. package/dist/src/chats/analysis-proposal.js +0 -41
  452. package/dist/src/chats/analysis-provenance.d.ts +0 -4
  453. package/dist/src/chats/analysis-provenance.js +0 -99
  454. package/dist/src/chats/analysis-shape.d.ts +0 -4
  455. package/dist/src/chats/analysis-shape.js +0 -235
  456. package/dist/src/chats/analysis.d.ts +0 -3
  457. package/dist/src/chats/analysis.js +0 -42
  458. package/dist/src/chats/corpus-input.d.ts +0 -5
  459. package/dist/src/chats/corpus-input.js +0 -288
  460. package/dist/src/chats/destination.d.ts +0 -4
  461. package/dist/src/chats/destination.js +0 -96
  462. package/dist/src/chats/import.d.ts +0 -15
  463. package/dist/src/chats/import.js +0 -243
  464. package/dist/src/chats/input-file.d.ts +0 -3
  465. package/dist/src/chats/input-file.js +0 -32
  466. package/dist/src/chats/normalize.d.ts +0 -29
  467. package/dist/src/chats/normalize.js +0 -155
  468. package/dist/src/chats/previous-import.d.ts +0 -5
  469. package/dist/src/chats/previous-import.js +0 -34
  470. package/dist/src/chats/reader.d.ts +0 -21
  471. package/dist/src/chats/reader.js +0 -118
  472. package/dist/src/chats/redact-import.d.ts +0 -14
  473. package/dist/src/chats/redact-import.js +0 -141
  474. package/dist/src/chats/redaction.d.ts +0 -41
  475. package/dist/src/chats/redaction.js +0 -161
  476. package/dist/src/chats/reference-mapping.d.ts +0 -16
  477. package/dist/src/chats/reference-mapping.js +0 -153
  478. package/dist/src/chats/revision-input.d.ts +0 -3
  479. package/dist/src/chats/revision-input.js +0 -180
  480. package/dist/src/chats/revision.d.ts +0 -48
  481. package/dist/src/chats/revision.js +0 -94
  482. package/dist/src/chats/selection.d.ts +0 -25
  483. package/dist/src/chats/selection.js +0 -109
  484. package/dist/src/chats/source.d.ts +0 -23
  485. package/dist/src/chats/source.js +0 -135
  486. package/dist/src/chats/structure.d.ts +0 -57
  487. package/dist/src/chats/structure.js +0 -216
  488. package/dist/src/chats/workflow-generation-projection.d.ts +0 -8
  489. package/dist/src/chats/workflow-generation-projection.js +0 -75
  490. package/dist/src/chats/workflow-generation-source.d.ts +0 -25
  491. package/dist/src/chats/workflow-generation-source.js +0 -124
  492. package/dist/src/chats/workflow-generation-text.d.ts +0 -23
  493. package/dist/src/chats/workflow-generation-text.js +0 -74
  494. package/dist/src/chats/workflow-generation.d.ts +0 -69
  495. package/dist/src/chats/workflow-generation.js +0 -142
  496. package/dist/src/daemon/analysis-launch.d.ts +0 -5
  497. package/dist/src/daemon/analysis-launch.js +0 -81
  498. package/dist/src/daemon/analysis-token.d.ts +0 -6
  499. package/dist/src/daemon/analysis-token.js +0 -88
  500. package/dist/src/daemon/analysis-worker.d.ts +0 -20
  501. package/dist/src/daemon/analysis-worker.js +0 -271
  502. package/dist/src/daemon/chats-batch-binding.d.ts +0 -23
  503. package/dist/src/daemon/chats-batch-binding.js +0 -99
  504. package/dist/src/daemon/chats-capture.d.ts +0 -18
  505. package/dist/src/daemon/chats-capture.js +0 -194
  506. package/dist/src/daemon/chats-checkpoints.d.ts +0 -41
  507. package/dist/src/daemon/chats-checkpoints.js +0 -186
  508. package/dist/src/daemon/chats-files.d.ts +0 -42
  509. package/dist/src/daemon/chats-files.js +0 -252
  510. package/dist/src/daemon/chats-follow-up.d.ts +0 -38
  511. package/dist/src/daemon/chats-follow-up.js +0 -180
  512. package/dist/src/daemon/chats-question.d.ts +0 -15
  513. package/dist/src/daemon/chats-question.js +0 -93
  514. package/dist/src/daemon/chats-worker.d.ts +0 -13
  515. package/dist/src/daemon/chats-worker.js +0 -201
  516. package/dist/workflows/analyze-chats.d.ts +0 -15
  517. package/dist/workflows/analyze-chats.declaration.json +0 -22
  518. package/dist/workflows/analyze-chats.js +0 -250
@@ -0,0 +1,59 @@
1
+ import { parseArgs } from "node:util";
2
+ const argumentCounts = { list: 1, get: 2, set: 3, unset: 2 };
3
+ function escapedValue(argumentsList) {
4
+ const flags = new Set(["--json", "--private", "--help", "-h"]);
5
+ const positionals = argumentsList
6
+ .map((value, index) => ({ value, index }))
7
+ .filter(({ value }) => !flags.has(value));
8
+ const [command, , value] = positionals;
9
+ if (command?.value !== "set" ||
10
+ value === undefined ||
11
+ !value.value.startsWith("-") ||
12
+ argumentsList.includes("--"))
13
+ return { argumentsList };
14
+ return {
15
+ argumentsList: argumentsList.map((item, index) => index === value.index ? "config-value" : item),
16
+ value: value.value,
17
+ };
18
+ }
19
+ function knownAction(value) {
20
+ return value !== undefined && Object.hasOwn(argumentCounts, value);
21
+ }
22
+ function mutation(action) {
23
+ return action === "set" || action === "unset";
24
+ }
25
+ export function configInvocation(argumentsList) {
26
+ try {
27
+ const escaped = escapedValue(argumentsList);
28
+ const { values, positionals } = parseArgs({
29
+ args: [...escaped.argumentsList],
30
+ options: {
31
+ private: { type: "boolean" },
32
+ json: { type: "boolean" },
33
+ help: { type: "boolean", short: "h" },
34
+ },
35
+ allowPositionals: true,
36
+ });
37
+ const [action, field, parsedValue] = positionals;
38
+ const value = escaped.value ?? parsedValue;
39
+ if (values.help)
40
+ return { kind: "config-help" };
41
+ if (!knownAction(action))
42
+ return "unknown-command";
43
+ if (positionals.length !== argumentCounts[action])
44
+ return "invalid-invocation";
45
+ if (values.private && !mutation(action))
46
+ return "unexpected-option";
47
+ return {
48
+ kind: "config",
49
+ action,
50
+ ...(field === undefined ? {} : { field }),
51
+ ...(value === undefined ? {} : { value }),
52
+ private: values.private === true,
53
+ json: values.json === true,
54
+ };
55
+ }
56
+ catch {
57
+ return "invalid-invocation";
58
+ }
59
+ }
@@ -0,0 +1,2 @@
1
+ import type { ConfigInvocation } from "./config-arguments.ts";
2
+ export declare function configCommand(invocation: ConfigInvocation, repository: string | undefined): Promise<number>;
@@ -0,0 +1,105 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { settingScope, validateSetting } from "../configuration-schema.js";
4
+ import { settingValue } from "../configuration-change.js";
5
+ import { configurationEntries, } from "../configuration-display.js";
6
+ import { isProfilesFile } from "../turn-profile.js";
7
+ import { changeConfigFile, readConfigFile } from "./config-file.js";
8
+ import { privateSettingsPath } from "./project-settings.js";
9
+ import { configNotice } from "./config-notice.js";
10
+ async function environmentProfiles() {
11
+ const path = process.env["CLOVING_PROFILES"];
12
+ if (path === undefined)
13
+ return undefined;
14
+ const value = JSON.parse(await readFile(path, "utf8"));
15
+ if (!isProfilesFile(value))
16
+ throw new Error("invalid-setting: profiles");
17
+ return value.profiles;
18
+ }
19
+ async function entries(repository, field) {
20
+ const [project, privateFile, profiles] = await Promise.all([
21
+ readConfigFile(join(repository, ".cloving/config.json")),
22
+ readConfigFile(privateSettingsPath(process.env, repository)),
23
+ environmentProfiles(),
24
+ ]);
25
+ return configurationEntries({
26
+ project,
27
+ private: privateFile,
28
+ environment: process.env,
29
+ ...(profiles === undefined ? {} : { profiles }),
30
+ ...(field === undefined ? {} : { field }),
31
+ });
32
+ }
33
+ function entryLine(entry) {
34
+ const hidden = entry.hidden
35
+ .map((item) => `; hidden ${item.source}: ${JSON.stringify(item.value)}`)
36
+ .join("");
37
+ return `${entry.field} = ${JSON.stringify(entry.value)} (${entry.source})${hidden}\n`;
38
+ }
39
+ function present(invocation, result) {
40
+ if (invocation.json) {
41
+ process.stdout.write(JSON.stringify({ schemaVersion: 1, ...result }) + "\n");
42
+ return;
43
+ }
44
+ if ("settings" in result) {
45
+ for (const entry of result.settings)
46
+ process.stdout.write(entryLine(entry));
47
+ return;
48
+ }
49
+ if ("source" in result) {
50
+ process.stdout.write(entryLine(result));
51
+ return;
52
+ }
53
+ process.stdout.write(`${result.action}: ${result.field}\n`);
54
+ if (result.notice !== null)
55
+ process.stdout.write(result.notice + "\n");
56
+ }
57
+ async function execute(invocation, repository) {
58
+ if (invocation.action === "list")
59
+ return { settings: await entries(repository) };
60
+ const field = invocation.field ?? "";
61
+ const defaultScope = settingScope(field);
62
+ const scope = invocation.private ? "private" : defaultScope;
63
+ if (invocation.action === "set")
64
+ validateSetting(field, settingValue(invocation.value ?? ""));
65
+ const [current] = await entries(repository, field);
66
+ if (current === undefined)
67
+ throw new Error(`unknown-setting: ${field}`);
68
+ if (invocation.action === "get")
69
+ return current;
70
+ const path = scope === "private"
71
+ ? privateSettingsPath(process.env, repository)
72
+ : join(repository, ".cloving/config.json");
73
+ await changeConfigFile(path, {
74
+ field,
75
+ scope,
76
+ action: invocation.action,
77
+ ...(invocation.value === undefined ? {} : { value: invocation.value }),
78
+ });
79
+ const notice = await configNotice(repository, {
80
+ scope,
81
+ entry: (await entries(repository, field))[0],
82
+ });
83
+ return { field, scope, action: invocation.action, notice };
84
+ }
85
+ export async function configCommand(invocation, repository) {
86
+ try {
87
+ if (repository === undefined)
88
+ throw new Error("repository-unknown");
89
+ present(invocation, await execute(invocation, repository));
90
+ return 0;
91
+ }
92
+ catch (error) {
93
+ const detail = error instanceof Error ? error.message : "configuration-error";
94
+ if (invocation.json)
95
+ process.stdout.write(JSON.stringify({
96
+ schemaVersion: 1,
97
+ kind: "error",
98
+ code: detail.split(":")[0],
99
+ detail,
100
+ }) + "\n");
101
+ else
102
+ process.stderr.write(detail + "\n");
103
+ return 2;
104
+ }
105
+ }
@@ -0,0 +1,3 @@
1
+ import { type SettingChange } from "../configuration-change.ts";
2
+ export declare function readConfigFile(path: string): Promise<string | undefined>;
3
+ export declare function changeConfigFile(path: string, change: SettingChange): Promise<void>;
@@ -0,0 +1,50 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { chmod, mkdir, readFile, rename, rm, stat, writeFile, } from "node:fs/promises";
3
+ import { dirname } from "node:path";
4
+ import { acquireSettingsLock, releaseSettingsLock } from "./config-lock.js";
5
+ import { changedConfiguration, } from "../configuration-change.js";
6
+ export async function readConfigFile(path) {
7
+ try {
8
+ return await readFile(path, "utf8");
9
+ }
10
+ catch (error) {
11
+ if (error instanceof Error && "code" in error && error.code === "ENOENT")
12
+ return undefined;
13
+ throw error;
14
+ }
15
+ }
16
+ async function atomicWrite(path, contents) {
17
+ const { text, mode = 0o600 } = contents;
18
+ const temporary = `${path}.${randomUUID()}.tmp`;
19
+ try {
20
+ await writeFile(temporary, text, { mode: 0o600, flag: "wx" });
21
+ if (mode !== 0o600)
22
+ await chmod(temporary, mode);
23
+ await rename(temporary, path);
24
+ }
25
+ finally {
26
+ await rm(temporary, { force: true });
27
+ }
28
+ }
29
+ export async function changeConfigFile(path, change) {
30
+ await mkdir(dirname(path), { recursive: true, mode: 0o700 });
31
+ const lock = await acquireSettingsLock(`${path}.lock`);
32
+ try {
33
+ await writeChange(path, change);
34
+ }
35
+ finally {
36
+ await releaseSettingsLock(lock);
37
+ }
38
+ }
39
+ async function writeChange(path, change) {
40
+ const previous = await readConfigFile(path);
41
+ const next = changedConfiguration(previous, change);
42
+ const mode = previous !== undefined && change.scope === "project"
43
+ ? (await stat(path)).mode & 0o777
44
+ : 0o600;
45
+ if (previous !== undefined && change.scope === "private")
46
+ await chmod(path, 0o600);
47
+ if (previous !== undefined)
48
+ await atomicWrite(`${path}.bak`, { text: previous });
49
+ await atomicWrite(path, { text: next, mode });
50
+ }
@@ -0,0 +1,7 @@
1
+ interface Lock {
2
+ readonly path: string;
3
+ readonly owner: string;
4
+ }
5
+ export declare function releaseSettingsLock(lock: Lock): Promise<void>;
6
+ export declare function acquireSettingsLock(path: string, deadline?: number): Promise<Lock>;
7
+ export {};
@@ -0,0 +1,61 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { readlink, symlink, unlink } from "node:fs/promises";
3
+ import { setTimeout } from "node:timers/promises";
4
+ function hasCode(error, code) {
5
+ return error instanceof Error && "code" in error && error.code === code;
6
+ }
7
+ async function owner(path) {
8
+ try {
9
+ return await readlink(path);
10
+ }
11
+ catch (error) {
12
+ if (hasCode(error, "ENOENT"))
13
+ return undefined;
14
+ throw error;
15
+ }
16
+ }
17
+ function stopped(value) {
18
+ const [pid] = value.split("-");
19
+ if (pid === undefined || !/^[1-9][0-9]*$/.test(pid))
20
+ return false;
21
+ try {
22
+ process.kill(Number(pid), 0);
23
+ return false;
24
+ }
25
+ catch (error) {
26
+ return hasCode(error, "ESRCH");
27
+ }
28
+ }
29
+ export async function releaseSettingsLock(lock) {
30
+ if ((await owner(lock.path)) === lock.owner)
31
+ await unlink(lock.path);
32
+ }
33
+ async function reclaim(path, input) {
34
+ const guard = await acquireSettingsLock(`${path}.reap`, input.deadline);
35
+ try {
36
+ if ((await owner(path)) === input.previous)
37
+ await unlink(path);
38
+ }
39
+ finally {
40
+ await releaseSettingsLock(guard);
41
+ }
42
+ }
43
+ export async function acquireSettingsLock(path, deadline = Date.now() + 10000) {
44
+ const lock = { path, owner: `${String(process.pid)}-${randomUUID()}` };
45
+ while (Date.now() < deadline) {
46
+ try {
47
+ await symlink(lock.owner, path);
48
+ return lock;
49
+ }
50
+ catch (error) {
51
+ if (!hasCode(error, "EEXIST"))
52
+ throw error;
53
+ }
54
+ const previous = await owner(path);
55
+ if (previous !== undefined && stopped(previous))
56
+ await reclaim(path, { previous, deadline });
57
+ else
58
+ await setTimeout(Math.min(25, Math.max(1, deadline - Date.now())));
59
+ }
60
+ throw new Error("settings-locked");
61
+ }
@@ -0,0 +1,5 @@
1
+ import type { SettingEntry } from "../configuration-display.ts";
2
+ export declare function configNotice(repository: string, input: {
3
+ readonly scope: "project" | "private";
4
+ readonly entry: SettingEntry | undefined;
5
+ }): Promise<string | null>;
@@ -0,0 +1,46 @@
1
+ import net from "node:net";
2
+ import { join } from "node:path";
3
+ import { socketAddress } from "../broker/socket-address.js";
4
+ import { runtimeDirectory } from "./runtime-directory.js";
5
+ function serviceDirectory(repository) {
6
+ try {
7
+ return runtimeDirectory(process.env, repository);
8
+ }
9
+ catch {
10
+ return undefined;
11
+ }
12
+ }
13
+ function running(repository) {
14
+ const directory = serviceDirectory(repository);
15
+ if (directory === undefined)
16
+ return Promise.resolve(false);
17
+ const address = socketAddress(join(directory, "control.sock"));
18
+ if (address.kind !== "address")
19
+ return Promise.resolve(false);
20
+ return new Promise((resolve) => {
21
+ const socket = net.connect(address.path);
22
+ const finish = (result) => {
23
+ socket.destroy();
24
+ resolve(result.connected);
25
+ };
26
+ socket.setTimeout(250);
27
+ socket.once("connect", () => {
28
+ finish({ connected: true });
29
+ });
30
+ const unavailable = () => {
31
+ finish({ connected: false });
32
+ };
33
+ socket.once("error", unavailable);
34
+ socket.once("timeout", unavailable);
35
+ });
36
+ }
37
+ export async function configNotice(repository, input) {
38
+ if (!(await running(repository)))
39
+ return null;
40
+ const source = input.entry?.source;
41
+ const hidden = source === "environment" ||
42
+ (input.scope === "project" && source === "private");
43
+ return hidden
44
+ ? `The ${source} source hides this file value. A restart keeps the value of that source.`
45
+ : "Restart the service to use the new value.";
46
+ }
@@ -0,0 +1,9 @@
1
+ import type { DoctorCode, DoctorObservation } from "../doctor-report.ts";
2
+ import type { ProbeRunner } from "./probe-command.ts";
3
+ export declare function githubObservations(repository: string, options: {
4
+ readonly environment: Readonly<NodeJS.ProcessEnv>;
5
+ readonly probe: ProbeRunner;
6
+ }): Promise<{
7
+ readonly observations: Partial<Record<DoctorCode, DoctorObservation>>;
8
+ readonly loginFix: string;
9
+ }>;
@@ -0,0 +1,138 @@
1
+ import { shellArgument } from "./runtime-directory.js";
2
+ import { record } from "../protocol.js";
3
+ import { listedSetting } from "./doctor-local.js";
4
+ import { prRepository } from "./watch-pr-identity.js";
5
+ async function read(context, argumentsList) {
6
+ const output = await context.probe(context.command[0] ?? "", {
7
+ arguments: [...context.command.slice(1), ...argumentsList],
8
+ env: context.environment,
9
+ directory: context.repository,
10
+ bytes: 8 * 1024 * 1024,
11
+ });
12
+ if (output.reason !== null)
13
+ throw new Error(output.reason === "probe-timeout"
14
+ ? "GitHub read timed out after 10 seconds"
15
+ : "GitHub command failed: " + output.reason);
16
+ return output.stdout;
17
+ }
18
+ async function origin(context) {
19
+ const output = await context.probe("git", {
20
+ arguments: ["remote", "get-url", "origin"],
21
+ env: context.environment,
22
+ directory: context.repository,
23
+ });
24
+ const identity = output.reason === null ? prRepository(output.stdout.trim()) : null;
25
+ const valid = identity !== null;
26
+ return {
27
+ observation: {
28
+ result: valid ? "ok" : "fail",
29
+ detail: valid
30
+ ? `GitHub origin ${identity.host}/${identity.owner}/${identity.repository}`
31
+ : "origin is absent or is not on GitHub",
32
+ },
33
+ identity: valid ? identity : null,
34
+ };
35
+ }
36
+ function list(text) {
37
+ const value = JSON.parse(text);
38
+ if (!Array.isArray(value))
39
+ throw new Error("Invalid GitHub response");
40
+ return Array.from(value).flatMap((item) => Array.isArray(item) ? Array.from(item) : [item]);
41
+ }
42
+ async function botActivity(context, pull) {
43
+ const { identity, number } = pull;
44
+ for (const endpoint of [
45
+ `pulls/${String(number)}/reviews`,
46
+ `issues/${String(number)}/comments`,
47
+ `pulls/${String(number)}/comments`,
48
+ ]) {
49
+ const entries = list(await read(context, [
50
+ "api",
51
+ "--method",
52
+ "GET",
53
+ "--hostname",
54
+ identity.host,
55
+ "--paginate",
56
+ "--slurp",
57
+ `repos/${identity.owner}/${identity.repository}/${endpoint}?per_page=100`,
58
+ ]));
59
+ if (entries.some((entry) => record(record(entry)?.["user"])?.["login"] === "greptile-apps[bot]"))
60
+ return true;
61
+ }
62
+ return false;
63
+ }
64
+ async function greptile(context, identity) {
65
+ const pulls = list(await read(context, [
66
+ "pr",
67
+ "list",
68
+ "--repo",
69
+ `${identity.host}/${identity.owner}/${identity.repository}`,
70
+ "--state",
71
+ "all",
72
+ "--limit",
73
+ "20",
74
+ "--json",
75
+ "number",
76
+ ]));
77
+ if (pulls.length === 0)
78
+ return { result: "skip", detail: "No pull requests in this repository" };
79
+ for (const pull of pulls.slice(0, 20)) {
80
+ const number = record(pull)?.["number"];
81
+ if (typeof number !== "number" ||
82
+ !Number.isSafeInteger(number) ||
83
+ number < 1)
84
+ throw new Error("Invalid GitHub pull request");
85
+ if (await botActivity(context, { identity, number }))
86
+ return {
87
+ result: "ok",
88
+ detail: "Recent activity of greptile-apps[bot]; this does not establish a usable review",
89
+ };
90
+ }
91
+ return {
92
+ result: "fail",
93
+ detail: "No Greptile review or comment found on the last 20 pull requests. This does not prove Greptile is not installed",
94
+ };
95
+ }
96
+ export async function githubObservations(repository, options) {
97
+ const { environment, probe } = options;
98
+ const command = environment["CLOVING_GH_COMMAND"] === undefined
99
+ ? ["gh"]
100
+ : (listedSetting(environment["CLOVING_GH_COMMAND"]) ?? []);
101
+ const context = { repository, environment, command, probe };
102
+ const found = await origin(context);
103
+ const host = found.identity?.host ?? "github.com";
104
+ const observations = {
105
+ "github-origin": found.observation,
106
+ "greptile-review": {
107
+ result: "skip",
108
+ detail: "GitHub login or origin prerequisite unavailable",
109
+ },
110
+ };
111
+ const loginFix = `Log in with the configured command: ${command.map(shellArgument).join(" ")} auth login --hostname ${shellArgument(host)}`;
112
+ try {
113
+ await read(context, ["auth", "status", "--hostname", host]);
114
+ observations["gh-login"] = {
115
+ result: "ok",
116
+ detail: `Configured GitHub command is authenticated on ${host}`,
117
+ };
118
+ }
119
+ catch (error) {
120
+ observations["gh-login"] = {
121
+ result: "fail",
122
+ detail: error instanceof Error ? error.message : "GitHub login unavailable",
123
+ };
124
+ return { observations, loginFix };
125
+ }
126
+ if (found.identity !== null) {
127
+ try {
128
+ observations["greptile-review"] = await greptile(context, found.identity);
129
+ }
130
+ catch (error) {
131
+ observations["greptile-review"] = {
132
+ result: "fail",
133
+ detail: error instanceof Error ? error.message : "GitHub read failed",
134
+ };
135
+ }
136
+ }
137
+ return { observations, loginFix };
138
+ }
@@ -0,0 +1,13 @@
1
+ import type { DoctorObservation } from "../doctor-report.ts";
2
+ import { type HarnessSettings } from "../harness-defaults.ts";
3
+ import type { ProbeRunner } from "./probe-command.ts";
4
+ export declare function harnessObservations(environment: Readonly<NodeJS.ProcessEnv>, location: {
5
+ readonly directory: string;
6
+ readonly settingsValid: boolean;
7
+ readonly probe: ProbeRunner;
8
+ readonly commandEnvironment: Readonly<NodeJS.ProcessEnv>;
9
+ readonly harness?: HarnessSettings["harness"];
10
+ }): Promise<{
11
+ readonly harnesses: DoctorObservation;
12
+ readonly selected: DoctorObservation;
13
+ }>;