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,82 @@
|
|
|
1
|
+
import { turnHarness } from "../harness-defaults.js";
|
|
2
|
+
import { reloadedSettingFields, } from "../project-settings.js";
|
|
3
|
+
import { record } from "../protocol.js";
|
|
4
|
+
import { parseFallbackModels, parseTokenPrices } from "../token-prices.js";
|
|
5
|
+
import { isProfilesFile } from "../turn-profile.js";
|
|
6
|
+
import { checkedProfiles } from "./worker-profile.js";
|
|
7
|
+
export function turnSettingsSource(initial) {
|
|
8
|
+
let current = initial;
|
|
9
|
+
return {
|
|
10
|
+
current: () => current,
|
|
11
|
+
replace: (next) => {
|
|
12
|
+
current = next;
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function turnSettingsOf(value) {
|
|
17
|
+
const fields = record(value) ?? {};
|
|
18
|
+
const profiles = { profiles: fields["profiles"] };
|
|
19
|
+
if (!isProfilesFile(profiles))
|
|
20
|
+
return undefined;
|
|
21
|
+
try {
|
|
22
|
+
return {
|
|
23
|
+
profiles: profiles.profiles,
|
|
24
|
+
fallbackModels: parseFallbackModels(JSON.stringify(fields["fallbackModels"])),
|
|
25
|
+
tokenPrices: parseTokenPrices(JSON.stringify(fields["tokenPrices"])),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function digestsOf(value) {
|
|
33
|
+
const fields = record(value);
|
|
34
|
+
if (fields === undefined)
|
|
35
|
+
return undefined;
|
|
36
|
+
const entries = Object.entries(fields);
|
|
37
|
+
const digests = entries.filter((entry) => typeof entry[1] === "string");
|
|
38
|
+
return digests.length === entries.length
|
|
39
|
+
? Object.fromEntries(digests)
|
|
40
|
+
: undefined;
|
|
41
|
+
}
|
|
42
|
+
export function reloadedSettings(output) {
|
|
43
|
+
const turnSettings = turnSettingsOf(output?.["turnSettings"]);
|
|
44
|
+
const settingDigests = digestsOf(output?.["settingDigests"]);
|
|
45
|
+
return turnSettings === undefined || settingDigests === undefined
|
|
46
|
+
? undefined
|
|
47
|
+
: { turnSettings, settingDigests };
|
|
48
|
+
}
|
|
49
|
+
export function settingChanges(current, next) {
|
|
50
|
+
const changed = [...new Set([...Object.keys(current), ...Object.keys(next)])]
|
|
51
|
+
.filter((field) => current[field] !== next[field])
|
|
52
|
+
.sort();
|
|
53
|
+
return {
|
|
54
|
+
reloadedFields: changed.filter((field) => reloadedSettingFields.includes(field)),
|
|
55
|
+
restartFields: changed.filter((field) => !reloadedSettingFields.includes(field)),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export function keptDigests(current, change) {
|
|
59
|
+
return {
|
|
60
|
+
...current,
|
|
61
|
+
...Object.fromEntries(Object.entries(change.digests).filter(([field]) => change.reloadedFields.includes(field))),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function newHarness(settings, profiles) {
|
|
65
|
+
const started = new Set([{}, ...Object.values(settings.profiles ?? {})].map((profile) => turnHarness(settings, profile).worker));
|
|
66
|
+
return Object.values(profiles)
|
|
67
|
+
.map((profile) => turnHarness(settings, profile).worker)
|
|
68
|
+
.find((name) => !started.has(name));
|
|
69
|
+
}
|
|
70
|
+
export function profileRefusal(settings, turnSettings) {
|
|
71
|
+
try {
|
|
72
|
+
checkedProfiles(settings, turnSettings.profiles);
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
const detail = String(Reflect.get(Object(error), "message"));
|
|
76
|
+
return { code: detail.replace(/:.*$/s, ""), detail };
|
|
77
|
+
}
|
|
78
|
+
const added = newHarness(settings, turnSettings.profiles);
|
|
79
|
+
return added === undefined
|
|
80
|
+
? undefined
|
|
81
|
+
: { code: "harness-no-worker", detail: `harness-no-worker: ${added}` };
|
|
82
|
+
}
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import { type DeclaredWorkflow } from "../workflow-declaration.ts";
|
|
2
2
|
import type { Resolver, WorkflowRegistration } from "../service/registry.ts";
|
|
3
|
+
import { type SubmissionContract } from "../submission.ts";
|
|
3
4
|
import type { LocalCommands } from "../command-settings.ts";
|
|
4
|
-
export declare const ticketWorkflow: "develop-ticket";
|
|
5
|
-
export declare const promptWorkflow: "develop-prompt";
|
|
6
|
-
export declare const issueWorkflow: "develop-issue";
|
|
7
|
-
export declare const ticketCapabilities: string[];
|
|
8
5
|
export type TicketRegistrations = {
|
|
9
6
|
readonly kind: "admitted";
|
|
10
7
|
readonly registrations: readonly WorkflowRegistration[];
|
|
@@ -24,10 +21,8 @@ export interface TicketRegistration extends Omit<WorkflowRegistration, "manifest
|
|
|
24
21
|
readonly effectLimit: number;
|
|
25
22
|
readonly capabilities?: readonly string[];
|
|
26
23
|
}
|
|
27
|
-
export declare function ticketResolver(source: TicketSource): Resolver;
|
|
28
|
-
export declare function issueResolver(source: TicketSource): Resolver;
|
|
29
|
-
export declare function promptResolver(repository: string): Resolver;
|
|
30
24
|
export declare function ticketRegistrationTable(source: TicketSource, declarations?: readonly DeclaredWorkflow[]): readonly TicketRegistration[];
|
|
25
|
+
export declare function declaredResolver(source: TicketSource, contract: SubmissionContract): Resolver;
|
|
31
26
|
export declare function ticketRegistrations(manifests: Readonly<Record<string, string | undefined>>, options: {
|
|
32
27
|
readonly table: readonly TicketRegistration[];
|
|
33
28
|
readonly bundleDigest?: string;
|
|
@@ -1,45 +1,34 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
1
|
import { admitCompiled } from "../cli/validate.js";
|
|
3
2
|
import { isCommandWaits, workflowQueueRefusals, } from "../workflow-declaration.js";
|
|
4
3
|
import { ticketCommandText, ticketText } from "./ticket-source.js";
|
|
5
4
|
import { declaredInput } from "./declared-input.js";
|
|
6
|
-
import { bundledWorkflowIds } from "../workflow-discovery.js";
|
|
7
5
|
import { declaredManifest } from "../execution-pin.js";
|
|
8
6
|
import { record } from "../protocol.js";
|
|
9
7
|
import { hasTicketField } from "../submission.js";
|
|
10
8
|
import { issueIdentity } from "../issue-identity.js";
|
|
11
9
|
import { ticketDependencyWaits, TicketDependencyReadError, } from "./ticket-dependency-waits.js";
|
|
12
|
-
|
|
13
|
-
export const promptWorkflow = bundledWorkflowIds.prompt;
|
|
14
|
-
export const issueWorkflow = bundledWorkflowIds.issue;
|
|
15
|
-
export const ticketCapabilities = ["claude", "github"];
|
|
10
|
+
const defaultCapabilities = ["claude", "github"];
|
|
16
11
|
const ticketIdentifier = /^[A-Za-z0-9._:-]{1,64}$/;
|
|
17
12
|
function rejected(code, detail) {
|
|
18
13
|
return { kind: "rejected", code, detail };
|
|
19
14
|
}
|
|
20
|
-
function digest(commandId) {
|
|
21
|
-
return createHash("sha256").update(commandId).digest("hex");
|
|
22
|
-
}
|
|
23
15
|
async function ticket(source, request) {
|
|
24
|
-
const { command
|
|
16
|
+
const { command } = source;
|
|
25
17
|
const ticketId = String(request.submission["ticket"]);
|
|
26
18
|
if (ticketId === "next")
|
|
27
19
|
return nextTicket(source, request);
|
|
28
20
|
if (!ticketIdentifier.test(ticketId))
|
|
29
21
|
return rejected("invalid-ticket-id", "A ticket ID has letters, digits and the characters . _ : - only.");
|
|
30
22
|
if (command === undefined)
|
|
31
|
-
return rejected("ticket-source-not-configured", "The daemon has no ticket command. Set CLOVING_TICKET_COMMAND
|
|
23
|
+
return rejected("ticket-source-not-configured", "The daemon has no ticket command. Set CLOVING_TICKET_COMMAND.");
|
|
32
24
|
const read = await ticketText(command, { ticketId, signal: request.signal });
|
|
33
25
|
if (read.kind === "failed")
|
|
34
26
|
return rejected("ticket-not-available", read.detail);
|
|
35
|
-
const name = ticketId.toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
36
27
|
return {
|
|
37
28
|
kind: "resolved",
|
|
38
29
|
input: {
|
|
39
|
-
cycleId: `${name}-${digest(request.commandId).slice(0, 8)}`,
|
|
40
30
|
ticketId,
|
|
41
31
|
ticket: read.text,
|
|
42
|
-
repository,
|
|
43
32
|
},
|
|
44
33
|
};
|
|
45
34
|
}
|
|
@@ -63,17 +52,10 @@ async function nextTicket(source, request) {
|
|
|
63
52
|
return rejected("invalid-ticket-id", "The next-ticket command must print one valid ticket ID other than next.");
|
|
64
53
|
return ticket(source, { ...request, submission: { ticket: selected.text } });
|
|
65
54
|
}
|
|
66
|
-
|
|
67
|
-
return {
|
|
68
|
-
id: "ticket-command",
|
|
69
|
-
version: "1",
|
|
70
|
-
resolve: (request) => ticket(source, request),
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
export function issueResolver(source) {
|
|
55
|
+
function ticketResolver(source) {
|
|
74
56
|
const waits = ticketDependencyWaits(source);
|
|
75
57
|
return {
|
|
76
|
-
id: "
|
|
58
|
+
id: "ticket-command",
|
|
77
59
|
version: "1",
|
|
78
60
|
skippedTickets: waits.skipped,
|
|
79
61
|
resolve: (request) => issueTicket({ source, waits }, request).catch((error) => {
|
|
@@ -107,66 +89,18 @@ async function issueTicket(context, request) {
|
|
|
107
89
|
return rejected("ticket-dependency-open", `Ticket ${String(input["ticketId"])} needs open issues: ${dependencies.map((id) => `#${id}`).join(", ")}.`);
|
|
108
90
|
return {
|
|
109
91
|
kind: "resolved",
|
|
110
|
-
input
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
export function promptResolver(repository) {
|
|
114
|
-
return {
|
|
115
|
-
id: "ticket-prompt",
|
|
116
|
-
version: "1",
|
|
117
|
-
resolve: (request) => Promise.resolve({
|
|
118
|
-
kind: "resolved",
|
|
119
|
-
input: {
|
|
120
|
-
cycleId: `task-${digest(request.commandId).slice(0, 12)}`,
|
|
121
|
-
ticket: String(request.submission["prompt"]),
|
|
122
|
-
repository,
|
|
123
|
-
},
|
|
124
|
-
}),
|
|
92
|
+
input,
|
|
125
93
|
};
|
|
126
94
|
}
|
|
127
95
|
export function ticketRegistrationTable(source, declarations = []) {
|
|
128
|
-
return
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
handoffs: [],
|
|
134
|
-
submission: { maximumBytes: 4_096, fields: { ticket: "string" } },
|
|
135
|
-
resolver: ticketResolver(source),
|
|
136
|
-
},
|
|
137
|
-
{
|
|
138
|
-
workflowId: issueWorkflow,
|
|
139
|
-
functionName: "developTicket",
|
|
140
|
-
effectLimit: 20,
|
|
141
|
-
handoffs: [],
|
|
142
|
-
submission: { maximumBytes: 4_096, fields: { ticket: "string" } },
|
|
143
|
-
resolver: issueResolver(source),
|
|
144
|
-
},
|
|
145
|
-
{
|
|
146
|
-
workflowId: bundledWorkflowIds.prd,
|
|
147
|
-
functionName: "developPrd",
|
|
148
|
-
effectLimit: 8,
|
|
149
|
-
handoffs: [issueWorkflow],
|
|
150
|
-
submission: { maximumBytes: 65_536, fields: { prompt: "string" } },
|
|
151
|
-
resolver: promptResolver(source.repository),
|
|
152
|
-
},
|
|
153
|
-
{
|
|
154
|
-
workflowId: promptWorkflow,
|
|
155
|
-
functionName: "developTicket",
|
|
156
|
-
effectLimit: 8,
|
|
157
|
-
handoffs: [],
|
|
158
|
-
submission: { maximumBytes: 65_536, fields: { prompt: "string" } },
|
|
159
|
-
resolver: promptResolver(source.repository),
|
|
160
|
-
},
|
|
161
|
-
...declarations.map(({ input, ...declaration }) => ({
|
|
162
|
-
...declaration,
|
|
163
|
-
submission: input,
|
|
164
|
-
resolver: declaredResolver(source, input),
|
|
165
|
-
})),
|
|
166
|
-
];
|
|
96
|
+
return declarations.map(({ input, ...declaration }) => ({
|
|
97
|
+
...declaration,
|
|
98
|
+
submission: input,
|
|
99
|
+
resolver: declaredResolver(source, input),
|
|
100
|
+
}));
|
|
167
101
|
}
|
|
168
|
-
function declaredResolver(source, contract) {
|
|
169
|
-
const tickets = hasTicketField(contract) ?
|
|
102
|
+
export function declaredResolver(source, contract) {
|
|
103
|
+
const tickets = hasTicketField(contract) ? ticketResolver(source) : undefined;
|
|
170
104
|
return {
|
|
171
105
|
id: "declared-input",
|
|
172
106
|
version: "1",
|
|
@@ -202,7 +136,7 @@ export async function ticketRegistrations(manifests, options) {
|
|
|
202
136
|
return { kind: "rejected", detail: refusal };
|
|
203
137
|
const registrations = [];
|
|
204
138
|
for (const row of options.table) {
|
|
205
|
-
const { functionName, capabilities =
|
|
139
|
+
const { functionName, capabilities = defaultCapabilities, ...registration } = row;
|
|
206
140
|
const manifest = manifests[functionName];
|
|
207
141
|
if (manifest === undefined)
|
|
208
142
|
return {
|
|
@@ -254,7 +188,7 @@ function registrationRefusal(table, commands) {
|
|
|
254
188
|
function commandRegistrationRefusal(row, commands) {
|
|
255
189
|
if (Object.hasOwn(row, "commandWaits") &&
|
|
256
190
|
!isCommandWaits(row.commandWaits, {
|
|
257
|
-
capabilities: row.capabilities ??
|
|
191
|
+
capabilities: row.capabilities ?? defaultCapabilities,
|
|
258
192
|
commands: row.commands ?? [],
|
|
259
193
|
}))
|
|
260
194
|
return `invalid-command-waits: ${row.workflowId}`;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type TurnEnd, type TurnProgress } from "./claude-turn.ts";
|
|
2
|
+
import { attemptCommand, type Attempts } from "./turn-attempts.ts";
|
|
3
|
+
declare function attemptEntry(attempts: Attempts, selected: ReturnType<typeof attemptCommand>): {
|
|
4
|
+
startedAt: string;
|
|
5
|
+
resumedAfter?: "daemon-restart";
|
|
6
|
+
attempt: number;
|
|
7
|
+
fallbackReason?: string;
|
|
8
|
+
budgetUsd?: number;
|
|
9
|
+
turnStartCommit: string | null;
|
|
10
|
+
model: string | null;
|
|
11
|
+
};
|
|
12
|
+
export declare function prepareAttempt(attempts: Attempts): Promise<{
|
|
13
|
+
entry: {
|
|
14
|
+
startedAt: string;
|
|
15
|
+
resumedAfter?: "daemon-restart";
|
|
16
|
+
attempt: number;
|
|
17
|
+
fallbackReason?: string;
|
|
18
|
+
budgetUsd?: number;
|
|
19
|
+
turnStartCommit: string | null;
|
|
20
|
+
model: string | null;
|
|
21
|
+
};
|
|
22
|
+
selected: {
|
|
23
|
+
fallbackReason?: string;
|
|
24
|
+
model: string | null;
|
|
25
|
+
budgetUsd?: number;
|
|
26
|
+
command: readonly string[];
|
|
27
|
+
};
|
|
28
|
+
folder: string;
|
|
29
|
+
} | undefined>;
|
|
30
|
+
export declare function attemptJournal(attempts: Attempts, entry: ReturnType<typeof attemptEntry>): {
|
|
31
|
+
progress: (snapshot: TurnProgress) => Promise<void>;
|
|
32
|
+
running: (identifier: number | null) => Promise<void>;
|
|
33
|
+
};
|
|
34
|
+
export declare function recordedEnd(attempts: Attempts, completion: {
|
|
35
|
+
readonly processId: number | null;
|
|
36
|
+
readonly end: TurnEnd;
|
|
37
|
+
}): Promise<void>;
|
|
38
|
+
export {};
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { mkdir } from "node:fs/promises";
|
|
3
|
+
import { readRecord, writeRecord } from "./operation-journal.js";
|
|
4
|
+
import { capacityRefusal, } from "./claude-turn.js";
|
|
5
|
+
import { attemptCommand, attemptUsage, attemptCost, } from "./turn-attempts.js";
|
|
6
|
+
function written(folder, entry) {
|
|
7
|
+
return writeRecord(folder, { ...entry, permissions: "private" });
|
|
8
|
+
}
|
|
9
|
+
function attemptEntry(attempts, selected) {
|
|
10
|
+
const attempt = attempts.ends.length + 1;
|
|
11
|
+
const resume = attempts.options.resume;
|
|
12
|
+
return {
|
|
13
|
+
...attempts.options.metadata,
|
|
14
|
+
turnStartCommit: attempts.turnStartCommit,
|
|
15
|
+
model: selected.model,
|
|
16
|
+
...(selected.budgetUsd === undefined
|
|
17
|
+
? {}
|
|
18
|
+
: { budgetUsd: selected.budgetUsd }),
|
|
19
|
+
...(selected.fallbackReason === undefined
|
|
20
|
+
? {}
|
|
21
|
+
: { fallbackReason: selected.fallbackReason }),
|
|
22
|
+
attempt,
|
|
23
|
+
...(resume !== undefined && attempt === resume.ends.length + 1
|
|
24
|
+
? { resumedAfter: "daemon-restart" }
|
|
25
|
+
: {}),
|
|
26
|
+
startedAt: attempt === 1 ? attempts.startedAt : new Date().toISOString(),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export async function prepareAttempt(attempts) {
|
|
30
|
+
const selected = attemptCommand(attempts, attempts.ends.length + 1);
|
|
31
|
+
if (selected.budgetUsd === 0) {
|
|
32
|
+
attempts.failure = "claude-turn-budget-exhausted";
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
const entry = attemptEntry(attempts, selected);
|
|
36
|
+
const folder = entry.attempt === 1
|
|
37
|
+
? attempts.start.folder
|
|
38
|
+
: join(attempts.start.folder, `attempt-${String(entry.attempt)}`);
|
|
39
|
+
await written(attempts.start.folder, {
|
|
40
|
+
name: "started.json",
|
|
41
|
+
value: {
|
|
42
|
+
...entry,
|
|
43
|
+
startedAt: attempts.startedAt,
|
|
44
|
+
phase: "starting",
|
|
45
|
+
processId: null,
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
await mkdir(folder, { recursive: true, mode: 0o700 });
|
|
49
|
+
return { entry, selected, folder };
|
|
50
|
+
}
|
|
51
|
+
function progressFields(attempts, progress) {
|
|
52
|
+
const result = progress?.result;
|
|
53
|
+
const end = { exitCode: null, result };
|
|
54
|
+
if (result === undefined)
|
|
55
|
+
return {
|
|
56
|
+
sessionId: progress?.sessionId ?? null,
|
|
57
|
+
sessionCostUsd: null,
|
|
58
|
+
costUsd: null,
|
|
59
|
+
};
|
|
60
|
+
return {
|
|
61
|
+
sessionId: progress?.sessionId ?? null,
|
|
62
|
+
sessionCostUsd: result.costUsd,
|
|
63
|
+
costUsd: attemptCost([...attempts.ends, end], attempts.ends.length),
|
|
64
|
+
usage: result.usage,
|
|
65
|
+
turns: result.turns,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
export function attemptJournal(attempts, entry) {
|
|
69
|
+
let saved = Promise.resolve();
|
|
70
|
+
let progress;
|
|
71
|
+
let processId = null;
|
|
72
|
+
const save = () => {
|
|
73
|
+
const value = {
|
|
74
|
+
...entry,
|
|
75
|
+
phase: "running",
|
|
76
|
+
processId,
|
|
77
|
+
...progressFields(attempts, progress),
|
|
78
|
+
};
|
|
79
|
+
saved = saved.then(() => written(attempts.start.folder, {
|
|
80
|
+
name: `attempt-${String(entry.attempt)}.json`,
|
|
81
|
+
value,
|
|
82
|
+
}));
|
|
83
|
+
return saved;
|
|
84
|
+
};
|
|
85
|
+
return {
|
|
86
|
+
progress: (snapshot) => {
|
|
87
|
+
progress = snapshot;
|
|
88
|
+
return save();
|
|
89
|
+
},
|
|
90
|
+
running: async (identifier) => {
|
|
91
|
+
processId = identifier;
|
|
92
|
+
await written(attempts.start.folder, {
|
|
93
|
+
name: "started.json",
|
|
94
|
+
value: {
|
|
95
|
+
...entry,
|
|
96
|
+
startedAt: attempts.startedAt,
|
|
97
|
+
phase: "running",
|
|
98
|
+
processId,
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
await save();
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export async function recordedEnd(attempts, completion) {
|
|
106
|
+
const { start, ends, options } = attempts;
|
|
107
|
+
const { processId, end } = completion;
|
|
108
|
+
const attempt = ends.length;
|
|
109
|
+
const selected = attemptCommand(attempts, attempt);
|
|
110
|
+
const name = `attempt-${String(attempt)}.json`;
|
|
111
|
+
const record = await readRecord(start.folder, name);
|
|
112
|
+
const started = typeof record === "object" && record !== null ? record : {};
|
|
113
|
+
const startedAt = Reflect.get(started, "startedAt");
|
|
114
|
+
if (typeof startedAt !== "string")
|
|
115
|
+
throw new Error("attempt-start-time-missing");
|
|
116
|
+
await written(start.folder, {
|
|
117
|
+
name,
|
|
118
|
+
value: {
|
|
119
|
+
...started,
|
|
120
|
+
...options.metadata,
|
|
121
|
+
turnStartCommit: attempts.turnStartCommit,
|
|
122
|
+
...attemptUsage(attempts, { end, attempt }),
|
|
123
|
+
...(selected.fallbackReason === undefined
|
|
124
|
+
? {}
|
|
125
|
+
: { fallbackReason: selected.fallbackReason }),
|
|
126
|
+
attempt,
|
|
127
|
+
processId,
|
|
128
|
+
startedAt,
|
|
129
|
+
endedAt: new Date().toISOString(),
|
|
130
|
+
exitCode: end.exitCode,
|
|
131
|
+
capacity: capacityRefusal(end.result),
|
|
132
|
+
sessionCostUsd: end.result?.costUsd ?? null,
|
|
133
|
+
turns: end.result?.turns ?? null,
|
|
134
|
+
},
|
|
135
|
+
});
|
|
136
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { usageOf, type WorkerAttemptUsage } from "../worker-usage.ts";
|
|
2
|
+
import { type TokenPrices } from "../token-prices.ts";
|
|
3
|
+
import { type TurnEnd, type TurnStart } from "./claude-turn.ts";
|
|
4
|
+
import type { TurnResume } from "./claude-recovery.ts";
|
|
5
|
+
export interface RetrySettings {
|
|
6
|
+
readonly tokenPrices?: TokenPrices;
|
|
7
|
+
readonly fallbackModels?: readonly string[];
|
|
8
|
+
readonly retryDelay?: (milliseconds: number, signal: AbortSignal) => Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export interface RetryOptions extends RetrySettings {
|
|
11
|
+
readonly resume?: TurnResume;
|
|
12
|
+
readonly stopping?: AbortController;
|
|
13
|
+
readonly stopMilliseconds?: number;
|
|
14
|
+
readonly metadata: Readonly<Record<string, unknown>>;
|
|
15
|
+
}
|
|
16
|
+
export interface Attempts {
|
|
17
|
+
failure?: string;
|
|
18
|
+
readonly start: TurnStart;
|
|
19
|
+
readonly turnStartCommit: string | null;
|
|
20
|
+
readonly startedAt: string;
|
|
21
|
+
readonly options: RetryOptions;
|
|
22
|
+
readonly stopping: AbortController;
|
|
23
|
+
readonly grace: {
|
|
24
|
+
milliseconds: number;
|
|
25
|
+
};
|
|
26
|
+
readonly ends: TurnEnd[];
|
|
27
|
+
}
|
|
28
|
+
export declare function total(values: readonly (number | null)[]): number | null;
|
|
29
|
+
export declare function combined(attempts: Attempts): TurnEnd;
|
|
30
|
+
export declare function attemptCommand(attempts: Attempts, attempt: number): {
|
|
31
|
+
fallbackReason?: string;
|
|
32
|
+
model: string | null;
|
|
33
|
+
budgetUsd?: number;
|
|
34
|
+
command: readonly string[];
|
|
35
|
+
};
|
|
36
|
+
export declare function attemptUsage(attempts: Attempts, completion: {
|
|
37
|
+
readonly end: TurnEnd;
|
|
38
|
+
readonly attempt: number;
|
|
39
|
+
}): WorkerAttemptUsage;
|
|
40
|
+
export declare function sessionCost(ends: readonly TurnEnd[]): number | null;
|
|
41
|
+
export declare function attemptCost(ends: readonly TurnEnd[], index: number): number | null;
|
|
42
|
+
export declare function attemptEstimate(attempts: Attempts, result: {
|
|
43
|
+
readonly end: TurnEnd;
|
|
44
|
+
readonly model: string | null;
|
|
45
|
+
readonly usage: ReturnType<typeof usageOf>;
|
|
46
|
+
}): number | null;
|
|
47
|
+
export declare function kindOf(attempts: Attempts, end: TurnEnd): import("../worker-usage.ts").RetryKind | null;
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { priceOf, sumUsage, usageOf, } from "../worker-usage.js";
|
|
2
|
+
import { commandModel, replaceCommandModel, estimatedCostUsd, priceForModel, } from "../token-prices.js";
|
|
3
|
+
import { capacityRefusal, retryKind, } from "./claude-turn.js";
|
|
4
|
+
import { nativeHarness } from "../harness-defaults.js";
|
|
5
|
+
import { profileCommand } from "../turn-profile.js";
|
|
6
|
+
export function total(values) {
|
|
7
|
+
if (values.includes(null))
|
|
8
|
+
return null;
|
|
9
|
+
return priceOf(values.reduce((sum, value) => sum + (value ?? 0), 0));
|
|
10
|
+
}
|
|
11
|
+
export function combined(attempts) {
|
|
12
|
+
const { ends } = attempts;
|
|
13
|
+
const last = ends.at(-1) ?? { exitCode: null, result: undefined };
|
|
14
|
+
const result = last.result ?? ends.find((end) => end.result)?.result;
|
|
15
|
+
if (result === undefined)
|
|
16
|
+
return last;
|
|
17
|
+
return {
|
|
18
|
+
...last,
|
|
19
|
+
result: {
|
|
20
|
+
...result,
|
|
21
|
+
attempts: ends.map((end, index) => attemptUsage(attempts, { end, attempt: index + 1 })),
|
|
22
|
+
...(last.result === undefined ? { failed: true, text: "" } : {}),
|
|
23
|
+
usage: sumUsage(ends.map((end) => end.result?.usage ?? usageOf(null))),
|
|
24
|
+
costUsd: (attempts.start.worker ?? "claude") === "claude"
|
|
25
|
+
? sessionCost(ends)
|
|
26
|
+
: total(ends.map((end) => end.result?.costUsd ?? null)),
|
|
27
|
+
turns: total(ends.map((end) => end.result?.turns ?? null)),
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function selectedCommand(attempts, attempt) {
|
|
32
|
+
const { start, options } = attempts;
|
|
33
|
+
const original = start.command;
|
|
34
|
+
const previous = attempts.ends[attempt - 2];
|
|
35
|
+
if (options.resume !== undefined &&
|
|
36
|
+
attempt === options.resume.ends.length + 1) {
|
|
37
|
+
const model = previous?.result?.model;
|
|
38
|
+
return {
|
|
39
|
+
command: model == null ? original : replaceCommandModel(original, model),
|
|
40
|
+
fallback: undefined,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
const ordinal = attempt -
|
|
44
|
+
attempts.ends
|
|
45
|
+
.slice(0, attempt - 1)
|
|
46
|
+
.filter((end) => end.resumedAfter !== undefined).length;
|
|
47
|
+
const fallback = previous !== undefined && kindOf(attempts, previous) === "capacity"
|
|
48
|
+
? options.fallbackModels?.[ordinal - 3]
|
|
49
|
+
: undefined;
|
|
50
|
+
return {
|
|
51
|
+
command: fallback === undefined
|
|
52
|
+
? original
|
|
53
|
+
: replaceCommandModel(original, fallback),
|
|
54
|
+
fallback,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export function attemptCommand(attempts, attempt) {
|
|
58
|
+
const { start } = attempts;
|
|
59
|
+
const { command: selected, fallback } = selectedCommand(attempts, attempt);
|
|
60
|
+
const budgetUsd = remainingBudget(attempts);
|
|
61
|
+
const command = budgetUsd === undefined
|
|
62
|
+
? selected
|
|
63
|
+
: profileCommand(selected, { maxBudgetUsd: budgetUsd });
|
|
64
|
+
const model = start.output === "text" ? null : commandModel(command);
|
|
65
|
+
return {
|
|
66
|
+
command,
|
|
67
|
+
...(budgetUsd === undefined ? {} : { budgetUsd }),
|
|
68
|
+
model,
|
|
69
|
+
...(fallback !== undefined && model === null
|
|
70
|
+
? { fallbackReason: "fallback-model-unavailable" }
|
|
71
|
+
: {}),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
export function attemptUsage(attempts, completion) {
|
|
75
|
+
const { end, attempt } = completion;
|
|
76
|
+
const result = end.result ?? {
|
|
77
|
+
model: null,
|
|
78
|
+
usage: usageOf(null),
|
|
79
|
+
costUsd: null,
|
|
80
|
+
pricingModel: undefined,
|
|
81
|
+
};
|
|
82
|
+
const model = result.model ?? attemptCommand(attempts, attempt).model;
|
|
83
|
+
const usage = result.usage;
|
|
84
|
+
return {
|
|
85
|
+
attempt,
|
|
86
|
+
...(end.resumedAfter === undefined
|
|
87
|
+
? {}
|
|
88
|
+
: { resumedAfter: end.resumedAfter }),
|
|
89
|
+
retryKind: kindOf(attempts, end),
|
|
90
|
+
model,
|
|
91
|
+
...(end.result?.models === undefined ? {} : { models: end.result.models }),
|
|
92
|
+
usage,
|
|
93
|
+
costUsd: (attempts.start.worker ?? "claude") === "claude"
|
|
94
|
+
? attemptCost(attempts.ends, attempt - 1)
|
|
95
|
+
: result.costUsd,
|
|
96
|
+
estimatedCostUsd: attemptEstimate(attempts, { end, model, usage }),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
export function sessionCost(ends) {
|
|
100
|
+
const sessions = new Map();
|
|
101
|
+
ends.forEach((end, index) => {
|
|
102
|
+
sessions.set(end.result?.sessionId ?? index, end.result?.costUsd ?? null);
|
|
103
|
+
});
|
|
104
|
+
return total([...sessions.values()]);
|
|
105
|
+
}
|
|
106
|
+
export function attemptCost(ends, index) {
|
|
107
|
+
const result = ends[index]?.result;
|
|
108
|
+
if (result?.costUsd == null)
|
|
109
|
+
return null;
|
|
110
|
+
const earlier = result.sessionId === null
|
|
111
|
+
? undefined
|
|
112
|
+
: ends
|
|
113
|
+
.slice(0, index)
|
|
114
|
+
.findLast((end) => end.result?.sessionId === result.sessionId);
|
|
115
|
+
if (earlier === undefined)
|
|
116
|
+
return result.costUsd;
|
|
117
|
+
const cost = earlier.result?.costUsd;
|
|
118
|
+
return cost == null
|
|
119
|
+
? null
|
|
120
|
+
: priceOf(Number((result.costUsd - cost).toFixed(12)));
|
|
121
|
+
}
|
|
122
|
+
function remainingBudget(attempts) {
|
|
123
|
+
if ((attempts.start.worker ?? "claude") !== "claude" ||
|
|
124
|
+
attempts.start.output === "text")
|
|
125
|
+
return undefined;
|
|
126
|
+
const budget = commandBudget(attempts.start.command);
|
|
127
|
+
if (budget === undefined)
|
|
128
|
+
return undefined;
|
|
129
|
+
const spent = sessionCost(attempts.ends);
|
|
130
|
+
return Math.max(0, Number((budget - (spent ?? 0)).toFixed(12)));
|
|
131
|
+
}
|
|
132
|
+
function commandBudget(original) {
|
|
133
|
+
const separator = original.indexOf("--");
|
|
134
|
+
const command = separator < 0 ? original : original.slice(0, separator);
|
|
135
|
+
const index = command.findLastIndex((part) => part === "--max-budget-usd" || part.startsWith("--max-budget-usd="));
|
|
136
|
+
if (index < 0)
|
|
137
|
+
return undefined;
|
|
138
|
+
const argument = command[index] ?? "";
|
|
139
|
+
const budget = Number(argument.includes("=") ? argument.split("=")[1] : command[index + 1]);
|
|
140
|
+
if (!Number.isFinite(budget) || budget < 0)
|
|
141
|
+
return undefined;
|
|
142
|
+
return budget;
|
|
143
|
+
}
|
|
144
|
+
export function attemptEstimate(attempts, result) {
|
|
145
|
+
const worker = attempts.start.worker ?? "claude";
|
|
146
|
+
if (!nativeHarness(worker))
|
|
147
|
+
return null;
|
|
148
|
+
const models = result.end.result?.models;
|
|
149
|
+
const prices = attempts.options.tokenPrices ?? {};
|
|
150
|
+
return estimatedCostUsd(result.usage, worker === "gemini" && models !== undefined
|
|
151
|
+
? { worker, models, prices }
|
|
152
|
+
: {
|
|
153
|
+
worker,
|
|
154
|
+
price: priceForModel(prices, result.end.result?.pricingModel === undefined
|
|
155
|
+
? result.model
|
|
156
|
+
: result.end.result.pricingModel),
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
export function kindOf(attempts, end) {
|
|
160
|
+
const { worker, output } = attempts.start;
|
|
161
|
+
if (output === "text" || !["claude", "codex"].includes(worker ?? "claude"))
|
|
162
|
+
return null;
|
|
163
|
+
if (worker !== "codex")
|
|
164
|
+
return end.retryKind ?? retryKind(end.result);
|
|
165
|
+
return capacityRefusal(end.result) ? "capacity" : null;
|
|
166
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type SweepSettings } from "./record-sweep.ts";
|
|
2
|
+
import { type RunTurns, type TurnDetails } from "../record-retention.ts";
|
|
3
|
+
export type TurnDetailsSettings = Pick<SweepSettings, "directory" | "retention" | "runs" | "now">;
|
|
4
|
+
export declare function turnDetailsPlace(settings: TurnDetailsSettings): (turns: RunTurns) => Promise<TurnDetails | undefined>;
|