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
@@ -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 {};
@@ -0,0 +1,33 @@
1
+ function isMetric(value) {
2
+ return typeof value["status"] === "string";
3
+ }
4
+ function sectionMetrics(section, prefix) {
5
+ return Object.fromEntries(Object.entries(section).flatMap(([name, value]) => isMetric(value)
6
+ ? [[`${prefix}.${name}`, value]]
7
+ : Object.entries(value).map(([key, metric]) => [`${prefix}.${name}.${key}`, metric])));
8
+ }
9
+ export function textReport(report) {
10
+ const lines = [`Loop report ${JSON.stringify(report.window)}`];
11
+ const { jobLogs, ...quality } = report.quality;
12
+ const metrics = {
13
+ ...report.metrics,
14
+ ...sectionMetrics(quality, "quality"),
15
+ ...sectionMetrics(report.ci, "ci"),
16
+ ...sectionMetrics(report.operator, "operator"),
17
+ };
18
+ for (const [name, metric] of Object.entries(metrics)) {
19
+ lines.push(`${name}: ${metric.status === "unavailable" ? "unavailable" : String(metric.value)}`);
20
+ const baseline = metric.baseline;
21
+ lines.push(` history: ${baseline.history}; median: ${String(baseline.median)}; band: ${JSON.stringify(baseline.band)}${metric.mark === "outside" ? "; outside" : ""}`);
22
+ lines.push(` comparison value: ${String(metric.comparisonValue)}`);
23
+ lines.push(` evidence: ${JSON.stringify(metric.evidence)}`);
24
+ lines.push(` baseline evidence: ${JSON.stringify(baseline.evidence)}`);
25
+ }
26
+ lines.push(`Quality job logs: ${JSON.stringify(jobLogs)}`);
27
+ lines.push(`Run costs (USD): ${JSON.stringify(report.runCosts)}`);
28
+ lines.push(`Completed ticket costs (USD): ${JSON.stringify(report.completedTicketCosts)}`);
29
+ lines.push(`Semantics: ${JSON.stringify(report.semantics)}`);
30
+ lines.push(`Sources: ${JSON.stringify(report.sources)}`);
31
+ lines.push(`Coverage: ${JSON.stringify(report.coverage)}`);
32
+ return lines.join("\n") + "\n";
33
+ }
@@ -2,6 +2,7 @@ import { type Fields } from "../protocol.ts";
2
2
  import { type ReportCompletion } from "../report.ts";
3
3
  import type { WatchPrSettings } from "./watch-pr-settings.ts";
4
4
  interface ReportEnvironment {
5
+ readonly now?: number;
5
6
  readonly runtimeDirectory: string;
6
7
  readonly workingDirectory: string;
7
8
  readonly watchPr?: WatchPrSettings;