cloving 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +329 -215
- 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-health.d.ts +9 -0
- package/dist/src/broker/actor/authority-health.js +24 -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-runtime.d.ts +4 -2
- package/dist/src/broker/actor/authority-runtime.js +29 -20
- package/dist/src/broker/actor/authority-session.d.ts +6 -19
- package/dist/src/broker/actor/authority-session.js +66 -88
- package/dist/src/broker/actor/authority-settings.d.ts +2 -1
- package/dist/src/broker/actor/authority-settings.js +6 -3
- package/dist/src/broker/actor/authority-upgrades.d.ts +23 -2
- package/dist/src/broker/actor/authority-upgrades.js +8 -2
- package/dist/src/broker/actor/authority-watchdog.d.ts +6 -2
- package/dist/src/broker/actor/authority-watchdog.js +31 -9
- package/dist/src/broker/actor/authority.js +3 -1
- 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/projection-memory.d.ts +43 -0
- package/dist/src/broker/actor/projection-memory.js +207 -0
- package/dist/src/broker/actor/runtime-parts.d.ts +5 -0
- package/dist/src/broker/actor/runtime-parts.js +8 -3
- 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 +3 -0
- package/dist/src/broker/effect-upgrade.js +11 -2
- package/dist/src/cli/arguments.d.ts +13 -0
- package/dist/src/cli/arguments.js +43 -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 +7 -2
- package/dist/src/cli/client.js +13 -7
- package/dist/src/cli/command-requests.d.ts +46 -0
- package/dist/src/cli/command-requests.js +84 -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 +70 -88
- package/dist/src/cli/config-file.d.ts +2 -2
- package/dist/src/cli/config-file.js +4 -2
- package/dist/src/cli/config-notice.js +5 -2
- package/dist/src/cli/doctor-retention.d.ts +2 -0
- package/dist/src/cli/doctor-retention.js +93 -0
- 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 +11 -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 +242 -0
- package/dist/src/cli/queue-arguments.d.ts +15 -0
- package/dist/src/cli/queue-arguments.js +31 -0
- package/dist/src/cli/queue-render.d.ts +3 -0
- package/dist/src/cli/queue-render.js +26 -0
- package/dist/src/cli/reload-render.d.ts +2 -0
- package/dist/src/cli/reload-render.js +12 -0
- package/dist/src/cli/render.d.ts +1 -1
- package/dist/src/cli/render.js +54 -38
- 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 +18 -3
- package/dist/src/cli/runtime-arguments.js +29 -20
- 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/toolchain.d.ts +1 -0
- package/dist/src/cli/toolchain.js +1 -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 +2 -2
- package/dist/src/cli/usage.js +89 -11
- package/dist/src/cli/watch-actions.js +2 -2
- package/dist/src/cli/watch-api-document.d.ts +430 -0
- package/dist/src/cli/watch-api-document.js +291 -0
- package/dist/src/cli/watch-api-run.d.ts +56 -0
- package/dist/src/cli/watch-api-run.js +112 -0
- package/dist/src/cli/watch-api.d.ts +17 -0
- package/dist/src/cli/watch-api.js +230 -0
- 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 +1 -5
- package/dist/src/cli/watch-header-view.js +17 -21
- package/dist/src/cli/watch-model.d.ts +5 -1
- package/dist/src/cli/watch-model.js +20 -11
- package/dist/src/cli/watch-page.js +15 -15
- 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 +3 -0
- package/dist/src/cli/watch-reads.js +22 -20
- package/dist/src/cli/watch-render.d.ts +15 -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 +24 -10
- package/dist/src/cli/watch-view.d.ts +0 -3
- package/dist/src/cli/watch-view.js +13 -13
- package/dist/src/cli.js +73 -12
- 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-display.js +2 -0
- package/dist/src/configuration-schema.d.ts +14 -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 +208 -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 +5 -4
- package/dist/src/daemon/claude-worker.js +127 -126
- package/dist/src/daemon/daemon-adapters.d.ts +9 -0
- package/dist/src/daemon/daemon-adapters.js +33 -5
- package/dist/src/daemon/daemon-loops.d.ts +5 -1
- package/dist/src/daemon/daemon-loops.js +18 -10
- package/dist/src/daemon/daemon.js +80 -61
- package/dist/src/daemon/github-attach.d.ts +2 -0
- package/dist/src/daemon/github-attach.js +222 -0
- package/dist/src/daemon/github-calls.js +1 -1
- 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 +18 -4
- 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 +4 -1
- package/dist/src/daemon/issue-queue.js +76 -78
- package/dist/src/daemon/merge-turns.d.ts +10 -0
- package/dist/src/daemon/merge-turns.js +37 -0
- 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-control.d.ts +13 -0
- package/dist/src/daemon/queue-control.js +86 -0
- package/dist/src/daemon/queue-journal.d.ts +20 -0
- package/dist/src/daemon/queue-journal.js +89 -0
- package/dist/src/daemon/queue-status.d.ts +9 -3
- package/dist/src/daemon/queue-status.js +17 -4
- package/dist/src/daemon/record-archive.d.ts +19 -0
- package/dist/src/daemon/record-archive.js +82 -0
- package/dist/src/daemon/record-sweep.d.ts +24 -0
- package/dist/src/daemon/record-sweep.js +147 -0
- 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/settings-reload.d.ts +26 -0
- package/dist/src/daemon/settings-reload.js +82 -0
- 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-details.d.ts +4 -0
- package/dist/src/daemon/turn-details.js +33 -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 +9 -0
- package/dist/src/daemon/worker-profile.js +44 -0
- package/dist/src/daemon/workflow-generations.d.ts +7 -4
- package/dist/src/daemon/workflow-generations.js +22 -14
- package/dist/src/daemon/workflow-reload.d.ts +41 -0
- package/dist/src/daemon/workflow-reload.js +244 -0
- package/dist/src/daemon/workflow-replay.d.ts +2 -1
- package/dist/src/daemon/workflow-replay.js +7 -3
- 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 +4 -6
- package/dist/src/doctor-report.js +8 -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 +71 -0
- package/dist/src/project-config.schema.json +40 -0
- package/dist/src/project-settings.d.ts +16 -2
- package/dist/src/project-settings.js +35 -1
- package/dist/src/queue-spend.d.ts +4 -0
- package/dist/src/queue-spend.js +21 -0
- package/dist/src/queue-state.d.ts +26 -0
- package/dist/src/queue-state.js +34 -0
- package/dist/src/record-retention.d.ts +46 -0
- package/dist/src/record-retention.js +81 -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 +11 -6
- package/dist/src/service/command-waits.d.ts +34 -0
- package/dist/src/service/command-waits.js +86 -0
- package/dist/src/service/dispatcher.d.ts +4 -0
- package/dist/src/service/dispatcher.js +33 -0
- package/dist/src/service/expiry.js +2 -0
- package/dist/src/service/gateway.js +3 -1
- package/dist/src/service/queue-handlers.d.ts +4 -0
- package/dist/src/service/queue-handlers.js +32 -0
- package/dist/src/service/queue-spend.d.ts +6 -0
- package/dist/src/service/queue-spend.js +68 -0
- package/dist/src/service/registry.d.ts +28 -2
- package/dist/src/service/registry.js +48 -0
- package/dist/src/service/replies.d.ts +22 -8
- package/dist/src/service/replies.js +16 -2
- package/dist/src/service/run-handlers.js +37 -12
- 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 +11 -3
- package/dist/src/service/service.js +22 -37
- 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 +6 -0
- package/dist/src/service/worker-totals.js +8 -1
- package/dist/src/service/workflow-reload.d.ts +35 -0
- package/dist/src/service/workflow-reload.js +52 -0
- 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 -2
- package/dist/src/storage/decision-snapshots.js +16 -8
- package/dist/src/storage/domain-changes.d.ts +3 -1
- package/dist/src/storage/domain-changes.js +4 -0
- package/dist/src/storage/domain-schema.d.ts +16 -1
- package/dist/src/storage/domain-schema.js +35 -4
- package/dist/src/storage/effect-schema.d.ts +2 -0
- package/dist/src/storage/effect-schema.js +9 -0
- package/dist/src/storage/projection-changes.d.ts +12 -0
- package/dist/src/storage/projection-changes.js +194 -0
- package/dist/src/storage/projection-lookups.d.ts +7 -0
- package/dist/src/storage/projection-lookups.js +30 -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-declaration.d.ts +1 -0
- package/dist/src/workflow-declaration.js +3 -0
- 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/compile-workflows.js +3 -0
- package/dist/tools/project-configuration.d.ts +7 -2
- package/dist/tools/project-configuration.js +30 -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 +69 -26
- package/dist/tools/self-host-project.d.ts +2 -0
- package/dist/tools/self-host-project.js +30 -77
- package/dist/tools/self-host-runtime.js +1 -1
- package/dist/tools/self-host.js +76 -34
- 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-program.d.ts +4 -2
- package/dist/tools/workflow-candidate-program.js +30 -11
- 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.d.ts +1 -0
- package/dist/tools/workflow-candidate-source.js +26 -4
- 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 +17 -9
- package/templates/develop/README.md +93 -4
- package/templates/develop/develop/flow-tests.ts +38 -1
- package/templates/develop/develop/interruption-tests.ts +157 -0
- package/templates/develop/develop/local.ts +1 -0
- package/templates/develop/develop/option-tests.ts +138 -9
- package/templates/develop/develop/pull.ts +5 -1
- package/templates/develop/develop/red-green.ts +55 -0
- package/templates/develop/develop/refusal-tests.ts +77 -0
- package/templates/develop/develop/report.ts +31 -11
- package/templates/develop/develop/round.ts +1 -0
- package/templates/develop/develop/scenarios.ts +27 -0
- package/templates/develop/develop/turn.ts +28 -7
- package/templates/develop/develop.declaration.json +1 -1
- package/templates/develop/develop.test.ts +4 -0
- package/templates/develop/template.json +29 -2
- 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
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"name": "idea-to-issue",
|
|
4
|
+
"summary": "Research an idea, check its draft, post a private-text-checked issue and choose what happens next. The first option at every point is the default.",
|
|
5
|
+
"points": [
|
|
6
|
+
{
|
|
7
|
+
"id": "review",
|
|
8
|
+
"question": "Who checks the draft?",
|
|
9
|
+
"options": [
|
|
10
|
+
{
|
|
11
|
+
"id": "turn",
|
|
12
|
+
"label": "A review turn corrects the draft",
|
|
13
|
+
"summary": "Compare the research with the code and correct the draft file.",
|
|
14
|
+
"change": "Keep reviewByTurn as checkDraft in idea-to-issue.ts.",
|
|
15
|
+
"requires": {},
|
|
16
|
+
"needs": ["default-harness"]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": "person",
|
|
20
|
+
"label": "I read the draft",
|
|
21
|
+
"summary": "Capture the draft through a protected effect and show its text to reviewByPerson. Post only if the captured digest still matches.",
|
|
22
|
+
"change": "Import reviewDraftByPerson as checkDraft from idea-to-issue/review.ts in idea-to-issue.ts. Add capture-draft to methods.github. Set selection.review to person in idea-to-issue/scenarios.ts.",
|
|
23
|
+
"requires": {},
|
|
24
|
+
"needs": []
|
|
25
|
+
}
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": "post",
|
|
30
|
+
"question": "Who approves posting the issue?",
|
|
31
|
+
"options": [
|
|
32
|
+
{
|
|
33
|
+
"id": "privacy",
|
|
34
|
+
"label": "Post after the privacy check",
|
|
35
|
+
"summary": "Post after the existing privacy check; retain any digest from a person review.",
|
|
36
|
+
"change": "Keep postAfterPrivacy as postDraft in idea-to-issue.ts. Configure privateTexts with at least one nonblank item.",
|
|
37
|
+
"requires": {},
|
|
38
|
+
"needs": ["gh-login", "github-origin", "private-texts"]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"id": "person",
|
|
42
|
+
"label": "I approve the post",
|
|
43
|
+
"summary": "Capture and show the draft in an approval gate before the checked post. Preserve both reviewed digests when both gates are selected.",
|
|
44
|
+
"change": "Import postByPerson as postDraft from idea-to-issue/post-person.ts in idea-to-issue.ts. Add capture-draft to methods.github. Set selection.post to person in idea-to-issue/scenarios.ts. Configure privateTexts with at least one nonblank item.",
|
|
45
|
+
"requires": {},
|
|
46
|
+
"needs": ["gh-login", "github-origin", "private-texts"]
|
|
47
|
+
}
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"id": "next",
|
|
52
|
+
"question": "What happens to the posted issue?",
|
|
53
|
+
"options": [
|
|
54
|
+
{
|
|
55
|
+
"id": "develop",
|
|
56
|
+
"label": "Hand the issue to develop",
|
|
57
|
+
"summary": "Start the repository-declared develop workflow. If starting it fails, put the issue in the queue.",
|
|
58
|
+
"change": "Keep handoffIssue as nextIssue in idea-to-issue.ts. Set targetWorkflow in idea-to-issue/next.ts and workflow.handoffs in idea-to-issue.declaration.json to the same repository-declared workflow ID. The default is develop.",
|
|
59
|
+
"requires": {},
|
|
60
|
+
"needs": ["gh-login", "github-origin"]
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"id": "queue",
|
|
64
|
+
"label": "Put the issue in the queue",
|
|
65
|
+
"summary": "Add cloving: ready without starting a develop workflow.",
|
|
66
|
+
"change": "Import queueIssue as nextIssue from idea-to-issue/queue.ts in idea-to-issue.ts. Set workflow.handoffs to [] and selection.next to queue in idea-to-issue/scenarios.ts. No develop workflow is required.",
|
|
67
|
+
"requires": {},
|
|
68
|
+
"needs": ["gh-login", "github-origin"]
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"id": "nothing",
|
|
72
|
+
"label": "Do nothing",
|
|
73
|
+
"summary": "Leave the posted issue for a person.",
|
|
74
|
+
"change": "Import leaveIssue as nextIssue from idea-to-issue/leave.ts in idea-to-issue.ts. Set workflow.handoffs to [], remove label from methods.github and set selection.next to nothing in idea-to-issue/scenarios.ts. No develop workflow is required.",
|
|
75
|
+
"requires": {},
|
|
76
|
+
"needs": []
|
|
77
|
+
}
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Review day
|
|
2
|
+
|
|
3
|
+
Copy the template into your private workflow folder, named by `workflows.folder`,
|
|
4
|
+
with `cloving templates copy review-day`. This operator step happens outside the
|
|
5
|
+
application repository. Inspect `cloving templates show review-day --json`, choose
|
|
6
|
+
the two options, apply their import and declaration edits, update `selection` in
|
|
7
|
+
`review-day/scenarios.ts`, then run `cloving workflows test review-day`.
|
|
8
|
+
|
|
9
|
+
The default schedule runs every 86400 seconds with `{}` input. The scheduler
|
|
10
|
+
skips a slot while the review runs, including its decision and child-run waits.
|
|
11
|
+
Use the scheduled copy as the single daily reviewer; avoid starting parallel
|
|
12
|
+
manual copies. A failed command or invalid JSON blocks the run before any turn,
|
|
13
|
+
report or issue. Unavailable metrics stay unavailable, never zero.
|
|
14
|
+
|
|
15
|
+
Set `CLOVING_COMMANDS` to JSON argv arrays for these three read-only commands:
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"report": [
|
|
20
|
+
"<absolute-cloving-executable>",
|
|
21
|
+
"report",
|
|
22
|
+
"--since",
|
|
23
|
+
"24",
|
|
24
|
+
"--json"
|
|
25
|
+
],
|
|
26
|
+
"reviews": [
|
|
27
|
+
"<absolute-gh-executable>",
|
|
28
|
+
"issue",
|
|
29
|
+
"list",
|
|
30
|
+
"--state",
|
|
31
|
+
"all",
|
|
32
|
+
"--label",
|
|
33
|
+
"cloving: review",
|
|
34
|
+
"--limit",
|
|
35
|
+
"7",
|
|
36
|
+
"--json",
|
|
37
|
+
"number,url,body,createdAt"
|
|
38
|
+
],
|
|
39
|
+
"improvements": ["<absolute-improvements-wrapper>"]
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Replace the executable placeholders with absolute paths (`command -v cloving`,
|
|
44
|
+
`command -v gh`, and your wrapper's absolute path). Bare executable names are
|
|
45
|
+
refused by command configuration.
|
|
46
|
+
|
|
47
|
+
`report` runs `cloving report --since 24 --json`. `reviews` supplies the last seven
|
|
48
|
+
review issues as an array, newest first. `improvements` must read all open issues
|
|
49
|
+
with `cloving: improvement` and return an array with `number`, `url`, `body` and
|
|
50
|
+
the stable `loop` identifier for each issue. Use a local read-only wrapper to
|
|
51
|
+
extract that identifier from its body; include the metric, before measurement,
|
|
52
|
+
change date, check date and after evidence in the body. Missing loop identifiers
|
|
53
|
+
prevent further proposals until clarified. Never truncate the open-issue list.
|
|
54
|
+
|
|
55
|
+
Before enabling the schedule, add a turn profile for this workflow with
|
|
56
|
+
`maxBudgetUsd` and read-only `allowedTools`. Configure a
|
|
57
|
+
Claude profile `reviewDay` with `workflows: ["review-day"]`, `maxBudgetUsd: 1` and
|
|
58
|
+
`allowedTools: ["Read", "Glob", "Grep"]`. Change the turn helper's method and its
|
|
59
|
+
declaration entry from `run-turn` to `run-turn:reviewDay` to use that profile.
|
|
60
|
+
The default unprofiled method does not apply the named profile's budget. The two
|
|
61
|
+
turns return JSON in their final summary; they need no write or shell tools.
|
|
62
|
+
Set the budget to your chosen per-turn limit.
|
|
63
|
+
Both turns must keep their complete serialized JSON within 12000 characters,
|
|
64
|
+
including escaping, below the worker's 16000-character summary limit. Condense
|
|
65
|
+
repeated prose while retaining every required section, evidence link and removal
|
|
66
|
+
reason. Oversized or incomplete JSON blocks the run before posting.
|
|
67
|
+
|
|
68
|
+
After the turns, including a failed turn or invalid report, `github discard`
|
|
69
|
+
removes this run's temporary worktree and branch before posting or waiting for a
|
|
70
|
+
decision. Failed cleanup blocks the run. Retain `github` in capabilities and
|
|
71
|
+
`discard` in methods for all options, including `post.result` with `next.nothing`.
|
|
72
|
+
|
|
73
|
+
Analyze and critique use the same nine rules and all three command outputs.
|
|
74
|
+
Critique is a separate turn. It removes unsupported claims, lists removals,
|
|
75
|
+
compares every open improvement before and after its change, and gives keep,
|
|
76
|
+
reverse or continue at the check date. The workflow also removes proposals
|
|
77
|
+
without evidence or for a loop with an open improvement, caps the list at three,
|
|
78
|
+
and refuses additions or rewrites by the critique. The report has the fixed
|
|
79
|
+
Facts, Went well, Went badly, The constraint, Improvements in progress, Proposals,
|
|
80
|
+
Watch list and Removed by the critique sections.
|
|
81
|
+
|
|
82
|
+
Posting requires nonblank `privateTexts` and uses the existing privacy check on
|
|
83
|
+
the exact rendered report. `post.result` keeps the `report` field in the durable
|
|
84
|
+
SDK run return value. `cloving status` shows completion metadata and does not
|
|
85
|
+
display that field.
|
|
86
|
+
With proposals, one question accepts a single number or `none`. A denial, expiry
|
|
87
|
+
or ambiguous answer starts no child. `next.nothing` records the choice and stops.
|
|
88
|
+
|
|
89
|
+
For `next.idea`, copy `idea-to-issue` into the same private workflow folder and
|
|
90
|
+
select its **next.nothing** option. Its default starts development and its queue
|
|
91
|
+
option adds `cloving: ready`; neither is suitable for review proposals. The child
|
|
92
|
+
must only write the ticket, keep the proposal's evidence, loop, metric and check
|
|
93
|
+
date, and leave queue selection to the operator. The review reads the issue
|
|
94
|
+
number from its `issue-N` outcome after `waitForRun`, then adds only
|
|
95
|
+
`cloving: improvement` to that new issue. Earlier issues and labels stay untouched.
|
|
96
|
+
A later review reports the verdict; applying or reversing a change remains an
|
|
97
|
+
operator decision.
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { ReviewFacts } from "./facts.ts";
|
|
2
|
+
import type { Proposal, ReviewReport } from "./report.ts";
|
|
3
|
+
|
|
4
|
+
function removal(
|
|
5
|
+
proposal: Proposal,
|
|
6
|
+
context: {
|
|
7
|
+
readonly draft: ReviewReport;
|
|
8
|
+
readonly facts: ReviewFacts;
|
|
9
|
+
readonly accepted: readonly Proposal[];
|
|
10
|
+
},
|
|
11
|
+
): string | null {
|
|
12
|
+
const original = context.draft.proposals.find(
|
|
13
|
+
(item) => item.id === proposal.id,
|
|
14
|
+
);
|
|
15
|
+
if (JSON.stringify(original) !== JSON.stringify(proposal))
|
|
16
|
+
return "not an unchanged analyzed proposal";
|
|
17
|
+
if (
|
|
18
|
+
proposal.evidence.length === 0 ||
|
|
19
|
+
proposal.evidence.some((link) => !/^https?:\/\/\S+$/.test(link))
|
|
20
|
+
)
|
|
21
|
+
return "missing evidence";
|
|
22
|
+
if (
|
|
23
|
+
context.facts.improvements.some(
|
|
24
|
+
(issue) =>
|
|
25
|
+
typeof issue["loop"] !== "string" ||
|
|
26
|
+
issue["loop"].trim() === "" ||
|
|
27
|
+
issue["loop"].trim() === proposal.loop.trim(),
|
|
28
|
+
)
|
|
29
|
+
)
|
|
30
|
+
return "open improvement";
|
|
31
|
+
if (context.accepted.some((item) => item.id === proposal.id))
|
|
32
|
+
return "duplicate proposal";
|
|
33
|
+
return context.accepted.length >= 3 ? "three proposal limit" : null;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function enforceCritique(
|
|
37
|
+
draft: ReviewReport,
|
|
38
|
+
review: {
|
|
39
|
+
readonly critique: ReviewReport;
|
|
40
|
+
readonly facts: ReviewFacts;
|
|
41
|
+
},
|
|
42
|
+
): ReviewReport {
|
|
43
|
+
const proposals: Proposal[] = [];
|
|
44
|
+
const removed = review.critique.removed.slice();
|
|
45
|
+
for (const proposal of review.critique.proposals) {
|
|
46
|
+
const reason = removal(proposal, {
|
|
47
|
+
draft,
|
|
48
|
+
facts: review.facts,
|
|
49
|
+
accepted: proposals,
|
|
50
|
+
});
|
|
51
|
+
if (reason === null) proposals.push(proposal);
|
|
52
|
+
else removed.push(`${proposal.id}: ${reason}`);
|
|
53
|
+
}
|
|
54
|
+
for (const proposal of draft.proposals)
|
|
55
|
+
if (!review.critique.proposals.some((item) => item.id === proposal.id))
|
|
56
|
+
removed.push(`${proposal.id}: removed by critique`);
|
|
57
|
+
return Object.assign({}, review.critique, { proposals, removed });
|
|
58
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { waitForDecision } from "cloving/workflows/steps/wait-for-decision";
|
|
2
|
+
import type { ReviewInput } from "./facts.ts";
|
|
3
|
+
import { proposalText, type Proposal } from "./report.ts";
|
|
4
|
+
|
|
5
|
+
export async function chooseProposal(
|
|
6
|
+
input: ReviewInput,
|
|
7
|
+
proposals: readonly Proposal[],
|
|
8
|
+
): Promise<Proposal | null> {
|
|
9
|
+
if (proposals.length === 0) return null;
|
|
10
|
+
const result = await waitForDecision({
|
|
11
|
+
gateId: `review-day:${input.cycleId}`,
|
|
12
|
+
kind: "question",
|
|
13
|
+
prompt: [
|
|
14
|
+
"Approve at most one proposal: answer its number, or none. This authorizes only an idea-to-issue handoff, never a code or settings change.",
|
|
15
|
+
]
|
|
16
|
+
.concat(
|
|
17
|
+
proposals.map(
|
|
18
|
+
(proposal, index) =>
|
|
19
|
+
`${String(index + 1)}. ${proposalText(proposal)}`,
|
|
20
|
+
),
|
|
21
|
+
)
|
|
22
|
+
.join("\n\n"),
|
|
23
|
+
});
|
|
24
|
+
if (!["approved", "answered"].includes(result.decision)) return null;
|
|
25
|
+
const answer = result.answer?.trim() ?? "";
|
|
26
|
+
return /^[1-3]$/.test(answer)
|
|
27
|
+
? (proposals.at(Number(answer) - 1) ?? null)
|
|
28
|
+
: null;
|
|
29
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { ProtectedResult } from "cloving/workflows";
|
|
2
|
+
import { runCommand } from "cloving/workflows/steps/run-command";
|
|
3
|
+
|
|
4
|
+
export interface ReviewInput {
|
|
5
|
+
readonly cycleId: string;
|
|
6
|
+
readonly input: Readonly<Record<string, never>>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function effectText(result: ProtectedResult): string {
|
|
10
|
+
if (result.kind !== "completed")
|
|
11
|
+
throw new Error(result.reason ?? result.kind);
|
|
12
|
+
if (result.result === null) throw new Error("missing-review-result");
|
|
13
|
+
return result.result;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function fields(value: unknown): Record<string, unknown> {
|
|
17
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
18
|
+
throw new Error("invalid-review-facts");
|
|
19
|
+
return Object.fromEntries(Object.entries(value));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function commandJson(result: ProtectedResult): unknown {
|
|
23
|
+
const text = effectText(result);
|
|
24
|
+
try {
|
|
25
|
+
const value: unknown = JSON.parse(text);
|
|
26
|
+
return value;
|
|
27
|
+
} catch {
|
|
28
|
+
throw new Error("invalid-review-facts");
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function issues(value: unknown): readonly Record<string, unknown>[] {
|
|
33
|
+
if (!Array.isArray(value)) throw new Error("invalid-review-facts");
|
|
34
|
+
return value.map((issue: unknown) => fields(issue));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function reviewFacts() {
|
|
38
|
+
const input: Readonly<Record<string, never>> = {};
|
|
39
|
+
const report = fields(
|
|
40
|
+
commandJson(
|
|
41
|
+
await runCommand({
|
|
42
|
+
scope: { phase: "review-day", operation: "report", round: 1 },
|
|
43
|
+
name: "report",
|
|
44
|
+
input: input,
|
|
45
|
+
}),
|
|
46
|
+
),
|
|
47
|
+
);
|
|
48
|
+
const reviews = issues(
|
|
49
|
+
commandJson(
|
|
50
|
+
await runCommand({
|
|
51
|
+
scope: { phase: "review-day", operation: "reviews", round: 1 },
|
|
52
|
+
name: "reviews",
|
|
53
|
+
input: input,
|
|
54
|
+
}),
|
|
55
|
+
),
|
|
56
|
+
);
|
|
57
|
+
const improvements = issues(
|
|
58
|
+
commandJson(
|
|
59
|
+
await runCommand({
|
|
60
|
+
scope: { phase: "review-day", operation: "improvements", round: 1 },
|
|
61
|
+
name: "improvements",
|
|
62
|
+
input: input,
|
|
63
|
+
}),
|
|
64
|
+
),
|
|
65
|
+
);
|
|
66
|
+
return { report, reviews, improvements };
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export type ReviewFacts = Awaited<ReturnType<typeof reviewFacts>>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { protectedEffect } from "cloving/workflows/steps/protected-effect";
|
|
2
|
+
import { effectText, type ReviewInput } from "./facts.ts";
|
|
3
|
+
|
|
4
|
+
export async function labelIssue(
|
|
5
|
+
input: ReviewInput,
|
|
6
|
+
issue: { readonly number: number; readonly label: string },
|
|
7
|
+
) {
|
|
8
|
+
effectText(
|
|
9
|
+
await protectedEffect({
|
|
10
|
+
capability: "github",
|
|
11
|
+
method: "label",
|
|
12
|
+
target: input.cycleId,
|
|
13
|
+
units: 1,
|
|
14
|
+
scope: {
|
|
15
|
+
phase: "review-day",
|
|
16
|
+
operation:
|
|
17
|
+
issue.label === "cloving: review"
|
|
18
|
+
? "label-review"
|
|
19
|
+
: "label-improvement",
|
|
20
|
+
round: 1,
|
|
21
|
+
},
|
|
22
|
+
payload: JSON.stringify({
|
|
23
|
+
number: issue.number,
|
|
24
|
+
add: [issue.label],
|
|
25
|
+
remove: [],
|
|
26
|
+
}),
|
|
27
|
+
}),
|
|
28
|
+
);
|
|
29
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { handoff } from "cloving/workflows/steps/handoff";
|
|
2
|
+
import { waitForRun } from "cloving/workflows/steps/wait-for-run";
|
|
3
|
+
import type { ReviewInput } from "./facts.ts";
|
|
4
|
+
import { proposalText, type Proposal } from "./report.ts";
|
|
5
|
+
import { labelIssue } from "./label.ts";
|
|
6
|
+
|
|
7
|
+
export async function handoffProposal(
|
|
8
|
+
input: ReviewInput,
|
|
9
|
+
proposal: Proposal,
|
|
10
|
+
): Promise<void> {
|
|
11
|
+
const runId = await handoff({
|
|
12
|
+
workflowId: "idea-to-issue",
|
|
13
|
+
input: { idea: proposalText(proposal) },
|
|
14
|
+
});
|
|
15
|
+
const outcome = await waitForRun({ runId, maximumWaitSeconds: 86400 });
|
|
16
|
+
const match =
|
|
17
|
+
outcome.promotionId === null
|
|
18
|
+
? null
|
|
19
|
+
: /^issue-([1-9]\d*)$/.exec(outcome.promotionId);
|
|
20
|
+
const number = Number(match?.[1]);
|
|
21
|
+
if (
|
|
22
|
+
outcome.kind !== "handoff_requested" ||
|
|
23
|
+
!Number.isSafeInteger(number) ||
|
|
24
|
+
number < 1
|
|
25
|
+
)
|
|
26
|
+
throw new Error("improvement-issue-missing");
|
|
27
|
+
await labelIssue(input, { number, label: "cloving: improvement" });
|
|
28
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { protectedEffect } from "cloving/workflows/steps/protected-effect";
|
|
2
|
+
import { effectText, fields, type ReviewInput } from "./facts.ts";
|
|
3
|
+
import { labelIssue } from "./label.ts";
|
|
4
|
+
|
|
5
|
+
export async function postAfterPrivacy(
|
|
6
|
+
input: ReviewInput,
|
|
7
|
+
report: string,
|
|
8
|
+
): Promise<void> {
|
|
9
|
+
const result = fields(
|
|
10
|
+
JSON.parse(
|
|
11
|
+
effectText(
|
|
12
|
+
await protectedEffect({
|
|
13
|
+
capability: "github",
|
|
14
|
+
method: "create-issue",
|
|
15
|
+
target: input.cycleId,
|
|
16
|
+
units: 1,
|
|
17
|
+
scope: { phase: "review-day", operation: "post", round: 1 },
|
|
18
|
+
payload: JSON.stringify({ text: report }),
|
|
19
|
+
}),
|
|
20
|
+
),
|
|
21
|
+
),
|
|
22
|
+
);
|
|
23
|
+
const number = result["number"];
|
|
24
|
+
if (typeof number !== "number" || !Number.isSafeInteger(number) || number < 1)
|
|
25
|
+
throw new Error("invalid-review-issue");
|
|
26
|
+
await labelIssue(input, { number, label: "cloving: review" });
|
|
27
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { fields } from "./facts.ts";
|
|
2
|
+
|
|
3
|
+
export interface Proposal {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
readonly loop: string;
|
|
6
|
+
readonly text: string;
|
|
7
|
+
readonly evidence: readonly string[];
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface ReviewReport {
|
|
11
|
+
readonly facts: string;
|
|
12
|
+
readonly wentWell: string;
|
|
13
|
+
readonly wentBadly: string;
|
|
14
|
+
readonly constraint: string;
|
|
15
|
+
readonly improvementsInProgress: string;
|
|
16
|
+
readonly proposals: readonly Proposal[];
|
|
17
|
+
readonly watchList: string;
|
|
18
|
+
readonly removed: readonly string[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function text(value: unknown): string {
|
|
22
|
+
if (typeof value !== "string" || value.trim() === "")
|
|
23
|
+
throw new Error("invalid-review-report");
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function texts(value: unknown): readonly string[] {
|
|
28
|
+
if (!Array.isArray(value)) throw new Error("invalid-review-report");
|
|
29
|
+
return value.map((item: unknown) => text(item));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function proposal(value: unknown): Proposal {
|
|
33
|
+
const item = fields(value);
|
|
34
|
+
return {
|
|
35
|
+
id: text(item["id"]),
|
|
36
|
+
loop: text(item["loop"]),
|
|
37
|
+
text: text(item["text"]),
|
|
38
|
+
evidence: texts(item["evidence"]),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function proposalText(proposal: Proposal): string {
|
|
43
|
+
const heading = `Loop: ${proposal.loop}\n\n`;
|
|
44
|
+
const missing = proposal.evidence.filter(
|
|
45
|
+
(link) => !proposal.text.includes(link),
|
|
46
|
+
);
|
|
47
|
+
const links =
|
|
48
|
+
missing.length === 0
|
|
49
|
+
? ""
|
|
50
|
+
: "\n\nEvidence:\n" + missing.map((link) => `- ${link}`).join("\n");
|
|
51
|
+
return (
|
|
52
|
+
(proposal.text.startsWith(heading)
|
|
53
|
+
? proposal.text
|
|
54
|
+
: heading + proposal.text) + links
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function parseReport(value: unknown): ReviewReport {
|
|
59
|
+
const item = fields(value);
|
|
60
|
+
const proposals = item["proposals"];
|
|
61
|
+
if (!Array.isArray(proposals)) throw new Error("invalid-review-report");
|
|
62
|
+
return {
|
|
63
|
+
facts: text(item["facts"]),
|
|
64
|
+
wentWell: text(item["wentWell"]),
|
|
65
|
+
wentBadly: text(item["wentBadly"]),
|
|
66
|
+
constraint: text(item["constraint"]),
|
|
67
|
+
improvementsInProgress: text(item["improvementsInProgress"]),
|
|
68
|
+
proposals: proposals.map((item: unknown) => proposal(item)),
|
|
69
|
+
watchList: text(item["watchList"]),
|
|
70
|
+
removed: texts(item["removed"]),
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function renderReport(report: ReviewReport): string {
|
|
75
|
+
const sections: readonly (readonly [string, string])[] = [
|
|
76
|
+
["Facts", report.facts],
|
|
77
|
+
["Went well", report.wentWell],
|
|
78
|
+
["Went badly", report.wentBadly],
|
|
79
|
+
["The constraint", report.constraint],
|
|
80
|
+
["Improvements in progress", report.improvementsInProgress],
|
|
81
|
+
[
|
|
82
|
+
"Proposals",
|
|
83
|
+
report.proposals
|
|
84
|
+
.map(
|
|
85
|
+
(proposal, index) =>
|
|
86
|
+
`${String(index + 1)}. ${proposalText(proposal)}`,
|
|
87
|
+
)
|
|
88
|
+
.join("\n\n") || "None.",
|
|
89
|
+
],
|
|
90
|
+
["Watch list", report.watchList],
|
|
91
|
+
["Removed by the critique", report.removed.join("\n\n") || "None."],
|
|
92
|
+
];
|
|
93
|
+
const text =
|
|
94
|
+
"# Daily loop review\n\n" +
|
|
95
|
+
sections.map(([heading, body]) => `## ${heading}\n\n${body}`).join("\n\n");
|
|
96
|
+
if (text.length > 65536) throw new Error("review-report-too-large");
|
|
97
|
+
return text;
|
|
98
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const reviewRules = [
|
|
2
|
+
"Real changes only: a problem must be marked outside its 7-day band or stay on one side of the median for 3 days or more. A value inside the band gets no proposal. Unavailable or short history is not zero or evidence of a problem.",
|
|
3
|
+
"One constraint: name the one step that limits throughput most, with its share of wait time or lost runs. Address that step first; use it better before adding capacity.",
|
|
4
|
+
"Paired metrics: read merged tickets with reverted or reopened work and main CI failures; busy lanes with flaky failures and fix rounds; faster CI with escaped faults. Never improve a value at the cost of its quality pair.",
|
|
5
|
+
"Evidence: each problem needs 2 or more occurrences in the window or a trend over 7 days, with links to runs, pull requests or CI jobs derived from the facts. Put a single event on the watch list. Remove claims without evidence; never invent values, links or trends.",
|
|
6
|
+
"At most 3 proposals. Each text contains the problem and evidence, a hypothesis, one change and its expected effect, a metric and a check date 3 to 7 days later, cost, how to reverse it and the result that shows failure. Prefer small reversible changes.",
|
|
7
|
+
"One change for each loop at a time: no proposal for a loop with an open improvement. If an open improvement's loop is unknown, propose no changes until it is identified.",
|
|
8
|
+
"Keep what works: list what went well and must not break.",
|
|
9
|
+
"Utilization: never propose keeping lanes, CI runners or the host busy above about 80% of the time.",
|
|
10
|
+
"The system, not a person: describe the system condition that allowed the problem; do not blame individuals.",
|
|
11
|
+
"Improvements in progress: for every open improvement compare its metric before and after the change, and at its check date give the verdict keep, reverse or continue with evidence. Unknown measurements mean continue, never a fabricated success.",
|
|
12
|
+
];
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { ScenarioRequest } from "cloving/workflows/testing";
|
|
2
|
+
|
|
3
|
+
export const selection = { post: "privacy", next: "idea" };
|
|
4
|
+
export const input = { cycleId: "review-1", input: {} };
|
|
5
|
+
export const report = {
|
|
6
|
+
facts:
|
|
7
|
+
"| Metric | Value | Median | Band | Mark |\n| --- | --- | --- | --- | --- |\n| merge minutes | 30 | 10 | 5–15 | outside |",
|
|
8
|
+
wentWell: "Main CI passed; preserve that quality.",
|
|
9
|
+
wentBadly: "Merge checks waited twice.",
|
|
10
|
+
constraint: "Merge checks account for 70% of wait time.",
|
|
11
|
+
improvementsInProgress: "None.",
|
|
12
|
+
proposals: [],
|
|
13
|
+
watchList: "One escaped fault; watch it.",
|
|
14
|
+
removed: [],
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const proposal = {
|
|
18
|
+
id: "merge-time",
|
|
19
|
+
loop: "merge",
|
|
20
|
+
text: "Loop: merge\n\nMerge checks timed out twice: https://github.com/acme/demo/actions/runs/10 and https://github.com/acme/demo/actions/runs/11. Hypothesis: the time limit is too short. One change: give the local merge check time factor 3. Expected effect: fewer timeouts; preserve main CI first-pass share. Check merge timeouts on 2026-11-06 (five days later). Cost: longer waits on real faults. Reverse by restoring factor 1. Failure: timeouts persist or main CI first-pass share drops.",
|
|
21
|
+
evidence: [
|
|
22
|
+
"https://github.com/acme/demo/actions/runs/10",
|
|
23
|
+
"https://github.com/acme/demo/actions/runs/11",
|
|
24
|
+
],
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export function completed(value: unknown = {}) {
|
|
28
|
+
return {
|
|
29
|
+
kind: "completed" as const,
|
|
30
|
+
operationId: "operation",
|
|
31
|
+
receipt: null,
|
|
32
|
+
result: JSON.stringify(value),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function effects() {
|
|
37
|
+
return {
|
|
38
|
+
"command run:report": [
|
|
39
|
+
completed({ metrics: { mergeMinutes: { value: 30, mark: "outside" } } }),
|
|
40
|
+
],
|
|
41
|
+
"command run:reviews": [completed([])],
|
|
42
|
+
"command run:improvements": [completed([])],
|
|
43
|
+
"claude run-turn": [
|
|
44
|
+
completed({ summary: JSON.stringify(report) }),
|
|
45
|
+
completed({ summary: JSON.stringify(report) }),
|
|
46
|
+
],
|
|
47
|
+
"github create-issue": [
|
|
48
|
+
completed({ number: 9, url: "https://github.com/acme/demo/issues/9" }),
|
|
49
|
+
],
|
|
50
|
+
"github discard": [completed()],
|
|
51
|
+
"github label": [completed(), completed()],
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function methods(requests: readonly ScenarioRequest[]) {
|
|
56
|
+
return requests.map((request) =>
|
|
57
|
+
request[0] === "effect" ? request[1].method : request[0],
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function proposalEffects() {
|
|
62
|
+
const draft = {
|
|
63
|
+
...report,
|
|
64
|
+
proposals: [
|
|
65
|
+
{ ...proposal, id: "first", text: "First measured change." },
|
|
66
|
+
proposal,
|
|
67
|
+
],
|
|
68
|
+
};
|
|
69
|
+
return {
|
|
70
|
+
...effects(),
|
|
71
|
+
"claude run-turn": [
|
|
72
|
+
completed({ summary: JSON.stringify(draft) }),
|
|
73
|
+
completed({ summary: JSON.stringify(draft) }),
|
|
74
|
+
],
|
|
75
|
+
};
|
|
76
|
+
}
|