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
@@ -1,4 +1,7 @@
1
1
  import { parseArgs } from "node:util";
2
+ import { configInvocation } from "./config-arguments.js";
3
+ import { repositoryArguments } from "./repository-arguments.js";
4
+ import { phoneInvocation } from "./phone-arguments.js";
2
5
  import { isRuntimeCommand, runtimeInvocation, } from "./runtime-arguments.js";
3
6
  const errorCodes = {
4
7
  ERR_PARSE_ARGS_UNKNOWN_OPTION: "unknown-option",
@@ -21,6 +24,8 @@ const options = {
21
24
  limit: { type: "string" },
22
25
  after: { type: "string" },
23
26
  follow: { type: "boolean" },
27
+ since: { type: "string" },
28
+ repository: { type: "string" },
24
29
  };
25
30
  const textOptions = ["--prompt", "--text"];
26
31
  function knownFlag(token) {
@@ -48,10 +53,27 @@ function textValues(argumentsList) {
48
53
  return option === undefined ? joined : [...joined, option];
49
54
  }
50
55
  export function parseInvocation(given) {
51
- if (given[0] === "chats" && given[1] === "import")
52
- return chatsImport(given.slice(2));
53
- if (given[0] === "chats" && given[1] === "redact")
54
- return chatsRedact(given.slice(2));
56
+ const selected = repositoryArguments(given, options);
57
+ if (typeof selected === "string")
58
+ return {
59
+ kind: "usage-error",
60
+ code: selected,
61
+ json: given.includes("--json"),
62
+ };
63
+ const invocation = selectedInvocation(selected.argumentsList);
64
+ return selected.repository === undefined
65
+ ? invocation
66
+ : { ...invocation, repository: selected.repository };
67
+ }
68
+ function selectedInvocation(given) {
69
+ if (given[0] === "config") {
70
+ const outcome = configInvocation(given.slice(1));
71
+ return typeof outcome === "string"
72
+ ? { kind: "usage-error", code: outcome, json: given.includes("--json") }
73
+ : outcome;
74
+ }
75
+ if (given[0] === "phone")
76
+ return phoneInvocation(given.slice(1));
55
77
  const argumentsList = textValues(given);
56
78
  const json = given.includes("--json");
57
79
  const parsed = parsedArguments(argumentsList);
@@ -61,6 +83,8 @@ export function parseInvocation(given) {
61
83
  const [command, ...remaining] = positionals;
62
84
  if (command === undefined)
63
85
  return topLevel(values);
86
+ if (command === "doctor")
87
+ return doctorInvocation(values, remaining);
64
88
  if (command === "workflows" && remaining[0] === "validate")
65
89
  return validation(values, remaining.slice(1));
66
90
  const outcome = runtimeInvocation({
@@ -72,109 +96,13 @@ export function parseInvocation(given) {
72
96
  return { kind: "usage-error", code: outcome, json };
73
97
  return outcome;
74
98
  }
75
- function chatsRedact(argumentsList) {
76
- if (argumentsList.length === 1 &&
77
- ["--help", "-h"].includes(String(argumentsList[0])))
78
- return { kind: "chats-redact-help" };
79
- const importId = argumentsList[0];
80
- if (argumentsList.length !== 1 ||
81
- importId === undefined ||
82
- !/^[a-f\d]{8}-[a-f\d]{4}-4[a-f\d]{3}-[89ab][a-f\d]{3}-[a-f\d]{12}$/.test(importId))
83
- return { kind: "usage-error", code: "invalid-import-id", json: false };
84
- return { kind: "chats-redact", importId };
85
- }
86
- function chatsImport(argumentsList) {
87
- const error = (code) => ({
88
- kind: "usage-error",
89
- code,
90
- json: false,
91
- });
92
- if (argumentsList.length === 1 &&
93
- ["--help", "-h"].includes(String(argumentsList[0])))
94
- return { kind: "chats-import-help" };
95
- const state = {
96
- paths: [],
97
- roots: [],
98
- excludeProjects: [],
99
- literal: false,
100
- option: undefined,
101
- previousImportId: undefined,
102
- };
103
- for (const argument of argumentsList) {
104
- const failure = importArgument(state, argument);
105
- if (failure !== undefined)
106
- return error(failure);
107
- }
108
- if (state.option !== undefined)
109
- return error("missing-value");
110
- if (state.excludeProjects.length > 0 && state.roots.length === 0)
111
- return error("roots-required");
112
- if (state.paths.length + state.roots.length === 0)
113
- return error("missing-argument");
114
- return importInvocation(state);
115
- }
116
- function importInvocation(state) {
117
- const previous = state.previousImportId === undefined
118
- ? {}
119
- : { previousImportId: state.previousImportId };
120
- return state.roots.length === 0
121
- ? { kind: "chats-import", paths: state.paths, ...previous }
122
- : {
123
- kind: "chats-import",
124
- paths: state.paths,
125
- ...previous,
126
- roots: state.roots,
127
- excludeProjects: state.excludeProjects,
128
- };
129
- }
130
- function importArgument(state, argument) {
131
- if (state.option !== undefined)
132
- return importValue(state, argument);
133
- if (argument === "")
134
- return "missing-argument";
135
- if (state.literal) {
136
- state.paths.push(argument);
137
- return;
138
- }
139
- if (argument === "--previous-import" && state.previousImportId !== undefined)
140
- return "repeated-previous-import";
141
- if (["--root", "--exclude-project", "--previous-import"].includes(argument)) {
142
- state.option = argument;
143
- return;
144
- }
145
- if (argument === "--") {
146
- state.literal = true;
147
- return;
148
- }
149
- if (argument.startsWith("-"))
150
- return "unexpected-option";
151
- state.paths.push(argument);
152
- return;
153
- }
154
- function importValue(state, argument) {
155
- if (argument === "" || argument.startsWith("-"))
156
- return "missing-value";
157
- const option = state.option;
158
- state.option = undefined;
159
- if (option === "--root") {
160
- state.roots.push(argument);
161
- return;
162
- }
163
- if (option === "--exclude-project" && !validProjectName(argument))
164
- return "invalid-exclusion";
165
- if (option === "--exclude-project") {
166
- state.excludeProjects.push(argument);
167
- return;
168
- }
169
- if (!/^[a-f\d]{8}-[a-f\d]{4}-4[a-f\d]{3}-[89ab][a-f\d]{3}-[a-f\d]{12}$/.test(argument))
170
- return "invalid-import-id";
171
- state.previousImportId = argument;
172
- return;
173
- }
174
- function validProjectName(name) {
175
- return (name !== "." &&
176
- name !== ".." &&
177
- !["/", "\\", "\0", "*", "?", "[", "]"].some((character) => name.includes(character)));
99
+ function doctorInvocation(values, remaining) {
100
+ const json = values.json === true;
101
+ if (unexpected(values, ["help", "json"]))
102
+ return { kind: "usage-error", code: "unexpected-option", json };
103
+ if (remaining.length > 0)
104
+ return { kind: "usage-error", code: "unexpected-argument", json };
105
+ return values.help ? { kind: "doctor-help" } : { kind: "doctor", json };
178
106
  }
179
107
  function parsedArguments(argumentsList) {
180
108
  try {
@@ -206,6 +134,8 @@ function knownCommand(positionals) {
206
134
  return true;
207
135
  if (command === "workflows")
208
136
  return subcommand === "validate";
137
+ if (command === "doctor")
138
+ return true;
209
139
  return isRuntimeCommand(command);
210
140
  }
211
141
  function givenOptions(tokens) {
@@ -0,0 +1,7 @@
1
+ import type { CommandEffect } from "../command-settings.ts";
2
+ import { type Shown } from "./watch-element.ts";
3
+ export declare function shownCommands(value: unknown): readonly CommandEffect[];
4
+ export declare function commandText(effect: CommandEffect): string;
5
+ export declare function Commands(props: {
6
+ readonly effects: readonly CommandEffect[];
7
+ }): Shown;
@@ -0,0 +1,39 @@
1
+ import { record } from "../protocol.js";
2
+ import { element } from "./watch-element.js";
3
+ export function shownCommands(value) {
4
+ if (!Array.isArray(value))
5
+ return [];
6
+ return value.flatMap((entry) => {
7
+ const fields = record(entry);
8
+ if (typeof fields?.["operationId"] !== "string" ||
9
+ typeof fields["name"] !== "string" ||
10
+ typeof fields["state"] !== "string")
11
+ return [];
12
+ return [
13
+ {
14
+ operationId: fields["operationId"],
15
+ name: fields["name"],
16
+ state: fields["state"],
17
+ exitCode: typeof fields["exitCode"] === "number" ? fields["exitCode"] : null,
18
+ durationMilliseconds: typeof fields["durationMilliseconds"] === "number"
19
+ ? fields["durationMilliseconds"]
20
+ : null,
21
+ },
22
+ ];
23
+ });
24
+ }
25
+ export function commandText(effect) {
26
+ const duration = effect.durationMilliseconds === null
27
+ ? "duration unknown"
28
+ : `${String(effect.durationMilliseconds)} ms`;
29
+ return `Command ${effect.name} · ${effect.state} · exit ${effect.exitCode === null ? "unknown" : String(effect.exitCode)} · ${duration}`;
30
+ }
31
+ export function Commands(props) {
32
+ return props.effects.map((effect) => element("section", {
33
+ class: "command-effect code-window",
34
+ children: element("h3", {
35
+ class: "code-head",
36
+ children: commandText(effect),
37
+ }),
38
+ }));
39
+ }
@@ -1,3 +1,5 @@
1
+ import { reportCommand } from "./report.js";
2
+ import { withCiReruns } from "./github-ci-progress.js";
1
3
  import { readFile } from "node:fs/promises";
2
4
  import { resolve } from "node:path";
3
5
  import { record, } from "../protocol.js";
@@ -45,8 +47,11 @@ function presented(environment, outcome) {
45
47
  return 0;
46
48
  }
47
49
  async function requested(environment, exchange) {
50
+ const reply = await send(environment.runtimeDirectory, exchange.request);
48
51
  return presented(environment, {
49
- reply: await send(environment.runtimeDirectory, exchange.request),
52
+ reply: exchange.request.operation === "status"
53
+ ? await withCiReruns(environment.runtimeDirectory, reply)
54
+ : reply,
50
55
  format: exchange.format,
51
56
  });
52
57
  }
@@ -138,7 +143,7 @@ async function status(environment, invocation) {
138
143
  if (!json && runId === null)
139
144
  await summarized(environment);
140
145
  if (!json && runId === null && limit === null && after === null) {
141
- const reply = await listRuns(environment.runtimeDirectory);
146
+ const reply = await withCiReruns(environment.runtimeDirectory, await listRuns(environment.runtimeDirectory));
142
147
  return presented(environment, {
143
148
  format: { json },
144
149
  reply: reply.kind === "result"
@@ -227,14 +232,16 @@ export function runtimeCommand(invocation, environment) {
227
232
  if (runtimeDirectory === undefined)
228
233
  return Promise.resolve(failed(environment, {
229
234
  error: {
230
- code: "runtime-directory-unknown",
231
- detail: "No runtime directory is known. Set CLOVING_RUNTIME_DIR to the runtime directory of the service.",
235
+ code: "repository-unknown",
236
+ detail: "Change to the service repository, use --repository <directory>, or set CLOVING_RUNTIME_DIR.",
232
237
  },
233
238
  format: { json: invocation.json },
234
239
  }));
235
240
  return located(invocation, { ...environment, runtimeDirectory });
236
241
  }
237
242
  function located(invocation, environment) {
243
+ if (invocation.kind === "report")
244
+ return reportCommand(invocation, environment);
238
245
  if (invocation.kind === "run")
239
246
  return run(environment, invocation);
240
247
  if (invocation.kind === "status")
@@ -0,0 +1,11 @@
1
+ export interface ConfigInvocation {
2
+ readonly kind: "config";
3
+ readonly action: "list" | "get" | "set" | "unset";
4
+ readonly field?: string;
5
+ readonly value?: string;
6
+ readonly private: boolean;
7
+ readonly json: boolean;
8
+ }
9
+ export declare function configInvocation(argumentsList: readonly string[]): ConfigInvocation | {
10
+ readonly kind: "config-help";
11
+ } | string;
@@ -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
+ }>;