cloving 1.3.0 → 1.5.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 (484) hide show
  1. package/README.md +329 -215
  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-health.d.ts +9 -0
  32. package/dist/src/broker/actor/authority-health.js +24 -0
  33. package/dist/src/broker/actor/authority-queries.d.ts +2 -1
  34. package/dist/src/broker/actor/authority-queries.js +14 -5
  35. package/dist/src/broker/actor/authority-receipts.js +1 -1
  36. package/dist/src/broker/actor/authority-runtime.d.ts +4 -2
  37. package/dist/src/broker/actor/authority-runtime.js +29 -20
  38. package/dist/src/broker/actor/authority-session.d.ts +6 -19
  39. package/dist/src/broker/actor/authority-session.js +66 -88
  40. package/dist/src/broker/actor/authority-settings.d.ts +2 -1
  41. package/dist/src/broker/actor/authority-settings.js +6 -3
  42. package/dist/src/broker/actor/authority-upgrades.d.ts +23 -2
  43. package/dist/src/broker/actor/authority-upgrades.js +8 -2
  44. package/dist/src/broker/actor/authority-watchdog.d.ts +6 -2
  45. package/dist/src/broker/actor/authority-watchdog.js +31 -9
  46. package/dist/src/broker/actor/authority.js +3 -1
  47. package/dist/src/broker/actor/delivery-intents.js +2 -0
  48. package/dist/src/broker/actor/effect-delivery.d.ts +1 -1
  49. package/dist/src/broker/actor/effect-delivery.js +15 -2
  50. package/dist/src/broker/actor/effect-plan.js +11 -2
  51. package/dist/src/broker/actor/effect-queries.d.ts +4 -0
  52. package/dist/src/broker/actor/effect-queries.js +9 -1
  53. package/dist/src/broker/actor/effect-turn.js +2 -0
  54. package/dist/src/broker/actor/projection-memory.d.ts +43 -0
  55. package/dist/src/broker/actor/projection-memory.js +207 -0
  56. package/dist/src/broker/actor/runtime-parts.d.ts +5 -0
  57. package/dist/src/broker/actor/runtime-parts.js +8 -3
  58. package/dist/src/broker/actor/stop-plan.js +9 -3
  59. package/dist/src/broker/actor/stop-turn.d.ts +2 -0
  60. package/dist/src/broker/actor/stop-turn.js +24 -11
  61. package/dist/src/broker/actor/turn-draft.d.ts +1 -0
  62. package/dist/src/broker/actor/turn-draft.js +4 -0
  63. package/dist/src/broker/actor/turn-state.js +5 -1
  64. package/dist/src/broker/authority-admission.js +60 -0
  65. package/dist/src/broker/authority-restore.d.ts +2 -0
  66. package/dist/src/broker/authority-restore.js +35 -1
  67. package/dist/src/broker/command-wait-restore.d.ts +31 -0
  68. package/dist/src/broker/command-wait-restore.js +86 -0
  69. package/dist/src/broker/decision-restore.d.ts +1 -1
  70. package/dist/src/broker/decision-restore.js +1 -0
  71. package/dist/src/broker/effect-upgrade.d.ts +3 -0
  72. package/dist/src/broker/effect-upgrade.js +11 -2
  73. package/dist/src/cli/arguments.d.ts +13 -0
  74. package/dist/src/cli/arguments.js +43 -3
  75. package/dist/src/cli/chat-stores.d.ts +2 -0
  76. package/dist/src/cli/chat-stores.js +113 -0
  77. package/dist/src/cli/client.d.ts +7 -2
  78. package/dist/src/cli/client.js +13 -7
  79. package/dist/src/cli/command-requests.d.ts +46 -0
  80. package/dist/src/cli/command-requests.js +84 -0
  81. package/dist/src/cli/command-waits.d.ts +9 -0
  82. package/dist/src/cli/command-waits.js +51 -0
  83. package/dist/src/cli/commands.js +70 -88
  84. package/dist/src/cli/config-file.d.ts +2 -2
  85. package/dist/src/cli/config-file.js +4 -2
  86. package/dist/src/cli/config-notice.js +5 -2
  87. package/dist/src/cli/doctor-retention.d.ts +2 -0
  88. package/dist/src/cli/doctor-retention.js +93 -0
  89. package/dist/src/cli/doctor-workflows.d.ts +5 -2
  90. package/dist/src/cli/doctor-workflows.js +12 -7
  91. package/dist/src/cli/doctor.js +11 -9
  92. package/dist/src/cli/harness-probes.d.ts +2 -0
  93. package/dist/src/cli/harness-probes.js +1 -1
  94. package/dist/src/cli/harness-processes.d.ts +6 -0
  95. package/dist/src/cli/harness-processes.js +36 -0
  96. package/dist/src/cli/init-command.d.ts +9 -0
  97. package/dist/src/cli/init-command.js +52 -0
  98. package/dist/src/cli/init-prompt-command.d.ts +10 -0
  99. package/dist/src/cli/init-prompt-command.js +145 -0
  100. package/dist/src/cli/init-prompt.d.ts +35 -0
  101. package/dist/src/cli/init-prompt.js +74 -0
  102. package/dist/src/cli/init-selection.d.ts +13 -0
  103. package/dist/src/cli/init-selection.js +75 -0
  104. package/dist/src/cli/main.d.ts +2 -0
  105. package/dist/src/cli/main.js +37 -7
  106. package/dist/src/cli/mcp-server.d.ts +1 -0
  107. package/dist/src/cli/mcp-server.js +156 -0
  108. package/dist/src/cli/mcp-tools.d.ts +15 -0
  109. package/dist/src/cli/mcp-tools.js +242 -0
  110. package/dist/src/cli/queue-arguments.d.ts +15 -0
  111. package/dist/src/cli/queue-arguments.js +31 -0
  112. package/dist/src/cli/queue-render.d.ts +3 -0
  113. package/dist/src/cli/queue-render.js +26 -0
  114. package/dist/src/cli/reload-render.d.ts +2 -0
  115. package/dist/src/cli/reload-render.js +12 -0
  116. package/dist/src/cli/render.d.ts +1 -1
  117. package/dist/src/cli/render.js +54 -38
  118. package/dist/src/cli/report-ci-jobs.d.ts +23 -0
  119. package/dist/src/cli/report-ci-jobs.js +103 -0
  120. package/dist/src/cli/report-ci-usage.d.ts +9 -0
  121. package/dist/src/cli/report-ci-usage.js +185 -0
  122. package/dist/src/cli/report-ci.d.ts +13 -0
  123. package/dist/src/cli/report-ci.js +74 -0
  124. package/dist/src/cli/report-closures.d.ts +6 -0
  125. package/dist/src/cli/report-closures.js +97 -0
  126. package/dist/src/cli/report-flow.d.ts +7 -0
  127. package/dist/src/cli/report-flow.js +122 -0
  128. package/dist/src/cli/report-github-reader.d.ts +29 -0
  129. package/dist/src/cli/report-github-reader.js +157 -0
  130. package/dist/src/cli/report-github.d.ts +15 -8
  131. package/dist/src/cli/report-github.js +131 -150
  132. package/dist/src/cli/report-operator.d.ts +3 -0
  133. package/dist/src/cli/report-operator.js +40 -0
  134. package/dist/src/cli/report-ready.d.ts +3 -0
  135. package/dist/src/cli/report-ready.js +96 -0
  136. package/dist/src/cli/report-text.d.ts +9 -0
  137. package/dist/src/cli/report-text.js +33 -0
  138. package/dist/src/cli/report.d.ts +1 -0
  139. package/dist/src/cli/report.js +104 -27
  140. package/dist/src/cli/runtime-arguments.d.ts +18 -3
  141. package/dist/src/cli/runtime-arguments.js +29 -20
  142. package/dist/src/cli/schedule-arguments.d.ts +14 -0
  143. package/dist/src/cli/schedule-arguments.js +26 -0
  144. package/dist/src/cli/schedule-render.d.ts +22 -0
  145. package/dist/src/cli/schedule-render.js +73 -0
  146. package/dist/src/cli/terminal-text.d.ts +3 -0
  147. package/dist/src/cli/terminal-text.js +28 -0
  148. package/dist/src/cli/toolchain.d.ts +1 -0
  149. package/dist/src/cli/toolchain.js +1 -0
  150. package/dist/src/cli/usage-render.d.ts +1 -0
  151. package/dist/src/cli/usage-render.js +28 -1
  152. package/dist/src/cli/usage.d.ts +2 -2
  153. package/dist/src/cli/usage.js +89 -11
  154. package/dist/src/cli/watch-actions.js +2 -2
  155. package/dist/src/cli/watch-api-document.d.ts +430 -0
  156. package/dist/src/cli/watch-api-document.js +291 -0
  157. package/dist/src/cli/watch-api-run.d.ts +56 -0
  158. package/dist/src/cli/watch-api-run.js +112 -0
  159. package/dist/src/cli/watch-api.d.ts +17 -0
  160. package/dist/src/cli/watch-api.js +230 -0
  161. package/dist/src/cli/watch-board-view.js +19 -2
  162. package/dist/src/cli/watch-board.d.ts +4 -2
  163. package/dist/src/cli/watch-board.js +53 -43
  164. package/dist/src/cli/watch-card-forms.d.ts +1 -1
  165. package/dist/src/cli/watch-card-forms.js +11 -10
  166. package/dist/src/cli/watch-client.d.ts +1 -1
  167. package/dist/src/cli/watch-client.js +2 -11
  168. package/dist/src/cli/watch-header-view.d.ts +1 -5
  169. package/dist/src/cli/watch-header-view.js +17 -21
  170. package/dist/src/cli/watch-model.d.ts +5 -1
  171. package/dist/src/cli/watch-model.js +20 -11
  172. package/dist/src/cli/watch-page.js +15 -15
  173. package/dist/src/cli/watch-phases.d.ts +12 -3
  174. package/dist/src/cli/watch-phases.js +68 -11
  175. package/dist/src/cli/watch-pr-board.js +1 -1
  176. package/dist/src/cli/watch-pr-command.d.ts +1 -0
  177. package/dist/src/cli/watch-pull-request.js +18 -8
  178. package/dist/src/cli/watch-reads.d.ts +3 -0
  179. package/dist/src/cli/watch-reads.js +22 -20
  180. package/dist/src/cli/watch-render.d.ts +15 -0
  181. package/dist/src/cli/watch-run-input.d.ts +0 -1
  182. package/dist/src/cli/watch-run-input.js +0 -13
  183. package/dist/src/cli/watch-server.js +24 -10
  184. package/dist/src/cli/watch-view.d.ts +0 -3
  185. package/dist/src/cli/watch-view.js +13 -13
  186. package/dist/src/cli.js +73 -12
  187. package/dist/src/command-wait.d.ts +4 -0
  188. package/dist/src/command-wait.js +45 -0
  189. package/dist/src/configuration-change.d.ts +7 -0
  190. package/dist/src/configuration-change.js +14 -0
  191. package/dist/src/configuration-display.js +2 -0
  192. package/dist/src/configuration-schema.d.ts +14 -0
  193. package/dist/src/configuration-schema.js +6 -2
  194. package/dist/src/daemon/attachment-file.d.ts +6 -0
  195. package/dist/src/daemon/attachment-file.js +86 -0
  196. package/dist/src/daemon/attachments.d.ts +14 -0
  197. package/dist/src/daemon/attachments.js +17 -0
  198. package/dist/src/daemon/claude-recovery.d.ts +50 -0
  199. package/dist/src/daemon/claude-recovery.js +208 -0
  200. package/dist/src/daemon/claude-stream.d.ts +27 -0
  201. package/dist/src/daemon/claude-stream.js +63 -0
  202. package/dist/src/daemon/claude-turn.d.ts +11 -25
  203. package/dist/src/daemon/claude-turn.js +64 -81
  204. package/dist/src/daemon/claude-worker.d.ts +5 -4
  205. package/dist/src/daemon/claude-worker.js +127 -126
  206. package/dist/src/daemon/daemon-adapters.d.ts +9 -0
  207. package/dist/src/daemon/daemon-adapters.js +33 -5
  208. package/dist/src/daemon/daemon-loops.d.ts +5 -1
  209. package/dist/src/daemon/daemon-loops.js +18 -10
  210. package/dist/src/daemon/daemon.js +80 -61
  211. package/dist/src/daemon/github-attach.d.ts +2 -0
  212. package/dist/src/daemon/github-attach.js +222 -0
  213. package/dist/src/daemon/github-calls.js +1 -1
  214. package/dist/src/daemon/github-ci-filters.d.ts +6 -0
  215. package/dist/src/daemon/github-ci-filters.js +138 -0
  216. package/dist/src/daemon/github-ci-workflows.d.ts +10 -0
  217. package/dist/src/daemon/github-ci-workflows.js +148 -0
  218. package/dist/src/daemon/github-ci.js +22 -4
  219. package/dist/src/daemon/github-issue-methods.d.ts +2 -0
  220. package/dist/src/daemon/github-issue-methods.js +37 -2
  221. package/dist/src/daemon/github-merge-call.d.ts +2 -1
  222. package/dist/src/daemon/github-merge-call.js +10 -3
  223. package/dist/src/daemon/github-merge.js +52 -24
  224. package/dist/src/daemon/github-methods.js +18 -4
  225. package/dist/src/daemon/github-operation.d.ts +4 -0
  226. package/dist/src/daemon/github-operation.js +6 -0
  227. package/dist/src/daemon/github-worker.d.ts +4 -0
  228. package/dist/src/daemon/github-worker.js +6 -0
  229. package/dist/src/daemon/issue-queue.d.ts +4 -1
  230. package/dist/src/daemon/issue-queue.js +76 -78
  231. package/dist/src/daemon/merge-turns.d.ts +10 -0
  232. package/dist/src/daemon/merge-turns.js +37 -0
  233. package/dist/src/daemon/notify-events.d.ts +6 -0
  234. package/dist/src/daemon/notify-events.js +84 -0
  235. package/dist/src/daemon/notify-journal.js +1 -1
  236. package/dist/src/daemon/notify-message.d.ts +4 -1
  237. package/dist/src/daemon/notify-message.js +36 -0
  238. package/dist/src/daemon/notify.d.ts +1 -1
  239. package/dist/src/daemon/notify.js +5 -77
  240. package/dist/src/daemon/operation-journal.d.ts +1 -0
  241. package/dist/src/daemon/queue-control.d.ts +13 -0
  242. package/dist/src/daemon/queue-control.js +86 -0
  243. package/dist/src/daemon/queue-journal.d.ts +20 -0
  244. package/dist/src/daemon/queue-journal.js +89 -0
  245. package/dist/src/daemon/queue-status.d.ts +9 -3
  246. package/dist/src/daemon/queue-status.js +17 -4
  247. package/dist/src/daemon/record-archive.d.ts +19 -0
  248. package/dist/src/daemon/record-archive.js +82 -0
  249. package/dist/src/daemon/record-sweep.d.ts +24 -0
  250. package/dist/src/daemon/record-sweep.js +147 -0
  251. package/dist/src/daemon/resume-index-lock.d.ts +13 -0
  252. package/dist/src/daemon/resume-index-lock.js +160 -0
  253. package/dist/src/daemon/resume-worktree.d.ts +7 -0
  254. package/dist/src/daemon/resume-worktree.js +29 -0
  255. package/dist/src/daemon/retrying-turn.d.ts +2 -12
  256. package/dist/src/daemon/retrying-turn.js +98 -172
  257. package/dist/src/daemon/schedule-control.d.ts +26 -0
  258. package/dist/src/daemon/schedule-control.js +110 -0
  259. package/dist/src/daemon/schedule-journal.d.ts +2 -15
  260. package/dist/src/daemon/schedule-journal.js +67 -4
  261. package/dist/src/daemon/settings-reload.d.ts +26 -0
  262. package/dist/src/daemon/settings-reload.js +82 -0
  263. package/dist/src/daemon/ticket-registration.d.ts +2 -7
  264. package/dist/src/daemon/ticket-registration.js +15 -81
  265. package/dist/src/daemon/turn-attempt-journal.d.ts +38 -0
  266. package/dist/src/daemon/turn-attempt-journal.js +136 -0
  267. package/dist/src/daemon/turn-attempts.d.ts +47 -0
  268. package/dist/src/daemon/turn-attempts.js +166 -0
  269. package/dist/src/daemon/turn-details.d.ts +4 -0
  270. package/dist/src/daemon/turn-details.js +33 -0
  271. package/dist/src/daemon/turn-report.d.ts +8 -1
  272. package/dist/src/daemon/turn-report.js +39 -0
  273. package/dist/src/daemon/work-tree.d.ts +9 -0
  274. package/dist/src/daemon/work-tree.js +20 -0
  275. package/dist/src/daemon/worker-profile.d.ts +9 -0
  276. package/dist/src/daemon/worker-profile.js +44 -0
  277. package/dist/src/daemon/workflow-generations.d.ts +7 -4
  278. package/dist/src/daemon/workflow-generations.js +22 -14
  279. package/dist/src/daemon/workflow-reload.d.ts +41 -0
  280. package/dist/src/daemon/workflow-reload.js +244 -0
  281. package/dist/src/daemon/workflow-replay.d.ts +2 -1
  282. package/dist/src/daemon/workflow-replay.js +7 -3
  283. package/dist/src/daemon/workflow-schedules.d.ts +3 -0
  284. package/dist/src/daemon/workflow-schedules.js +98 -45
  285. package/dist/src/daemon/worktree-processes.d.ts +9 -0
  286. package/dist/src/daemon/worktree-processes.js +151 -0
  287. package/dist/src/doctor-report.d.ts +4 -6
  288. package/dist/src/doctor-report.js +8 -13
  289. package/dist/src/harness-start.d.ts +15 -0
  290. package/dist/src/harness-start.js +37 -0
  291. package/dist/src/host/command-wait.d.ts +38 -0
  292. package/dist/src/host/command-wait.js +115 -0
  293. package/dist/src/host/start-delivery.d.ts +5 -7
  294. package/dist/src/host/start-delivery.js +3 -15
  295. package/dist/src/host/step-bridge-host.d.ts +2 -0
  296. package/dist/src/host/step-bridge-host.js +21 -0
  297. package/dist/src/operation-identity.d.ts +1 -0
  298. package/dist/src/operation-identity.js +4 -0
  299. package/dist/src/private-config.schema.json +71 -0
  300. package/dist/src/project-config.schema.json +40 -0
  301. package/dist/src/project-settings.d.ts +16 -2
  302. package/dist/src/project-settings.js +35 -1
  303. package/dist/src/queue-spend.d.ts +4 -0
  304. package/dist/src/queue-spend.js +21 -0
  305. package/dist/src/queue-state.d.ts +26 -0
  306. package/dist/src/queue-state.js +34 -0
  307. package/dist/src/record-retention.d.ts +46 -0
  308. package/dist/src/record-retention.js +81 -0
  309. package/dist/src/relay/relay-service.d.ts +3 -0
  310. package/dist/src/relay/relay-service.js +5 -3
  311. package/dist/src/report-ci.d.ts +164 -0
  312. package/dist/src/report-ci.js +32 -0
  313. package/dist/src/report-effects.d.ts +15 -0
  314. package/dist/src/report-effects.js +212 -0
  315. package/dist/src/report-flow-types.d.ts +38 -0
  316. package/dist/src/report-flow-types.js +7 -0
  317. package/dist/src/report-flow.d.ts +43 -0
  318. package/dist/src/report-flow.js +193 -0
  319. package/dist/src/report-operator.d.ts +67 -0
  320. package/dist/src/report-operator.js +25 -0
  321. package/dist/src/report-quality.d.ts +221 -0
  322. package/dist/src/report-quality.js +94 -0
  323. package/dist/src/report-ready.d.ts +23 -0
  324. package/dist/src/report-ready.js +117 -0
  325. package/dist/src/report-statistics.d.ts +2 -1
  326. package/dist/src/report-statistics.js +40 -4
  327. package/dist/src/report.d.ts +588 -47
  328. package/dist/src/report.js +156 -41
  329. package/dist/src/schedule-progress.d.ts +33 -0
  330. package/dist/src/schedule-progress.js +45 -0
  331. package/dist/src/service/active-tickets.js +11 -6
  332. package/dist/src/service/command-waits.d.ts +34 -0
  333. package/dist/src/service/command-waits.js +86 -0
  334. package/dist/src/service/dispatcher.d.ts +4 -0
  335. package/dist/src/service/dispatcher.js +33 -0
  336. package/dist/src/service/expiry.js +2 -0
  337. package/dist/src/service/gateway.js +3 -1
  338. package/dist/src/service/queue-handlers.d.ts +4 -0
  339. package/dist/src/service/queue-handlers.js +32 -0
  340. package/dist/src/service/queue-spend.d.ts +6 -0
  341. package/dist/src/service/queue-spend.js +68 -0
  342. package/dist/src/service/registry.d.ts +28 -2
  343. package/dist/src/service/registry.js +48 -0
  344. package/dist/src/service/replies.d.ts +22 -8
  345. package/dist/src/service/replies.js +16 -2
  346. package/dist/src/service/run-handlers.js +37 -12
  347. package/dist/src/service/run-metadata.d.ts +15 -1
  348. package/dist/src/service/run-metadata.js +93 -8
  349. package/dist/src/service/service.d.ts +11 -3
  350. package/dist/src/service/service.js +22 -37
  351. package/dist/src/service/submission-handler.js +18 -4
  352. package/dist/src/service/worker-port.js +9 -1
  353. package/dist/src/service/worker-totals.d.ts +6 -0
  354. package/dist/src/service/worker-totals.js +8 -1
  355. package/dist/src/service/workflow-reload.d.ts +35 -0
  356. package/dist/src/service/workflow-reload.js +52 -0
  357. package/dist/src/step-bridge.d.ts +20 -0
  358. package/dist/src/steps/command-wait.d.ts +12 -0
  359. package/dist/src/steps/command-wait.js +26 -0
  360. package/dist/src/steps/open-decision-wait.d.ts +2 -0
  361. package/dist/src/steps/{decision-gate.js → open-decision-wait.js} +0 -7
  362. package/dist/src/steps/review-by-person.js +4 -1
  363. package/dist/src/steps/wait-for-command.d.ts +3 -0
  364. package/dist/src/steps/wait-for-command.js +17 -0
  365. package/dist/src/steps/wait-for-decision.js +1 -1
  366. package/dist/src/storage/command-wait-rows.d.ts +30 -0
  367. package/dist/src/storage/command-wait-rows.js +96 -0
  368. package/dist/src/storage/decision-snapshots.d.ts +8 -2
  369. package/dist/src/storage/decision-snapshots.js +16 -8
  370. package/dist/src/storage/domain-changes.d.ts +3 -1
  371. package/dist/src/storage/domain-changes.js +4 -0
  372. package/dist/src/storage/domain-schema.d.ts +16 -1
  373. package/dist/src/storage/domain-schema.js +35 -4
  374. package/dist/src/storage/effect-schema.d.ts +2 -0
  375. package/dist/src/storage/effect-schema.js +9 -0
  376. package/dist/src/storage/projection-changes.d.ts +12 -0
  377. package/dist/src/storage/projection-changes.js +194 -0
  378. package/dist/src/storage/projection-lookups.d.ts +7 -0
  379. package/dist/src/storage/projection-lookups.js +30 -0
  380. package/dist/src/testing-requests.d.ts +15 -0
  381. package/dist/src/testing-requests.js +93 -0
  382. package/dist/src/testing.d.ts +4 -10
  383. package/dist/src/testing.js +33 -86
  384. package/dist/src/worker-usage.d.ts +1 -0
  385. package/dist/src/worker-usage.js +3 -0
  386. package/dist/src/workflow-candidate.d.ts +1 -0
  387. package/dist/src/workflow-candidate.js +12 -1
  388. package/dist/src/workflow-contracts.d.ts +1 -0
  389. package/dist/src/workflow-contracts.js +9 -2
  390. package/dist/src/workflow-declaration.d.ts +1 -0
  391. package/dist/src/workflow-declaration.js +3 -0
  392. package/dist/src/workflow-discovery.d.ts +2 -13
  393. package/dist/src/workflow-discovery.js +1 -13
  394. package/dist/src/workflow-refusals.js +0 -1
  395. package/dist/src/workflows.d.ts +1 -1
  396. package/dist/src/workflows.js +1 -1
  397. package/dist/tools/compile-workflows.js +3 -0
  398. package/dist/tools/project-configuration.d.ts +7 -2
  399. package/dist/tools/project-configuration.js +30 -1
  400. package/dist/tools/red-green-command.d.ts +1 -0
  401. package/dist/tools/red-green-command.js +174 -0
  402. package/dist/tools/red-green-process.d.ts +10 -0
  403. package/dist/tools/red-green-process.js +59 -0
  404. package/dist/tools/self-host-processes.d.ts +2 -0
  405. package/dist/tools/self-host-processes.js +69 -26
  406. package/dist/tools/self-host-project.d.ts +2 -0
  407. package/dist/tools/self-host-project.js +30 -77
  408. package/dist/tools/self-host-runtime.js +1 -1
  409. package/dist/tools/self-host.js +76 -34
  410. package/dist/tools/template-command.d.ts +1 -0
  411. package/dist/tools/template-command.js +160 -0
  412. package/dist/tools/template-copy.d.ts +11 -0
  413. package/dist/tools/template-copy.js +130 -0
  414. package/dist/tools/template-files.d.ts +17 -0
  415. package/dist/tools/template-files.js +74 -0
  416. package/dist/tools/workflow-bundles.js +1 -0
  417. package/dist/tools/workflow-candidate-counts.js +2 -2
  418. package/dist/tools/workflow-candidate-program.d.ts +4 -2
  419. package/dist/tools/workflow-candidate-program.js +30 -11
  420. package/dist/tools/workflow-candidate-shape.d.ts +3 -0
  421. package/dist/tools/workflow-candidate-shape.js +90 -0
  422. package/dist/tools/workflow-candidate-source.d.ts +1 -0
  423. package/dist/tools/workflow-candidate-source.js +26 -4
  424. package/dist/tools/workflow-candidate-syntax.d.ts +2 -2
  425. package/dist/tools/workflow-candidate-syntax.js +24 -94
  426. package/dist/tools/workflow-command.js +1 -2
  427. package/dist/tools/workflow-folders.d.ts +2 -3
  428. package/dist/tools/workflow-folders.js +1 -1
  429. package/package.json +17 -9
  430. package/templates/develop/README.md +93 -4
  431. package/templates/develop/develop/flow-tests.ts +38 -1
  432. package/templates/develop/develop/interruption-tests.ts +157 -0
  433. package/templates/develop/develop/local.ts +1 -0
  434. package/templates/develop/develop/option-tests.ts +138 -9
  435. package/templates/develop/develop/pull.ts +5 -1
  436. package/templates/develop/develop/red-green.ts +55 -0
  437. package/templates/develop/develop/refusal-tests.ts +77 -0
  438. package/templates/develop/develop/report.ts +31 -11
  439. package/templates/develop/develop/round.ts +1 -0
  440. package/templates/develop/develop/scenarios.ts +27 -0
  441. package/templates/develop/develop/turn.ts +28 -7
  442. package/templates/develop/develop.declaration.json +1 -1
  443. package/templates/develop/develop.test.ts +4 -0
  444. package/templates/develop/template.json +29 -2
  445. package/templates/idea-to-issue/README.md +27 -0
  446. package/templates/idea-to-issue/idea-to-issue/effects.ts +52 -0
  447. package/templates/idea-to-issue/idea-to-issue/leave.ts +10 -0
  448. package/templates/idea-to-issue/idea-to-issue/next.ts +29 -0
  449. package/templates/idea-to-issue/idea-to-issue/post-person.ts +18 -0
  450. package/templates/idea-to-issue/idea-to-issue/post.ts +50 -0
  451. package/templates/idea-to-issue/idea-to-issue/queue.ts +27 -0
  452. package/templates/idea-to-issue/idea-to-issue/review.ts +42 -0
  453. package/templates/idea-to-issue/idea-to-issue/scenarios.ts +50 -0
  454. package/templates/idea-to-issue/idea-to-issue/turn.ts +40 -0
  455. package/templates/idea-to-issue/idea-to-issue.declaration.json +16 -0
  456. package/templates/idea-to-issue/idea-to-issue.test.ts +79 -0
  457. package/templates/idea-to-issue/idea-to-issue.ts +49 -0
  458. package/templates/idea-to-issue/template.json +81 -0
  459. package/templates/review-day/README.md +97 -0
  460. package/templates/review-day/review-day/critique.ts +58 -0
  461. package/templates/review-day/review-day/decision.ts +29 -0
  462. package/templates/review-day/review-day/facts.ts +69 -0
  463. package/templates/review-day/review-day/label.ts +29 -0
  464. package/templates/review-day/review-day/next.ts +28 -0
  465. package/templates/review-day/review-day/post.ts +27 -0
  466. package/templates/review-day/review-day/report.ts +98 -0
  467. package/templates/review-day/review-day/rules.ts +12 -0
  468. package/templates/review-day/review-day/scenarios.ts +76 -0
  469. package/templates/review-day/review-day/turn.ts +73 -0
  470. package/templates/review-day/review-day.declaration.json +16 -0
  471. package/templates/review-day/review-day.test.ts +362 -0
  472. package/templates/review-day/review-day.ts +37 -0
  473. package/templates/review-day/template.json +56 -0
  474. package/dist/src/cli/watch-start-view.d.ts +0 -18
  475. package/dist/src/cli/watch-start-view.js +0 -77
  476. package/dist/src/steps/decision-gate.d.ts +0 -3
  477. package/dist/workflows/develop-prd.d.ts +0 -7
  478. package/dist/workflows/develop-prd.js +0 -165
  479. package/dist/workflows/develop-ticket.d.ts +0 -9
  480. package/dist/workflows/develop-ticket.js +0 -207
  481. package/dist/workflows/issue-labels.d.ts +0 -16
  482. package/dist/workflows/issue-labels.js +0 -70
  483. package/dist/workflows/ticket-prompts.d.ts +0 -35
  484. package/dist/workflows/ticket-prompts.js +0 -147
@@ -0,0 +1,157 @@
1
+ import { record } from "../protocol.js";
2
+ import { githubRetry } from "./github-retry.js";
3
+ import { prRepository } from "./watch-pr-identity.js";
4
+ export function reportSource(result) {
5
+ if (result.status === "fulfilled")
6
+ return { status: "available" };
7
+ const reason = result.reason instanceof Error &&
8
+ result.reason.message === "github-network-failed"
9
+ ? "github-network-failed"
10
+ : "read-failed";
11
+ return { status: "unavailable", reason };
12
+ }
13
+ function commandOf(value) {
14
+ const command = JSON.parse(value ?? '["gh"]');
15
+ if (!Array.isArray(command) ||
16
+ command.length === 0 ||
17
+ !command.every((part) => typeof part === "string" && part !== "" && !part.includes("\0")))
18
+ throw new Error("configuration");
19
+ return command.map(String);
20
+ }
21
+ export function rows(value) {
22
+ if (!Array.isArray(value))
23
+ throw new Error("response");
24
+ return value.map((item) => {
25
+ const row = record(item);
26
+ if (row === undefined)
27
+ throw new Error("response");
28
+ return row;
29
+ });
30
+ }
31
+ export function identity(row, context) {
32
+ const { repository, kind } = context;
33
+ const number = row["number"];
34
+ const url = row["html_url"];
35
+ if (typeof number !== "number" ||
36
+ !Number.isSafeInteger(number) ||
37
+ number <= 0 ||
38
+ typeof url !== "string" ||
39
+ url.toLowerCase() !==
40
+ `https://${repository.host}/${repository.owner}/${repository.repository}/${kind}/${String(number)}`)
41
+ throw new Error("identity");
42
+ return number;
43
+ }
44
+ export function timestamp(value) {
45
+ if (typeof value !== "string" || !Number.isFinite(Date.parse(value)))
46
+ throw new Error("response");
47
+ return Date.parse(value);
48
+ }
49
+ export async function repositoryReader(input) {
50
+ const settings = input.settings;
51
+ if (settings?.repository === undefined)
52
+ throw new Error("configuration");
53
+ const command = commandOf(settings.githubCommand);
54
+ const signal = AbortSignal.timeout(120_000);
55
+ const origin = await settings.execute({
56
+ command: ["git", "config", "--local", "--get-all", "remote.origin.url"],
57
+ directory: settings.repository,
58
+ signal,
59
+ });
60
+ const repository = origin.status === 0 && origin.errorCode === null
61
+ ? prRepository(origin.stdout)
62
+ : null;
63
+ if (repository === null)
64
+ throw new Error("identity");
65
+ const timelines = new Map();
66
+ return {
67
+ repository,
68
+ readNode: (nodeId) => readEndpoint(input, {
69
+ repository,
70
+ command,
71
+ endpoint: "",
72
+ flags: [
73
+ "-f",
74
+ `query=query{node(id:${JSON.stringify(nodeId)}){id ... on ClosedEvent{stateReason}}}`,
75
+ ],
76
+ format: "graphql",
77
+ }),
78
+ readLog: async (endpoint) => String(await readEndpoint(input, {
79
+ repository,
80
+ command,
81
+ endpoint,
82
+ flags: [],
83
+ format: "text",
84
+ })),
85
+ read: (endpoint, flags = []) => {
86
+ const key = JSON.stringify([endpoint, flags]);
87
+ const cached = timelines.get(key);
88
+ if (cached !== undefined)
89
+ return cached;
90
+ const reading = readEndpoint(input, {
91
+ repository,
92
+ command,
93
+ endpoint,
94
+ flags,
95
+ });
96
+ timelines.set(key, reading);
97
+ return reading;
98
+ },
99
+ };
100
+ }
101
+ async function readEndpoint(input, request) {
102
+ const settings = input.settings;
103
+ if (settings?.repository === undefined)
104
+ throw new Error("configuration");
105
+ const { repository, command, endpoint, flags } = request;
106
+ const directory = settings.repository;
107
+ const signal = AbortSignal.timeout(120_000);
108
+ const output = await githubRetry({
109
+ signal,
110
+ pollMilliseconds: input.retryMilliseconds ?? 30_000,
111
+ action: async () => {
112
+ const output = await settings.execute({
113
+ outputBytes: request.format === "text" ? 2 * 1024 * 1024 : 1024 * 1024,
114
+ directory,
115
+ signal,
116
+ command: [
117
+ ...command,
118
+ "api",
119
+ "--method",
120
+ request.format === "graphql" ? "POST" : "GET",
121
+ "--hostname",
122
+ repository.host,
123
+ request.format === "graphql"
124
+ ? "graphql"
125
+ : `repos/${repository.owner}/${repository.repository}${endpoint === "" ? "" : `/${endpoint}`}`,
126
+ ...flags,
127
+ ],
128
+ });
129
+ if (output.status !== 0 || output.errorCode !== null)
130
+ throw Object.assign(new Error("github-call-failed"), {
131
+ status: Number(/\bHTTP (\d{3})\b/.exec(output.stderr)?.[1]),
132
+ detail: output.stderr,
133
+ });
134
+ return output.stdout;
135
+ },
136
+ });
137
+ if (request.format === "text")
138
+ return Buffer.from(output)
139
+ .subarray(0, 2 * 1024 * 1024)
140
+ .toString("utf8");
141
+ const parsed = JSON.parse(output);
142
+ return parsed;
143
+ }
144
+ export async function issueTimeline(reader, issue) {
145
+ const result = [];
146
+ const seen = new Set();
147
+ for (let page = 1;; page += 1) {
148
+ const values = rows(await reader.read(`issues/${String(issue)}/timeline?per_page=100&page=${String(page)}`));
149
+ const signature = JSON.stringify(values);
150
+ if (seen.has(signature))
151
+ throw new Error("response");
152
+ seen.add(signature);
153
+ result.push(...values);
154
+ if (values.length < 100)
155
+ return result;
156
+ }
157
+ }
@@ -1,18 +1,25 @@
1
+ import { readCiJobs } from "./report-ci-jobs.ts";
2
+ import { reportFailureData } from "../report-quality.ts";
3
+ import type { ReportCiData } from "../report-ci.ts";
1
4
  import type { ReportDatum } from "../report-statistics.ts";
2
- import type { WatchPrSettings } from "./watch-pr-settings.ts";
5
+ import { type GithubReportInput } from "./report-github-reader.ts";
6
+ import type { ReportReadyTicket } from "../report-flow-types.ts";
3
7
  export interface ReportGithub {
8
+ readonly labels: readonly ReportDatum[] | null;
9
+ readonly ciUsage: ReportCiData | null;
10
+ readonly reopened: readonly ReportDatum[] | null;
11
+ readonly reverts: readonly ReportDatum[] | null;
12
+ readonly jobLogs: Awaited<ReturnType<typeof readCiJobs>>["jobLogs"] | null;
13
+ readonly failures: ReturnType<typeof reportFailureData> | null;
14
+ readonly mainFirstPass: readonly ReportDatum[] | null;
4
15
  readonly observedSince: number | null;
5
16
  readonly issues: readonly ReportDatum[] | null;
6
17
  readonly pulls: readonly ReportDatum[] | null;
7
- readonly sources: Readonly<Record<"issues" | "pulls" | "history", {
18
+ readonly leadTimes: readonly ReportDatum[] | null;
19
+ readonly ready: readonly ReportReadyTicket[] | null;
20
+ readonly sources: Readonly<Record<"issues" | "pulls" | "history" | "timelines" | "ready" | "ci" | "ciUsage" | "ciUsageJobs" | "ciUsageWorkflows" | "jobs" | "labels", {
8
21
  readonly status: string;
9
22
  readonly reason?: string;
10
23
  }>>;
11
24
  }
12
- interface GithubReportInput {
13
- readonly since: string;
14
- readonly settings?: WatchPrSettings;
15
- readonly retryMilliseconds?: number;
16
- }
17
25
  export declare function readReportGithub(input: GithubReportInput): Promise<ReportGithub>;
18
- export {};
@@ -1,102 +1,93 @@
1
+ import { readOperatorLabels } from "./report-operator.js";
2
+ import { readClosureHistory } from "./report-closures.js";
3
+ import { readCiJobs } from "./report-ci-jobs.js";
4
+ import { reportFailureData } from "../report-quality.js";
5
+ import { readCiUsage } from "./report-ci-usage.js";
6
+ import { ciRuns, mainRuns, firstPassData } from "./report-ci.js";
7
+ import { repositoryReader, issueTimeline, rows, identity, timestamp, reportSource as source, } from "./report-github-reader.js";
8
+ import { readyTicketsOf } from "./report-ready.js";
9
+ function unavailableGithub() {
10
+ const unavailable = {
11
+ status: "unavailable",
12
+ reason: "configuration-or-identity",
13
+ };
14
+ return {
15
+ labels: null,
16
+ ciUsage: null,
17
+ reopened: null,
18
+ reverts: null,
19
+ jobLogs: null,
20
+ failures: null,
21
+ mainFirstPass: null,
22
+ observedSince: null,
23
+ issues: null,
24
+ pulls: null,
25
+ leadTimes: null,
26
+ ready: null,
27
+ sources: {
28
+ labels: unavailable,
29
+ jobs: unavailable,
30
+ ci: unavailable,
31
+ ciUsage: unavailable,
32
+ ciUsageJobs: unavailable,
33
+ ciUsageWorkflows: unavailable,
34
+ ready: unavailable,
35
+ issues: unavailable,
36
+ pulls: unavailable,
37
+ history: unavailable,
38
+ timelines: unavailable,
39
+ },
40
+ };
41
+ }
1
42
  export async function readReportGithub(input) {
2
43
  const reader = await repositoryReader(input).catch(() => null);
3
44
  if (reader === null)
4
- return {
5
- observedSince: null,
6
- issues: null,
7
- pulls: null,
8
- sources: {
9
- issues: { status: "unavailable", reason: "configuration-or-identity" },
10
- pulls: { status: "unavailable", reason: "configuration-or-identity" },
11
- history: { status: "unavailable", reason: "configuration-or-identity" },
12
- },
13
- };
14
- const [issues, pulls, history] = await Promise.allSettled([
15
- issuesOf(reader, input.since),
45
+ return unavailableGithub();
46
+ const runsRead = mainRuns(reader, {
47
+ since: input.since,
48
+ activity: "created",
49
+ });
50
+ const issueRead = readClosureHistory(reader, input.since);
51
+ const [issues, pulls, history, timelines, ready, ci, jobs, ciUsage, labels] = await Promise.allSettled([
52
+ issueRead,
16
53
  pullsOf(reader, input.since),
17
54
  repositoryCreatedAt(reader),
55
+ issueRead.then((values) => leadTimesOf(reader, { issues: values.completed, since: input.since })),
56
+ readyTicketsOf(reader),
57
+ runsRead.then((runs) => firstPassData(reader, runs)),
58
+ mainRuns(reader, { since: input.since, activity: "updated" }).then((runs) => readCiJobs(reader, runs)),
59
+ ciRuns(reader, { since: input.since, activity: "updated" }).then((runs) => readCiUsage(reader, runs)),
60
+ readOperatorLabels(reader, input.since),
18
61
  ]);
19
62
  return {
63
+ labels: settledValue(labels),
64
+ reopened: issues.status === "fulfilled" ? issues.value.reopened : null,
65
+ reverts: pulls.status === "fulfilled" ? pulls.value.reverts : null,
66
+ ...ciSourceData({ jobs, ci, ciUsage }),
20
67
  observedSince: history.status === "fulfilled" ? history.value : null,
21
- issues: issues.status === "fulfilled" ? issues.value : null,
22
- pulls: pulls.status === "fulfilled" ? pulls.value : null,
68
+ issues: issues.status === "fulfilled" ? issues.value.completed : null,
69
+ pulls: pulls.status === "fulfilled" ? pulls.value.pulls : null,
70
+ ready: ready.status === "fulfilled" ? ready.value : null,
71
+ leadTimes: timelines.status === "fulfilled" ? timelines.value : null,
23
72
  sources: {
73
+ labels: source(labels),
74
+ jobs: source(jobs),
75
+ ci: source(ci),
76
+ ciUsage: source(ciUsage),
77
+ ...(ciUsage.status === "fulfilled"
78
+ ? ciUsage.value.sources
79
+ : { ciUsageJobs: source(ciUsage), ciUsageWorkflows: source(ciUsage) }),
80
+ ready: source(ready),
24
81
  issues: source(issues),
25
82
  pulls: source(pulls),
26
83
  history: source(history),
84
+ timelines: source(timelines),
27
85
  },
28
86
  };
29
87
  }
30
88
  import { record } from "../protocol.js";
31
- import { githubRetry } from "./github-retry.js";
32
- import { prRepository } from "./watch-pr-identity.js";
33
- function commandOf(value) {
34
- const command = JSON.parse(value ?? '["gh"]');
35
- if (!Array.isArray(command) ||
36
- command.length === 0 ||
37
- !command.every((part) => typeof part === "string" && part !== "" && !part.includes("\0")))
38
- throw new Error("configuration");
39
- return command.map(String);
40
- }
41
- function rows(value) {
42
- if (!Array.isArray(value))
43
- throw new Error("response");
44
- return value.map((item) => {
45
- const row = record(item);
46
- if (row === undefined)
47
- throw new Error("response");
48
- return row;
49
- });
50
- }
51
- function identity(row, context) {
52
- const { repository, kind } = context;
53
- const number = row["number"];
54
- const url = row["html_url"];
55
- if (typeof number !== "number" ||
56
- !Number.isSafeInteger(number) ||
57
- number <= 0 ||
58
- typeof url !== "string" ||
59
- url.toLowerCase() !==
60
- `https://${repository.host}/${repository.owner}/${repository.repository}/${kind}/${String(number)}`)
61
- throw new Error("identity");
62
- return number;
63
- }
64
- function timestamp(value) {
65
- if (typeof value !== "string" || !Number.isFinite(Date.parse(value)))
66
- throw new Error("response");
67
- return Date.parse(value);
68
- }
69
- async function issuesOf(reader, since) {
70
- const result = [];
71
- const seen = new Set();
72
- for (let page = 1;; page += 1) {
73
- const values = rows(await reader.read(`issues?state=closed&since=${encodeURIComponent(since)}&per_page=100&page=${String(page)}`, [
74
- "--jq",
75
- 'map({number, html_url, closed_at, state, state_reason} + (if has("pull_request") then {pull_request: {}} else {} end))',
76
- ]));
77
- for (const row of values) {
78
- if (Object.hasOwn(row, "pull_request"))
79
- continue;
80
- const number = identity(row, {
81
- repository: reader.repository,
82
- kind: "issues",
83
- });
84
- if (seen.has(number))
85
- throw new Error("response");
86
- seen.add(number);
87
- if (!completedIssue(row))
88
- continue;
89
- result.push({
90
- at: timestamp(row["closed_at"]),
91
- value: 1,
92
- evidence: { issue: number },
93
- });
94
- }
95
- if (values.length < 100)
96
- return result;
97
- }
98
- }
99
89
  async function pullsOf(reader, since) {
90
+ const reverts = [];
100
91
  const result = [];
101
92
  const seen = new Set();
102
93
  for (let page = 1;; page += 1) {
@@ -112,77 +103,24 @@ async function pullsOf(reader, since) {
112
103
  timestamp(row["updated_at"]);
113
104
  if (row["merged_at"] === null)
114
105
  continue;
115
- result.push({
106
+ const datum = {
116
107
  at: timestamp(row["merged_at"]),
117
108
  value: 1,
118
109
  evidence: { pullRequest: number },
119
- });
110
+ };
111
+ result.push(datum);
112
+ reverts.push(...revertOf(row, datum));
120
113
  }
121
114
  if (values.length < 100 ||
122
115
  values.some((row) => Date.parse(String(row["updated_at"])) < Date.parse(since)))
123
- return result;
116
+ return {
117
+ pulls: result,
118
+ reverts: reverts.includes(null)
119
+ ? null
120
+ : reverts.filter((item) => item !== null),
121
+ };
124
122
  }
125
123
  }
126
- async function repositoryReader(input) {
127
- const settings = input.settings;
128
- if (settings?.repository === undefined)
129
- throw new Error("configuration");
130
- const command = commandOf(settings.githubCommand);
131
- const signal = AbortSignal.timeout(120_000);
132
- const origin = await settings.execute({
133
- command: ["git", "config", "--local", "--get-all", "remote.origin.url"],
134
- directory: settings.repository,
135
- signal,
136
- });
137
- const repository = origin.status === 0 && origin.errorCode === null
138
- ? prRepository(origin.stdout)
139
- : null;
140
- if (repository === null)
141
- throw new Error("identity");
142
- const directory = settings.repository;
143
- return {
144
- repository,
145
- read: async (endpoint, flags = []) => {
146
- const output = await githubRetry({
147
- signal,
148
- pollMilliseconds: input.retryMilliseconds ?? 30_000,
149
- action: async () => {
150
- const output = await settings.execute({
151
- directory,
152
- signal,
153
- command: [
154
- ...command,
155
- "api",
156
- "--method",
157
- "GET",
158
- "--hostname",
159
- repository.host,
160
- `repos/${repository.owner}/${repository.repository}${endpoint === "" ? "" : `/${endpoint}`}`,
161
- ...flags,
162
- ],
163
- });
164
- if (output.status !== 0 || output.errorCode !== null)
165
- throw Object.assign(new Error("github-call-failed"), {
166
- status: Number(/\(HTTP (\d{3})\)/.exec(output.stderr)?.[1]),
167
- detail: output.stderr,
168
- });
169
- return output.stdout;
170
- },
171
- });
172
- const parsed = JSON.parse(output);
173
- return parsed;
174
- },
175
- };
176
- }
177
- function source(result) {
178
- if (result.status === "fulfilled")
179
- return { status: "available" };
180
- const reason = result.reason instanceof Error &&
181
- result.reason.message === "github-network-failed"
182
- ? "github-network-failed"
183
- : "read-failed";
184
- return { status: "unavailable", reason };
185
- }
186
124
  async function repositoryCreatedAt(reader) {
187
125
  const repository = record(await reader.read(""));
188
126
  const name = repository?.["full_name"];
@@ -192,9 +130,52 @@ async function repositoryCreatedAt(reader) {
192
130
  throw new Error("identity");
193
131
  return timestamp(repository?.["created_at"]);
194
132
  }
195
- function completedIssue(row) {
196
- if (row["state"] !== "closed" ||
197
- !["completed", "not_planned", "duplicate"].includes(String(row["state_reason"])))
198
- throw new Error("response");
199
- return row["state_reason"] === "completed";
133
+ async function lastReadyAt(reader, issue) {
134
+ let ready = null;
135
+ for (const row of await issueTimeline(reader, Number(issue.evidence["issue"]))) {
136
+ if (!readyLabel(row))
137
+ continue;
138
+ const at = timestamp(row["created_at"]);
139
+ if (at <= issue.at && (ready === null || at > ready))
140
+ ready = at;
141
+ }
142
+ return ready;
143
+ }
144
+ async function leadTimesOf(reader, input) {
145
+ const result = [];
146
+ for (const issue of input.issues.filter((item) => item.at >= Date.parse(input.since))) {
147
+ const ready = await lastReadyAt(reader, issue);
148
+ result.push({
149
+ at: issue.at,
150
+ value: ready === null ? null : (issue.at - ready) / 3_600_000,
151
+ evidence: {
152
+ ...issue.evidence,
153
+ readyAt: ready === null ? null : new Date(ready).toISOString(),
154
+ closedAt: new Date(issue.at).toISOString(),
155
+ },
156
+ });
157
+ }
158
+ return result;
159
+ }
160
+ function readyLabel(row) {
161
+ return (row["event"] === "labeled" &&
162
+ record(row["label"])?.["name"] === "cloving: ready");
163
+ }
164
+ function ciSourceData(input) {
165
+ const { jobs, ci, ciUsage } = input;
166
+ return {
167
+ ciUsage: ciUsage.status === "fulfilled" ? ciUsage.value.data : null,
168
+ jobLogs: jobs.status === "fulfilled" ? jobs.value.jobLogs : null,
169
+ failures: jobs.status === "fulfilled" ? reportFailureData(jobs.value) : null,
170
+ mainFirstPass: ci.status === "fulfilled" ? ci.value : null,
171
+ };
172
+ }
173
+ function revertOf(row, datum) {
174
+ const title = row["title"];
175
+ if (typeof title !== "string")
176
+ return [null];
177
+ return title.startsWith('Revert "') ? [datum] : [];
178
+ }
179
+ function settledValue(result) {
180
+ return result.status === "fulfilled" ? result.value : null;
200
181
  }
@@ -0,0 +1,3 @@
1
+ import type { ReportDatum } from "../report-statistics.ts";
2
+ import { type Reader } from "./report-github-reader.ts";
3
+ export declare function readOperatorLabels(reader: Reader, since: string): Promise<ReportDatum[]>;
@@ -0,0 +1,40 @@
1
+ import { record } from "../protocol.js";
2
+ import { positiveInteger } from "./report-ci.js";
3
+ import { rows, timestamp } from "./report-github-reader.js";
4
+ export async function readOperatorLabels(reader, since) {
5
+ const result = [];
6
+ const seen = new Set();
7
+ for (let page = 1;; page += 1) {
8
+ const events = rows(await reader.read(`issues/events?per_page=100&page=${String(page)}`));
9
+ for (const event of events) {
10
+ const id = positiveInteger(event["id"]);
11
+ if (seen.has(id))
12
+ throw new Error("response");
13
+ seen.add(id);
14
+ result.push(...labelDatum(event, since));
15
+ }
16
+ if (events.length < 100)
17
+ return result;
18
+ }
19
+ }
20
+ function labelDatum(event, since) {
21
+ const id = positiveInteger(event["id"]);
22
+ if (!["labeled", "unlabeled"].includes(String(event["event"])))
23
+ return [];
24
+ const label = record(event["label"])?.["name"];
25
+ if (typeof label !== "string")
26
+ throw new Error("response");
27
+ if (!label.startsWith("cloving:"))
28
+ return [];
29
+ const at = timestamp(event["created_at"]);
30
+ if (at < Date.parse(since))
31
+ return [];
32
+ const issue = positiveInteger(record(event["issue"])?.["number"]);
33
+ return [
34
+ {
35
+ at,
36
+ value: 1,
37
+ evidence: { issue, eventId: id, event: event["event"], label },
38
+ },
39
+ ];
40
+ }
@@ -0,0 +1,3 @@
1
+ import type { ReportReadyTicket } from "../report-flow-types.ts";
2
+ import { type Reader } from "./report-github-reader.ts";
3
+ export declare function readyTicketsOf(reader: Pick<Reader, "repository" | "read">): Promise<ReportReadyTicket[]>;
@@ -0,0 +1,96 @@
1
+ import { record } from "../protocol.js";
2
+ import { hardDependencies } from "../ticket-dependencies.js";
3
+ import { rows, identity, timestamp, issueTimeline, } from "./report-github-reader.js";
4
+ function intervals(events) {
5
+ const labels = events
6
+ .filter((event) => ["labeled", "unlabeled"].includes(String(event["event"])) &&
7
+ record(event["label"])?.["name"] === "cloving: ready")
8
+ .map((event) => ({
9
+ type: event["event"],
10
+ at: timestamp(event["created_at"]),
11
+ }))
12
+ .toSorted((a, b) => a.at - b.at);
13
+ const result = [];
14
+ let start = null;
15
+ for (const label of labels) {
16
+ if (label.type === "labeled")
17
+ start ??= label.at;
18
+ else if (start !== null) {
19
+ result.push({ start, end: label.at });
20
+ start = null;
21
+ }
22
+ }
23
+ if (start !== null)
24
+ result.push({ start, end: null });
25
+ return result;
26
+ }
27
+ async function detail(reader, number) {
28
+ const row = record(await reader.read(`issues/${String(number)}`));
29
+ if (row === undefined ||
30
+ identity(row, { repository: reader.repository, kind: "issues" }) !==
31
+ number ||
32
+ Object.hasOwn(row, "pull_request"))
33
+ throw new Error("identity");
34
+ return row;
35
+ }
36
+ async function dependencies(reader, row) {
37
+ const body = row["body"];
38
+ if (body !== null && typeof body !== "string")
39
+ throw new Error("response");
40
+ const result = [];
41
+ for (const id of hardDependencies(body ?? "")) {
42
+ const number = Number(id);
43
+ if (!Number.isSafeInteger(number))
44
+ throw new Error("identity");
45
+ const dependency = await detail(reader, number);
46
+ const state = dependency["state"];
47
+ if (state !== "closed" && state !== "open")
48
+ throw new Error("response");
49
+ result.push({
50
+ issue: number,
51
+ closedAt: state === "open" ? null : timestamp(dependency["closed_at"]),
52
+ });
53
+ }
54
+ return result;
55
+ }
56
+ export async function readyTicketsOf(reader) {
57
+ const result = [];
58
+ const seen = new Set();
59
+ for (let page = 1;; page += 1) {
60
+ const values = rows(await reader.read(`issues?state=all&per_page=100&page=${String(page)}`, [
61
+ "--jq",
62
+ 'map({number, html_url} + (if has("pull_request") then {pull_request: {}} else {} end))',
63
+ ]));
64
+ const numbers = [];
65
+ for (const row of values) {
66
+ if (Object.hasOwn(row, "pull_request"))
67
+ continue;
68
+ const number = identity(row, {
69
+ repository: reader.repository,
70
+ kind: "issues",
71
+ });
72
+ if (seen.has(number))
73
+ throw new Error("response");
74
+ seen.add(number);
75
+ numbers.push(number);
76
+ }
77
+ for (let offset = 0; offset < numbers.length; offset += 5) {
78
+ const tickets = await Promise.all(numbers
79
+ .slice(offset, offset + 5)
80
+ .map((number) => readyTicket(reader, number)));
81
+ result.push(...tickets.filter((ticket) => ticket !== null));
82
+ }
83
+ if (values.length < 100)
84
+ return result;
85
+ }
86
+ }
87
+ async function readyTicket(reader, number) {
88
+ const ready = intervals(await issueTimeline(reader, number));
89
+ if (ready.length === 0)
90
+ return null;
91
+ return {
92
+ issue: number,
93
+ intervals: ready,
94
+ dependencies: await dependencies(reader, await detail(reader, number)),
95
+ };
96
+ }
@@ -0,0 +1,9 @@
1
+ import type { loopReport } from "../report.ts";
2
+ type TextReport = Omit<ReturnType<typeof loopReport>, "window" | "runCosts"> & {
3
+ readonly window: Readonly<Record<string, string | number>>;
4
+ readonly runCosts: readonly (Omit<ReturnType<typeof loopReport>["runCosts"][number], "completedAt"> & {
5
+ readonly completedAt: string;
6
+ })[];
7
+ };
8
+ export declare function textReport(report: TextReport): string;
9
+ export {};