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
package/README.md CHANGED
@@ -6,7 +6,7 @@ Build a software factory with simple TypeScript for your project, and your proje
6
6
 
7
7
  The end of vibe coding. This is agentic engineering.
8
8
 
9
- A workflow file in TypeScript is the factory. It sets the steps: a worker turn in a work tree, a pull request, a review and a merge. Cloving keeps the state of each run and a record of each step. A GitHub step continues after a restart of the service. A worker turn in work stops at a restart. Cloving builds itself through `develop-issue` in this repository.
9
+ A workflow file in TypeScript is the factory. It sets the steps: a worker turn in a work tree, a pull request, a review and a merge. Cloving keeps the state of each run and a record of each step. A GitHub step continues after a restart of the service. A worker turn in work stops at a restart. Cloving builds itself through a private copy of the `develop` template for this repository.
10
10
 
11
11
  ## Cloving
12
12
 
@@ -17,18 +17,18 @@ This pre-release has one supervised slice: a service for one git repository, a w
17
17
  What works now:
18
18
 
19
19
  - `cloving start` starts the service for one git repository, with the workflow host, the Claude worker and a watch page.
20
- - Three workflows from one workflow file: `develop-prompt`, `develop-ticket` and `develop-issue`.
21
- - `cloving start` loads the bundled `workflows/`, repository `.cloving/workflows/` and user `cloving/workflows/` folders (see "Develop a workflow").
22
- - In a run of `develop-ticket` or `develop-prompt`, the operator approves or denies the work of each round. A run has a maximum of three rounds.
23
- - In a run of `develop-issue`, Greptile reviews the pull request. The GitHub worker merges the pull request at the confidence score 5/5, with no human approval.
24
- - Cloving develops itself through `develop-issue`, with a Greptile review and an automatic merge.
20
+ - `cloving start` registers workflows from repository `.cloving/workflows/` and user `cloving/workflows/` folders (see "Develop a workflow").
21
+ - The `develop` template supports ticket or task-text input and human or automatic review.
22
+ - The default `develop` template uses Greptile review and merges at the confidence score 5/5, with no human approval.
23
+ - Cloving develops itself through `develop`, a private copy of the develop template, with a Greptile review and an automatic merge.
25
24
  - The watch page shows the runs, the events and the work of the worker as it occurs.
26
25
 
26
+ - `cloving init-prompt` lists local chat-store metadata without reading chat contents. Its setup instructions ask for consent before the agent counts repeated work and samples chats to suggest linked workflows.
27
+
27
28
  What does not work yet:
28
29
 
29
30
  - The Claude worker is not confined. It runs as the current user.
30
31
  - An approval does not merge the branch. You merge the branch yourself.
31
- - Cloving cannot make a workflow from your earlier chats yet. The issues [#42](https://github.com/cloving-ai/cloving-ai/issues/42), [#43](https://github.com/cloving-ai/cloving-ai/issues/43) and [#44](https://github.com/cloving-ai/cloving-ai/issues/44) are open for this work. Until then, the prompt "Find workflows in your chats" is a guide for a coding agent.
32
32
 
33
33
  ## Install
34
34
 
@@ -38,7 +38,7 @@ A run needs these tools:
38
38
 
39
39
  - `git`.
40
40
  - The `claude` command of Claude Code on the search path. The Claude worker runs it as the current user.
41
- - For `develop-issue` only: the `gh` command with a login, and a GitHub repository that Greptile reviews. The worker uses the `gh` login and the git credentials of the current user.
41
+ - For workflows that use GitHub: the `gh` command with a login. Workflows that select Greptile review also need Greptile on the repository. The worker uses the `gh` login and the git credentials of the current user.
42
42
 
43
43
  Install the executable from npm:
44
44
 
@@ -47,7 +47,7 @@ npm install --global cloving --ignore-scripts
47
47
  cloving --version
48
48
  ```
49
49
 
50
- This package replaces the older Cloving CLI under the same npm name. The installed package includes startup, the watch command, bundled workflows and the SDK compiler integration. It starts without a source checkout or development dependencies, using the installed runtime dependencies. Installation runs no scripts and starts no service.
50
+ This package replaces the older Cloving CLI under the same npm name. The installed package includes startup, the watch command, workflow templates and the SDK compiler integration. It starts without a source checkout or development dependencies, using the installed runtime dependencies. Installation runs no scripts and starts no service.
51
51
 
52
52
  For checkout development, get the code and install the dependencies:
53
53
 
@@ -90,7 +90,7 @@ npm install --ignore-scripts --omit=dev /path/to/TARBALL
90
90
  ./node_modules/.bin/cloving start
91
91
  ```
92
92
 
93
- The installed executable includes JavaScript for startup, the watch command and bundled workflows. It uses the installed runtime dependencies, including the SDK compiler, without a source checkout. Runtime state and generated workflow artifacts use the configured runtime location outside the installation. Installation scripts are unnecessary. The checkout launcher above remains supported, including its existing checkout self-update behavior; installing a tarball does not add package self-updates.
93
+ The installed executable includes JavaScript for startup, the watch command and workflow support. It uses the installed runtime dependencies, including the SDK compiler, without a source checkout. Runtime state and generated workflow artifacts use the configured runtime location outside the installation. Installation scripts are unnecessary. The checkout launcher above remains supported, including its existing checkout self-update behavior; installing a tarball does not add package self-updates.
94
94
 
95
95
  For a project-local tarball installation, use `./node_modules/.bin/cloving` wherever the examples below say `cloving`, or add your project's `node_modules/.bin` to the search path. After a build, `npm link` also supplies the executable.
96
96
 
@@ -100,7 +100,7 @@ For a project-local tarball installation, use `./node_modules/.bin/cloving` wher
100
100
 
101
101
  Each file requires `"version": 1`. Environment settings override private settings, which override project settings, which override built-in defaults. The start guide names each configured field's source: `environment`, `private` or `project`.
102
102
 
103
- The project file supports `checks.beforeMerge`, `checks.required`, `tickets.command`, `tickets.nextCommand`, `queue.everySeconds` and `queue.lanes`. The private file supports these same fields plus `harness.name`, `harness.kind`, `harness.path`, `harness.command`, `harness.turn`, `harness.output`, `profiles`, `fallbackModels`, `tokenPrices`, `privateTexts`, `notify.command`, `watch.port`, `watch.actions`, `selfUpdate.everySeconds`, `github.command` and `workflows.folder`. Commands are arrays of arguments; seconds, lanes and ports are numbers. A watch port can also be `"off"`; watch actions are `"on"` or `"off"`.
103
+ The project file supports `checks.beforeMerge`, `checks.required`, `checks.redGreen`, `tickets.command`, `tickets.nextCommand`, `queue.everySeconds`, `queue.lanes` and `queue.dailySpendLimitUsd`. The private file supports these same fields plus `harness.name`, `harness.kind`, `harness.path`, `harness.command`, `harness.turn`, `harness.output`, `profiles`, `fallbackModels`, `tokenPrices`, `privateTexts`, `notify.command`, `watch.port`, `watch.actions`, `selfUpdate.everySeconds`, `github.command` and `workflows.folder`. Commands are arrays of arguments; seconds, lanes, spend limits and ports are numbers. A watch port can also be `"off"`; watch actions are `"on"` or `"off"`.
104
104
 
105
105
  For example, a shared `.cloving/config.json` can contain:
106
106
 
@@ -134,61 +134,19 @@ The package includes [the project schema](src/project-config.schema.json) and [t
134
134
 
135
135
  Run `cloving doctor` from the repository before starting the service. It lists each requirement with a fixed code, `ok`, `fail` or `skip`, and a fixing command. Required failures and skipped prerequisites exit with status 1. `cloving doctor --json` prints the same checks as `{ "version": 1, "checks": [...] }` for setup agents.
136
136
 
137
+ The required `no-workflow` check fails when neither the project nor the user folder has a workflow declaration. Its fix is `cloving init`. During `cloving init-prompt` setup, defer this check to the template step, copy or create the workflow, then run doctor again. `no-workflow` must report `ok` before setup is ready.
138
+
137
139
  Doctor probes harness versions and effective executable paths without running a turn. Shell scripts and simple `node script` wrappers receive `--version` from the repository folder; unsupported launcher arguments fail the probe. GitHub login and reads use the origin's host, including GitHub Enterprise. GitHub calls are reads limited to ten seconds each; a service probe waits at most five seconds. Recent Greptile activity does not establish that a usable review is available, and missing activity does not prove the app is absent.
138
140
 
139
141
  ## First run
140
142
 
141
- This first run uses `develop-prompt` on a test repository. It needs no ticket command and no GitHub repository.
142
-
143
- 1. Make a test repository with one commit:
144
-
145
- ```sh
146
- mkdir ~/cloving-trial
147
- cd ~/cloving-trial
148
- git init
149
- echo "A test project." > README.md
150
- git add README.md
151
- git commit -m "Start the test project"
152
- ```
153
-
154
- 2. In terminal 1, in the test repository, start the service. Keep this terminal open:
155
-
156
- ```sh
157
- cloving start
158
- ```
159
-
160
- `cloving start` copies the workflow file into a host project, compiles it there, and starts the service. Then it prints the commands for a second terminal.
161
-
162
- 3. Open the watch page on `http://127.0.0.1:3663/`.
163
-
164
- 4. In terminal 2, submit a run:
165
-
166
- ```sh
167
- cloving run develop-prompt --prompt "Add a file HELLO.md with one line of text."
168
- ```
169
-
170
- The command prints a committed receipt with the run ID. A receipt does not mean completed work.
171
-
172
- 5. The Claude worker does one Claude Code turn. Then the run opens one approval. Show the pending decisions:
173
-
174
- ```sh
175
- cloving questions
176
- ```
177
-
178
- The output has the approval text and the values that a decision command needs. The approval text has the round, the ticket ID, the branch, the commits, the changed files and the report of the worker.
179
-
180
- 6. Read the diff before you decide. In the test repository, `git diff HEAD...BRANCH` shows the work of the branch.
181
-
182
- 7. Approve or deny the work:
183
-
184
- ```sh
185
- cloving approve DECISION_REF --expected-revision N --generation N --subject-digest DIGEST
186
- cloving deny DECISION_REF --text "FEEDBACK" --expected-revision N --generation N --subject-digest DIGEST
187
- ```
143
+ ```sh
144
+ cloving init
145
+ ```
188
146
 
189
- An approval completes the run. It does not merge the branch, so merge the branch yourself, for example with `git merge BRANCH`. A denial with a feedback text starts one more round.
147
+ Run this in your git repository. Choose the agent harness for setup; Cloving saves it in your private repository settings and opens the agent with ``run `cloving init-prompt` `` as its first message. The agent walks through setup, a first run and a first ticket with you.
190
148
 
191
- 8. `cloving status` lists the runs. `cloving status RUN_ID` shows one run with its reason, evidence and next action.
149
+ Use `cloving init --harness <name or path>` to skip the question. A name with both a file and a shell entry needs an explicit path or `--harness shell:<name>`. A later `cloving init` lists your current default first. The harness stays attached to your terminal, uses its normal permissions and returns its exit status when the session ends.
192
150
 
193
151
  ### The service and its settings
194
152
 
@@ -200,15 +158,15 @@ On start, Cloving keeps the old default runtime path only when all retained work
200
158
 
201
159
  `cloving watch` serves a local page on `http://127.0.0.1:3663/` (`--port` selects a different port). The page shows the runs, the events, the work of the worker as it occurs, and each pending decision with its approve and deny commands. `cloving start` starts the page too; `CLOVING_WATCH_PORT` selects its port, and the value `off` starts none.
202
160
 
203
- Each workflow board with supported inputs has **+ Add a card** at the bottom of its first column, including an empty board. It opens an inline form: **Issue number** for `develop-issue`, **Ticket ID** for `develop-ticket`, **Idea** for `develop-prd` and **Task** for `develop-prompt`. Declared workflows use the string fields in their bundled declaration. Unsupported inputs have no control. Select **Add card**, press Enter in a one-line field, or Command/Control+Enter in a text area to send. **Cancel** and Esc close the form. The service reply shows the admitted run ID or a refusal code; admitted cards arrive through the existing live stream. For `workflow-active`, add `cloving: ready` to the issue to queue it.
161
+ Each workflow board with supported inputs has **+ Add a card** at the bottom of its first column, including an empty board. The form uses the string and ticket fields of the workflow's registered declaration. Ticket fields are labeled **Ticket ID**; other fields use their declared names, and optional fields can be left out. Unsupported inputs have no control. Select **Add card** or press Enter in a field to send. **Cancel** and Esc close the form. The service reply shows the admitted run ID or a refusal code; admitted cards arrive through the existing live stream.
204
162
 
205
- The form sends the same run request as the CLI and retains its random command ID for retries, including a lost reply. Retry the same form to avoid duplicate runs. The write endpoint accepts at most 16 KiB of JSON, requires the page's random token, matching Origin and a loopback/localhost Host with the bound port, and allows no cross-origin preflight. `CLOVING_WATCH_ACTIONS=off` removes both the form control and the endpoint; actions are enabled by default. The **Start a run** section remains available with prompts to copy into agents. Decisions and other run actions still use their displayed CLI commands.
163
+ The form sends the same run request as the CLI and retains its random command ID for retries, including a lost reply. Retry the same form to avoid duplicate runs. The write endpoint accepts at most 16 KiB of JSON, requires the page's random token, matching Origin and a loopback/localhost Host with the bound port, and allows no cross-origin preflight. `CLOVING_WATCH_ACTIONS=off` removes both the form control and the endpoint; actions are enabled by default. Decisions and other run actions still use their displayed CLI commands.
206
164
 
207
165
  `cloving start` reads its settings from the environment. `cloving start --help` gives the form and the default of each setting:
208
166
 
209
167
  - `CLOVING_RUNTIME_DIR`: the runtime directory.
210
168
  - `CLOVING_TICKET_COMMAND`: the ticket command (see "Daily development").
211
- - `CLOVING_NOTIFY_COMMAND`: a JSON list naming a command to notify the operator about pending decisions, blocked runs and failed runs. It has no default.
169
+ - `CLOVING_NOTIFY_COMMAND`: a JSON list naming a command to notify the operator about pending decisions, blocked runs, failed runs and stopped schedules. It has no default.
212
170
  - `CLOVING_NEXT_COMMAND`: a JSON list of a command and its arguments that prints the next ready ticket ID for `--next`. It has no default.
213
171
  - `CLOVING_CLAUDE_COMMAND`: a replacement of the `claude` command of the worker.
214
172
  - `CLOVING_PROFILES`: a JSON file of named turn profiles, read once when the service starts.
@@ -218,7 +176,7 @@ The form sends the same run request as the CLI and retains its random command ID
218
176
  - `CLOVING_WATCH_PORT`: the port of the watch page, or `off`.
219
177
  - `CLOVING_WATCH_REPOSITORY`: repository context for a separate watch process. `start` sets this from its service repository. The watch process uses its local origin and has no current-directory default.
220
178
  - `CLOVING_OWNERSHIP_LEASE_SECONDS` and `CLOVING_HOST_BOUND`: limits of the workflow host.
221
- - `CLOVING_GH_COMMAND`, `CLOVING_CHECK_COMMAND` and `CLOVING_PRIVATE_TEXTS`: settings of `develop-issue`; the GitHub command and private-text list also apply to `develop-prd`.
179
+ - `CLOVING_GH_COMMAND`, `CLOVING_CHECK_COMMAND` and `CLOVING_PRIVATE_TEXTS`: settings of `develop`; the GitHub command and private-text list also apply to `idea-to-issue`.
222
180
 
223
181
  A command setting is a JSON list of texts, for example `CLOVING_CHECK_COMMAND='["npm", "test"]'`.
224
182
 
@@ -251,44 +209,78 @@ The questions of `analyze-chats` are private. Their full text goes only to your
251
209
 
252
210
  Run `cloving report --since 24 --json` for a versioned JSON report, or omit `--json` for text. `--since` accepts whole hours from 1 to 168 and defaults to 24. The window includes its start and excludes its end; the command captures the end time once. It reads the daemon's committed events and individual run status through the control socket. Set `CLOVING_WATCH_REPOSITORY` to the service repository to enable GitHub reads; its local origin supplies the host, owner and repository. There is no current-directory fallback. `CLOVING_GH_COMMAND` selects the GitHub command as a JSON argument array, defaulting to `gh`.
253
211
 
254
- This is the first part of the daily report. The implemented values are:
255
-
256
- | JSON value | Meaning |
257
- | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
258
- | `metrics.tickets.completed` | Currently closed GitHub issues whose state reason is completed and whose latest closure falls in the window. Pull requests and issues closed for another reason are excluded. This is a current snapshot: reopening an issue removes that closure from these figures. |
259
- | `metrics.pullRequests.merged` | Pull requests with a GitHub merge timestamp in the window. Closed, unmerged pull requests are excluded. |
260
- | `metrics.runs.completed` | Terminal `run.completed` events with no outcome or with `handoff_requested`, excluding partial ticket handoffs. |
261
- | `metrics.runs.partial` | Handoffs explicitly marked with partial ticket status. |
262
- | `metrics.runs.blocked` | Terminal `run.completed` events with the blocked outcome. |
263
- | `metrics.runs.failed` | Terminal `run.failed` events. |
264
- | `metrics.runs.cancelled` | Terminal `run.cancelled` events. |
265
- | `metrics.cost.medianRunUsd` | Median lifetime actual turn cost among runs ending in the window. Any unknown run cost makes this value unavailable. |
266
- | `runCosts` | Each ended run's outcome, end time, actual total USD cost, individual turn operation IDs and actual prices, plus the historical daily median run-cost baseline. All of a run's turn cost is attributed to its end time, including turns before the window. Estimates never replace unknown actual prices. An observed run with no worker turns and settled effects has cost zero. A cancelled run that is still draining, or any unresolved effect, leaves its total unavailable. Active runs are excluded. |
267
-
268
- Every metric has `value`, `comparisonValue`, `baseline` and `evidence`. Counts retain their requested-window totals in `value`; `comparisonValue` is their equivalent per 24 hours. Costs are not scaled. The baseline uses the seven consecutive 24-hour periods immediately before the window, anchored at the same time of day in UTC. It contains the median and the band from median minus three times the median absolute deviation to median plus three times that deviation. Only values strictly outside the band receive `mark: "outside"`. Individual run costs use the band of daily median run costs. With fewer than five complete observed days, `history` is `short`, the median and band are null, and there is no mark. Empty observed days count as zero for counts; days with no cost sample or with an unknown cost do not establish a daily cost median. An unrepresentable numeric band has unavailable history and no mark. Daemon history starts at its earliest retained event; GitHub history starts at repository creation.
212
+ The implemented report values are:
213
+
214
+ | JSON value | Meaning |
215
+ | ---------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
216
+ | `metrics.tickets.completed` | Issue close events with reason `completed` in the window. Reopened issues retain their completed closes. Each completed close counts, including repeated closes. Pull requests and other close reasons are excluded. `semantics.tickets` is `closed-completed-in-window`. |
217
+ | `metrics.pullRequests.merged` | Pull requests with a GitHub merge timestamp in the window. Closed, unmerged pull requests are excluded. |
218
+ | `metrics.runs.completed` | Terminal `run.completed` events with no outcome or with `handoff_requested`, excluding partial ticket handoffs. |
219
+ | `metrics.runs.partial` | Handoffs explicitly marked with partial ticket status. |
220
+ | `metrics.runs.blocked` | Terminal `run.completed` events with the blocked outcome. |
221
+ | `metrics.runs.failed` | Terminal `run.failed` events. |
222
+ | `metrics.runs.cancelled` | Terminal `run.cancelled` events. |
223
+ | `metrics.cost.medianRunUsd` | Median lifetime actual turn cost among runs ending in the window. Any unknown run cost makes this value unavailable. |
224
+ | `runCosts` | Each ended run's outcome, end time, actual total USD cost, individual turn operation IDs and actual prices, plus the historical daily median run-cost baseline. All of a run's turn cost is attributed to its end time, including turns before the window. Estimates never replace unknown actual prices. An observed run with no worker turns and settled effects has cost zero. A cancelled run that is still draining, or any unresolved effect, leaves its total unavailable. Active runs are excluded. |
225
+ | `metrics.fixRounds.medianPerMergedPullRequest` | Median count of `run-turn` operations after the first `open-pr` request, for each successful merge in the window. Evidence includes the run ID, pull request number, merge operation ID and fix-round count. Unmerged runs do not contribute. |
226
+ | `metrics.leadTime.medianHours` | Median hours from the last `cloving: ready` label before each completed ticket's close to that close. The command reads all issue timeline pages, including labels before the window. Evidence includes issue numbers and label and close times. An unreadable timeline or missing ready label leaves the value unavailable. |
227
+ | `metrics.phases.workerTurn.medianMinutes` | Median minutes from request to report for `run-turn` operations that end in the window, including failed operations. Evidence includes run IDs and operation IDs. |
228
+ | `metrics.phases.codeReview.medianMinutes` | Median request-to-report minutes for `wait-review` operations that end in the window. |
229
+ | `metrics.phases.merge.medianMinutes` | Median request-to-report minutes for `merge` operations that end in the window. This duration includes the merge check and CI wait; separate times are unavailable. |
230
+ | `metrics.cost.medianCompletedTicketUsd` | Median total actual run cost for tickets that close as completed in the window. Each ticket includes all of its ended attempts at report time, including older partial, blocked, failed and cancelled attempts. |
231
+ | `completedTicketCosts` | Each completed ticket's issue number, close time, total USD cost, contributing runs and turn prices, evidence and historical daily median ticket-cost baseline. An unknown turn price, unreadable run identity or absent run history leaves the cost null. Estimates never replace actual prices. |
232
+ | `metrics.flow.busyLaneShare` | Queue run active milliseconds divided by current lanes times window milliseconds. Runs start at `run.started` and end at their terminal event; crossing and ongoing runs are clipped to the window. Evidence names the workflow, current lanes and runs. |
233
+ | `metrics.flow.idleLaneHoursWithReadyTicket` | Elapsed hours with fewer active queue runs than lanes and at least one eligible ready ticket. An interval counts once even when several lanes are idle or several tickets are eligible. |
234
+ | `metrics.flow.readyWaitHours.dependency` | Sum of ticket-hours carrying `cloving: ready` while at least one issue in the ticket's current `Needs` lines is open. Tickets without `Needs` have no dependency wait. Evidence names tickets and dependencies. |
235
+ | `metrics.flow.readyWaitHours.noLane` | Sum of eligible ticket-hours while all current queue lanes are occupied. Eligibility requires the ready label and every needed issue closed. |
236
+ | `metrics.flow.peakActiveRuns` | Largest simultaneous active run count across all workflows in the window, with the run IDs at the first peak. |
237
+ | `metrics.flow.scheduleSkips` | Total `schedule.skipped` events in the window. `metrics.flow.scheduleSkips.<workflowId>` gives the count for each observed workflow, with workflow IDs and event sequences. |
238
+ | `metrics.flow.unsuccessfulStreak.current` | Number of consecutive last-ended runs whose outcome was not completed at the window end, including a streak starting before the window. Terminal time orders runs, with event sequence breaking ties. Evidence names the streak's runs. |
239
+ | `metrics.flow.unsuccessfulStreak.longest` | Longest unsuccessful streak among runs ending in the window. A completed outcome resets both streaks; partial, blocked, failed and cancelled outcomes extend them. |
240
+ | `ci.jobMinutes.localMacos` | Median job duration in minutes. The same key is available for `localLinux`, `hostedMacos` and `hostedLinux`. Evidence gives job IDs, run IDs, attempts, names, duration and limit. |
241
+ | `ci.jobLimitShare.localMacos` | Median of each job's duration divided by its own `timeout-minutes`. Also reported for `localLinux`, `hostedMacos` and `hostedLinux`. A job with no known limit contributes duration without a share. |
242
+ | `ci.runnerWaitMinutes.localMacos` | Median minutes from job creation to start, also reported for `localLinux`, `hostedMacos` and `hostedLinux`. |
243
+ | `ci.timeouts` | Jobs with conclusion `timed_out`, or duration at least their known limit. Each job counts once, with job and run IDs as evidence. |
244
+ | `ci.reruns` | Workflow runs whose latest attempt number exceeds one. Each run counts once at the latest attempt start (`run_started_at`, falling back to `updated_at`). Evidence includes run IDs and attempt numbers. |
245
+ | `operator.merges` | Merged pull requests with no completed daemon `merge` effect reporting `merged: true` or the daemon's merge commit SHA for that pull request number before report end. |
246
+ | `operator.labelChanges` | `labeled` and `unlabeled` events for `cloving:` labels with no daemon `label` effect ending within two minutes for the same issue. This is a time match, recorded in `semantics.operatorLabels`; it does not identify the actor. Evidence gives issue numbers, event IDs, label and change type. |
247
+ | `quality.mainFirstPassShare` | CI runs on `main` that passed on attempt 1, divided by all CI runs created in the window. Later successful attempts do not count as first passes. No runs gives unavailable. Evidence includes run IDs, commits and first-attempt conclusions. |
248
+ | `quality.flakyFailures` | Failed job names and commits with a later successful attempt. Each job-name and commit pair counts once. Evidence includes test names from the failed logs, the commit, run IDs and failed and successful job IDs. |
249
+ | `quality.realFailures` | Failed job names and commits without a later successful attempt. Repeated failed attempts count once per job-name and commit pair. Evidence includes the failed job IDs and test names. |
250
+ | `quality.revertedPullRequests` | Merged pull requests in the window whose title starts with `Revert "`. Evidence gives the pull request numbers. |
251
+ | `quality.reopenedTickets` | Reopened issue events in the window after an earlier completed close. Evidence gives issue numbers, event IDs and the earlier close time. |
252
+ | `quality.reviewScore.round1` | Median score reported by the first `wait-review` operation in each run. `round2` and later keys use the operation order in that run. The report time selects the window. Evidence includes run IDs, operation IDs, event sequences and scores. |
253
+
254
+ Quality values have the same metric fields and seven-day baseline as other metrics. First-pass shares compare directly with daily shares. Failure, revert and reopen counts compare their daily equivalents. Review scores compare daily medians. CI data comes from the workflow named `CI` on `main`, with each run attempt read separately. Closure reasons come from issue events, with a GraphQL close-event read when REST omits the reason. An unreadable close reason leaves closure and reopen values unavailable.
255
+
256
+ Failure metrics use job completion times. The report scans all run pages and selects recent run activity, including completions and reruns of older runs. First-pass shares use run creation times. Ticket costs count each ticket once at its latest completed close before the report end. Repeated completed closes still count separately toward ticket throughput.
257
+
258
+ The report reads at most 50 distinct failed job logs, with a 2 MB output limit for each log. `quality.jobLogs` gives `read`, `notRead`, `limit` and `maximumBytes`. Each failed job without readable names uses `unknown`. Unread and unreadable logs do not erase known job failures. Logs use the `Failed tests:` list from the quality gate.
259
+
260
+ Flow uses the current queue workflow and lane setting and the current ticket bodies, as recorded in `semantics`; earlier settings and bodies are not reconstructed. Ready-label intervals come from all issue timeline pages, including removed and reapplied labels. Dependency closure times come from the current issue records; an open dependency remains blocking. Issue discovery includes every issue so an old, still-ready ticket is retained. This definition uses the label and dependency conditions regardless of ticket closure or assignment. Ready wait sums ticket-hours, while idle time measures elapsed hours. Hours and skip counts compare their per-day equivalent with the baseline; busy share, peak and streak values compare directly. Ready-history baselines start at repository creation; idle and no-lane baselines require both GitHub and daemon history. Unreadable timelines, dependencies or queue identity leave affected values unavailable while independent daemon values remain readable.
261
+
262
+ Every metric has `value`, `comparisonValue`, `baseline` and `evidence`. Counts retain their requested-window totals in `value`; `comparisonValue` is their equivalent per 24 hours. Medians are not scaled. The baseline uses the seven consecutive 24-hour periods immediately before the window, anchored at the same time of day in UTC. It contains the median and the band from median minus three times the median absolute deviation to median plus three times that deviation. Only values strictly outside the band receive `mark: "outside"`. Individual run and ticket costs use their respective daily median cost bands. With fewer than five complete observed days, `history` is `short`, the median and band are null, and there is no mark. Empty observed days count as zero for counts; days without samples, or with an unknown sample, do not establish a daily median. An unrepresentable numeric band has unavailable history and no mark. Daemon history starts at its earliest retained event; GitHub history starts at repository creation. Ticket-cost history starts at the later of those two dates.
269
263
 
270
264
  Evidence includes the contributing run IDs and event sequences, issue numbers or pull request numbers. Baseline evidence is separate from current-window evidence. Run cost details also expose each turn's operation ID. The daemon event read is pinned to the first page's latest sequence; later appended events are excluded. Run status and GitHub sources are separate reads, so the report is not an atomic cross-source snapshot.
271
265
 
272
266
  Each GitHub read uses the existing retry rules: transient network errors and HTTP 500, 502, 503 and 504 receive up to three attempts, with growing waits of 30 and 60 seconds. Read failure, invalid data, an unknown actual price or missing repository context is represented as `unavailable` with a null metric value, rather than zero. A failed source does not hide readable sources. `sources` shows which reads succeeded; the command exits zero when it produces a report, including one with unavailable sources. Invalid command arguments exit two.
273
267
 
274
- The `coverage` object explicitly marks the remaining facts unavailable: immutable ticket closure and reopening history, fix rounds per merged pull request, ready-to-merge lead time, phase durations, lane utilization and ready-ticket idle time, peak active runs, skips and unsuccessful streaks, first-attempt main CI passes, flaky failures and test names, reverted work, review scores, CI runner/OS utilization and limits, time-outs, reruns and runner waits, completed-ticket costs across attempts, and operator merges, reruns, labels and restarts. These facts are not inferred from the implemented counts. The report performs no model call, writes no state and changes no queue.
268
+ CI usage reads the workflow named `CI` on every branch, including every attempt of runs with recent activity. Job completion time selects job samples. Labels containing `self-hosted` identify local runners; other runners are hosted. macOS and Linux come from explicit system labels, falling back for hosted runners to the workflow's image (`runs-on`). Unrecognized runner data leaves job metrics unavailable. Limits come from the workflow file at the run's commit through the GitHub contents API. Only JSON documents are parsed; non-JSON workflows and jobs without numeric limits have duration and wait samples without shares. An unreadable workflow leaves shares and timeouts unavailable while duration, wait and rerun values remain independent. An unreadable job source preserves rerun counts. Unreadable run activity makes CI usage unavailable. `sources.github.ciUsage` reports the all-branch run read. `sources.github.ciUsageJobs` and `sources.github.ciUsageWorkflows` report its job and workflow reads, with failure reasons. These statuses are separate from `ci` and `jobs`, which report quality reads on `main`.
269
+
270
+ Operator values combine GitHub merges and repository issue-label events with daemon `effect.reported` events joined to their requests. Missing daemon history makes operator values unavailable. Their baselines start at the later of daemon history and repository creation. CI and operator values use the same seven-day median, band, evidence and short-history rules as other report values. CI durations, limit shares and waits compare daily medians; timeout, rerun and operator counts compare daily equivalents. The `coverage` object has no remaining unimplemented report sections. The report performs no model call, writes no state and changes no queue.
275
271
 
276
272
  ## Daily development
277
273
 
278
- `cloving start` copies the TypeScript files in `workflows/` into a host project and compiles them there. The bundled workflows are:
274
+ `cloving start` compiles and registers only project and user workflows. The start guide lists each registered workflow with a run command that matches its input contract. With no workflow, the service still starts and prints "No workflow. Run: cloving init". Status continues to show stored runs after their workflows have been removed.
279
275
 
280
- - `develop-prompt` takes the text of a task. Use it for a small task with no ticket, or for a first try in a new repository.
281
- - `develop-ticket` takes a ticket ID and reads the ticket itself. Use it for the normal work on a ticket, when you want to read each diff and merge the branch yourself.
282
- - `develop-issue` takes a ticket ID too, and sends the work through a GitHub pull request. Use it for a small ticket with clear criteria, in a GitHub repository that Greptile reviews and that has a check command. It is the workflow of the continuous process.
283
- - `develop-prd` takes an idea, researches the code and web, reviews a draft PRD, and posts it as a GitHub issue. It then hands the issue number to `develop-issue` to build automatically. Set `CLOVING_PRIVATE_TEXTS` to a nonempty JSON list before starting the daemon. A refused post preserves the worktree and draft. If the handoff is refused, it adds `cloving: ready` so the issue queue can build it later. The PRD run retains `issue-N` as its promotion, shows the refusal code in its outcome reason, and removes its worktree after posting. If the fallback label fails, status also shows `issueUpdate: failed`; inspect the GitHub operation and queue the issue after resolving the failure.
276
+ Use `cloving init` to choose and configure a template. The `develop` template supports ticket input, queue selection, review and merge choices. The `idea-to-issue` template researches an idea and hands the resulting issue to a declared development workflow. The commands below assume those templates have been copied and configured:
284
277
 
285
278
  ```sh
286
279
  cloving start # terminal 1, in the repository
287
- cloving run develop-ticket --ticket TICKET_ID # terminal 2
288
- cloving run develop-issue --ticket TICKET_ID # the work goes through a pull request
289
- cloving run develop-issue --next # select the next ready ticket
290
- cloving run develop-prompt --prompt "the text of the task"
291
- cloving run develop-prd --prompt "Show the cost of each run on the watch page"
280
+ cloving run develop --ticket TICKET_ID # terminal 2
281
+ cloving run develop --next # select the next ready ticket
282
+ printf '%s\n' '{"idea":"Show the cost of each run on the watch page"}' > idea.json
283
+ cloving run idea-to-issue --input idea.json
292
284
  cloving watch # the live page, also started by cloving start
293
285
  cloving questions
294
286
  cloving approve DECISION_REF --expected-revision N --generation N --subject-digest DIGEST
@@ -299,17 +291,17 @@ The rule: read the diff before you approve.
299
291
 
300
292
  Claude turns have web research tools by default, an empty GitHub CLI configuration folder, and no GitHub token environment variables. This is not a sandbox: a turn can still find other credentials. The PRD refusal rules catch the listed private text and common sensitive forms; unlisted private names can pass. A `post-uncertain` result requires checking GitHub before trying another run.
301
293
 
302
- `cloving status RUN_ID --json` includes `run.input`, and `cloving status --json` includes `input` on each listed run. It is the normalized submission admitted with the run, such as `{"ticket":"297"}` for `develop-issue` or the submitted fields of a declared workflow. It survives service restarts and excludes resolver-added ticket text and repository paths. Older runs without a stored submission show `null`. The text status of one run shows `Input:` as compact JSON, limited to the first 200 characters with `…` appended when longer. Terminal control and hidden format characters are escaped.
294
+ `cloving status RUN_ID --json` includes `run.input`, and `cloving status --json` includes `input` on each listed run. It is the normalized submission admitted with the run, such as `{"ticket":"297"}` for a ticket workflow or the submitted fields of another declared workflow. It survives service restarts and excludes resolver-added ticket text and repository paths. Older runs without a stored submission show `null`. The text status of one run shows `Input:` as compact JSON, limited to the first 200 characters with `…` appended when longer. Terminal control and hidden format characters are escaped.
303
295
 
304
296
  ### The ticket command
305
297
 
306
298
  `CLOVING_TICKET_COMMAND` (a JSON list of texts) names the ticket command. The contract of a ticket command:
307
299
 
308
300
  - It gets a ticket ID as its last argument and prints the text of the ticket.
309
- - For `develop-issue`, a first line that starts with `# ` gives the title of the pull request. With no such line, the title is `Cloving task <cycle ID>`.
310
- - For `develop-issue`, a line `GitHub issue: <owner>/<repository>#<number>` makes the pull request reference that issue. Cloving closes it after a merge only when the worker reports complete work.
301
+ - The `develop` template uses the first ticket line as the pull request title, removes leading Markdown heading markers and limits it to 200 characters.
302
+ - For `develop`, a line `GitHub issue: <owner>/<repository>#<number>` makes the pull request reference that issue. Cloving closes it after a merge only when the worker reports complete work.
311
303
 
312
- The daemon runs the ticket command when it admits a run. The printed text becomes the stored input of the run, so a later change of the ticket does not change the run. A ticket that the command does not give is refused with `ticket-not-available`. With no ticket command, `develop-ticket` is refused with `ticket-source-not-configured`. A ticket ID has letters, digits and the characters `. _ : -` only.
304
+ The daemon runs the ticket command when it admits a run. The printed text becomes the stored input of the run, so a later change of the ticket does not change the run. A ticket that the command does not give is refused with `ticket-not-available`. With no ticket command, `develop` is refused with `ticket-source-not-configured`. A ticket ID has letters, digits and the characters `. _ : -` only.
313
305
 
314
306
  This example ticket command reads a GitHub issue. Save it as `~/.local/bin/github-ticket`, and make it executable:
315
307
 
@@ -328,9 +320,11 @@ Then start the service with the setting:
328
320
  CLOVING_TICKET_COMMAND='["github-ticket"]' cloving start
329
321
  ```
330
322
 
331
- `cloving run develop-issue --next` and `cloving run develop-ticket --next` use the reserved ticket ID `next`, just like `--ticket next`. Set `CLOVING_NEXT_COMMAND` to a JSON list naming your selection command and its arguments. The daemon adds no argument. The command chooses a ready ticket in your tracker and prints its ID; the daemon trims it and reads the ticket with `CLOVING_TICKET_COMMAND`. Both commands share the resolver's 30-second deadline. Selection logic stays in your command, and each invocation submits only one run.
323
+ `cloving run develop --next` uses the reserved ticket ID `next`, just like `--ticket next`. Set `CLOVING_NEXT_COMMAND` to a JSON list naming your selection command and its arguments. The daemon adds no argument. The command chooses a ready ticket in your tracker and prints its ID; the daemon trims it and reads the ticket with `CLOVING_TICKET_COMMAND`. Both commands share the resolver's 30-second deadline. Selection logic stays in your command, and each invocation submits only one run.
324
+
325
+ Set `CLOVING_QUEUE_SECONDS` to a whole number from 10 to 3600 to poll for ready tickets. The queue starts the declared workflow with `"queue": true` and requires both ticket commands when that workflow exists. If no workflow declares it, no queue starts, even when the interval is set. `CLOVING_QUEUE_LANES` sets the number of simultaneous runs, from 1 to 4, and requires `CLOVING_QUEUE_SECONDS`; its default is 1. For example, `CLOVING_QUEUE_LANES=4` admits at most one new ticket each cycle until four lanes are busy. Each run has its own branch and work tree. Manual submissions to the queue workflow share this limit and receive `workflow-active` when all lanes are busy. A ticket already being developed receives `ticket-active`. After a restart that moves the queue to another workflow, active runs of earlier queue workflows still occupy lanes and exclude their tickets.
332
326
 
333
- Set `CLOVING_QUEUE_SECONDS` to a whole number from 10 to 3600 to poll for ready tickets. It requires both ticket commands. The queue starts the declared workflow with `"queue": true`; when none declares it, the bundled `develop-issue` takes the queue. `CLOVING_QUEUE_LANES` sets the number of simultaneous runs, from 1 to 4, and requires `CLOVING_QUEUE_SECONDS`; its default is 1. For example, `CLOVING_QUEUE_LANES=4` admits at most one new ticket each cycle until four lanes are busy. Each run has its own branch and work tree. Manual submissions to the queue workflow share this limit and receive `workflow-active` when all lanes are busy. A ticket already being developed receives `ticket-active`. After a restart that moves the queue to another workflow, active runs of earlier queue workflows still occupy lanes and exclude their tickets.
327
+ Set `queue.dailySpendLimitUsd` in project or private configuration, or `CLOVING_QUEUE_DAILY_SPEND_USD`, to a positive finite USD limit. It requires `CLOVING_QUEUE_SECONDS`. At 85 percent of this limit, the queue holds new runs until spend falls below the threshold. Spend covers worker turns of queue workflows settled in the last 24 hours, using each reported price or its token-price estimate. Runs in work continue, so spend can exceed the limit. Status and watch show spend, the limit, unknown costs and turns in work. Unknown costs are never counted as zero; when every settled turn has unknown cost, they show `Price not known`. The window and hold are reconstructed from stored settlements after restart. Runs of other workflows do not count.
334
328
 
335
329
  The optional declaration field `queue` is a boolean. `"queue": true` requires a field named `ticket` with `"type": "ticket"` (`queue-needs-ticket-field`), and every other input field must be optional (`queue-input-incomplete`). Two queue declarations stop startup with `queue-workflow-conflict`. `cloving doctor` requires `next-command` and `queue-interval` whenever a declared workflow takes the queue.
336
330
 
@@ -346,21 +340,21 @@ A saved harness named `grok` runs `grok --output-format streaming-messages-json
346
340
 
347
341
  Grok token counts come only from the terminal result, including its subagents. Input includes uncached input and cache creation; cache reads and output remain separate. Missing, all-zero or stderr-warned incomplete usage shows `Token usage not known`. An estimate requires complete usage attributed to exactly one model with a configured price. Mixed models and missing prices show `Price not known`. Grok uses token-based estimates and ignores its projected cost field. No Grok model prices are built in.
348
342
 
349
- ### Review rounds of `develop-ticket` and `develop-prompt`
343
+ ### Human review with a local branch
350
344
 
351
345
  Worker turns retry an exact Codex capacity refusal or a Claude overload after 60 seconds, then 180 seconds. Claude worker turns also retry a failed result whose text starts with `API Error: Can't reach the API server`: the first retry waits 10 minutes and the second waits 40 minutes. The retry number selects the wait for its kind, with at most three attempts across both kinds. Other failures are not retried. Each wait starts after the failed attempt ends. Stopping during a wait returns `stopped`; a daemon restart fails the recorded operation for existing recovery.
352
346
 
353
347
  Each retry keeps the work tree, profile, budget and limits, and starts a new session with a continuation line before the full prompt. After any network failure, every later attempt gets the network continuation, which asks it to check earlier commits, pushes, review comments and messages, avoid repeating completed writes, and stop to report a write whose result is unknown. It also gets fresh git evidence for commits since this turn's first attempt. Cloving fetches the branch from `origin` and marks each commit `pushed`, `not pushed` or `unknown`; an absent origin branch means `not pushed`. Each git command has a 30-second limit and is cancelled by drop. Failed reads give explicit unknown evidence.
354
348
 
355
- Before a retry, Cloving checks the work tree's git index lock, including linked work trees. It never removes a lock: `worktree-index-locked` records its path and tells the operator to remove it when no git process uses the work tree. An unreadable index path gives `worktree-index-unknown`. Neither failure starts another attempt. The step keeps one operation identity and sums usage across attempts. Private turn journals, status text and JSON, and watch retain each attempt's model, token counts, cost estimate and `retryKind` (`capacity`, `network`, or `null` for other results). Older attempts without the field show no kind. Attempt kinds appear after the turn ends.
349
+ Before a retry, Cloving checks the work tree's git index lock, including linked work trees. Capacity and network retries never remove a lock: `worktree-index-locked` records its path and tells the operator to remove it when no git process uses the work tree. Before a Claude resume after a daemon restart or a dead turn process, Cloving stops same-user processes whose working directories are in the turn work tree, waits up to 15 seconds after SIGTERM, then sends SIGKILL. The daemon itself and processes outside that tree are excluded. Cloving removes a work tree index lock only when it identified the lock owners before cleanup, those owners have exited, and the lock has not changed. A lock with an unknown owner, including one whose owner closed its descriptor, stays in place and reports `worktree-index-locked`; inspect its owner before removing it manually. Stopped process IDs are recorded in `resume-processes.json` in the turn folder. An unreadable index path gives `worktree-index-unknown`. Neither failure starts another attempt. The step keeps one operation identity and sums usage across attempts. Private turn journals, status text and JSON, and watch retain each attempt's model, token counts, cost estimate and `retryKind` (`capacity`, `network`, or `null` for other results). Older attempts without the field show no kind. Attempt kinds appear after the turn ends. Resumed attempts also show `resumedAfter: daemon-restart` in status text, JSON and watch.
356
350
 
357
351
  `CLOVING_FALLBACK_MODELS` accepts a JSON array of at most three nonempty model names, for example `'["gpt-6-astra"]'`. Without the setting or with `[]`, every attempt keeps the main model. The first attempt and first retry use the main model; each later attempt uses the next configured fallback within the existing attempt limit. With three attempts, only the first fallback can be used. The worker command must explicitly name a model with `-m NAME`, `--model NAME` or `--model=NAME`; otherwise it stays unchanged and the private journal records `fallback-model-unavailable`. Fallbacks apply only when the preceding attempt ended with a capacity refusal. A network retry keeps the model of the configured command. A fallback model can have a higher price. Each attempt's estimate uses its own model's price; an unknown price or missing token count leaves the total estimate unknown. Malformed settings refuse daemon start with `invalid-fallback-models`.
358
352
 
359
- A run of `develop-ticket` or `develop-prompt` has one to three review rounds. Each round does one Claude Code turn in the work tree of the run, on the branch `cloving/<ticket id>-…`, and then opens one approval. The first round makes the work tree. The approval text has the round, the ticket ID, the branch, the commits, the changed files and the report of the worker. Read the diff before you decide. The decision has these results:
353
+ A develop template copy configured for human review and the local-branch merge option has up to four review rounds. Each round does one Claude Code turn in the work tree of the run, on its generated task branch, and then opens one approval. The first round makes the work tree. The approval identifies the immutable review subject, including its target and commit. Read that commit’s diff before you decide. The decision has these results:
360
354
 
361
355
  - An approval completes the run. It does not merge the branch. Merge the branch yourself.
362
- - A denial with a feedback text (`--text`) in round 1 or 2 starts the next round. The Claude worker gets the feedback text and adds commits to the same branch.
363
- - A denial with no text, or a denial in round 3, ends the run.
356
+ - A denial with a feedback text (`--text`) in rounds 1 to 3 starts the next round. The Claude worker gets the feedback text and adds commits to the same branch.
357
+ - A denial with no text, or a denial in round 4, ends the run.
364
358
 
365
359
  The worker is not confined. It runs the `claude` command of the search path as the current user, with file edits and shell commands permitted in the work tree and a spend limit of 5 USD for each turn. `CLOVING_CLAUDE_COMMAND` (a JSON list of texts) replaces the command.
366
360
 
@@ -446,19 +440,19 @@ separate starting commits; concurrent runs on one branch do not isolate their
446
440
  commits. Index flags inside submodules and other settings that hide changes
447
441
  are outside these checks. Every GitHub worker method refuses `branch:` targets
448
442
  with `branch-target-not-supported`, so this target adds no Cloving push or merge
449
- step. The bundled development workflows keep their existing targets.
443
+ step. Each project or user workflow declares its own targets.
450
444
 
451
- ### Pull requests of `develop-issue`
445
+ ### Pull requests of `develop`
452
446
 
453
- A run of `develop-issue` opens no approval. The GitHub worker makes the work tree from the newest commit of the default branch of `origin`. After the Claude turn, the worker pushes the branch and opens a pull request. The title and the referenced issue come from the ticket text (see "The ticket command"). The pull request body uses `Refs owner/repository#N`, so the merge itself does not close the issue. Then the worker waits for the Greptile review of the pushed commit, and asks for a review with a comment after 5 minutes.
447
+ The default `develop` template uses automatic review without an approval. The GitHub worker makes the work tree from the newest commit of the default branch of `origin`. After the Claude turn, the worker pushes the branch and opens a pull request. The title and the referenced issue come from the ticket text (see "The ticket command"). The pull request body uses `Refs owner/repository#N`, so the merge itself does not close the issue. Then the worker waits for the Greptile review of the pushed commit, and asks for a review with a comment after 5 minutes.
454
448
 
455
- When the ticket names a GitHub issue, the workflow adds `cloving: in progress` after preparing the work tree and removes `cloving: ready` and `cloving: blocked`. A blocked run adds `cloving: blocked` and removes `cloving: in progress`. Start and blocked label failures leave the run's outcome unchanged. Cloving creates the labels it adds or removes with the fixed color `ededed`; existing labels have their color and description reset by `gh label create --force`.
449
+ When the ticket names a GitHub issue, the workflow adds `cloving: in progress` after preparing the work tree and removes `cloving: ready` and `cloving: blocked`. A blocked run adds `cloving: blocked` and removes `cloving: in progress`. A failed label operation throws and can fail the template run. Cloving creates the labels it adds or removes with the fixed color `ededed`; existing labels have their color and description reset by `gh label create --force`.
456
450
 
457
451
  The last worker report must end with exactly one line: `Ticket status: complete` or `Ticket status: partial`. A partial report must put `Remaining:` immediately before a list with one `- ` item per line, followed by the status line. The worker records the parsed status and remaining items before shortening the summary, so summary limits cannot remove those fields. If the preserved fields exceed the result byte limit, the turn fails with `claude-result-too-large` and retains bounded cost metadata; the full report stays in the private turn log. Older recorded turns still use summary parsing. Missing, repeated, unknown or malformed status reports count as partial with the remaining item "The worker report has no ticket status line."
458
452
 
459
453
  After a merge, a protected GitHub operation updates the issue body and labels. Complete work closes the issue with reason `completed` and adds "Completed in pull request #M." to `## Cloving status`. Partial work keeps the issue open and appends `- Pull request #M: partial. Remaining: ...` to that section at the end of the body, preserving earlier partial lines and other body text. Items are separated by semicolons. The issue privacy check runs before new remaining text is written; a refusal uses "Remaining work is in the private run report." instead. No issue comment is posted. Status writes add and remove only workflow labels, preserving unrelated label edits. Before a body write, Cloving rereads the issue and refuses a changed body with `github-issue-conflict`; the merged outcome records `issueUpdate: failed`. GitHub does not support conditional PATCH requests for this endpoint, so this check cannot make the read and write atomic.
460
454
 
461
- Partial work removes `cloving: in progress` and adds `cloving: ready`, so the next queue cycle can select the same issue and read its remaining work from the issue body. The third partial run adds `cloving: blocked` instead of `cloving: ready`. Completion removes these workflow labels. Status operations reconcile the pull request number in the stored history after a restart to avoid duplicate writes. The effect limit stays at 20 units: the post-merge status operation replaces the final label operation.
455
+ Partial work removes `cloving: in progress` and adds `cloving: ready`, so the next queue cycle can select the same issue and read its remaining work from the issue body. The third partial run adds `cloving: blocked` instead of `cloving: ready`. Completion removes these workflow labels. Status operations reconcile the pull request number in the stored history after a restart to avoid duplicate writes. The unmodified develop template declares an effect limit of 27 units.
462
456
 
463
457
  Partial history comes only from a hidden HTML comment at the end of the issue body, beginning with `cloving-status`. Its JSON object has `version: 1`, a `partialRuns` array of pull request numbers and remaining-item lists, and an optional `completedPullRequest`. Double hyphens and greater-than signs in JSON strings are escaped so they cannot end the comment. Each write regenerates the readable section from this data and replaces the exact previously generated section. Other Markdown stays unchanged, including status examples, lists, tables, HTML and unclosed fences. Missing, broken or unknown metadata counts as zero earlier partial runs and is replaced on the next write; readable text is never used to reconstruct history. A block followed by other issue text is left unchanged and counts as missing terminal metadata.
464
458
 
@@ -476,7 +470,7 @@ When a GitHub Actions check fails in its first workflow attempt, Cloving request
476
470
 
477
471
  A second failure returns `ci-failed` with the outputs of both attempts, including failed check names, failed steps and failed log tails, with private texts hidden and at most 6,000 characters in total. Checks outside GitHub Actions or without an Actions run link retain the immediate failure behavior. The failure starts a worker fix round that must repair CI, including failures the pull request did not cause, and commit the fix. The new commit receives a new Greptile review and CI gate. Review, local check, conflict and CI repairs share the existing limit of three fix rounds.
478
472
 
479
- The watch board keeps blocked `develop-issue` runs in `Stopped`. A validated local merge report shows `PR merged · #N`. A later completed run for the same established GitHub issue must have its own validated merge report to show `Ticket completed by later run`. The original and later run have separate links. Either local proof prevents a GitHub read. These marks preserve the recorded run outcome.
473
+ The watch board preserves the displays of historical pull-request runs, including blocked runs in `Stopped`. A validated local merge report shows `PR merged · #N`. A later completed run for the same established GitHub issue must have its own validated merge report to show `Ticket completed by later run`. The original and later run have separate links. Either local proof prevents a GitHub read. These marks preserve the recorded run outcome.
480
474
 
481
475
  Otherwise, the board reads the recorded pull request with `CLOVING_GH_COMMAND` (default `gh`). It validates the PR and issue identities against the configured repository's local origin. The first queued or active read shows `Checking PR`. A confirmed merge shows `PR merged · #N`; a failed read shows `PR status unavailable`. An unmerged PR shows `Needs attention`. A separate `Stale` mark appears when the last successful unmerged observation is older than 120 seconds, including after a failed refresh. A successful refresh resets its age. Confirmed merges never become stale.
482
476
 
@@ -486,10 +480,14 @@ The GitHub worker does not push a change that has the path of the home folder in
486
480
 
487
481
  ## Continuous process
488
482
 
489
- In a continuous process, Cloving develops one ticket after the next with `develop-issue`. Use one terminal session for the service that stays open, for example a `tmux` session. Do these steps for each issue:
483
+ In a continuous process, Cloving develops one ticket after the next with `develop`. Keep the workflow outside this public repository. In a private repository, run `cloving templates copy develop`. From the Cloving repository, set `cloving config set workflows.folder "$WORKFLOW_FOLDER"`, where `WORKFLOW_FOLDER` is the absolute folder containing that copy, and restart the service. The setting stays in the operator’s private settings file. Do not commit a workflow copy here.
484
+
485
+ The unmodified template takes a ticket, selects from the queue (`"queue": true`), accepts Greptile at 5/5, lets Cloving merge after the checks, and returns partial tickets to the queue. Configure the ticket command, next-ticket command and queue interval in the operator’s settings. The queue starts only the declared queue workflow, `develop`.
486
+
487
+ Use one terminal session for the service that stays open, for example a `tmux` session. Do these steps for each issue:
490
488
 
491
489
  1. Write a small issue: one behavior, clear criteria that a test can check, and the first tests. The prompt "Write a ticket for Cloving" helps.
492
- 2. Run it: `cloving run develop-issue --ticket ISSUE_NUMBER`.
490
+ 2. Run it: `cloving run develop --ticket ISSUE_NUMBER`.
493
491
  3. Follow the run on the watch page, or with `cloving status RUN_ID` and `cloving events RUN_ID --follow`.
494
492
  4. Check the merge. The run completes when the GitHub worker merges the pull request. The watch page shows the number of the pull request of the run (`PR_NUMBER`). It is also `pullRequest.number` of the run in `http://127.0.0.1:3663/data.json`. The pull request number and the issue number are different.
495
493
  - Make sure that the pull request is merged: `gh pr view PR_NUMBER --json state,mergedAt`.
@@ -502,39 +500,27 @@ When a run stops and the pull request stays open, read the review. Fix the work
502
500
 
503
501
  Know these limits before you start:
504
502
 
505
- - The cost limit of each Claude turn is 5 USD. A run of `develop-issue` can have up to four Claude turns. `CLOVING_CLAUDE_COMMAND` changes the command and its limit.
503
+ - The cost limit of each Claude turn is 5 USD. A run of `develop` can have up to four Claude turns. `CLOVING_CLAUDE_COMMAND` changes the command and its limit.
506
504
  - The text of a pull request is public in a public repository. The worker gets an instruction to write no local file path in a file or in a commit message.
507
505
  - `CLOVING_PRIVATE_TEXTS` adds texts that the GitHub worker refuses to push, for example the names of private projects. The path of the home folder is always refused.
508
- - `CLOVING_CHECK_COMMAND` names the checks of the repository. Set it, because a merge at 5/5 has no human approval. With no setting, the merge occurs with no check.
506
+ - The default develop workflow runs `checks.beforeMerge` before merging. With no configured command, it stops with `check-not-configured` and leaves the pull request open. This repository commits `["npm", "run", "check:quality"]` as that command and requires the CI checks `quality` and `quality_linux` in `.cloving/config.json`. An environment or private-file override takes precedence.
509
507
 
510
508
  ## Prompts for a coding agent
511
509
 
512
510
  Copy a prompt, replace the words in capital letters, and give it to a coding agent.
513
511
 
514
- ### Set up Cloving for a repository
512
+ ### Set up a repository
515
513
 
516
- ```text
517
- Set up Cloving for my repository REPOSITORY_PATH. Ask me for each value that you do not know. Do not push, publish or merge anything in this setup.
518
-
519
- 1. Check the platform: macOS or Linux on arm64 or x64, with the Node and npm versions of "engines" in package.json of Cloving. Check that git and the claude command work. If I want develop-issue, check that gh has a login and that Greptile reviews the GitHub repository.
520
- 2. If I have no Cloving checkout, clone https://github.com/cloving-ai/cloving-ai.git to ~/cloving. In the checkout, run: npm ci --ignore-scripts
521
- 3. Write a launcher ~/.local/bin/cloving that runs src/cli.ts of the checkout with the correct node program, and make it executable. Do not use npm link. Make sure that ~/.local/bin is on the search path and that "cloving --version" works.
522
- 4. Ask me which tracker has my tickets. Write a ticket command for that tracker in ~/.local/bin. The command gets a ticket ID as its last argument and prints the text of the ticket. For develop-issue, the first line is "# " and the title, and one line is "GitHub issue: OWNER/REPOSITORY#NUMBER". Test the command with one ticket ID, and show me the output.
523
- 5. Start the service in a terminal session that stays open, for example a tmux session. In that session, in my repository, run: CLOVING_TICKET_COMMAND='["TICKET_COMMAND"]' cloving start
524
- For develop-issue, also set CLOVING_CHECK_COMMAND to the checks of my repository. Give me the address of the watch page.
525
- 6. Make a first run with develop-prompt and a small task that I agree to. Show me the output of "cloving questions" and the diff of the branch. Do not approve or deny. I decide.
526
- 7. Then run my first ticket: cloving run develop-ticket --ticket TICKET_ID
527
- Show me the diff again before I decide.
528
- ```
514
+ Run `cloving init` in the repository and select your agent harness. The agent runs `cloving init-prompt` to get repository facts and the setup instructions, then guides you through the remaining steps.
529
515
 
530
516
  ### Run a continuous process
531
517
 
532
518
  ```text
533
- Run a continuous process with Cloving and develop-issue in my repository REPOSITORY_PATH. The Cloving service runs in the terminal session SESSION_NAME. Do the issues ISSUE_LIST one at a time, in this order.
519
+ Run a continuous process with Cloving and develop in my repository REPOSITORY_PATH. The Cloving service runs in the terminal session SESSION_NAME. Do the issues ISSUE_LIST one at a time, in this order.
534
520
 
535
521
  For each issue:
536
522
  1. Read the issue. Do not change it.
537
- 2. Run: cloving run develop-issue --ticket ISSUE_NUMBER
523
+ 2. Run: cloving run develop --ticket ISSUE_NUMBER
538
524
  ISSUE_NUMBER is the number of the issue. Record the run ID.
539
525
  3. Follow the run with "cloving status RUN_ID" and "cloving events RUN_ID --follow".
540
526
  4. When the run completes, get the number of its pull request (PR_NUMBER). It is pullRequest.number of the run in http://127.0.0.1:3663/data.json, and the watch page shows it too. Then:
@@ -562,9 +548,9 @@ Do not merge a pull request yourself. Do not approve or deny for me.
562
548
  Help me write a ticket for Cloving. A Claude Code worker gets the full text of the ticket and no other context. Ask me questions until each part is clear. Then write the ticket in Markdown with these parts:
563
549
 
564
550
  # TITLE
565
- One line. For develop-issue, it becomes the title of the pull request.
551
+ One line. For develop, it becomes the title of the pull request.
566
552
  GitHub issue: OWNER/REPOSITORY#NUMBER
567
- Only for develop-issue. The pull request references this issue; complete work closes it after the merge.
553
+ Only for develop. The pull request references this issue; complete work closes it after the merge.
568
554
  ## Problem
569
555
  What is wrong now, with facts.
570
556
  ## Desired outcome
@@ -582,83 +568,47 @@ GitHub issue: OWNER/REPOSITORY#NUMBER
582
568
 
583
569
  Rules:
584
570
  - One ticket has one behavior. If the work needs more than one pull request, split the ticket.
585
- - Write no secret, no private data and no local file path. For develop-issue, the ticket text and the branch become public.
571
+ - Write no secret, no private data and no local file path. For develop, the ticket text and the branch become public.
586
572
  - Use one term for one thing.
587
573
  ```
588
574
 
589
- ### Find workflows in your chats
590
-
591
- ```text
592
- Find workflows in my chats with coding agents, and write a draft Cloving workflow for one of them.
593
-
594
- Rules:
595
- - Read only the chats that I select. Ask me for the list first. Do not read other chats.
596
- - Keep the chat text and private data out of the repository. Do not copy chat text, names of persons, secrets or local paths into a file of the repository. Keep your notes outside the repository.
597
-
598
- Steps:
599
- 1. In the selected chats, find sequences of steps that repeat. For each sequence, list the steps, the tool of each step (for example git, a test command, gh or a model), and each decision of a person (for example "approve the diff").
600
- 2. Show me the list, and ask me which sequence to use.
601
- 3. Map each step that changes something outside the workflow to protectedEffect, with a capability and a method. Map each decision of a person to decisionGate.
602
- 4. Use only the capabilities that have a worker: claude (method run-turn) and github. Put each step that needs a different capability in a list of open points, not in the draft.
603
- 5. Write the draft in the form of workflows/develop-ticket.ts of the Cloving checkout: an exported async function with the directive "use workflow", and the step helpers from the subpaths of cloving/workflows.
604
- 6. Write a list of the human decisions in the draft: for each decisionGate, the question, the person who decides, and the result of each answer.
605
- 7. Write workflow tests with a fake step bridge, in the form of test/develop-workflow-fixture.ts.
606
- 8. Tell me which changes of the Cloving code the draft needs before the service can run it. The section "Develop a workflow" of the Cloving README lists them.
607
- ```
608
-
609
575
  ## Develop a workflow
610
576
 
611
- `cloving start` loads workflows from three folders:
577
+ `cloving start` loads workflows from two folders:
612
578
 
613
- - The bundled `workflows/` folder in the Cloving package. Startup compiles each TypeScript file in this folder.
614
579
  - The repository `.cloving/workflows/` folder.
615
580
  - The user `cloving/workflows/` folder under an absolute `XDG_CONFIG_HOME`, otherwise under `~/.config`. An unset or relative `XDG_CONFIG_HOME` uses that default.
616
581
 
617
582
  The private setting `workflows.folder` replaces the user folder with an absolute folder path, for example a private git repository of your own workflows. Set it with `cloving config set workflows.folder <path>`. Cloving reads the folder where it is. The folder itself must not be a symbolic link; a link in the path above it is allowed. `cloving workflows list` shows its workflows with the scope `user`.
618
583
 
619
- A workflow is a TypeScript file in the form of `workflows/develop-ticket.ts`:
584
+ A workflow is a TypeScript file in the form of `templates/develop/develop.ts`:
620
585
 
621
586
  - An exported async function with the directive `"use workflow"` as its first statement. The directive needs the compiler of the Workflow SDK, not only TypeScript.
622
- - The first argument is the input of the run. A resolver of the daemon makes it, for example `cycleId`, `ticketId`, `ticket` and `repository`. With `decisionGate`, the host calls the function again with the decision (`gateId`, `decision` and `answer`) as the second argument. The function must examine that argument before it asks for an effect, as `decided()` in `workflows/develop-ticket.ts` does. With `waitForDecision`, the decision returns to the same call.
623
- - The step helpers come from the subpaths of `cloving/workflows`: `protectedEffect` from `cloving/workflows/steps/protected-effect`, `decisionGate` from `cloving/workflows/steps/decision-gate`, `waitForDecision` from `cloving/workflows/steps/wait-for-decision`, `loadCycle` from `cloving/workflows/steps/load-cycle`, `handoff` from `cloving/workflows/steps/handoff`, `waitForRun` from `cloving/workflows/steps/wait-for-run` and `runCommand` from `cloving/workflows/steps/run-command`. The type `CycleOutcome` comes from `cloving/workflows`. An import of `cloving/workflows` starts no service.
624
- - `protectedEffect` asks the daemon for one effect of a capability, for example a Claude turn. `decisionGate` opens a decision for a person.
587
+ - The only argument is the input of the run. The declared resolver provides `cycleId`, `repository` and the submitted fields under `input`; a ticket field becomes `{ id, text }`. With `waitForDecision`, the decision returns to the same call.
588
+ - The step helpers come from the subpaths of `cloving/workflows`: `protectedEffect` from `cloving/workflows/steps/protected-effect`, `waitForDecision` from `cloving/workflows/steps/wait-for-decision`, `loadCycle` from `cloving/workflows/steps/load-cycle`, `handoff` from `cloving/workflows/steps/handoff`, `waitForRun` from `cloving/workflows/steps/wait-for-run` and `runCommand` from `cloving/workflows/steps/run-command`. The type `CycleOutcome` comes from `cloving/workflows`. An import of `cloving/workflows` starts no service.
589
+ - `protectedEffect` asks the daemon for one effect of a capability, for example a Claude turn. `waitForDecision` opens a decision for a person and waits for the result.
625
590
  - The function returns a `CycleOutcome`: `waiting_for_decision`, `handoff_requested` or `blocked`.
626
591
 
627
592
  For `handoff_requested`, the daemon retains the workflow's `promotionId` in the completion event. An optional bounded `reason` records a handoff refusal while preserving the promotion. `cloving status <runId>` shows the promotion as `Promotion:` and the reason beside the outcome; JSON status includes `run.outcome.promotionId` and `run.outcome.reason`. Watch retains the promotion in the run model and completed-run details. This identifier is an opaque reference and grants no authority.
628
593
 
629
594
  ```ts
630
595
  import type { CycleOutcome } from "cloving/workflows";
631
- import { decisionGate } from "cloving/workflows/steps/decision-gate";
596
+ import { waitForDecision } from "cloving/workflows/steps/wait-for-decision";
632
597
  import { protectedEffect } from "cloving/workflows/steps/protected-effect";
633
598
 
634
- export async function developTicket(
635
- input: { readonly cycleId: string; readonly ticket: string },
636
- decision?: {
637
- readonly gateId: string;
638
- readonly decision: string;
639
- readonly answer: string | null;
640
- },
641
- ): Promise<CycleOutcome> {
599
+ export async function developTicket(input: {
600
+ readonly cycleId: string;
601
+ readonly input: {
602
+ readonly ticket: { readonly id: string; readonly text: string };
603
+ };
604
+ }): Promise<CycleOutcome> {
642
605
  "use workflow";
643
- if (decision?.decision === "approved")
644
- return {
645
- kind: "handoff_requested",
646
- cycleId: input.cycleId,
647
- promotionId: `cloving-${input.cycleId}`,
648
- };
649
- if (decision !== undefined)
650
- return {
651
- kind: "blocked",
652
- cycleId: input.cycleId,
653
- reason: "The operator denied the work.",
654
- evidenceId: decision.gateId,
655
- };
656
606
  const turn = await protectedEffect({
657
607
  scope: { phase: "implement", operation: "claude-turn", round: 1 },
658
608
  capability: "claude",
659
609
  method: "run-turn",
660
610
  target: input.cycleId,
661
- payload: input.ticket,
611
+ payload: input.input.ticket.text,
662
612
  units: 1,
663
613
  });
664
614
  if (turn.kind !== "completed")
@@ -668,29 +618,29 @@ export async function developTicket(
668
618
  reason: "The Claude turn did not complete.",
669
619
  evidenceId: "claude-turn",
670
620
  };
671
- const gate = await decisionGate({
621
+ const decision = await waitForDecision({
672
622
  gateId: "review-1",
673
623
  kind: "approval",
674
624
  prompt: "Review the work of the Claude worker.",
675
625
  });
676
- if (gate.kind !== "opened")
626
+ if (decision.decision !== "approved")
677
627
  return {
678
628
  kind: "blocked",
679
629
  cycleId: input.cycleId,
680
- reason: "The review gate did not open.",
630
+ reason: "The operator did not approve the work.",
681
631
  evidenceId: "review-1",
682
632
  };
683
633
  return {
684
- kind: "waiting_for_decision",
634
+ kind: "handoff_requested",
685
635
  cycleId: input.cycleId,
686
- decisionId: gate.decisionId,
636
+ promotionId: `cloving-${input.cycleId}`,
687
637
  };
688
638
  }
689
639
  ```
690
640
 
691
- In this example, an approval completes the run and a denial ends it. `workflows/develop-ticket.ts` also starts one more round after a denial with a feedback text.
641
+ In this example, an approval completes the run and a denial ends it. A copy of `templates/develop/develop.ts` configured for person review and local-branch delivery also supports repair rounds after a denial with feedback.
692
642
 
693
- New workflows can await a decision in the same call:
643
+ A workflow can also wait for a decision without requesting an effect:
694
644
 
695
645
  ```ts
696
646
  import { waitForDecision } from "cloving/workflows/steps/wait-for-decision";
@@ -710,7 +660,7 @@ export async function review(input: { cycleId: string }) {
710
660
  }
711
661
  ```
712
662
 
713
- `waitForDecision` accepts the same request as `decisionGate` and returns `{ decision, answer }`. The decision is `approved`, `denied`, `answered` or `expired`. An optional `expiresAt` resumes the wait with `expired` and `answer: null`. The SDK hook survives daemon restarts and replay. Gate IDs belong to a run, so different runs can use the same gate ID. The existing questions, decision commands and binding values apply; dropping the run cancels the wait. `waitForDecision` is also exported by `cloving/workflows`.
663
+ `waitForDecision` accepts `{ gateId, kind, prompt, expiresAt? }` and returns `{ decision, answer }`. The decision is `approved`, `denied`, `answered` or `expired`. An optional `expiresAt` resumes the wait with `expired` and `answer: null`. The SDK hook survives daemon restarts and replay. Gate IDs belong to a run, so different runs can use the same gate ID. The existing questions, decision commands and binding values apply; dropping the run cancels the wait. `waitForDecision` is also exported by `cloving/workflows`.
714
664
 
715
665
  Use `sleep({ seconds })` inside a workflow to pause between short outside-state checks. Whole seconds from 1 through 86400 are accepted; other requests reject with `invalid-sleep-seconds` before any wait. Import it from `cloving/workflows` or `cloving/workflows/steps/sleep`. It uses the SDK workflow timer and consumes no protected effect units or slots.
716
666
 
@@ -842,9 +792,24 @@ Replace that call with `mergeByPerson({ pull: pull, check: "beforeMerge" })` to
842
792
 
843
793
  Both steps use the existing GitHub `merge` worker method and one protected effect unit. The candidate declaration must include the `github` capability and `methods: { "github": ["merge"] }`. The step subpaths and `cloving/workflows` export the step functions. Import the types `PullRequest`, `MergeRequest` and `MergeResult` from `cloving/workflows`. Fake scenarios give worker results in `effects["github merge"]` and person decisions in `decisions`.
844
794
 
845
- The workflow tests run the workflow function with a fake step bridge (`test/develop-workflow-fixture.ts`). The fixture resolves `cloving/workflows` to the files of `src`, records each effect request and gate request, and gives the results of a scenario. `test/develop-ticket-workflow.test.ts` and `test/develop-issue-workflow.test.ts` use it.
795
+ To show a file on a pull request, for example a demo video, a worker turn writes the file into the folder in `CLOVING_ATTACHMENTS_DIRECTORY`. Each turn of a run gets the same folder, outside the work tree. Then the workflow asks for the GitHub method `attach-asset`:
846
796
 
847
- Use `cloving workflows list` to inspect bundled, project and user workflows without a service. `--json` prints an array with `scope`, `workflowId`, `file`, `admitted`, `codes` and each valid parsed declaration. Invalid declarations have a null ID. Inspection uses the same folder admission and compiler as startup in a disposable project directory.
797
+ ```ts
798
+ const attached = await protectedEffect({
799
+ scope: { phase: "pull-request", operation: "github-attach-demo", round: 1 },
800
+ capability: "github",
801
+ method: "attach-asset",
802
+ target: runTarget,
803
+ payload: JSON.stringify({ number: pull.number, name: "demo.mp4", release: "pr-demos", comment: "Demo of the change." }),
804
+ units: 1,
805
+ });
806
+ ```
807
+
808
+ The method uploads the file as an asset of the release `release`, with the asset name `pr-<number>-<name>`. Then it creates or updates one comment on the pull request with a link to the asset, so a second call adds no second comment. When the release does not exist, the method creates it as a pre-release that is not the latest release. `name` is a file name with the extension `.mp4`, `.webm` or `.png`. The file must be a regular file of at most 100 MB, and a symbolic link is refused. `release` has lowercase letters, digits and hyphens, and it cannot start with `v` and a digit, so it never matches a version tag. The comment text must pass the same privacy check as issue texts. The failure reasons are `invalid-payload`, `attachment-not-available`, `attachment-too-large` and the usual GitHub reasons. The candidate declaration must include `methods: { "github": ["attach-asset"] }`.
809
+
810
+ The template tests use `fakeStepBridge` from `cloving/workflows/testing` to record effect and gate requests and supply fake results. `templates/develop/develop.test.ts` exercises the develop template through that public testing API.
811
+
812
+ Use `cloving workflows list` to inspect project and user workflows without a service. `--json` prints an array with `scope`, `workflowId`, `file`, `admitted`, `codes` and each valid parsed declaration. Invalid declarations have a null ID. Inspection uses the same folder admission and compiler as startup in a disposable project directory.
848
813
 
849
814
  Put tests beside each folder workflow as `<name>.test.ts`, then run `cloving workflows test <workflow-id>`. Omit the ID to run all available project and user workflow tests. Both commands accept `--repository <directory>`. The Node test runner prints its results and supplies the exit status. Unknown IDs report `unknown-workflow`; known workflows without tests report `workflow-test-missing`. Neither needs a running service.
850
815
 
@@ -877,11 +842,11 @@ await test("develop uses the fake worker result", async () => {
877
842
  });
878
843
  ```
879
844
 
880
- Each scenario runs in an isolated Node process. `effects` maps `"<capability> <method>"` to result queues; `gate` supplies a decision-gate result, `effects.handoff` supplies handoff results, `waits` supplies run-wait outcomes, `decisions` supplies `{ decision, answer }` results for `waitForDecision` in call order, and `decision` supplies the workflow's second argument. A missing `waitForDecision` result throws `no-scenario-result`. Sleep requests are recorded in order and complete immediately in both testing APIs, without consuming the simulated effect budget. An optional `effectLimit` simulates a budget and adds `spent` to the result. Missing effect or gate results return `unavailable`. For tests that import the workflow directly, `using bridge = fakeStepBridge(scenario)` installs the same fake bridge until disposal and exposes `requests` and `spent`. It refuses to replace an active host bridge. The test command resolves public Cloving imports from its own package, including a global installation, without adding a package to the consumer repository.
845
+ Each scenario runs in an isolated Node process. `effects` maps `"<capability> <method>"` to result queues; `effects.handoff` supplies handoff results, `waits` supplies run-wait outcomes, and `decisions` supplies `{ decision, answer }` results for `waitForDecision` in call order. A missing `waitForDecision` result throws `no-scenario-result`. Sleep requests are recorded in order and complete immediately in both testing APIs, without consuming the simulated effect budget. An optional `effectLimit` simulates a budget and adds `spent` to the result. Missing effect results return `unavailable`. For tests that import the workflow directly, `using bridge = fakeStepBridge(scenario)` installs the same fake bridge until disposal and exposes `requests` and `spent`. It refuses to replace an active host bridge. The test command resolves public Cloving imports from its own package, including a global installation, without adding a package to the consumer repository.
881
846
 
882
- The four built-in registrations (`develop-ticket`, `develop-issue`, `develop-prd` and `develop-prompt`) keep their existing input contracts and resolvers.
847
+ There are no built-in registrations. Workflow IDs are available to project and user declarations.
883
848
 
884
- For a repository or user folder workflow, use one `<name>.ts` file with one exported workflow function. Put one `<name>.declaration.json` file beside it. Function names and workflow IDs must be unique across the folders and bundled workflows.
849
+ For a repository or user folder workflow, use one `<name>.ts` file with one exported workflow function. Put one `<name>.declaration.json` file beside it. Function names and workflow IDs must be unique across the project and user folders.
885
850
 
886
851
  Discovery considers files in the folder root and ignores `.d.ts` and `.test.ts` files. Put local TypeScript helpers in subfolders: for example, `develop.ts` can import `./develop/prompts.ts`. Helpers can import further `.ts` files through `./` paths within those subfolders and need no workflow function or declaration. Imports with parent traversal, absolute paths or a `node_modules` component are refused, as are package imports outside the public `cloving/workflows` modules.
887
852
 
@@ -916,13 +881,31 @@ The declaration has two fields: `workflow` contains the workflow declaration, an
916
881
 
917
882
  The ID accepts 1–64 letters, digits or hyphens. The effect limit is 1–100; capabilities contain one or more of `claude`, `github` and `command`. The input byte limit is 1–1048576, subject to the service's own limit. Fields accept nonempty strings, integers with optional inclusive bounds, booleans, or tickets. Fields are required unless `optional` is `true`; unknown fields are rejected. Bounds apply only to integers.
918
883
 
919
- A declaration can have one `"ticket": { "type": "ticket" }` field, named `ticket`. Submit its ID as a string. When it is the only required field, use `cloving run <workflow-id> --ticket 312` or `--next`. You can also use `--input ticket.json` with `{"ticket":"312"}`; include every other required field in that file. At admission, the daemon reads the configured ticket command and replaces the ID with `{ "id": "312", "text": "# ..." }` inside the workflow's `input`. `--next` selects the ID through the configured next command. Missing sources keep the `ticket-source-not-configured` and `next-source-not-configured` refusals. The `Needs #N` dependency rule and `ticket-active` refusal apply as for `develop-issue`. Active tickets are checked within each workflow, so different workflows can work on the same ticket. Doctor requires `ticket-command` for these declarations, and the watch form labels the field **Ticket ID**.
884
+ A declaration can have one `"ticket": { "type": "ticket" }` field, named `ticket`. Submit its ID as a string. When it is the only required field, use `cloving run <workflow-id> --ticket 312` or `--next`. You can also use `--input ticket.json` with `{"ticket":"312"}`; include every other required field in that file. At admission, the daemon reads the configured ticket command and replaces the ID with `{ "id": "312", "text": "# ..." }` inside the workflow's `input`. `--next` selects the ID through the configured next command. Missing sources keep the `ticket-source-not-configured` and `next-source-not-configured` refusals. The `Needs #N` dependency rule and `ticket-active` refusal apply as for `develop`. Active tickets are checked within each workflow, so different workflows can work on the same ticket. Doctor requires `ticket-command` for these declarations, and the watch form labels the field **Ticket ID**.
920
885
 
921
886
  Optional `commands` lists distinct names from `CLOVING_COMMANDS`; executable paths and arguments belong only in the operator setting. The `command` capability requires at least one name. Registration refuses an unknown name with `command-unknown`. The execution pin retains these names with each run, and authority refuses `command` effects whose `run:<name>` method is absent from that run's pinned list with `command-not-declared`. Reordering names preserves the pin; changing names changes it. Omitted and empty lists preserve legacy pins.
922
887
 
923
- Optional `commandWaits` currently supports declaration validation and execution pinning only; the polling helper and separate time allowance are not implemented yet. It maps names of 1–64 ASCII letters, digits or hyphens to entries containing exactly `command`, `maximumWaitSeconds` and `pollEverySeconds`. The command must be declared in `commands`, configured in `CLOVING_COMMANDS` and permitted by the `command` capability. Maximum wait is an integer from 60 through 2,592,000 seconds; polling interval is an integer from 60 through 86,400 seconds and cannot exceed that maximum. For example, `"commandWaits": { "team-review": { "command": "review-state", "maximumWaitSeconds": 2592000, "pollEverySeconds": 3600 } }` pins that named permission. Reordering entries preserves the execution pin; changing a name, command, duration or interval changes it and refuses incompatible resumption. Legacy runs retain their original pin without wait permission. Ordinary `runCommand` calls still spend effect units, including calls to a command named in this map. Operators must choose read-only, repeat-safe checks; command execution does not enforce read-only access.
888
+ Optional `commandWaits` declares named command checks outside the ordinary effect budget. Internal `HostPorts.commandWait` methods open a wait with serialized input, request its next check and read its durable state. Authority admits checks from the pinned declaration and recorded schedule, permits one in-flight check, and schedules the next check from settlement time. Checks use the command worker and operation journal, with each process bounded by the shorter of its command time limit and the remaining wait duration. Pending output is a JSON object with `ready: false`; `ready: true` completes with the optional `value` or `null`. Command failure, interruption or malformed output fails the wait without retry. Restart preserves the deadline, schedule and results. Expiry continues while paused or stopped and requests that an in-flight check stop; dropping the run also requests a stop. Status JSON includes `commandWaits` in both run details and list summaries. Each entry shows its name, command, state, declared `maximumWaitSeconds`, `startedAt`, `deadline`, `nextCheckAt`, `checkCount`, `remainingSeconds` and terminal `reason`. Before opening, its state is `not-started`, its times are null and the full allowance remains. Active countdowns round up to whole seconds and stop at zero; early settlement freezes the remaining time. Plain status, watch cards and run details show these times beside the ordinary effect budget. Watch refreshes quiet waits between polls and retains active runs beyond one week. Wait data excludes command input and output.
889
+
890
+ The map accepts names of 1–64 ASCII letters, digits or hyphens, with entries containing exactly `command`, `maximumWaitSeconds` and `pollEverySeconds`. The command must be declared in `commands`, configured in `CLOVING_COMMANDS` and permitted by the `command` capability. Maximum wait is an integer from 60 through 2,592,000 seconds; polling interval is an integer from 60 through 86,400 seconds and cannot exceed that maximum. For example, `"commandWaits": { "team-review": { "command": "review-state", "maximumWaitSeconds": 2592000, "pollEverySeconds": 3600 } }` pins that named permission. Reordering entries preserves the execution pin; changing a name, command, duration or interval changes it and refuses incompatible resumption. Legacy runs retain their original pin without wait permission. Ordinary `runCommand` calls still spend effect units, including calls to a command named in this map. Operators must choose read-only, repeat-safe checks; command execution does not enforce read-only access.
924
891
 
925
- Internal command delivery supports an earlier absolute deadline in preparation for polling waits. An attempt uses the shorter of `CLOVING_COMMAND_SECONDS` and the remaining milliseconds, refuses to spawn at or after expiry, and reports `command-wait-timeout` if it settles too late. A recorded result still replays after expiry; an unfinished journaled command retains `command-interrupted` recovery. This internal cap is not exposed through workflow requests and supplies no budget exemption. Durable polling admission, scheduling and deadline enforcement at authority commit remain pending.
892
+ Internal command delivery accepts the wait's absolute deadline. An attempt uses the shorter of `CLOVING_COMMAND_SECONDS` and the remaining milliseconds, refuses to spawn at or after expiry, and reports `command-wait-timeout` if it settles too late. A recorded result still replays after expiry; authority accepts readiness only when it records the result before the wait's deadline. An unfinished journaled command retains `command-interrupted` recovery. This internal cap is not exposed through ordinary workflow command requests.
893
+
894
+ Use `waitForCommand({ name, input })` for a declared command wait, imported from `cloving/workflows` or `cloving/workflows/steps/wait-for-command`:
895
+
896
+ ```ts
897
+ import { waitForCommand } from "cloving/workflows/steps/wait-for-command";
898
+
899
+ const outcome = await waitForCommand({
900
+ name: "team-review",
901
+ input: { change: 42 },
902
+ });
903
+ if (outcome.kind === "ready") return outcome.value;
904
+ ```
905
+
906
+ The request accepts only a declared literal `name` and JSON-serializable `input`. Extra fields, including callbacks, executables, arguments, deadlines and exemptions, are refused before dispatch. The step returns a terminal result: `{ kind: "ready", value }`, `{ kind: "timed-out", reason: "command-wait-timeout" }` or `{ kind: "failed", reason }`. Missing hosts return `kind: "unavailable"`; unknown waits and invalid requests return `kind: "refused"` with an explicit reason. Pending checks stay inside the workflow loop and never reach its caller.
907
+
908
+ The first check is immediate. Each later check is due at the previous settlement time plus the declared interval. The workflow uses durable SDK suspension between checks and wakes at the earlier of the next check and the original deadline. The deadline continues through host downtime and pauses; restart preserves it and never catches up missed checks. No check starts at or after the deadline, no automatic SDK retry repeats a failed check, and wait checks spend no ordinary effect units. Each name identifies one wait per run: identical input joins it and changed input is refused. The operator must configure a read-only check command that is safe to run again; Cloving does not enforce read-only filesystem or network access.
926
909
 
927
910
  Use `runCommand` inside a workflow to request a named command:
928
911
 
@@ -942,7 +925,39 @@ The daemon starts the operator command without a shell in the repository folder
942
925
 
943
926
  The journal records a claim before starting the process. Completed effects replay their stored result after restart. A claimed effect without a result fails with `command-interrupted` after restart and never starts again, including when the earlier process may have written data. Each logical operation starts at most one command; use a new operation scope for a new invocation. The watch run page and `cloving status <run>` show each command name, state, exit status and duration.
944
927
 
945
- Optional `handoffs` lists distinct registered workflow IDs. Registration refuses unknown targets. The execution pin retains these permissions with each run: target order does not affect the pin, while adding or removing a target changes it. Omitted and empty lists keep existing pins. Stored permissions survive restart and retained workflow versions. The built-in `develop-prd` declares `develop-issue` as its only handoff target and calls it after creating an issue; the other built-in workflows declare none. A refused PRD handoff adds `cloving: ready` for the queue and records the refusal in the PRD run's outcome.
928
+ `cloving red-green` checks the changed tests of a commit. It reads `{"head":"<full commit ID>"}` on standard input in the repository folder. The base is the merge base of that commit and `refs/remotes/origin/HEAD`. Configure `checks.redGreen` in `.cloving/config.json`:
929
+
930
+ ```json
931
+ {
932
+ "version": 1,
933
+ "checks": {
934
+ "redGreen": {
935
+ "test": ["node", "--test"],
936
+ "testFiles": ["test/"],
937
+ "prepare": ["npm", "ci", "--ignore-scripts"]
938
+ }
939
+ }
940
+ }
941
+ ```
942
+
943
+ The daemon maps this object to `CLOVING_RED_GREEN`. An environment value takes priority. For direct use, set `CLOVING_RED_GREEN` to the same JSON object. `test` is an argument array. The tool appends the added or changed file paths under the `testFiles` prefixes. It excludes deleted files. `prepare` is optional and runs before each test command. Optional `assertionPattern` and `skipPattern` are regular expression strings. The defaults are `ERR_ASSERTION` and `# SKIP\b`, which match non-terminal `node --test` output.
944
+
945
+ Register the tool in `CLOVING_COMMANDS` with the absolute path of the installed executable, for example `{"red-green":["/opt/cloving/bin/cloving","red-green"]}`. Declare `red-green` in the workflow's `commands` list. A workflow can then call `runCommand` with `name: "red-green"` and `input: { head: commitId }`. Increase `CLOVING_COMMAND_SECONDS`, for example to `600`, to allow both preparation and test runs. This setting also bounds each preparation or test command inside the tool.
946
+
947
+ The red run uses a detached temporary worktree at the base with only the selected tests restored from the head. The green run uses another detached worktree at the head. Both runs use the same test paths. The tool removes each tree after the run, a command failure, a timeout, SIGINT or SIGTERM. Cleanup also runs after the operator stops the command or its process group. It preserves the repository folder's branch, index and files. The commands run as the current user.
948
+
949
+ The tool prints one JSON object with `verdict`, `base`, `head`, `files` and `output`. The output contains the last 16,000 characters from the command that decides the verdict. Successful preparation logs do not supply assertion or skip evidence. With no selected tests, the verdict is `no-test-change` and no command runs. Otherwise, both runs occur. The first applicable rule decides:
950
+
951
+ 1. Preparation fails in either run: `prepare-failed`.
952
+ 2. Either run matches the skip pattern: `skipped-test`.
953
+ 3. The red run succeeds: `false-red`.
954
+ 4. The red run is interrupted, times out, or fails without the assertion pattern: `red-not-assertion`.
955
+ 5. The green run fails: `green-failed`.
956
+ 6. Otherwise: `accepted`.
957
+
958
+ Every verdict exits with status 0 so a workflow can send the result to a fix turn. Invalid input, invalid settings and git errors exit with status 1. This tool does not change the develop template or the full-suite checks on the head.
959
+
960
+ Optional `handoffs` lists distinct registered workflow IDs. Registration refuses unknown targets. The execution pin retains these permissions with each run: target order does not affect the pin, while adding or removing a target changes it. Omitted and empty lists keep existing pins. Stored permissions survive restart and retained workflow versions. The `idea-to-issue` template declares `develop` as its only handoff target and calls it after creating an issue. Both workflows must be copied and admitted. A refused PRD handoff adds `cloving: ready` for the queue and records the refusal in the PRD run's outcome.
946
961
 
947
962
  Use `handoff` inside a workflow to submit input to a declared target:
948
963
 
@@ -950,7 +965,7 @@ Use `handoff` inside a workflow to submit input to a declared target:
950
965
  import { handoff } from "cloving/workflows/steps/handoff";
951
966
 
952
967
  const runId = await handoff({
953
- workflowId: "develop-issue",
968
+ workflowId: "develop",
954
969
  input: { ticket: "CLV-123" },
955
970
  });
956
971
  ```
@@ -979,7 +994,7 @@ The compiled SDK step uses durable retries and its original start time, so resta
979
994
 
980
995
  Optional `stages` contains 1–12 entries in board order. Each entry has a unique `name` (1–64 ASCII letters, digits or hyphens), a unique `label` (1–40 printable characters on one line, without outer spaces), and any combination of `operations`, `gateKinds` and `gateIds`. At least one selector array must be nonempty; the others may be omitted or empty. Operations match the `scope.operation` passed to `protectedEffect`; gate IDs match the `gateId` recorded when a gate opens. Both use 1–128 ASCII letters, digits or `._:/-`. Gate kinds are `approval` and `question`. Selectors cannot repeat within an array or belong to two stages of the same selector type within one workflow. Different selector types may share text, and different workflows may reuse IDs. Unknown fields and labels `Other`, `Done` and `Stopped` are rejected.
981
996
 
982
- For declared stages, the board and its `data.json` response use the latest committed `effect.requested` or `gate.opened` sequence, preserving that event's start time. Effect requests select by operation. Gate openings first search every stage for an exact, case-sensitive gate ID match, regardless of declaration order; without one, they fall back to the gate kind. Unmatched events and runs without a relevant event use Other. Unused valid IDs are allowed. Decisions and worker output do not advance a card; later requests or gate openings can move it back. Declared labels are followed by Other, Done and Stopped. Existing terminal retention rules take precedence. Unstaged workflows and `develop-issue` keep their existing columns and placement. Declarations load at service startup; stages provide display metadata and grant no capabilities.
997
+ For declared stages, the board and its `data.json` response use the latest committed `effect.requested` or `gate.opened` sequence, preserving that event's start time. Effect requests select by operation. Gate openings first search every stage for an exact, case-sensitive gate ID match, regardless of declaration order; without one, they fall back to the gate kind. Unmatched events and runs without a relevant event use Other. Unused valid IDs are allowed. Decisions and worker output do not advance a card; later requests or gate openings can move it back. Declared labels are followed by Other, Done and Stopped. Existing terminal retention rules take precedence. Declared stages apply regardless of the workflow ID. Unstaged workflows keep their existing columns and placement. Declarations load at service startup; stages provide display metadata and grant no capabilities.
983
998
 
984
999
  For example, a `review-flow` declaration can distinguish successive approval gates without another workflow or handoff step:
985
1000
 
@@ -1019,9 +1034,19 @@ A declared workflow can include an interval schedule:
1019
1034
 
1020
1035
  The first run starts after one interval. Slots retain increasing numbers in private Cloving state (`state/schedules.json`); each submission uses the operator command ID `schedule:<workflowId>:<slot>`. Restart preserves the next boundary and retries an unacknowledged submission with its saved input and command ID. Missed intervals coalesce into the latest due slot rather than a burst of catch-up runs. Changing the interval starts a fresh interval while retaining slot numbers and any active run.
1021
1036
 
1022
- An earlier scheduled run blocks later scheduled slots while queued, running, waiting for a decision or paused. Each overlap records a `schedule.skipped` event on that earlier run, with `workflowId` and `slot`, without changing its status or observation. Manual runs remain independent. The `develop-issue` queue continues to use `CLOVING_QUEUE_SECONDS`.
1037
+ An earlier scheduled run blocks later scheduled slots while queued, running, waiting for a decision or paused. Each overlap records a `schedule.skipped` event on that earlier run, with `workflowId` and `slot`, without changing its status or observation. Manual runs remain independent. The ticket queue continues to use `CLOVING_QUEUE_SECONDS`.
1038
+
1039
+ Use `cloving schedule [--json]` to list workflow IDs, intervals, state, failure counts, slots, next run times and active runs. `cloving schedule pause <workflowId> [--json]` stops new scheduled runs without interrupting an active run or recording skips. `cloving schedule resume <workflowId> [--json]` clears the failure count and starts the next run one interval later, retaining increasing slot numbers. Repeating pause or resume leaves the current state and timing unchanged. Paused and stopped schedules survive restarts and interval changes.
1040
+
1041
+ `cloving status` shows each schedule after the queue lines, for example `Schedule review-queue: every 300 s, active, next run at 2026-10-14T12:05:00.000Z, 0 failures in a row`. Paused schedules show `paused` without a next run time; stopped schedules show `stopped`, the stop time and the failure count. The watch board shows the same information on the workflow's board and refreshes it on the next poll. Status times use ISO timestamps; watch times use the browser's local date and time.
1023
1042
 
1024
- This first scheduling slice does not yet implement schedule pause/resume commands, stopping and notification after repeated failures, or schedule displays and scheduled-run marks in status and watch. Schedule settings load at startup. A scheduler transport or journal failure stops scheduling and writes a diagnostic; reconcile the state and restart to retry a pending slot. Full product admission remains subject to the external verification policy.
1043
+ Status JSON includes `schedules` entries with `workflowId`, `everySeconds`, `state`, `failuresInRow`, `nextAt` and `stoppedAt`. Times are epoch milliseconds or `null`; paused and stopped schedules have `nextAt: null`. The field is absent when no schedules are configured. A scheduler that is not running yet is shown as `schedules: { "status": "unavailable" }` and `Schedules: unavailable` in status and watch.
1044
+
1045
+ Runs admitted by a schedule show `scheduled 12` for slot 12 on the status run line, in run status, on the watch card and in the watch run detail. Their JSON summary and detail include `scheduled: { "slot": 12 }`. Manual runs have no scheduled mark.
1046
+
1047
+ Three consecutive failed scheduled runs stop a schedule. A completed run with outcome `blocked` counts as a failure; cancellation leaves the count unchanged, and any other completion clears it. With `CLOVING_NOTIFY_COMMAND` configured, each stop sends a `schedule-stopped` notification with the three failed run IDs and the resume command; its `runId` names the third failed run.
1048
+
1049
+ Schedule settings load at startup. A scheduler transport or journal failure stops scheduling and writes a diagnostic; reconcile the state and restart to retry a pending slot. Full product admission remains subject to the external verification policy.
1025
1050
 
1026
1051
  Startup retains each complete compiled project under `workflow-bundles` in private daemon state, beside the generated `project` directory. Each content-addressed snapshot includes workflow sources, declarations, registration manifests, all compiler artifacts, and the installed dependency graph and Node identity. Snapshots bind to the canonical repository and survive later source edits or removal. Storage lookup validates every captured file and returns `pinned-workflow-unavailable` for missing or changed bytes; startup refuses reuse of a matching damaged snapshot without repairing it. No retained generation is deleted automatically. Before Local World starts, the daemon loads the retained generations needed by unfinished runs. Their starts, replays and continuations use the recorded bundle, including after workflow removal; new submissions use current registrations. Duplicate answers and replay preserve effect receipts and spending.
1027
1052
 
@@ -1032,7 +1057,7 @@ At daemon startup, Cloving also checks these folders on both macOS and Linux:
1032
1057
  - Project: `.cloving/workflows` under the repository selected by `cloving start --repository REPOSITORY` (the current repository by default).
1033
1058
  - User: `$XDG_CONFIG_HOME/cloving/workflows` when `XDG_CONFIG_HOME` is absolute; otherwise `$HOME/.config/cloving/workflows`. macOS uses these same XDG rules.
1034
1059
 
1035
- Missing folders are left absent. Discovery reads top-level `.ts` files, excluding `.d.ts`, and requires a matching `<name>.declaration.json`. Unlike the bundled declaration above, an operator declaration wraps the workflow metadata and lists the effect methods it may request:
1060
+ Missing folders are left absent. Discovery reads top-level `.ts` files, excluding `.d.ts`, and requires a matching `<name>.declaration.json`. A project or user declaration wraps the workflow metadata and lists the effect methods it may request:
1036
1061
 
1037
1062
  ```json
1038
1063
  {
@@ -1051,7 +1076,7 @@ Missing folders are left absent. Discovery reads top-level `.ts` files, excludin
1051
1076
 
1052
1077
  Use one exported async workflow function with `"use workflow"` and the public `cloving/workflows` helpers. Each capability requires a nonempty list of distinct method names. Declaration, source and actual SDK compilation must pass admission before registration. Declaring a method grants no execution authority; the broker still enforces each run's capabilities and budget. Submit inputs with `cloving run project-review --input input.json`.
1053
1078
 
1054
- Admitted project and user workflows appear beside the bundled registrations. A refused neighbor does not stop valid workflows from loading. `cloving status --json` exposes `workflowRefusals`; status and watch show each refusal's scope, safe file label and codes without its source text. These codes identify the failed check:
1079
+ Only admitted project and user workflows are registered. A refused neighbor does not stop valid workflows from loading. `cloving status --json` exposes `workflowRefusals`; status and watch show each refusal's scope, safe file label and codes without its source text. These codes identify the failed check:
1055
1080
 
1056
1081
  | Codes | Meaning |
1057
1082
  | --- | --- |
@@ -1059,7 +1084,7 @@ Admitted project and user workflows appear beside the bundled registrations. A r
1059
1084
  | `forbidden-import`, `missing-export` | Import outside the public helper surface, or an unavailable named export. |
1060
1085
  | `unsupported-source`, `dynamic-effect`, `direct-effect` | Unsupported source form, a nonliteral effect request, or a direct effect outside helpers. |
1061
1086
  | `undeclared-effect`, `effect-limit` | Requested method absent from the declaration, or statically known work exceeding the limit. |
1062
- | `workflow-conflict`, `bundled-name-reserved` | Conflicting basename, workflow ID or function name across operator files, or collision with a bundled registration. |
1087
+ | `workflow-conflict` | Conflicting basename, workflow ID or function name across project and user files. |
1063
1088
  | `unsafe-workflow-path`, `workflow-read-failed`, `workflow-source-changed` | Unsafe file or folder path, unreadable input, or input changed during capture. |
1064
1089
  | `compile-failed` | Candidate analysis or SDK compilation could not complete. |
1065
1090
 
@@ -1073,6 +1098,8 @@ The caller supplies imported symbol names, literal effect pairs (`null` represen
1073
1098
 
1074
1099
  ## Development of Cloving
1075
1100
 
1101
+ The terminal integration test uses `/usr/bin/python3` (Python 3.9 or newer) and its standard `pty` module to exercise a real terminal. No Python packages are needed.
1102
+
1076
1103
  The shell tests require both zsh at `/bin/zsh` and Bash at `/bin/bash`. macOS includes them. Linux contributors and CI runners must install both before setup; on Ubuntu, install the `zsh` and `bash` system packages. The fixtures exercise zsh 5.9 and Bash 3.2 or 5.2, including their real startup files; neither shell's tests are optional. `npm run check:setup` checks that both executables run and reports a missing prerequisite before compilation.
1077
1104
 
1078
1105
  ```sh
@@ -1085,7 +1112,7 @@ npm pack --ignore-scripts
1085
1112
 
1086
1113
  After a merge or branch update changes `package.json` or `package-lock.json`, rerun `npm ci --ignore-scripts` in the worktree before running checks. Copied `node_modules` can still contain the previous versions; the developer gate rejects a mismatch with the lockfile.
1087
1114
 
1088
- `npm pack` prints the file name of the tarball. Install it into a separate project with `npm install --ignore-scripts --omit=dev /absolute/path/to/TARBALL`, then run `./node_modules/.bin/cloving --version` or `./node_modules/.bin/cloving start`. The package includes the emitted CLI, start program, compiler and bundled workflows; startup uses the installed runtime dependencies. The package has no installation hooks. An import of `cloving/workflows` gives the step helpers `loadCycle`, `protectedEffect`, `decisionGate`, `waitForDecision`, `handoff`, `waitForRun` and `runCommand`, and starts no service.
1115
+ `npm pack` prints the file name of the tarball. Install it into a separate project with `npm install --ignore-scripts --omit=dev /absolute/path/to/TARBALL`, then run `./node_modules/.bin/cloving --version` or `./node_modules/.bin/cloving start`. The package includes the emitted CLI, start program, compiler and workflow templates; startup uses the installed runtime dependencies. The package has no installation hooks. An import of `cloving/workflows` gives the step helpers `loadCycle`, `protectedEffect`, `waitForDecision`, `handoff`, `waitForRun`, `runCommand`, `sleep` and `waitForCommand`, and starts no service.
1089
1116
 
1090
1117
  `npm run check` and `npm run test:concurrency` currently reject admission because the complete quality policy is not implemented. Setup checks are not product acceptance. State and retained releases will live outside the package installation; installing or updating the package does not activate a daemon or migrate state.
1091
1118
 
@@ -1095,6 +1122,8 @@ Run `npm run test:scale` on an otherwise idle machine to measure authority openi
1095
1122
 
1096
1123
  The gate uses the committed `quality/test-durations.json` record to start files with unknown durations first in path order, then recorded files from longest to shortest, breaking ties by path. Stale entries have no effect. The launcher passes the ordered list directly to Node’s programmatic test runner because CLI discovery sorts positional paths. The test inventory and sorted report stay the same. Run `npm run record:test-durations` to refresh the record after adding or changing tests, then commit the JSON. This runs the regular suite with the gate's worker count, timeout settings, isolated environment and V8 coverage, sums each file's top-level test and suite durations in seconds, and writes entries in path order after a successful complete run. Nested tests are not counted twice. Temporary coverage stays outside the repository and is removed afterward. The command accepts the same concurrency and time-factor settings as the gate.
1097
1124
 
1125
+ CI runs two duration-balanced shards for macOS and each Linux Node version. Only shard 1 runs the static checks. Each shard builds the package before testing so runtime declarations are available independently of other test files, then exports raw production coverage. A final job checks their joined coverage. The required checks remain `quality` and `quality_linux`. Without a shard setting, the local gate runs all checks and coverage as before.
1126
+
1098
1127
  The quality report includes elapsed time and the effective limit in milliseconds for each bounded command: npm inventory, clone detection, tests and coverage conversion. Commands using more than 80 percent of their limit produce a warning in the JSON report and on stderr after the report. Failed checks print the collected timings and warnings with the original error and a failing exit status. Warnings preserve a passing result. If your change made the check slower, address the warning in the same ticket.
1099
1128
 
1100
1129
  The watch scrolling tests launch an isolated headless Chrome process at desktop and phone widths. They require Chrome on the test machine. Run them with `node --test test/watch-scrolling.test.ts`. The fixture serves bundled Preact and board data over loopback and blocks external page resources.
@@ -1113,9 +1142,9 @@ Before a ticket report, commit your work and run `npm run check:clean`. It refus
1113
1142
 
1114
1143
  After merging dependency changes, run `npm ci --ignore-scripts` in the worktree before checking it. Copied dependencies can belong to an earlier lockfile; `check:clean` copies them unchanged. An `installed-lock-mismatch` requires refreshing that installation and rerunning the checks. If existing `dist/` output produces `generated-output-mismatch`, regenerate it with `npm run build` before rerunning `check:quality`.
1115
1144
 
1116
- Set `CLOVING_CHECK_TIME_FACTOR` to a whole number from 1 to 5 (default 1) to multiply the developer gate test and coverage command time limits, the inner hook check limit (15 seconds by default), and the installed hook limit (30 seconds by default). With factor 3, the hook limits are 45 and 90 seconds, respectively.
1145
+ Set `CLOVING_CHECK_TIME_FACTOR` to a whole number from 1 to 9 (default 1) to multiply the developer gate test and coverage command time limits, the inner hook check limit (15 seconds by default), and the installed hook limit (30 seconds by default). With factor 3, the hook limits are 45 and 90 seconds, respectively.
1117
1146
 
1118
- Set `CLOVING_TEST_CONCURRENCY` to a whole number from 1 to 8 to override the developer gate's test worker count. Without the setting, the gate uses one fewer worker than the available cores, with a minimum of 2 and a maximum of 4. macOS CI sets it to 3 and Ubuntu CI sets it to 4. Pull requests from branches of this repository run both jobs on local runners with the label `cloving-ci` (macOS arm64 and Linux arm64) with 8 workers; the local macOS runner accepts the macOS version of its machine. Invalid values fail with an error.
1147
+ Set `CLOVING_TEST_CONCURRENCY` to a whole number from 1 to 8 to override the developer gate's test worker count. Without the setting, the gate uses one fewer worker than the available cores, with a minimum of 2 and a maximum of 4. macOS CI sets it to 3 and Ubuntu CI sets it to 4. CI also sets `NODE_OPTIONS` to `--max-old-space-size=4096`, because the gate process needs about 2 GB of heap, and the hosted macOS runner gives only about 2 GB by default. Pull requests run on the same hosted runners. Pushes start CI only for `main` and `v*` tags. A new push to a pull request cancels the older CI runs of that pull request, and a new manual run cancels the older manual runs of its branch; runs of `main` and of tags are never cancelled. Invalid values fail with an error.
1119
1148
 
1120
1149
  Tests that stop a child process should await `stopChild` from `test/stop-child.ts`. Use `stopChildGroup` for a detached process group, including descendants whose leader has exited. Both helpers send `SIGTERM`, wait up to five seconds times `CLOVING_CHECK_TIME_FACTOR` for exit, then escalate to `SIGKILL`. When a test requires a hard crash or an unresponsive child, start that child with `NODE_V8_COVERAGE` omitted so a kill cannot interrupt its coverage recording. Keep coverage enabled for ordinary child runs and recovery runs.
1121
1150