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.
- package/README.md +235 -206
- package/dist/src/agent-harness-shell.d.ts +2 -1
- package/dist/src/agent-harness-shell.js +8 -5
- package/dist/src/authority/command-wait-checks.d.ts +8 -0
- package/dist/src/authority/command-wait-checks.js +88 -0
- package/dist/src/authority/command-wait-results.d.ts +15 -0
- package/dist/src/authority/command-wait-results.js +73 -0
- package/dist/src/authority/command-wait-view.d.ts +21 -0
- package/dist/src/authority/command-wait-view.js +34 -0
- package/dist/src/authority/command-waits.d.ts +39 -0
- package/dist/src/authority/command-waits.js +97 -0
- package/dist/src/authority/commands.js +22 -1
- package/dist/src/authority/dispatch-decision.d.ts +8 -0
- package/dist/src/authority/dispatch-decision.js +26 -1
- package/dist/src/authority/effect-requests.js +6 -3
- package/dist/src/authority/effect-results.js +4 -2
- package/dist/src/authority/history-state.d.ts +2 -0
- package/dist/src/authority/history-state.js +13 -1
- package/dist/src/authority/instants.d.ts +1 -0
- package/dist/src/authority/instants.js +21 -0
- package/dist/src/authority/reduction-state.d.ts +2 -0
- package/dist/src/authority/reduction-state.js +5 -0
- package/dist/src/authority/reduction.js +24 -0
- package/dist/src/authority/status-input.d.ts +2 -0
- package/dist/src/authority/status.d.ts +2 -0
- package/dist/src/authority/status.js +1 -0
- package/dist/src/authority/stop-sequence.d.ts +1 -0
- package/dist/src/authority/stop-sequence.js +2 -1
- package/dist/src/authority/transitions.d.ts +6 -4
- package/dist/src/authority/transitions.js +7 -0
- package/dist/src/broker/actor/authority-queries.d.ts +2 -1
- package/dist/src/broker/actor/authority-queries.js +14 -5
- package/dist/src/broker/actor/authority-receipts.js +1 -1
- package/dist/src/broker/actor/authority-settings.js +2 -2
- package/dist/src/broker/actor/authority-upgrades.d.ts +19 -2
- package/dist/src/broker/actor/authority-upgrades.js +7 -2
- package/dist/src/broker/actor/delivery-intents.js +2 -0
- package/dist/src/broker/actor/effect-delivery.d.ts +1 -1
- package/dist/src/broker/actor/effect-delivery.js +15 -2
- package/dist/src/broker/actor/effect-plan.js +11 -2
- package/dist/src/broker/actor/effect-queries.d.ts +4 -0
- package/dist/src/broker/actor/effect-queries.js +9 -1
- package/dist/src/broker/actor/effect-turn.js +2 -0
- package/dist/src/broker/actor/stop-plan.js +9 -3
- package/dist/src/broker/actor/stop-turn.d.ts +2 -0
- package/dist/src/broker/actor/stop-turn.js +24 -11
- package/dist/src/broker/actor/turn-draft.d.ts +1 -0
- package/dist/src/broker/actor/turn-draft.js +4 -0
- package/dist/src/broker/actor/turn-state.js +5 -1
- package/dist/src/broker/authority-admission.js +60 -0
- package/dist/src/broker/authority-restore.d.ts +2 -0
- package/dist/src/broker/authority-restore.js +35 -1
- package/dist/src/broker/command-wait-restore.d.ts +31 -0
- package/dist/src/broker/command-wait-restore.js +86 -0
- package/dist/src/broker/decision-restore.d.ts +1 -1
- package/dist/src/broker/decision-restore.js +1 -0
- package/dist/src/broker/effect-upgrade.d.ts +2 -0
- package/dist/src/broker/effect-upgrade.js +8 -2
- package/dist/src/cli/arguments.d.ts +13 -0
- package/dist/src/cli/arguments.js +42 -3
- package/dist/src/cli/chat-stores.d.ts +2 -0
- package/dist/src/cli/chat-stores.js +113 -0
- package/dist/src/cli/client.d.ts +4 -1
- package/dist/src/cli/client.js +9 -3
- package/dist/src/cli/command-requests.d.ts +17 -0
- package/dist/src/cli/command-requests.js +43 -0
- package/dist/src/cli/command-waits.d.ts +9 -0
- package/dist/src/cli/command-waits.js +51 -0
- package/dist/src/cli/commands.js +14 -41
- package/dist/src/cli/config-file.d.ts +2 -2
- package/dist/src/cli/config-file.js +4 -2
- package/dist/src/cli/doctor-workflows.d.ts +5 -2
- package/dist/src/cli/doctor-workflows.js +12 -7
- package/dist/src/cli/doctor.js +6 -9
- package/dist/src/cli/harness-probes.d.ts +2 -0
- package/dist/src/cli/harness-probes.js +1 -1
- package/dist/src/cli/harness-processes.d.ts +6 -0
- package/dist/src/cli/harness-processes.js +36 -0
- package/dist/src/cli/init-command.d.ts +9 -0
- package/dist/src/cli/init-command.js +52 -0
- package/dist/src/cli/init-prompt-command.d.ts +10 -0
- package/dist/src/cli/init-prompt-command.js +145 -0
- package/dist/src/cli/init-prompt.d.ts +35 -0
- package/dist/src/cli/init-prompt.js +74 -0
- package/dist/src/cli/init-selection.d.ts +13 -0
- package/dist/src/cli/init-selection.js +75 -0
- package/dist/src/cli/main.d.ts +2 -0
- package/dist/src/cli/main.js +37 -7
- package/dist/src/cli/mcp-server.d.ts +1 -0
- package/dist/src/cli/mcp-server.js +156 -0
- package/dist/src/cli/mcp-tools.d.ts +15 -0
- package/dist/src/cli/mcp-tools.js +80 -0
- package/dist/src/cli/render.d.ts +1 -1
- package/dist/src/cli/render.js +17 -30
- package/dist/src/cli/report-ci-jobs.d.ts +23 -0
- package/dist/src/cli/report-ci-jobs.js +103 -0
- package/dist/src/cli/report-ci-usage.d.ts +9 -0
- package/dist/src/cli/report-ci-usage.js +185 -0
- package/dist/src/cli/report-ci.d.ts +13 -0
- package/dist/src/cli/report-ci.js +74 -0
- package/dist/src/cli/report-closures.d.ts +6 -0
- package/dist/src/cli/report-closures.js +97 -0
- package/dist/src/cli/report-flow.d.ts +7 -0
- package/dist/src/cli/report-flow.js +122 -0
- package/dist/src/cli/report-github-reader.d.ts +29 -0
- package/dist/src/cli/report-github-reader.js +157 -0
- package/dist/src/cli/report-github.d.ts +15 -8
- package/dist/src/cli/report-github.js +131 -150
- package/dist/src/cli/report-operator.d.ts +3 -0
- package/dist/src/cli/report-operator.js +40 -0
- package/dist/src/cli/report-ready.d.ts +3 -0
- package/dist/src/cli/report-ready.js +96 -0
- package/dist/src/cli/report-text.d.ts +9 -0
- package/dist/src/cli/report-text.js +33 -0
- package/dist/src/cli/report.d.ts +1 -0
- package/dist/src/cli/report.js +104 -27
- package/dist/src/cli/runtime-arguments.d.ts +2 -1
- package/dist/src/cli/runtime-arguments.js +7 -2
- package/dist/src/cli/schedule-arguments.d.ts +14 -0
- package/dist/src/cli/schedule-arguments.js +26 -0
- package/dist/src/cli/schedule-render.d.ts +22 -0
- package/dist/src/cli/schedule-render.js +73 -0
- package/dist/src/cli/terminal-text.d.ts +3 -0
- package/dist/src/cli/terminal-text.js +28 -0
- package/dist/src/cli/usage-render.d.ts +1 -0
- package/dist/src/cli/usage-render.js +28 -1
- package/dist/src/cli/usage.d.ts +1 -1
- package/dist/src/cli/usage.js +50 -7
- package/dist/src/cli/watch-actions.js +2 -2
- package/dist/src/cli/watch-board-view.js +19 -2
- package/dist/src/cli/watch-board.d.ts +4 -2
- package/dist/src/cli/watch-board.js +53 -43
- package/dist/src/cli/watch-card-forms.d.ts +1 -1
- package/dist/src/cli/watch-card-forms.js +11 -10
- package/dist/src/cli/watch-client.d.ts +1 -1
- package/dist/src/cli/watch-client.js +2 -11
- package/dist/src/cli/watch-header-view.d.ts +0 -5
- package/dist/src/cli/watch-header-view.js +8 -20
- package/dist/src/cli/watch-model.d.ts +4 -1
- package/dist/src/cli/watch-model.js +17 -11
- package/dist/src/cli/watch-page.js +12 -14
- package/dist/src/cli/watch-phases.d.ts +12 -3
- package/dist/src/cli/watch-phases.js +68 -11
- package/dist/src/cli/watch-pr-board.js +1 -1
- package/dist/src/cli/watch-pr-command.d.ts +1 -0
- package/dist/src/cli/watch-pull-request.js +18 -8
- package/dist/src/cli/watch-reads.d.ts +2 -0
- package/dist/src/cli/watch-reads.js +17 -16
- package/dist/src/cli/watch-render.d.ts +14 -0
- package/dist/src/cli/watch-run-input.d.ts +0 -1
- package/dist/src/cli/watch-run-input.js +0 -13
- package/dist/src/cli/watch-server.js +6 -6
- package/dist/src/cli/watch-view.d.ts +0 -3
- package/dist/src/cli/watch-view.js +13 -13
- package/dist/src/cli.js +59 -5
- package/dist/src/command-wait.d.ts +4 -0
- package/dist/src/command-wait.js +45 -0
- package/dist/src/configuration-change.d.ts +7 -0
- package/dist/src/configuration-change.js +14 -0
- package/dist/src/configuration-schema.d.ts +9 -0
- package/dist/src/configuration-schema.js +6 -2
- package/dist/src/daemon/attachment-file.d.ts +6 -0
- package/dist/src/daemon/attachment-file.js +86 -0
- package/dist/src/daemon/attachments.d.ts +14 -0
- package/dist/src/daemon/attachments.js +17 -0
- package/dist/src/daemon/claude-recovery.d.ts +50 -0
- package/dist/src/daemon/claude-recovery.js +204 -0
- package/dist/src/daemon/claude-stream.d.ts +27 -0
- package/dist/src/daemon/claude-stream.js +63 -0
- package/dist/src/daemon/claude-turn.d.ts +11 -25
- package/dist/src/daemon/claude-turn.js +64 -81
- package/dist/src/daemon/claude-worker.d.ts +2 -1
- package/dist/src/daemon/claude-worker.js +124 -122
- package/dist/src/daemon/daemon-adapters.d.ts +2 -0
- package/dist/src/daemon/daemon-adapters.js +26 -2
- package/dist/src/daemon/daemon-loops.d.ts +3 -1
- package/dist/src/daemon/daemon-loops.js +3 -1
- package/dist/src/daemon/daemon.js +14 -6
- package/dist/src/daemon/github-attach.d.ts +2 -0
- package/dist/src/daemon/github-attach.js +149 -0
- package/dist/src/daemon/github-ci-filters.d.ts +6 -0
- package/dist/src/daemon/github-ci-filters.js +138 -0
- package/dist/src/daemon/github-ci-workflows.d.ts +10 -0
- package/dist/src/daemon/github-ci-workflows.js +148 -0
- package/dist/src/daemon/github-ci.js +22 -4
- package/dist/src/daemon/github-issue-methods.d.ts +2 -0
- package/dist/src/daemon/github-issue-methods.js +37 -2
- package/dist/src/daemon/github-merge-call.d.ts +2 -1
- package/dist/src/daemon/github-merge-call.js +10 -3
- package/dist/src/daemon/github-merge.js +52 -24
- package/dist/src/daemon/github-methods.js +12 -2
- package/dist/src/daemon/github-operation.d.ts +4 -0
- package/dist/src/daemon/github-operation.js +6 -0
- package/dist/src/daemon/github-worker.d.ts +4 -0
- package/dist/src/daemon/github-worker.js +6 -0
- package/dist/src/daemon/issue-queue.d.ts +1 -1
- package/dist/src/daemon/issue-queue.js +16 -11
- package/dist/src/daemon/notify-events.d.ts +6 -0
- package/dist/src/daemon/notify-events.js +84 -0
- package/dist/src/daemon/notify-journal.js +1 -1
- package/dist/src/daemon/notify-message.d.ts +4 -1
- package/dist/src/daemon/notify-message.js +36 -0
- package/dist/src/daemon/notify.d.ts +1 -1
- package/dist/src/daemon/notify.js +5 -77
- package/dist/src/daemon/operation-journal.d.ts +1 -0
- package/dist/src/daemon/queue-status.d.ts +9 -3
- package/dist/src/daemon/queue-status.js +17 -4
- package/dist/src/daemon/resume-index-lock.d.ts +13 -0
- package/dist/src/daemon/resume-index-lock.js +160 -0
- package/dist/src/daemon/resume-worktree.d.ts +7 -0
- package/dist/src/daemon/resume-worktree.js +29 -0
- package/dist/src/daemon/retrying-turn.d.ts +2 -12
- package/dist/src/daemon/retrying-turn.js +98 -172
- package/dist/src/daemon/schedule-control.d.ts +26 -0
- package/dist/src/daemon/schedule-control.js +110 -0
- package/dist/src/daemon/schedule-journal.d.ts +2 -15
- package/dist/src/daemon/schedule-journal.js +67 -4
- package/dist/src/daemon/ticket-registration.d.ts +2 -7
- package/dist/src/daemon/ticket-registration.js +15 -81
- package/dist/src/daemon/turn-attempt-journal.d.ts +38 -0
- package/dist/src/daemon/turn-attempt-journal.js +136 -0
- package/dist/src/daemon/turn-attempts.d.ts +47 -0
- package/dist/src/daemon/turn-attempts.js +166 -0
- package/dist/src/daemon/turn-report.d.ts +8 -1
- package/dist/src/daemon/turn-report.js +39 -0
- package/dist/src/daemon/work-tree.d.ts +9 -0
- package/dist/src/daemon/work-tree.js +20 -0
- package/dist/src/daemon/worker-profile.d.ts +8 -0
- package/dist/src/daemon/worker-profile.js +40 -0
- package/dist/src/daemon/workflow-schedules.d.ts +3 -0
- package/dist/src/daemon/workflow-schedules.js +98 -45
- package/dist/src/daemon/worktree-processes.d.ts +9 -0
- package/dist/src/daemon/worktree-processes.js +151 -0
- package/dist/src/doctor-report.d.ts +3 -5
- package/dist/src/doctor-report.js +6 -13
- package/dist/src/harness-start.d.ts +15 -0
- package/dist/src/harness-start.js +37 -0
- package/dist/src/host/command-wait.d.ts +38 -0
- package/dist/src/host/command-wait.js +115 -0
- package/dist/src/host/start-delivery.d.ts +5 -7
- package/dist/src/host/start-delivery.js +3 -15
- package/dist/src/host/step-bridge-host.d.ts +2 -0
- package/dist/src/host/step-bridge-host.js +21 -0
- package/dist/src/operation-identity.d.ts +1 -0
- package/dist/src/operation-identity.js +4 -0
- package/dist/src/private-config.schema.json +40 -0
- package/dist/src/project-config.schema.json +40 -0
- package/dist/src/project-settings.d.ts +2 -2
- package/dist/src/project-settings.js +3 -1
- package/dist/src/queue-spend.d.ts +4 -0
- package/dist/src/queue-spend.js +21 -0
- package/dist/src/relay/relay-service.d.ts +3 -0
- package/dist/src/relay/relay-service.js +5 -3
- package/dist/src/report-ci.d.ts +164 -0
- package/dist/src/report-ci.js +32 -0
- package/dist/src/report-effects.d.ts +15 -0
- package/dist/src/report-effects.js +212 -0
- package/dist/src/report-flow-types.d.ts +38 -0
- package/dist/src/report-flow-types.js +7 -0
- package/dist/src/report-flow.d.ts +43 -0
- package/dist/src/report-flow.js +193 -0
- package/dist/src/report-operator.d.ts +67 -0
- package/dist/src/report-operator.js +25 -0
- package/dist/src/report-quality.d.ts +221 -0
- package/dist/src/report-quality.js +94 -0
- package/dist/src/report-ready.d.ts +23 -0
- package/dist/src/report-ready.js +117 -0
- package/dist/src/report-statistics.d.ts +2 -1
- package/dist/src/report-statistics.js +40 -4
- package/dist/src/report.d.ts +588 -47
- package/dist/src/report.js +156 -41
- package/dist/src/schedule-progress.d.ts +33 -0
- package/dist/src/schedule-progress.js +45 -0
- package/dist/src/service/active-tickets.js +6 -6
- package/dist/src/service/command-waits.d.ts +34 -0
- package/dist/src/service/command-waits.js +86 -0
- package/dist/src/service/expiry.js +2 -0
- package/dist/src/service/gateway.js +3 -1
- package/dist/src/service/queue-spend.d.ts +6 -0
- package/dist/src/service/queue-spend.js +68 -0
- package/dist/src/service/replies.d.ts +8 -1
- package/dist/src/service/replies.js +11 -0
- package/dist/src/service/run-handlers.js +22 -2
- package/dist/src/service/run-metadata.d.ts +15 -1
- package/dist/src/service/run-metadata.js +93 -8
- package/dist/src/service/service.d.ts +4 -0
- package/dist/src/service/service.js +8 -8
- package/dist/src/service/submission-handler.js +18 -4
- package/dist/src/service/worker-port.js +9 -1
- package/dist/src/service/worker-totals.d.ts +2 -0
- package/dist/src/service/worker-totals.js +1 -1
- package/dist/src/step-bridge.d.ts +20 -0
- package/dist/src/steps/command-wait.d.ts +12 -0
- package/dist/src/steps/command-wait.js +26 -0
- package/dist/src/steps/open-decision-wait.d.ts +2 -0
- package/dist/src/steps/{decision-gate.js → open-decision-wait.js} +0 -7
- package/dist/src/steps/review-by-person.js +4 -1
- package/dist/src/steps/wait-for-command.d.ts +3 -0
- package/dist/src/steps/wait-for-command.js +17 -0
- package/dist/src/steps/wait-for-decision.js +1 -1
- package/dist/src/storage/command-wait-rows.d.ts +30 -0
- package/dist/src/storage/command-wait-rows.js +96 -0
- package/dist/src/storage/decision-snapshots.d.ts +8 -1
- package/dist/src/storage/decision-snapshots.js +15 -1
- package/dist/src/storage/domain-changes.d.ts +2 -0
- package/dist/src/storage/domain-changes.js +3 -0
- package/dist/src/storage/domain-schema.d.ts +13 -1
- package/dist/src/storage/domain-schema.js +31 -4
- package/dist/src/storage/effect-schema.d.ts +1 -0
- package/dist/src/storage/effect-schema.js +5 -0
- package/dist/src/testing-requests.d.ts +15 -0
- package/dist/src/testing-requests.js +93 -0
- package/dist/src/testing.d.ts +4 -10
- package/dist/src/testing.js +33 -86
- package/dist/src/worker-usage.d.ts +1 -0
- package/dist/src/worker-usage.js +3 -0
- package/dist/src/workflow-candidate.d.ts +1 -0
- package/dist/src/workflow-candidate.js +12 -1
- package/dist/src/workflow-contracts.d.ts +1 -0
- package/dist/src/workflow-contracts.js +9 -2
- package/dist/src/workflow-discovery.d.ts +2 -13
- package/dist/src/workflow-discovery.js +1 -13
- package/dist/src/workflow-refusals.js +0 -1
- package/dist/src/workflows.d.ts +1 -1
- package/dist/src/workflows.js +1 -1
- package/dist/tools/red-green-command.d.ts +1 -0
- package/dist/tools/red-green-command.js +174 -0
- package/dist/tools/red-green-process.d.ts +10 -0
- package/dist/tools/red-green-process.js +59 -0
- package/dist/tools/self-host-processes.d.ts +2 -0
- package/dist/tools/self-host-processes.js +32 -13
- package/dist/tools/self-host-project.js +13 -78
- package/dist/tools/self-host-runtime.js +1 -1
- package/dist/tools/self-host.js +42 -10
- package/dist/tools/template-command.d.ts +1 -0
- package/dist/tools/template-command.js +160 -0
- package/dist/tools/template-copy.d.ts +11 -0
- package/dist/tools/template-copy.js +130 -0
- package/dist/tools/template-files.d.ts +17 -0
- package/dist/tools/template-files.js +74 -0
- package/dist/tools/workflow-bundles.js +1 -0
- package/dist/tools/workflow-candidate-counts.js +2 -2
- package/dist/tools/workflow-candidate-shape.d.ts +3 -0
- package/dist/tools/workflow-candidate-shape.js +90 -0
- package/dist/tools/workflow-candidate-source.js +15 -1
- package/dist/tools/workflow-candidate-syntax.d.ts +2 -2
- package/dist/tools/workflow-candidate-syntax.js +24 -94
- package/dist/tools/workflow-command.js +1 -2
- package/dist/tools/workflow-folders.d.ts +2 -3
- package/dist/tools/workflow-folders.js +1 -1
- package/package.json +16 -8
- package/templates/develop/README.md +12 -0
- package/templates/develop/develop/flow-tests.ts +37 -0
- package/templates/develop/develop/pull.ts +5 -1
- package/templates/develop/develop/refusal-tests.ts +77 -0
- package/templates/develop/develop/turn.ts +2 -1
- package/templates/idea-to-issue/README.md +27 -0
- package/templates/idea-to-issue/idea-to-issue/effects.ts +52 -0
- package/templates/idea-to-issue/idea-to-issue/leave.ts +10 -0
- package/templates/idea-to-issue/idea-to-issue/next.ts +29 -0
- package/templates/idea-to-issue/idea-to-issue/post-person.ts +18 -0
- package/templates/idea-to-issue/idea-to-issue/post.ts +50 -0
- package/templates/idea-to-issue/idea-to-issue/queue.ts +27 -0
- package/templates/idea-to-issue/idea-to-issue/review.ts +42 -0
- package/templates/idea-to-issue/idea-to-issue/scenarios.ts +50 -0
- package/templates/idea-to-issue/idea-to-issue/turn.ts +40 -0
- package/templates/idea-to-issue/idea-to-issue.declaration.json +16 -0
- package/templates/idea-to-issue/idea-to-issue.test.ts +79 -0
- package/templates/idea-to-issue/idea-to-issue.ts +49 -0
- package/templates/idea-to-issue/template.json +81 -0
- package/templates/review-day/README.md +97 -0
- package/templates/review-day/review-day/critique.ts +58 -0
- package/templates/review-day/review-day/decision.ts +29 -0
- package/templates/review-day/review-day/facts.ts +69 -0
- package/templates/review-day/review-day/label.ts +29 -0
- package/templates/review-day/review-day/next.ts +28 -0
- package/templates/review-day/review-day/post.ts +27 -0
- package/templates/review-day/review-day/report.ts +98 -0
- package/templates/review-day/review-day/rules.ts +12 -0
- package/templates/review-day/review-day/scenarios.ts +76 -0
- package/templates/review-day/review-day/turn.ts +73 -0
- package/templates/review-day/review-day.declaration.json +16 -0
- package/templates/review-day/review-day.test.ts +362 -0
- package/templates/review-day/review-day.ts +37 -0
- package/templates/review-day/template.json +56 -0
- package/dist/src/cli/watch-start-view.d.ts +0 -18
- package/dist/src/cli/watch-start-view.js +0 -77
- package/dist/src/steps/decision-gate.d.ts +0 -3
- package/dist/workflows/develop-prd.d.ts +0 -7
- package/dist/workflows/develop-prd.js +0 -165
- package/dist/workflows/develop-ticket.d.ts +0 -9
- package/dist/workflows/develop-ticket.js +0 -207
- package/dist/workflows/issue-labels.d.ts +0 -16
- package/dist/workflows/issue-labels.js +0 -70
- package/dist/workflows/ticket-prompts.d.ts +0 -35
- 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
|
|
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
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
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
|
|
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,
|
|
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
|
|
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.
|
|
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
|
-
|
|
142
|
-
|
|
143
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
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
|
-
|
|
255
|
-
|
|
256
|
-
| JSON value
|
|
257
|
-
|
|
|
258
|
-
| `metrics.tickets.completed`
|
|
259
|
-
| `metrics.pullRequests.merged`
|
|
260
|
-
| `metrics.runs.completed`
|
|
261
|
-
| `metrics.runs.partial`
|
|
262
|
-
| `metrics.runs.blocked`
|
|
263
|
-
| `metrics.runs.failed`
|
|
264
|
-
| `metrics.runs.cancelled`
|
|
265
|
-
| `metrics.cost.medianRunUsd`
|
|
266
|
-
| `runCosts`
|
|
267
|
-
|
|
268
|
-
|
|
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
|
-
|
|
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`
|
|
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
|
-
|
|
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
|
|
288
|
-
cloving run develop
|
|
289
|
-
|
|
290
|
-
cloving run
|
|
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
|
|
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
|
-
-
|
|
310
|
-
- For `develop
|
|
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
|
|
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
|
|
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 `
|
|
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
|
-
###
|
|
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.
|
|
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
|
|
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
|
|
363
|
-
- A denial with no text, or a denial in round
|
|
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.
|
|
443
|
+
step. Each project or user workflow declares its own targets.
|
|
450
444
|
|
|
451
|
-
### Pull requests of `develop
|
|
445
|
+
### Pull requests of `develop`
|
|
452
446
|
|
|
453
|
-
|
|
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`.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
-
|
|
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
|
|
512
|
+
### Set up a repository
|
|
515
513
|
|
|
516
|
-
|
|
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
|
|
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
|
|
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
|
|
551
|
+
One line. For develop, it becomes the title of the pull request.
|
|
566
552
|
GitHub issue: OWNER/REPOSITORY#NUMBER
|
|
567
|
-
Only for develop
|
|
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
|
|
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
|
|
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 `
|
|
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
|
|
623
|
-
- The step helpers come from the subpaths of `cloving/workflows`: `protectedEffect` from `cloving/workflows/steps/protected-effect`, `
|
|
624
|
-
- `protectedEffect` asks the daemon for one effect of a capability, for example a Claude turn. `
|
|
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 {
|
|
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
|
-
|
|
636
|
-
|
|
637
|
-
readonly
|
|
638
|
-
|
|
639
|
-
|
|
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
|
|
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 (
|
|
626
|
+
if (decision.decision !== "approved")
|
|
677
627
|
return {
|
|
678
628
|
kind: "blocked",
|
|
679
629
|
cycleId: input.cycleId,
|
|
680
|
-
reason: "The
|
|
630
|
+
reason: "The operator did not approve the work.",
|
|
681
631
|
evidenceId: "review-1",
|
|
682
632
|
};
|
|
683
633
|
return {
|
|
684
|
-
kind: "
|
|
634
|
+
kind: "handoff_requested",
|
|
685
635
|
cycleId: input.cycleId,
|
|
686
|
-
|
|
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. `
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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; `
|
|
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
|
-
|
|
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
|
|
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
|
|
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`
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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`.
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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
|
|