cloving 1.3.0 → 1.4.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 (396) hide show
  1. package/README.md +235 -206
  2. package/dist/src/agent-harness-shell.d.ts +2 -1
  3. package/dist/src/agent-harness-shell.js +8 -5
  4. package/dist/src/authority/command-wait-checks.d.ts +8 -0
  5. package/dist/src/authority/command-wait-checks.js +88 -0
  6. package/dist/src/authority/command-wait-results.d.ts +15 -0
  7. package/dist/src/authority/command-wait-results.js +73 -0
  8. package/dist/src/authority/command-wait-view.d.ts +21 -0
  9. package/dist/src/authority/command-wait-view.js +34 -0
  10. package/dist/src/authority/command-waits.d.ts +39 -0
  11. package/dist/src/authority/command-waits.js +97 -0
  12. package/dist/src/authority/commands.js +22 -1
  13. package/dist/src/authority/dispatch-decision.d.ts +8 -0
  14. package/dist/src/authority/dispatch-decision.js +26 -1
  15. package/dist/src/authority/effect-requests.js +6 -3
  16. package/dist/src/authority/effect-results.js +4 -2
  17. package/dist/src/authority/history-state.d.ts +2 -0
  18. package/dist/src/authority/history-state.js +13 -1
  19. package/dist/src/authority/instants.d.ts +1 -0
  20. package/dist/src/authority/instants.js +21 -0
  21. package/dist/src/authority/reduction-state.d.ts +2 -0
  22. package/dist/src/authority/reduction-state.js +5 -0
  23. package/dist/src/authority/reduction.js +24 -0
  24. package/dist/src/authority/status-input.d.ts +2 -0
  25. package/dist/src/authority/status.d.ts +2 -0
  26. package/dist/src/authority/status.js +1 -0
  27. package/dist/src/authority/stop-sequence.d.ts +1 -0
  28. package/dist/src/authority/stop-sequence.js +2 -1
  29. package/dist/src/authority/transitions.d.ts +6 -4
  30. package/dist/src/authority/transitions.js +7 -0
  31. package/dist/src/broker/actor/authority-queries.d.ts +2 -1
  32. package/dist/src/broker/actor/authority-queries.js +14 -5
  33. package/dist/src/broker/actor/authority-receipts.js +1 -1
  34. package/dist/src/broker/actor/authority-settings.js +2 -2
  35. package/dist/src/broker/actor/authority-upgrades.d.ts +19 -2
  36. package/dist/src/broker/actor/authority-upgrades.js +7 -2
  37. package/dist/src/broker/actor/delivery-intents.js +2 -0
  38. package/dist/src/broker/actor/effect-delivery.d.ts +1 -1
  39. package/dist/src/broker/actor/effect-delivery.js +15 -2
  40. package/dist/src/broker/actor/effect-plan.js +11 -2
  41. package/dist/src/broker/actor/effect-queries.d.ts +4 -0
  42. package/dist/src/broker/actor/effect-queries.js +9 -1
  43. package/dist/src/broker/actor/effect-turn.js +2 -0
  44. package/dist/src/broker/actor/stop-plan.js +9 -3
  45. package/dist/src/broker/actor/stop-turn.d.ts +2 -0
  46. package/dist/src/broker/actor/stop-turn.js +24 -11
  47. package/dist/src/broker/actor/turn-draft.d.ts +1 -0
  48. package/dist/src/broker/actor/turn-draft.js +4 -0
  49. package/dist/src/broker/actor/turn-state.js +5 -1
  50. package/dist/src/broker/authority-admission.js +60 -0
  51. package/dist/src/broker/authority-restore.d.ts +2 -0
  52. package/dist/src/broker/authority-restore.js +35 -1
  53. package/dist/src/broker/command-wait-restore.d.ts +31 -0
  54. package/dist/src/broker/command-wait-restore.js +86 -0
  55. package/dist/src/broker/decision-restore.d.ts +1 -1
  56. package/dist/src/broker/decision-restore.js +1 -0
  57. package/dist/src/broker/effect-upgrade.d.ts +2 -0
  58. package/dist/src/broker/effect-upgrade.js +8 -2
  59. package/dist/src/cli/arguments.d.ts +13 -0
  60. package/dist/src/cli/arguments.js +42 -3
  61. package/dist/src/cli/chat-stores.d.ts +2 -0
  62. package/dist/src/cli/chat-stores.js +113 -0
  63. package/dist/src/cli/client.d.ts +4 -1
  64. package/dist/src/cli/client.js +9 -3
  65. package/dist/src/cli/command-requests.d.ts +17 -0
  66. package/dist/src/cli/command-requests.js +43 -0
  67. package/dist/src/cli/command-waits.d.ts +9 -0
  68. package/dist/src/cli/command-waits.js +51 -0
  69. package/dist/src/cli/commands.js +14 -41
  70. package/dist/src/cli/config-file.d.ts +2 -2
  71. package/dist/src/cli/config-file.js +4 -2
  72. package/dist/src/cli/doctor-workflows.d.ts +5 -2
  73. package/dist/src/cli/doctor-workflows.js +12 -7
  74. package/dist/src/cli/doctor.js +6 -9
  75. package/dist/src/cli/harness-probes.d.ts +2 -0
  76. package/dist/src/cli/harness-probes.js +1 -1
  77. package/dist/src/cli/harness-processes.d.ts +6 -0
  78. package/dist/src/cli/harness-processes.js +36 -0
  79. package/dist/src/cli/init-command.d.ts +9 -0
  80. package/dist/src/cli/init-command.js +52 -0
  81. package/dist/src/cli/init-prompt-command.d.ts +10 -0
  82. package/dist/src/cli/init-prompt-command.js +145 -0
  83. package/dist/src/cli/init-prompt.d.ts +35 -0
  84. package/dist/src/cli/init-prompt.js +74 -0
  85. package/dist/src/cli/init-selection.d.ts +13 -0
  86. package/dist/src/cli/init-selection.js +75 -0
  87. package/dist/src/cli/main.d.ts +2 -0
  88. package/dist/src/cli/main.js +37 -7
  89. package/dist/src/cli/mcp-server.d.ts +1 -0
  90. package/dist/src/cli/mcp-server.js +156 -0
  91. package/dist/src/cli/mcp-tools.d.ts +15 -0
  92. package/dist/src/cli/mcp-tools.js +80 -0
  93. package/dist/src/cli/render.d.ts +1 -1
  94. package/dist/src/cli/render.js +17 -30
  95. package/dist/src/cli/report-ci-jobs.d.ts +23 -0
  96. package/dist/src/cli/report-ci-jobs.js +103 -0
  97. package/dist/src/cli/report-ci-usage.d.ts +9 -0
  98. package/dist/src/cli/report-ci-usage.js +185 -0
  99. package/dist/src/cli/report-ci.d.ts +13 -0
  100. package/dist/src/cli/report-ci.js +74 -0
  101. package/dist/src/cli/report-closures.d.ts +6 -0
  102. package/dist/src/cli/report-closures.js +97 -0
  103. package/dist/src/cli/report-flow.d.ts +7 -0
  104. package/dist/src/cli/report-flow.js +122 -0
  105. package/dist/src/cli/report-github-reader.d.ts +29 -0
  106. package/dist/src/cli/report-github-reader.js +157 -0
  107. package/dist/src/cli/report-github.d.ts +15 -8
  108. package/dist/src/cli/report-github.js +131 -150
  109. package/dist/src/cli/report-operator.d.ts +3 -0
  110. package/dist/src/cli/report-operator.js +40 -0
  111. package/dist/src/cli/report-ready.d.ts +3 -0
  112. package/dist/src/cli/report-ready.js +96 -0
  113. package/dist/src/cli/report-text.d.ts +9 -0
  114. package/dist/src/cli/report-text.js +33 -0
  115. package/dist/src/cli/report.d.ts +1 -0
  116. package/dist/src/cli/report.js +104 -27
  117. package/dist/src/cli/runtime-arguments.d.ts +2 -1
  118. package/dist/src/cli/runtime-arguments.js +7 -2
  119. package/dist/src/cli/schedule-arguments.d.ts +14 -0
  120. package/dist/src/cli/schedule-arguments.js +26 -0
  121. package/dist/src/cli/schedule-render.d.ts +22 -0
  122. package/dist/src/cli/schedule-render.js +73 -0
  123. package/dist/src/cli/terminal-text.d.ts +3 -0
  124. package/dist/src/cli/terminal-text.js +28 -0
  125. package/dist/src/cli/usage-render.d.ts +1 -0
  126. package/dist/src/cli/usage-render.js +28 -1
  127. package/dist/src/cli/usage.d.ts +1 -1
  128. package/dist/src/cli/usage.js +50 -7
  129. package/dist/src/cli/watch-actions.js +2 -2
  130. package/dist/src/cli/watch-board-view.js +19 -2
  131. package/dist/src/cli/watch-board.d.ts +4 -2
  132. package/dist/src/cli/watch-board.js +53 -43
  133. package/dist/src/cli/watch-card-forms.d.ts +1 -1
  134. package/dist/src/cli/watch-card-forms.js +11 -10
  135. package/dist/src/cli/watch-client.d.ts +1 -1
  136. package/dist/src/cli/watch-client.js +2 -11
  137. package/dist/src/cli/watch-header-view.d.ts +0 -5
  138. package/dist/src/cli/watch-header-view.js +8 -20
  139. package/dist/src/cli/watch-model.d.ts +4 -1
  140. package/dist/src/cli/watch-model.js +17 -11
  141. package/dist/src/cli/watch-page.js +12 -14
  142. package/dist/src/cli/watch-phases.d.ts +12 -3
  143. package/dist/src/cli/watch-phases.js +68 -11
  144. package/dist/src/cli/watch-pr-board.js +1 -1
  145. package/dist/src/cli/watch-pr-command.d.ts +1 -0
  146. package/dist/src/cli/watch-pull-request.js +18 -8
  147. package/dist/src/cli/watch-reads.d.ts +2 -0
  148. package/dist/src/cli/watch-reads.js +17 -16
  149. package/dist/src/cli/watch-render.d.ts +14 -0
  150. package/dist/src/cli/watch-run-input.d.ts +0 -1
  151. package/dist/src/cli/watch-run-input.js +0 -13
  152. package/dist/src/cli/watch-server.js +6 -6
  153. package/dist/src/cli/watch-view.d.ts +0 -3
  154. package/dist/src/cli/watch-view.js +13 -13
  155. package/dist/src/cli.js +59 -5
  156. package/dist/src/command-wait.d.ts +4 -0
  157. package/dist/src/command-wait.js +45 -0
  158. package/dist/src/configuration-change.d.ts +7 -0
  159. package/dist/src/configuration-change.js +14 -0
  160. package/dist/src/configuration-schema.d.ts +9 -0
  161. package/dist/src/configuration-schema.js +6 -2
  162. package/dist/src/daemon/attachment-file.d.ts +6 -0
  163. package/dist/src/daemon/attachment-file.js +86 -0
  164. package/dist/src/daemon/attachments.d.ts +14 -0
  165. package/dist/src/daemon/attachments.js +17 -0
  166. package/dist/src/daemon/claude-recovery.d.ts +50 -0
  167. package/dist/src/daemon/claude-recovery.js +204 -0
  168. package/dist/src/daemon/claude-stream.d.ts +27 -0
  169. package/dist/src/daemon/claude-stream.js +63 -0
  170. package/dist/src/daemon/claude-turn.d.ts +11 -25
  171. package/dist/src/daemon/claude-turn.js +64 -81
  172. package/dist/src/daemon/claude-worker.d.ts +2 -1
  173. package/dist/src/daemon/claude-worker.js +124 -122
  174. package/dist/src/daemon/daemon-adapters.d.ts +2 -0
  175. package/dist/src/daemon/daemon-adapters.js +26 -2
  176. package/dist/src/daemon/daemon-loops.d.ts +3 -1
  177. package/dist/src/daemon/daemon-loops.js +3 -1
  178. package/dist/src/daemon/daemon.js +14 -6
  179. package/dist/src/daemon/github-attach.d.ts +2 -0
  180. package/dist/src/daemon/github-attach.js +149 -0
  181. package/dist/src/daemon/github-ci-filters.d.ts +6 -0
  182. package/dist/src/daemon/github-ci-filters.js +138 -0
  183. package/dist/src/daemon/github-ci-workflows.d.ts +10 -0
  184. package/dist/src/daemon/github-ci-workflows.js +148 -0
  185. package/dist/src/daemon/github-ci.js +22 -4
  186. package/dist/src/daemon/github-issue-methods.d.ts +2 -0
  187. package/dist/src/daemon/github-issue-methods.js +37 -2
  188. package/dist/src/daemon/github-merge-call.d.ts +2 -1
  189. package/dist/src/daemon/github-merge-call.js +10 -3
  190. package/dist/src/daemon/github-merge.js +52 -24
  191. package/dist/src/daemon/github-methods.js +12 -2
  192. package/dist/src/daemon/github-operation.d.ts +4 -0
  193. package/dist/src/daemon/github-operation.js +6 -0
  194. package/dist/src/daemon/github-worker.d.ts +4 -0
  195. package/dist/src/daemon/github-worker.js +6 -0
  196. package/dist/src/daemon/issue-queue.d.ts +1 -1
  197. package/dist/src/daemon/issue-queue.js +16 -11
  198. package/dist/src/daemon/notify-events.d.ts +6 -0
  199. package/dist/src/daemon/notify-events.js +84 -0
  200. package/dist/src/daemon/notify-journal.js +1 -1
  201. package/dist/src/daemon/notify-message.d.ts +4 -1
  202. package/dist/src/daemon/notify-message.js +36 -0
  203. package/dist/src/daemon/notify.d.ts +1 -1
  204. package/dist/src/daemon/notify.js +5 -77
  205. package/dist/src/daemon/operation-journal.d.ts +1 -0
  206. package/dist/src/daemon/queue-status.d.ts +9 -3
  207. package/dist/src/daemon/queue-status.js +17 -4
  208. package/dist/src/daemon/resume-index-lock.d.ts +13 -0
  209. package/dist/src/daemon/resume-index-lock.js +160 -0
  210. package/dist/src/daemon/resume-worktree.d.ts +7 -0
  211. package/dist/src/daemon/resume-worktree.js +29 -0
  212. package/dist/src/daemon/retrying-turn.d.ts +2 -12
  213. package/dist/src/daemon/retrying-turn.js +98 -172
  214. package/dist/src/daemon/schedule-control.d.ts +26 -0
  215. package/dist/src/daemon/schedule-control.js +110 -0
  216. package/dist/src/daemon/schedule-journal.d.ts +2 -15
  217. package/dist/src/daemon/schedule-journal.js +67 -4
  218. package/dist/src/daemon/ticket-registration.d.ts +2 -7
  219. package/dist/src/daemon/ticket-registration.js +15 -81
  220. package/dist/src/daemon/turn-attempt-journal.d.ts +38 -0
  221. package/dist/src/daemon/turn-attempt-journal.js +136 -0
  222. package/dist/src/daemon/turn-attempts.d.ts +47 -0
  223. package/dist/src/daemon/turn-attempts.js +166 -0
  224. package/dist/src/daemon/turn-report.d.ts +8 -1
  225. package/dist/src/daemon/turn-report.js +39 -0
  226. package/dist/src/daemon/work-tree.d.ts +9 -0
  227. package/dist/src/daemon/work-tree.js +20 -0
  228. package/dist/src/daemon/worker-profile.d.ts +8 -0
  229. package/dist/src/daemon/worker-profile.js +40 -0
  230. package/dist/src/daemon/workflow-schedules.d.ts +3 -0
  231. package/dist/src/daemon/workflow-schedules.js +98 -45
  232. package/dist/src/daemon/worktree-processes.d.ts +9 -0
  233. package/dist/src/daemon/worktree-processes.js +151 -0
  234. package/dist/src/doctor-report.d.ts +3 -5
  235. package/dist/src/doctor-report.js +6 -13
  236. package/dist/src/harness-start.d.ts +15 -0
  237. package/dist/src/harness-start.js +37 -0
  238. package/dist/src/host/command-wait.d.ts +38 -0
  239. package/dist/src/host/command-wait.js +115 -0
  240. package/dist/src/host/start-delivery.d.ts +5 -7
  241. package/dist/src/host/start-delivery.js +3 -15
  242. package/dist/src/host/step-bridge-host.d.ts +2 -0
  243. package/dist/src/host/step-bridge-host.js +21 -0
  244. package/dist/src/operation-identity.d.ts +1 -0
  245. package/dist/src/operation-identity.js +4 -0
  246. package/dist/src/private-config.schema.json +40 -0
  247. package/dist/src/project-config.schema.json +40 -0
  248. package/dist/src/project-settings.d.ts +2 -2
  249. package/dist/src/project-settings.js +3 -1
  250. package/dist/src/queue-spend.d.ts +4 -0
  251. package/dist/src/queue-spend.js +21 -0
  252. package/dist/src/relay/relay-service.d.ts +3 -0
  253. package/dist/src/relay/relay-service.js +5 -3
  254. package/dist/src/report-ci.d.ts +164 -0
  255. package/dist/src/report-ci.js +32 -0
  256. package/dist/src/report-effects.d.ts +15 -0
  257. package/dist/src/report-effects.js +212 -0
  258. package/dist/src/report-flow-types.d.ts +38 -0
  259. package/dist/src/report-flow-types.js +7 -0
  260. package/dist/src/report-flow.d.ts +43 -0
  261. package/dist/src/report-flow.js +193 -0
  262. package/dist/src/report-operator.d.ts +67 -0
  263. package/dist/src/report-operator.js +25 -0
  264. package/dist/src/report-quality.d.ts +221 -0
  265. package/dist/src/report-quality.js +94 -0
  266. package/dist/src/report-ready.d.ts +23 -0
  267. package/dist/src/report-ready.js +117 -0
  268. package/dist/src/report-statistics.d.ts +2 -1
  269. package/dist/src/report-statistics.js +40 -4
  270. package/dist/src/report.d.ts +588 -47
  271. package/dist/src/report.js +156 -41
  272. package/dist/src/schedule-progress.d.ts +33 -0
  273. package/dist/src/schedule-progress.js +45 -0
  274. package/dist/src/service/active-tickets.js +6 -6
  275. package/dist/src/service/command-waits.d.ts +34 -0
  276. package/dist/src/service/command-waits.js +86 -0
  277. package/dist/src/service/expiry.js +2 -0
  278. package/dist/src/service/gateway.js +3 -1
  279. package/dist/src/service/queue-spend.d.ts +6 -0
  280. package/dist/src/service/queue-spend.js +68 -0
  281. package/dist/src/service/replies.d.ts +8 -1
  282. package/dist/src/service/replies.js +11 -0
  283. package/dist/src/service/run-handlers.js +22 -2
  284. package/dist/src/service/run-metadata.d.ts +15 -1
  285. package/dist/src/service/run-metadata.js +93 -8
  286. package/dist/src/service/service.d.ts +4 -0
  287. package/dist/src/service/service.js +8 -8
  288. package/dist/src/service/submission-handler.js +18 -4
  289. package/dist/src/service/worker-port.js +9 -1
  290. package/dist/src/service/worker-totals.d.ts +2 -0
  291. package/dist/src/service/worker-totals.js +1 -1
  292. package/dist/src/step-bridge.d.ts +20 -0
  293. package/dist/src/steps/command-wait.d.ts +12 -0
  294. package/dist/src/steps/command-wait.js +26 -0
  295. package/dist/src/steps/open-decision-wait.d.ts +2 -0
  296. package/dist/src/steps/{decision-gate.js → open-decision-wait.js} +0 -7
  297. package/dist/src/steps/review-by-person.js +4 -1
  298. package/dist/src/steps/wait-for-command.d.ts +3 -0
  299. package/dist/src/steps/wait-for-command.js +17 -0
  300. package/dist/src/steps/wait-for-decision.js +1 -1
  301. package/dist/src/storage/command-wait-rows.d.ts +30 -0
  302. package/dist/src/storage/command-wait-rows.js +96 -0
  303. package/dist/src/storage/decision-snapshots.d.ts +8 -1
  304. package/dist/src/storage/decision-snapshots.js +15 -1
  305. package/dist/src/storage/domain-changes.d.ts +2 -0
  306. package/dist/src/storage/domain-changes.js +3 -0
  307. package/dist/src/storage/domain-schema.d.ts +13 -1
  308. package/dist/src/storage/domain-schema.js +31 -4
  309. package/dist/src/storage/effect-schema.d.ts +1 -0
  310. package/dist/src/storage/effect-schema.js +5 -0
  311. package/dist/src/testing-requests.d.ts +15 -0
  312. package/dist/src/testing-requests.js +93 -0
  313. package/dist/src/testing.d.ts +4 -10
  314. package/dist/src/testing.js +33 -86
  315. package/dist/src/worker-usage.d.ts +1 -0
  316. package/dist/src/worker-usage.js +3 -0
  317. package/dist/src/workflow-candidate.d.ts +1 -0
  318. package/dist/src/workflow-candidate.js +12 -1
  319. package/dist/src/workflow-contracts.d.ts +1 -0
  320. package/dist/src/workflow-contracts.js +9 -2
  321. package/dist/src/workflow-discovery.d.ts +2 -13
  322. package/dist/src/workflow-discovery.js +1 -13
  323. package/dist/src/workflow-refusals.js +0 -1
  324. package/dist/src/workflows.d.ts +1 -1
  325. package/dist/src/workflows.js +1 -1
  326. package/dist/tools/red-green-command.d.ts +1 -0
  327. package/dist/tools/red-green-command.js +174 -0
  328. package/dist/tools/red-green-process.d.ts +10 -0
  329. package/dist/tools/red-green-process.js +59 -0
  330. package/dist/tools/self-host-processes.d.ts +2 -0
  331. package/dist/tools/self-host-processes.js +32 -13
  332. package/dist/tools/self-host-project.js +13 -78
  333. package/dist/tools/self-host-runtime.js +1 -1
  334. package/dist/tools/self-host.js +42 -10
  335. package/dist/tools/template-command.d.ts +1 -0
  336. package/dist/tools/template-command.js +160 -0
  337. package/dist/tools/template-copy.d.ts +11 -0
  338. package/dist/tools/template-copy.js +130 -0
  339. package/dist/tools/template-files.d.ts +17 -0
  340. package/dist/tools/template-files.js +74 -0
  341. package/dist/tools/workflow-bundles.js +1 -0
  342. package/dist/tools/workflow-candidate-counts.js +2 -2
  343. package/dist/tools/workflow-candidate-shape.d.ts +3 -0
  344. package/dist/tools/workflow-candidate-shape.js +90 -0
  345. package/dist/tools/workflow-candidate-source.js +15 -1
  346. package/dist/tools/workflow-candidate-syntax.d.ts +2 -2
  347. package/dist/tools/workflow-candidate-syntax.js +24 -94
  348. package/dist/tools/workflow-command.js +1 -2
  349. package/dist/tools/workflow-folders.d.ts +2 -3
  350. package/dist/tools/workflow-folders.js +1 -1
  351. package/package.json +16 -8
  352. package/templates/develop/README.md +12 -0
  353. package/templates/develop/develop/flow-tests.ts +37 -0
  354. package/templates/develop/develop/pull.ts +5 -1
  355. package/templates/develop/develop/refusal-tests.ts +77 -0
  356. package/templates/develop/develop/turn.ts +2 -1
  357. package/templates/idea-to-issue/README.md +27 -0
  358. package/templates/idea-to-issue/idea-to-issue/effects.ts +52 -0
  359. package/templates/idea-to-issue/idea-to-issue/leave.ts +10 -0
  360. package/templates/idea-to-issue/idea-to-issue/next.ts +29 -0
  361. package/templates/idea-to-issue/idea-to-issue/post-person.ts +18 -0
  362. package/templates/idea-to-issue/idea-to-issue/post.ts +50 -0
  363. package/templates/idea-to-issue/idea-to-issue/queue.ts +27 -0
  364. package/templates/idea-to-issue/idea-to-issue/review.ts +42 -0
  365. package/templates/idea-to-issue/idea-to-issue/scenarios.ts +50 -0
  366. package/templates/idea-to-issue/idea-to-issue/turn.ts +40 -0
  367. package/templates/idea-to-issue/idea-to-issue.declaration.json +16 -0
  368. package/templates/idea-to-issue/idea-to-issue.test.ts +79 -0
  369. package/templates/idea-to-issue/idea-to-issue.ts +49 -0
  370. package/templates/idea-to-issue/template.json +81 -0
  371. package/templates/review-day/README.md +97 -0
  372. package/templates/review-day/review-day/critique.ts +58 -0
  373. package/templates/review-day/review-day/decision.ts +29 -0
  374. package/templates/review-day/review-day/facts.ts +69 -0
  375. package/templates/review-day/review-day/label.ts +29 -0
  376. package/templates/review-day/review-day/next.ts +28 -0
  377. package/templates/review-day/review-day/post.ts +27 -0
  378. package/templates/review-day/review-day/report.ts +98 -0
  379. package/templates/review-day/review-day/rules.ts +12 -0
  380. package/templates/review-day/review-day/scenarios.ts +76 -0
  381. package/templates/review-day/review-day/turn.ts +73 -0
  382. package/templates/review-day/review-day.declaration.json +16 -0
  383. package/templates/review-day/review-day.test.ts +362 -0
  384. package/templates/review-day/review-day.ts +37 -0
  385. package/templates/review-day/template.json +56 -0
  386. package/dist/src/cli/watch-start-view.d.ts +0 -18
  387. package/dist/src/cli/watch-start-view.js +0 -77
  388. package/dist/src/steps/decision-gate.d.ts +0 -3
  389. package/dist/workflows/develop-prd.d.ts +0 -7
  390. package/dist/workflows/develop-prd.js +0 -165
  391. package/dist/workflows/develop-ticket.d.ts +0 -9
  392. package/dist/workflows/develop-ticket.js +0 -207
  393. package/dist/workflows/issue-labels.d.ts +0 -16
  394. package/dist/workflows/issue-labels.js +0 -70
  395. package/dist/workflows/ticket-prompts.d.ts +0 -35
  396. package/dist/workflows/ticket-prompts.js +0 -147
@@ -0,0 +1,80 @@
1
+ import { isRecordKey } from "../authority/commands.js";
2
+ import { record } from "../protocol.js";
3
+ import { commandJson, readCommandReply, readCommandRequest, } from "./command-requests.js";
4
+ const identifier = {
5
+ type: "string",
6
+ minLength: 1,
7
+ maxLength: 128,
8
+ pattern: "^[A-Za-z0-9._:/-]+$",
9
+ };
10
+ const limit = { type: "integer", minimum: 1, maximum: 500 };
11
+ function tool(name, properties) {
12
+ return {
13
+ name,
14
+ inputSchema: { type: "object", properties, additionalProperties: false },
15
+ annotations: { readOnlyHint: true },
16
+ };
17
+ }
18
+ export const mcpTools = [
19
+ tool("cloving_status", { runId: identifier, limit, after: identifier }),
20
+ tool("cloving_questions", { runId: identifier }),
21
+ tool("cloving_events", {
22
+ runId: identifier,
23
+ after: { type: "integer", minimum: 0, maximum: Number.MAX_SAFE_INTEGER },
24
+ limit: { ...limit, maximum: 1000 },
25
+ }),
26
+ ];
27
+ function validArgument(value, schema) {
28
+ if (schema["type"] === "string")
29
+ return typeof value === "string" && /^[A-Za-z0-9._:/-]{1,128}$/.test(value);
30
+ return (typeof value === "number" &&
31
+ Number.isSafeInteger(value) &&
32
+ value >= Number(schema["minimum"]) &&
33
+ value <= Number(schema["maximum"]));
34
+ }
35
+ function validArguments(argumentsObject, schemas) {
36
+ for (const [name, value] of Object.entries(argumentsObject)) {
37
+ const schema = schemas[name];
38
+ if (schema === undefined || !validArgument(value, schema))
39
+ return false;
40
+ if (name === "runId" && !isRecordKey(value))
41
+ return false;
42
+ }
43
+ return true;
44
+ }
45
+ function commandInput(kind, argumentsObject) {
46
+ const { runId, limit, after } = argumentsObject;
47
+ return {
48
+ kind,
49
+ ...(typeof runId === "string" ? { runId } : {}),
50
+ ...(typeof limit === "number" ? { limit } : {}),
51
+ ...(typeof after === "string" || typeof after === "number"
52
+ ? { after }
53
+ : {}),
54
+ };
55
+ }
56
+ export function mcpToolRequest(parameters) {
57
+ const selected = mcpTools.find((tool) => tool.name === parameters["name"]);
58
+ if (selected === undefined)
59
+ return undefined;
60
+ const argumentsObject = parameters["arguments"] === undefined
61
+ ? {}
62
+ : record(parameters["arguments"]);
63
+ if (argumentsObject === undefined)
64
+ return undefined;
65
+ if (!validArguments(argumentsObject, selected.inputSchema.properties))
66
+ return undefined;
67
+ const kind = selected.name.slice("cloving_".length);
68
+ if (kind !== "status" && kind !== "questions" && kind !== "events")
69
+ return undefined;
70
+ return readCommandRequest(commandInput(kind, argumentsObject));
71
+ }
72
+ export async function callMcpTool(runtimeDirectory, request) {
73
+ const reply = await readCommandReply(runtimeDirectory, request);
74
+ const structuredContent = commandJson(reply);
75
+ return {
76
+ structuredContent,
77
+ content: [{ type: "text", text: JSON.stringify(structuredContent) }],
78
+ ...(reply.kind === "error" ? { isError: true } : {}),
79
+ };
80
+ }
@@ -1,5 +1,5 @@
1
1
  import { type Fields } from "../protocol.ts";
2
- export declare function oneLine(value: unknown): string;
2
+ export { oneLine } from "./terminal-text.ts";
3
3
  export declare function errorText(error: Fields): string;
4
4
  export declare function runOverview(result: Fields): Fields;
5
5
  export declare function queueLines(value: unknown): readonly string[];
@@ -1,35 +1,11 @@
1
- import { priceText, usageText, totalsSuffix, attemptTexts, } from "./usage-render.js";
1
+ import { shownCommandWaits, commandWaitText } from "./command-waits.js";
2
+ import { priceText, queueSpendLines, usageText, totalsSuffix, attemptTexts, } from "./usage-render.js";
2
3
  import { record } from "../protocol.js";
3
4
  import { workflowRefusals } from "../workflow-refusals.js";
4
5
  import { commandText, shownCommands } from "./command-effects.js";
5
- function show(value) {
6
- return typeof value === "string" ? value : JSON.stringify(value);
7
- }
8
- function escaped(character) {
9
- return `\\u${(character.codePointAt(0) ?? 0).toString(16).padStart(4, "0")}`;
10
- }
11
- const hiddenRanges = [
12
- [0x00, 0x1f],
13
- [0x7f, 0x9f],
14
- [0x061c, 0x061c],
15
- [0x200b, 0x200f],
16
- [0x2028, 0x202e],
17
- [0x2060, 0x2069],
18
- [0xfeff, 0xfeff],
19
- ];
20
- function hidden(character) {
21
- const code = character.codePointAt(0) ?? 0;
22
- return hiddenRanges.some(([first, last]) => code >= first && code <= last);
23
- }
24
- export function oneLine(value) {
25
- return Array.from(show(value), (character) => hidden(character) ? escaped(character) : character).join("");
26
- }
27
- function visible(value) {
28
- return show(value)
29
- .split("\n")
30
- .map((line) => Array.from(line, (character) => hidden(character) ? escaped(character) : character).join(""))
31
- .join("\n ");
32
- }
6
+ import { scheduledText, statusScheduleLines, scheduleLines, } from "./schedule-render.js";
7
+ import { show, oneLine, visible } from "./terminal-text.js";
8
+ export { oneLine } from "./terminal-text.js";
33
9
  export function errorText(error) {
34
10
  const { candidates } = error;
35
11
  const lines = [`${visible(error["code"])}: ${visible(error["detail"])}`];
@@ -62,7 +38,7 @@ function admitted(result) {
62
38
  ];
63
39
  }
64
40
  function runLine(run) {
65
- const line = ` ${show(part(run, "runId"))} ${show(part(run, "workflowId"))} ${show(part(run, "condition"))} revision ${show(part(run, "revision"))} latest at ${show(part(run, "latestAt") ?? "none")}`;
41
+ const line = ` ${show(part(run, "runId"))} ${show(part(run, "workflowId"))} ${show(part(run, "condition"))} revision ${show(part(run, "revision"))} latest at ${show(part(run, "latestAt") ?? "none")}${part(run, "scheduled") === undefined ? "" : ` ${scheduledText(part(run, "scheduled"))}`}`;
66
42
  return [
67
43
  line,
68
44
  ...ciLines(run).map((notice) => ` ${notice}`),
@@ -110,6 +86,7 @@ function runList(result) {
110
86
  return [
111
87
  `Workflows: ${visible(listing(result["workflows"]))}`,
112
88
  ...queueLines(result["queue"]),
89
+ ...statusScheduleLines(result["schedules"]).map(oneLine),
113
90
  ...(refusals.length === 0
114
91
  ? []
115
92
  : [
@@ -132,6 +109,7 @@ export function queueLines(value) {
132
109
  const skipped = queue["skipped"];
133
110
  return [
134
111
  `Queue: ${visible(queue["busy"])} of ${visible(queue["lanes"])} lanes busy`,
112
+ ...queueSpendLines(queue["spend"]),
135
113
  ...(Array.isArray(skipped)
136
114
  ? skipped.map((item) => {
137
115
  const dependencies = part(item, "dependencies");
@@ -209,6 +187,7 @@ export function runStatus(result) {
209
187
  const suffix = totalsSuffix(part(run, "state"));
210
188
  return [
211
189
  `Run ${show(part(run, "runId"))} (${show(part(run, "workflowId"))})`,
190
+ ...[scheduledText(part(run, "scheduled"))].filter((mark) => mark !== ""),
212
191
  `Title: ${visible(part(run, "title") ?? "none")}`,
213
192
  `State: ${show(part(run, "state"))}`,
214
193
  ...outcomeLines(part(run, "outcome")),
@@ -225,6 +204,12 @@ export function runStatus(result) {
225
204
  `Cost${suffix}: ${priceText(part(run, "claudeCostUsd"), part(run, "estimatedCostUsd"))}`,
226
205
  `Token usage${suffix}: ${usageText(part(run, "usage"))}`,
227
206
  ...workerLines(part(run, "workerTurns")),
207
+ ...shownCommandWaits(part(run, "commandWaits")).map((wait) => visible(commandWaitText(wait))),
208
+ ...(record(part(run, "budget")) === undefined
209
+ ? []
210
+ : [
211
+ `Effects: ${show(part(part(run, "budget"), "spent"))} of ${show(part(part(run, "budget"), "limit"))}`,
212
+ ]),
228
213
  ...shownCommands(part(run, "commandEffects")).map((effect) => visible(commandText(effect))),
229
214
  `Next action: ${show(part(run, "nextAction") ?? "none")}${at === null ? "" : ` at ${show(at)}`}`,
230
215
  `Human input can help: ${part(run, "humanInputCanHelp") === true ? "yes" : "no"}`,
@@ -296,6 +281,8 @@ function eventPage(result) {
296
281
  return (Array.isArray(events) ? events : []).map((event) => eventText(record(event) ?? {}));
297
282
  }
298
283
  const renderers = new Map([
284
+ ["schedules", scheduleLines],
285
+ ["schedule", scheduleLines],
299
286
  ["run-admitted", admitted],
300
287
  ["run-list", runList],
301
288
  ["run-status", runStatus],
@@ -0,0 +1,23 @@
1
+ import { type Fields } from "../protocol.ts";
2
+ import { type Reader } from "./report-github-reader.ts";
3
+ export interface ReportJob {
4
+ readonly details: Fields;
5
+ readonly id: number;
6
+ readonly runId: number;
7
+ readonly commit: string;
8
+ readonly name: string;
9
+ readonly attempt: number;
10
+ readonly at: number;
11
+ readonly conclusion: string | null;
12
+ }
13
+ export declare function ciJobs(reader: Reader, runs: readonly Fields[]): Promise<ReportJob[]>;
14
+ export declare function readCiJobs(reader: Reader, runs: readonly Fields[]): Promise<{
15
+ jobs: ReportJob[];
16
+ names: Record<number, readonly string[]>;
17
+ jobLogs: {
18
+ read: number;
19
+ notRead: number;
20
+ limit: number;
21
+ maximumBytes: number;
22
+ };
23
+ }>;
@@ -0,0 +1,103 @@
1
+ import { record } from "../protocol.js";
2
+ import { rows, timestamp } from "./report-github-reader.js";
3
+ import { positiveInteger } from "./report-ci.js";
4
+ function parsedJob(row, run) {
5
+ const name = row["name"];
6
+ const commit = run["head_sha"];
7
+ const conclusion = jobConclusion(row["conclusion"]);
8
+ if (typeof name !== "string" ||
9
+ name === "" ||
10
+ typeof commit !== "string" ||
11
+ !/^[a-f0-9]{40,64}$/i.test(commit) ||
12
+ row["head_sha"] !== commit ||
13
+ row["run_id"] !== run["id"])
14
+ throw new Error("response");
15
+ return {
16
+ details: row,
17
+ id: positiveInteger(row["id"]),
18
+ name,
19
+ commit,
20
+ conclusion,
21
+ runId: positiveInteger(run["id"]),
22
+ attempt: positiveInteger(run["run_attempt"]),
23
+ at: timestamp(row["completed_at"] ?? row["started_at"] ?? run["created_at"]),
24
+ };
25
+ }
26
+ async function attemptJobs(reader, run) {
27
+ const result = [];
28
+ const seen = new Set();
29
+ for (let page = 1;; page += 1) {
30
+ const response = record(await reader.read(`actions/runs/${String(run["id"])}/attempts/${String(run["run_attempt"])}/jobs?per_page=100&page=${String(page)}`));
31
+ const values = rows(response?.["jobs"]);
32
+ for (const row of values) {
33
+ const job = parsedJob(row, run);
34
+ if (seen.has(job.id))
35
+ throw new Error("response");
36
+ seen.add(job.id);
37
+ result.push(job);
38
+ }
39
+ if (values.length < 100)
40
+ return result;
41
+ }
42
+ }
43
+ export async function ciJobs(reader, runs) {
44
+ const jobs = [];
45
+ for (const run of runs) {
46
+ const attempts = positiveInteger(run["run_attempt"]);
47
+ for (let attempt = 1; attempt <= attempts; attempt += 1)
48
+ jobs.push(...(await attemptJobs(reader, { ...run, run_attempt: attempt })));
49
+ }
50
+ return jobs;
51
+ }
52
+ export async function readCiJobs(reader, runs) {
53
+ const jobs = await ciJobs(reader, runs);
54
+ const names = {};
55
+ const failed = [
56
+ ...new Map(jobs
57
+ .filter((item) => item.conclusion === "failure")
58
+ .map((job) => [job.id, job])).values(),
59
+ ];
60
+ for (const job of failed.slice(0, 50)) {
61
+ const log = await reader
62
+ .readLog(`actions/jobs/${String(job.id)}/logs`)
63
+ .catch(() => "");
64
+ names[job.id] = failedTestNames(log);
65
+ }
66
+ return {
67
+ jobs,
68
+ names,
69
+ jobLogs: {
70
+ read: Math.min(failed.length, 50),
71
+ notRead: Math.max(0, failed.length - 50),
72
+ limit: 50,
73
+ maximumBytes: 2 * 1024 * 1024,
74
+ },
75
+ };
76
+ }
77
+ function failedTestNames(log) {
78
+ const lines = log
79
+ .split(/\r?\n/)
80
+ .map((line) => line.replace(/^\d{4}-\d{2}-\d{2}T\S+ /, ""));
81
+ const names = new Set();
82
+ let reading = false;
83
+ for (const line of lines) {
84
+ if (line === "Failed tests:") {
85
+ reading = true;
86
+ continue;
87
+ }
88
+ if (!reading || /^\s/.test(line))
89
+ continue;
90
+ if (line === "" ||
91
+ /^(?:\d+ failures not shown\.|Error: test-report-failure\. Full test report:)/.test(line)) {
92
+ reading = false;
93
+ continue;
94
+ }
95
+ names.add(line);
96
+ }
97
+ return names.size === 0 ? ["unknown"] : [...names];
98
+ }
99
+ function jobConclusion(value) {
100
+ if (value === null || typeof value === "string")
101
+ return value;
102
+ throw new Error("response");
103
+ }
@@ -0,0 +1,9 @@
1
+ import { type Fields } from "../protocol.ts";
2
+ import { type ReportCiData } from "../report-ci.ts";
3
+ import { reportSource, type Reader } from "./report-github-reader.ts";
4
+ interface CiUsageRead {
5
+ readonly data: ReportCiData;
6
+ readonly sources: Readonly<Record<"ciUsageJobs" | "ciUsageWorkflows", ReturnType<typeof reportSource>>>;
7
+ }
8
+ export declare function readCiUsage(reader: Reader, runs: readonly Fields[]): Promise<CiUsageRead>;
9
+ export {};
@@ -0,0 +1,185 @@
1
+ import { record } from "../protocol.js";
2
+ import {} from "../report-ci.js";
3
+ import { ciJobs } from "./report-ci-jobs.js";
4
+ import { reportSource, timestamp, } from "./report-github-reader.js";
5
+ function groups() {
6
+ return { localMacos: [], localLinux: [], hostedMacos: [], hostedLinux: [] };
7
+ }
8
+ function workflowEndpoint(run) {
9
+ const path = run["path"];
10
+ const commit = run["head_sha"];
11
+ if (typeof path !== "string" ||
12
+ !path.startsWith(".github/workflows/") ||
13
+ typeof commit !== "string" ||
14
+ !/^[a-f0-9]{40,64}$/i.test(commit))
15
+ throw new Error("response");
16
+ const file = path.replace(/@.*$/, "");
17
+ return `contents/${file}?ref=${commit}`;
18
+ }
19
+ async function workflowJobs(reader, run) {
20
+ const response = record(await reader.read(workflowEndpoint(run)));
21
+ if (response?.["encoding"] !== "base64" ||
22
+ typeof response["content"] !== "string")
23
+ throw new Error("response");
24
+ const text = Buffer.from(response["content"], "base64").toString("utf8");
25
+ try {
26
+ return record(record(JSON.parse(text))?.["jobs"]) ?? {};
27
+ }
28
+ catch {
29
+ return {};
30
+ }
31
+ }
32
+ function definitionOf(jobs, name) {
33
+ const key = name.split(" (")[0] ?? name;
34
+ return (record(jobs[key]) ??
35
+ Object.values(jobs)
36
+ .map(record)
37
+ .find((job) => job?.["name"] === name) ??
38
+ {});
39
+ }
40
+ function runnerSystem(value) {
41
+ if (typeof value === "string")
42
+ return runnerSystem([value]);
43
+ if (!Array.isArray(value) ||
44
+ !value.every((item) => typeof item === "string"))
45
+ return null;
46
+ const description = value.join(" ").toLowerCase();
47
+ const macos = /\bmacos\b|\bosx\b/.test(description);
48
+ const linux = /\blinux\b|\bubuntu\b/.test(description);
49
+ if (macos === linux)
50
+ return null;
51
+ return macos ? "Macos" : "Linux";
52
+ }
53
+ function runnerKind(row, definition) {
54
+ const labels = row["labels"];
55
+ if (!Array.isArray(labels) ||
56
+ !labels.every((label) => typeof label === "string"))
57
+ throw new Error("response");
58
+ const local = labels.includes("self-hosted");
59
+ const system = runnerSystem(labels) ??
60
+ (local ? null : runnerSystem(definition["runs-on"]));
61
+ if (system === null)
62
+ throw new Error("runner-kind");
63
+ return `${local ? "local" : "hosted"}${system}`;
64
+ }
65
+ function jobValues(job, definition) {
66
+ const row = job.details;
67
+ const start = timestamp(row["started_at"]);
68
+ const end = row["completed_at"] === null ? null : timestamp(row["completed_at"]);
69
+ const created = timestamp(row["created_at"]);
70
+ if (created > start || (end !== null && start > end))
71
+ throw new Error("response");
72
+ const minutes = end === null ? null : (end - start) / 60_000;
73
+ const timeout = definition["timeout-minutes"];
74
+ const limit = typeof timeout === "number" && Number.isFinite(timeout) && timeout > 0
75
+ ? timeout
76
+ : null;
77
+ return {
78
+ kind: runnerKind(row, definition),
79
+ minutes,
80
+ wait: (start - created) / 60_000,
81
+ limit,
82
+ };
83
+ }
84
+ function appendJob(target, input) {
85
+ const { job, definitions } = input;
86
+ const definition = definitionOf(definitions.get(job.runId) ?? {}, job.name);
87
+ const values = jobValues(job, definition);
88
+ const evidence = {
89
+ jobId: job.id,
90
+ runId: job.runId,
91
+ attempt: job.attempt,
92
+ jobName: job.name,
93
+ minutes: values.minutes,
94
+ limitMinutes: values.limit,
95
+ };
96
+ const datum = { at: job.at, evidence };
97
+ if (values.minutes !== null)
98
+ target.jobMinutes[values.kind].push({ ...datum, value: values.minutes });
99
+ target.runnerWaitMinutes[values.kind].push({ ...datum, value: values.wait });
100
+ if (values.limit !== null && values.minutes !== null)
101
+ target.jobLimitShare[values.kind].push({
102
+ ...datum,
103
+ value: values.minutes / values.limit,
104
+ });
105
+ if (job.conclusion === "timed_out" ||
106
+ (values.limit !== null &&
107
+ values.minutes !== null &&
108
+ values.minutes >= values.limit))
109
+ target.timeouts.push({ ...datum, value: 1 });
110
+ }
111
+ function jobData(jobs, definitions) {
112
+ const jobMinutes = groups();
113
+ const jobLimitShare = groups();
114
+ const runnerWaitMinutes = groups();
115
+ const timeouts = [];
116
+ for (const job of jobs) {
117
+ if (job.details["started_at"] === null || job.conclusion === "skipped")
118
+ continue;
119
+ appendJob({ jobMinutes, jobLimitShare, runnerWaitMinutes, timeouts }, { job, definitions });
120
+ }
121
+ const limitsKnown = [...definitions.values()].every((value) => value !== null);
122
+ return {
123
+ jobMinutes,
124
+ runnerWaitMinutes,
125
+ jobLimitShare: limitsKnown ? jobLimitShare : null,
126
+ timeouts: limitsKnown ? timeouts : null,
127
+ };
128
+ }
129
+ async function workflowDefinitions(reader, runs) {
130
+ const results = [];
131
+ for (const run of runs)
132
+ results.push(...(await Promise.allSettled([workflowJobs(reader, run)])));
133
+ return {
134
+ definitions: new Map(runs.map((run, index) => {
135
+ const result = results[index];
136
+ return [
137
+ Number(run["id"]),
138
+ result?.status === "fulfilled" ? result.value : null,
139
+ ];
140
+ })),
141
+ source: reportSource(results.find((result) => result.status === "rejected") ?? {
142
+ status: "fulfilled",
143
+ value: null,
144
+ }),
145
+ };
146
+ }
147
+ export async function readCiUsage(reader, runs) {
148
+ const reruns = runs
149
+ .filter((run) => Number(run["run_attempt"]) > 1)
150
+ .map((run) => ({
151
+ at: timestamp(run["run_started_at"] ?? run["updated_at"]),
152
+ value: 1,
153
+ evidence: { runId: run["id"], attempt: run["run_attempt"] },
154
+ }));
155
+ const empty = {
156
+ jobMinutes: null,
157
+ jobLimitShare: null,
158
+ runnerWaitMinutes: null,
159
+ timeouts: null,
160
+ reruns,
161
+ };
162
+ const [jobs] = await Promise.allSettled([ciJobs(reader, runs)]);
163
+ const workflows = await workflowDefinitions(reader, runs);
164
+ const sources = {
165
+ ciUsageJobs: reportSource(jobs),
166
+ ciUsageWorkflows: workflows.source,
167
+ };
168
+ if (jobs.status === "rejected")
169
+ return { data: empty, sources };
170
+ try {
171
+ return {
172
+ data: { ...jobData(jobs.value, workflows.definitions), reruns },
173
+ sources,
174
+ };
175
+ }
176
+ catch (reason) {
177
+ return {
178
+ data: empty,
179
+ sources: {
180
+ ...sources,
181
+ ciUsageJobs: reportSource({ status: "rejected", reason }),
182
+ },
183
+ };
184
+ }
185
+ }
@@ -0,0 +1,13 @@
1
+ import { type Fields } from "../protocol.ts";
2
+ import type { ReportDatum } from "../report-statistics.ts";
3
+ import { type Reader } from "./report-github-reader.ts";
4
+ export declare function positiveInteger(value: unknown): number;
5
+ export declare function mainRuns(reader: Reader, input: {
6
+ readonly since: string;
7
+ readonly activity: "created" | "updated";
8
+ }): Promise<Readonly<Record<string, unknown>>[]>;
9
+ export declare function ciRuns(reader: Reader, input: {
10
+ readonly since: string;
11
+ readonly activity: "created" | "updated";
12
+ }): Promise<Readonly<Record<string, unknown>>[]>;
13
+ export declare function firstPassData(reader: Reader, runs: readonly Fields[]): Promise<ReportDatum[]>;
@@ -0,0 +1,74 @@
1
+ import { record } from "../protocol.js";
2
+ import { rows, timestamp } from "./report-github-reader.js";
3
+ export function positiveInteger(value) {
4
+ if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 1)
5
+ throw new Error("response");
6
+ return value;
7
+ }
8
+ export async function mainRuns(reader, input) {
9
+ return (await ciRuns(reader, input)).filter((run) => run["head_branch"] === "main");
10
+ }
11
+ export async function ciRuns(reader, input) {
12
+ const filter = input.activity === "created"
13
+ ? `branch=main&created=%3E%3D${encodeURIComponent(input.since)}&`
14
+ : "";
15
+ const runs = await runPages(reader, {
16
+ filter,
17
+ maximum: input.activity === "created" ? 1000 : Infinity,
18
+ });
19
+ return runs.filter((run) => {
20
+ if (run["name"] !== "CI")
21
+ return false;
22
+ if (timestamp(run[`${input.activity}_at`]) < Date.parse(input.since))
23
+ return false;
24
+ timestamp(run["created_at"]);
25
+ positiveInteger(run["run_attempt"]);
26
+ return true;
27
+ });
28
+ }
29
+ async function runPages(reader, input) {
30
+ const result = [];
31
+ const seen = new Set();
32
+ for (let page = 1;; page += 1) {
33
+ const response = record(await reader.read(`actions/runs?${input.filter}per_page=100&page=${String(page)}`));
34
+ if (Number(response?.["total_count"]) > input.maximum)
35
+ throw new Error("response-truncated");
36
+ const values = rows(response?.["workflow_runs"]);
37
+ for (const run of values) {
38
+ const id = positiveInteger(run["id"]);
39
+ if (seen.has(id))
40
+ throw new Error("response");
41
+ seen.add(id);
42
+ result.push(run);
43
+ }
44
+ if (values.length < 100)
45
+ return result;
46
+ }
47
+ }
48
+ export async function firstPassData(reader, runs) {
49
+ const result = [];
50
+ for (const run of runs) {
51
+ const first = run["run_attempt"] === 1
52
+ ? run
53
+ : record(await reader.read(`actions/runs/${String(run["id"])}/attempts/1`));
54
+ if (first === undefined ||
55
+ first["id"] !== run["id"] ||
56
+ first["run_attempt"] !== 1 ||
57
+ first["head_sha"] !== run["head_sha"])
58
+ throw new Error("response");
59
+ const conclusion = first["conclusion"];
60
+ if (conclusion !== null && typeof conclusion !== "string")
61
+ throw new Error("response");
62
+ result.push({
63
+ at: timestamp(run["created_at"]),
64
+ value: conclusion === "success" ? 1 : 0,
65
+ evidence: {
66
+ runId: run["id"],
67
+ commit: run["head_sha"],
68
+ attempt: 1,
69
+ conclusion,
70
+ },
71
+ });
72
+ }
73
+ return result;
74
+ }
@@ -0,0 +1,6 @@
1
+ import type { ReportDatum } from "../report-statistics.ts";
2
+ import { type Reader } from "./report-github-reader.ts";
3
+ export declare function readClosureHistory(reader: Reader, since: string): Promise<{
4
+ completed: ReportDatum[];
5
+ reopened: ReportDatum[];
6
+ }>;