cloving 1.2.0 → 1.3.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 +525 -185
- package/dist/src/agent-harness-shell.d.ts +12 -0
- package/dist/src/agent-harness-shell.js +90 -0
- package/dist/src/agent-harness-versions.d.ts +8 -0
- package/dist/src/agent-harness-versions.js +49 -0
- package/dist/src/agent-harnesses.d.ts +4 -0
- package/dist/src/agent-harnesses.js +13 -0
- package/dist/src/authority/commands.d.ts +1 -0
- package/dist/src/authority/commands.js +24 -4
- package/dist/src/authority/gate-reduction.d.ts +1 -0
- package/dist/src/authority/gate-reduction.js +18 -3
- package/dist/src/authority/gates.d.ts +2 -1
- package/dist/src/authority/gates.js +5 -1
- package/dist/src/authority/operations.js +1 -1
- package/dist/src/authority/reduction.d.ts +1 -1
- package/dist/src/authority/reduction.js +6 -1
- package/dist/src/authority/status-input.d.ts +1 -1
- package/dist/src/authority/status.d.ts +1 -0
- package/dist/src/authority/status.js +27 -3
- package/dist/src/authority/transitions.d.ts +5 -5
- package/dist/src/authority/transitions.js +6 -0
- package/dist/src/broker/actor/authority-delivery.js +1 -0
- package/dist/src/broker/actor/authority-queries.d.ts +7 -1
- package/dist/src/broker/actor/authority-queries.js +17 -2
- package/dist/src/broker/actor/authority-receipts.js +11 -1
- package/dist/src/broker/actor/authority-session.js +2 -2
- package/dist/src/broker/actor/authority-settings.js +4 -0
- package/dist/src/broker/actor/delivery-intents.d.ts +2 -1
- package/dist/src/broker/actor/delivery-intents.js +4 -4
- package/dist/src/broker/actor/effect-delivery.js +4 -1
- package/dist/src/broker/actor/effect-queries.d.ts +1 -0
- package/dist/src/broker/actor/effect-queries.js +7 -0
- package/dist/src/broker/actor/pin-check.js +1 -1
- package/dist/src/broker/actor/stop-plan.js +1 -1
- package/dist/src/broker/actor/turn-state.js +1 -1
- package/dist/src/broker/authority-admission.js +22 -9
- package/dist/src/broker/authority-restore.js +1 -0
- package/dist/src/broker/decision-restore.js +4 -4
- package/dist/src/broker/socket-address.d.ts +3 -1
- package/dist/src/broker/socket-address.js +2 -2
- package/dist/src/cli/arguments.d.ts +11 -13
- package/dist/src/cli/arguments.js +37 -107
- package/dist/src/cli/command-effects.d.ts +7 -0
- package/dist/src/cli/command-effects.js +39 -0
- package/dist/src/cli/commands.js +11 -4
- package/dist/src/cli/config-arguments.d.ts +11 -0
- package/dist/src/cli/config-arguments.js +59 -0
- package/dist/src/cli/config-command.d.ts +2 -0
- package/dist/src/cli/config-command.js +105 -0
- package/dist/src/cli/config-file.d.ts +3 -0
- package/dist/src/cli/config-file.js +50 -0
- package/dist/src/cli/config-lock.d.ts +7 -0
- package/dist/src/cli/config-lock.js +61 -0
- package/dist/src/cli/config-notice.d.ts +5 -0
- package/dist/src/cli/config-notice.js +46 -0
- package/dist/src/cli/doctor-github.d.ts +9 -0
- package/dist/src/cli/doctor-github.js +138 -0
- package/dist/src/cli/doctor-harness.d.ts +13 -0
- package/dist/src/cli/doctor-harness.js +242 -0
- package/dist/src/cli/doctor-local.d.ts +18 -0
- package/dist/src/cli/doctor-local.js +77 -0
- package/dist/src/cli/doctor-runtime.d.ts +15 -0
- package/dist/src/cli/doctor-runtime.js +176 -0
- package/dist/src/cli/doctor-service.d.ts +1 -0
- package/dist/src/cli/doctor-service.js +11 -0
- package/dist/src/cli/doctor-workflows.d.ts +3 -0
- package/dist/src/cli/doctor-workflows.js +45 -0
- package/dist/src/cli/doctor.d.ts +15 -0
- package/dist/src/cli/doctor.js +190 -0
- package/dist/src/cli/github-ci-progress.d.ts +8 -0
- package/dist/src/cli/github-ci-progress.js +83 -0
- package/dist/src/cli/github-retry.d.ts +6 -0
- package/dist/src/cli/github-retry.js +47 -0
- package/dist/src/cli/harness-probes.d.ts +22 -0
- package/dist/src/cli/harness-probes.js +183 -0
- package/dist/src/cli/main.d.ts +7 -1
- package/dist/src/cli/main.js +39 -61
- package/dist/src/cli/phone-arguments.d.ts +14 -0
- package/dist/src/cli/phone-arguments.js +37 -0
- package/dist/src/cli/phone-client.d.ts +2 -0
- package/dist/src/cli/phone-client.js +32 -0
- package/dist/src/cli/phone-command.d.ts +13 -0
- package/dist/src/cli/phone-command.js +101 -0
- package/dist/src/cli/probe-command.d.ts +36 -0
- package/dist/src/cli/probe-command.js +59 -0
- package/dist/src/cli/project-settings.d.ts +4 -0
- package/dist/src/cli/project-settings.js +33 -0
- package/dist/src/cli/render.d.ts +2 -1
- package/dist/src/cli/render.js +44 -28
- package/dist/src/cli/report-github.d.ts +18 -0
- package/dist/src/cli/report-github.js +200 -0
- package/dist/src/cli/report.d.ts +17 -0
- package/dist/src/cli/report.js +192 -0
- package/dist/src/cli/repository-arguments.d.ts +5 -0
- package/dist/src/cli/repository-arguments.js +34 -0
- package/dist/src/cli/runtime-arguments.d.ts +4 -0
- package/dist/src/cli/runtime-arguments.js +15 -0
- package/dist/src/cli/runtime-directory.d.ts +6 -2
- package/dist/src/cli/runtime-directory.js +72 -14
- package/dist/src/cli/toolchain.d.ts +2 -0
- package/dist/src/cli/toolchain.js +22 -2
- package/dist/src/cli/usage-render.d.ts +5 -0
- package/dist/src/cli/usage-render.js +40 -1
- package/dist/src/cli/usage.d.ts +3 -3
- package/dist/src/cli/usage.js +70 -44
- package/dist/src/cli/watch-actions.d.ts +2 -0
- package/dist/src/cli/watch-actions.js +4 -4
- package/dist/src/cli/watch-board-view.d.ts +1 -1
- package/dist/src/cli/watch-board-view.js +8 -2
- package/dist/src/cli/watch-board.js +23 -10
- package/dist/src/cli/watch-card-forms.js +2 -2
- package/dist/src/cli/watch-client.d.ts +1 -1
- package/dist/src/cli/watch-client.js +7 -2
- package/dist/src/cli/watch-header-view.d.ts +27 -0
- package/dist/src/cli/watch-header-view.js +116 -0
- package/dist/src/cli/watch-model.js +17 -4
- package/dist/src/cli/watch-page.js +48 -12
- package/dist/src/cli/watch-phone-client.d.ts +1 -0
- package/dist/src/cli/watch-phone-client.js +84 -0
- package/dist/src/cli/watch-phone-view.d.ts +56 -0
- package/dist/src/cli/watch-phone-view.js +113 -0
- package/dist/src/cli/watch-phone.d.ts +5 -0
- package/dist/src/cli/watch-phone.js +53 -0
- package/dist/src/cli/watch-pull-request.d.ts +3 -1
- package/dist/src/cli/watch-pull-request.js +4 -0
- package/dist/src/cli/watch-render.d.ts +9 -1
- package/dist/src/cli/watch-server.js +23 -5
- package/dist/src/cli/watch-turn.d.ts +4 -1
- package/dist/src/cli/watch-turn.js +37 -1
- package/dist/src/cli/watch-usage.js +5 -1
- package/dist/src/cli/watch-view.d.ts +6 -20
- package/dist/src/cli/watch-view.js +14 -106
- package/dist/src/cli.js +106 -23
- package/dist/src/command-settings.d.ts +16 -0
- package/dist/src/command-settings.js +42 -0
- package/dist/src/configuration-change.d.ts +11 -0
- package/dist/src/configuration-change.js +62 -0
- package/dist/src/configuration-display.d.ts +21 -0
- package/dist/src/configuration-display.js +69 -0
- package/dist/src/configuration-schema.d.ts +49 -0
- package/dist/src/configuration-schema.js +159 -0
- package/dist/src/daemon/claude-turn.d.ts +19 -5
- package/dist/src/daemon/claude-turn.js +116 -53
- package/dist/src/daemon/claude-worker.d.ts +3 -3
- package/dist/src/daemon/claude-worker.js +65 -76
- package/dist/src/daemon/command-journal.d.ts +5 -0
- package/dist/src/daemon/command-journal.js +50 -0
- package/dist/src/daemon/command-process.d.ts +28 -0
- package/dist/src/daemon/command-process.js +164 -0
- package/dist/src/daemon/command-worker.d.ts +19 -0
- package/dist/src/daemon/command-worker.js +182 -0
- package/dist/src/daemon/cursor-stream.d.ts +4 -0
- package/dist/src/daemon/cursor-stream.js +154 -0
- package/dist/src/daemon/daemon-adapters.d.ts +58 -0
- package/dist/src/daemon/daemon-adapters.js +102 -0
- package/dist/src/daemon/daemon-loops.d.ts +14 -0
- package/dist/src/daemon/daemon-loops.js +39 -0
- package/dist/src/daemon/daemon.d.ts +2 -33
- package/dist/src/daemon/daemon.js +126 -132
- package/dist/src/daemon/declared-input.d.ts +3 -0
- package/dist/src/daemon/declared-input.js +9 -0
- package/dist/src/daemon/delivery-router.js +1 -1
- package/dist/src/daemon/gemini-stream.d.ts +4 -0
- package/dist/src/daemon/gemini-stream.js +129 -0
- package/dist/src/daemon/github-ci-rerun.d.ts +26 -0
- package/dist/src/daemon/github-ci-rerun.js +92 -0
- package/dist/src/daemon/github-ci.js +89 -8
- package/dist/src/daemon/github-merge-call.d.ts +2 -0
- package/dist/src/daemon/github-merge.js +7 -3
- package/dist/src/daemon/github-methods.js +10 -0
- package/dist/src/daemon/github-operation.d.ts +1 -0
- package/dist/src/daemon/github-retry.js +8 -44
- package/dist/src/daemon/issue-queue.d.ts +1 -0
- package/dist/src/daemon/issue-queue.js +3 -26
- package/dist/src/daemon/notify.js +2 -1
- package/dist/src/daemon/opencode-stream.d.ts +5 -0
- package/dist/src/daemon/opencode-stream.js +87 -0
- package/dist/src/daemon/queue-status.d.ts +4 -0
- package/dist/src/daemon/queue-status.js +38 -0
- package/dist/src/daemon/retry-worktree.d.ts +18 -0
- package/dist/src/daemon/retry-worktree.js +139 -0
- package/dist/src/daemon/retrying-turn.d.ts +2 -0
- package/dist/src/daemon/retrying-turn.js +108 -30
- package/dist/src/daemon/schedule-journal.d.ts +19 -0
- package/dist/src/daemon/schedule-journal.js +57 -0
- package/dist/src/daemon/text-output.d.ts +18 -0
- package/dist/src/daemon/text-output.js +44 -0
- package/dist/src/daemon/ticket-registration.d.ts +5 -7
- package/dist/src/daemon/ticket-registration.js +85 -40
- package/dist/src/daemon/turn-command.d.ts +10 -0
- package/dist/src/daemon/turn-command.js +33 -0
- package/dist/src/daemon/turn-report.d.ts +18 -0
- package/dist/src/daemon/turn-report.js +79 -0
- package/dist/src/daemon/work-tree.d.ts +2 -1
- package/dist/src/daemon/work-tree.js +15 -12
- package/dist/src/daemon/workflow-generations.d.ts +32 -0
- package/dist/src/daemon/workflow-generations.js +57 -0
- package/dist/src/daemon/workflow-replay.d.ts +16 -0
- package/dist/src/daemon/workflow-replay.js +58 -0
- package/dist/src/daemon/workflow-schedules.d.ts +27 -0
- package/dist/src/daemon/workflow-schedules.js +185 -0
- package/dist/src/decision-wait.d.ts +1 -0
- package/dist/src/decision-wait.js +3 -0
- package/dist/src/delivery-backoff.d.ts +1 -0
- package/dist/src/delivery-backoff.js +3 -0
- package/dist/src/doctor-report.d.ts +24 -0
- package/dist/src/doctor-report.js +70 -0
- package/dist/src/execution-pin.d.ts +5 -0
- package/dist/src/execution-pin.js +67 -4
- package/dist/src/grok-result.d.ts +12 -0
- package/dist/src/grok-result.js +61 -0
- package/dist/src/harness-defaults.d.ts +35 -0
- package/dist/src/harness-defaults.js +121 -0
- package/dist/src/host/decision-resume.d.ts +35 -0
- package/dist/src/host/decision-resume.js +86 -0
- package/dist/src/host/gate-bridge.d.ts +48 -0
- package/dist/src/host/gate-bridge.js +124 -0
- package/dist/src/host/run-wait.d.ts +26 -0
- package/dist/src/host/run-wait.js +37 -0
- package/dist/src/host/start-delivery.d.ts +1 -1
- package/dist/src/host/start-delivery.js +10 -3
- package/dist/src/host/step-bridge-host.d.ts +6 -20
- package/dist/src/host/step-bridge-host.js +44 -58
- package/dist/src/merge-request.d.ts +19 -0
- package/dist/src/merge-request.js +32 -0
- package/dist/src/phone/canonical-json.d.ts +1 -0
- package/dist/src/phone/canonical-json.js +16 -0
- package/dist/src/phone/phone-link.d.ts +7 -0
- package/dist/src/phone/phone-link.js +21 -0
- package/dist/src/phone/qr-data.d.ts +8 -0
- package/dist/src/phone/qr-data.js +133 -0
- package/dist/src/phone/qr-matrix.d.ts +6 -0
- package/dist/src/phone/qr-matrix.js +175 -0
- package/dist/src/phone/qr-penalty.d.ts +3 -0
- package/dist/src/phone/qr-penalty.js +67 -0
- package/dist/src/phone/qr-picture.d.ts +5 -0
- package/dist/src/phone/qr-picture.js +24 -0
- package/dist/src/private-config.schema.json +263 -0
- package/dist/src/project-config.schema.json +65 -0
- package/dist/src/project-settings.d.ts +19 -0
- package/dist/src/project-settings.js +131 -0
- package/dist/src/relay/answer-check.d.ts +24 -0
- package/dist/src/relay/answer-check.js +145 -0
- package/dist/src/relay/answer-inbox.d.ts +15 -0
- package/dist/src/relay/answer-inbox.js +173 -0
- package/dist/src/relay/daemon-keys.d.ts +16 -0
- package/dist/src/relay/daemon-keys.js +75 -0
- package/dist/src/relay/decision-check.d.ts +3 -0
- package/dist/src/relay/decision-check.js +77 -0
- package/dist/src/relay/decision-close.d.ts +6 -0
- package/dist/src/relay/decision-close.js +72 -0
- package/dist/src/relay/decision-envelopes.d.ts +29 -0
- package/dist/src/relay/decision-envelopes.js +93 -0
- package/dist/src/relay/decision-watch.d.ts +14 -0
- package/dist/src/relay/decision-watch.js +68 -0
- package/dist/src/relay/envelope-post.d.ts +8 -0
- package/dist/src/relay/envelope-post.js +71 -0
- package/dist/src/relay/envelope.d.ts +28 -0
- package/dist/src/relay/envelope.js +53 -0
- package/dist/src/relay/hpke.d.ts +25 -0
- package/dist/src/relay/hpke.js +108 -0
- package/dist/src/relay/pairing-checks.d.ts +42 -0
- package/dist/src/relay/pairing-checks.js +172 -0
- package/dist/src/relay/pairing-follow.d.ts +8 -0
- package/dist/src/relay/pairing-follow.js +95 -0
- package/dist/src/relay/pairing-session.d.ts +29 -0
- package/dist/src/relay/pairing-session.js +87 -0
- package/dist/src/relay/phone-delivery.d.ts +51 -0
- package/dist/src/relay/phone-delivery.js +139 -0
- package/dist/src/relay/phone-devices.d.ts +36 -0
- package/dist/src/relay/phone-devices.js +46 -0
- package/dist/src/relay/phone-inbox.d.ts +18 -0
- package/dist/src/relay/phone-inbox.js +17 -0
- package/dist/src/relay/phone-operations.d.ts +18 -0
- package/dist/src/relay/phone-operations.js +121 -0
- package/dist/src/relay/phone-outbox.d.ts +21 -0
- package/dist/src/relay/phone-outbox.js +25 -0
- package/dist/src/relay/phone-socket.d.ts +6 -0
- package/dist/src/relay/phone-socket.js +63 -0
- package/dist/src/relay/relay-control.d.ts +7 -0
- package/dist/src/relay/relay-control.js +24 -0
- package/dist/src/relay/relay-files.d.ts +2 -0
- package/dist/src/relay/relay-files.js +23 -0
- package/dist/src/relay/relay-heartbeat.d.ts +17 -0
- package/dist/src/relay/relay-heartbeat.js +81 -0
- package/dist/src/relay/relay-http.d.ts +14 -0
- package/dist/src/relay/relay-http.js +63 -0
- package/dist/src/relay/relay-registration.d.ts +15 -0
- package/dist/src/relay/relay-registration.js +63 -0
- package/dist/src/relay/relay-service.d.ts +25 -0
- package/dist/src/relay/relay-service.js +216 -0
- package/dist/src/relay/relay-store.d.ts +48 -0
- package/dist/src/relay/relay-store.js +131 -0
- package/dist/src/relay/sealed-post.d.ts +25 -0
- package/dist/src/relay/sealed-post.js +52 -0
- package/dist/src/relay.d.ts +1 -0
- package/dist/src/relay.js +8 -0
- package/dist/src/report-statistics.d.ts +50 -0
- package/dist/src/report-statistics.js +70 -0
- package/dist/src/report.d.ts +171 -0
- package/dist/src/report.js +119 -0
- package/dist/src/repository-identity.d.ts +4 -0
- package/dist/src/repository-identity.js +4 -0
- package/dist/src/review-subject.d.ts +41 -0
- package/dist/src/review-subject.js +91 -0
- package/dist/src/run-wait.d.ts +23 -0
- package/dist/src/run-wait.js +20 -0
- package/dist/src/service/active-tickets.d.ts +4 -0
- package/dist/src/service/active-tickets.js +49 -0
- package/dist/src/service/command-effects.d.ts +4 -0
- package/dist/src/service/command-effects.js +16 -0
- package/dist/src/service/decision-handler.d.ts +4 -0
- package/dist/src/service/decision-handler.js +39 -4
- package/dist/src/service/gateway.js +18 -3
- package/dist/src/service/registry.d.ts +16 -3
- package/dist/src/service/registry.js +34 -3
- package/dist/src/service/replies.d.ts +9 -1
- package/dist/src/service/replies.js +12 -0
- package/dist/src/service/run-handlers.js +14 -55
- package/dist/src/service/run-metadata.d.ts +8 -0
- package/dist/src/service/run-metadata.js +53 -0
- package/dist/src/service/run-waits.d.ts +3 -0
- package/dist/src/service/run-waits.js +41 -0
- package/dist/src/service/service.d.ts +18 -2
- package/dist/src/service/service.js +23 -7
- package/dist/src/service/submission-handler.d.ts +0 -1
- package/dist/src/service/submission-handler.js +6 -34
- package/dist/src/service/worker-port.d.ts +1 -0
- package/dist/src/service/worker-totals.js +8 -23
- package/dist/src/step-bridge.d.ts +23 -0
- package/dist/src/steps/decision-gate.d.ts +2 -1
- package/dist/src/steps/decision-gate.js +7 -0
- package/dist/src/steps/merge-by-person.d.ts +2 -0
- package/dist/src/steps/merge-by-person.js +18 -0
- package/dist/src/steps/merge-when-green.d.ts +2 -0
- package/dist/src/steps/merge-when-green.js +62 -0
- package/dist/src/steps/review-by-agent.d.ts +5 -0
- package/dist/src/steps/review-by-agent.js +124 -0
- package/dist/src/steps/review-by-person.d.ts +4 -0
- package/dist/src/steps/review-by-person.js +16 -0
- package/dist/src/steps/review-subject.d.ts +2 -0
- package/dist/src/steps/review-subject.js +11 -0
- package/dist/src/steps/run-command.d.ts +2 -0
- package/dist/src/steps/run-command.js +15 -0
- package/dist/src/steps/sleep.d.ts +3 -0
- package/dist/src/steps/sleep.js +19 -0
- package/dist/src/steps/wait-for-decision.d.ts +2 -0
- package/dist/src/steps/wait-for-decision.js +71 -0
- package/dist/src/steps/wait-for-run.d.ts +5 -0
- package/dist/src/steps/wait-for-run.js +9 -0
- package/dist/src/storage/decision-snapshots.d.ts +1 -0
- package/dist/src/storage/decision-snapshots.js +7 -1
- package/dist/src/submission.d.ts +4 -0
- package/dist/src/submission.js +6 -2
- package/dist/src/testing.d.ts +29 -0
- package/dist/src/testing.js +264 -0
- package/dist/src/ticket-status-stream.d.ts +9 -0
- package/dist/src/ticket-status-stream.js +94 -0
- package/dist/src/token-prices.d.ts +12 -4
- package/dist/src/token-prices.js +15 -2
- package/dist/src/turn-profile.d.ts +1 -0
- package/dist/src/turn-profile.js +8 -1
- package/dist/src/worker-usage.d.ts +16 -0
- package/dist/src/worker-usage.js +57 -0
- package/dist/src/workflow-admission.d.ts +5 -0
- package/dist/src/workflow-candidate.d.ts +7 -2
- package/dist/src/workflow-candidate.js +47 -5
- package/dist/src/workflow-declaration.d.ts +21 -3
- package/dist/src/workflow-declaration.js +77 -9
- package/dist/src/workflow-discovery.d.ts +2 -1
- package/dist/src/workflow-discovery.js +4 -1
- package/dist/src/workflow-refusals.js +3 -0
- package/dist/src/workflow-schedule.d.ts +22 -0
- package/dist/src/workflow-schedule.js +53 -0
- package/dist/src/workflows.d.ts +11 -1
- package/dist/src/workflows.js +8 -0
- package/dist/tools/admit-workflow.d.ts +1 -0
- package/dist/tools/admit-workflow.js +18 -5
- package/dist/tools/doctor-adoption.d.ts +1 -0
- package/dist/tools/doctor-adoption.js +11 -0
- package/dist/tools/project-configuration.d.ts +4 -0
- package/dist/tools/project-configuration.js +47 -0
- package/dist/tools/self-host-processes.d.ts +1 -0
- package/dist/tools/self-host-processes.js +33 -22
- package/dist/tools/self-host-project.d.ts +4 -0
- package/dist/tools/self-host-project.js +61 -14
- package/dist/tools/self-host-runtime.d.ts +16 -0
- package/dist/tools/self-host-runtime.js +60 -0
- package/dist/tools/self-host-workflows.d.ts +1 -0
- package/dist/tools/self-host-workflows.js +36 -1
- package/dist/tools/self-host.js +86 -61
- package/dist/tools/workflow-candidate-counts.d.ts +6 -2
- package/dist/tools/workflow-candidate-counts.js +31 -16
- package/dist/tools/workflow-candidate-fields.d.ts +5 -0
- package/dist/tools/workflow-candidate-fields.js +24 -0
- package/dist/tools/workflow-candidate-helper-counts.d.ts +10 -0
- package/dist/tools/workflow-candidate-helper-counts.js +129 -0
- package/dist/tools/workflow-candidate-program.d.ts +2 -0
- package/dist/tools/workflow-candidate-program.js +36 -8
- package/dist/tools/workflow-candidate-source.js +77 -15
- package/dist/tools/workflow-candidate-syntax.d.ts +8 -2
- package/dist/tools/workflow-candidate-syntax.js +70 -26
- package/dist/tools/workflow-command.d.ts +1 -0
- package/dist/tools/workflow-command.js +143 -0
- package/dist/tools/workflow-folder-capture.d.ts +1 -0
- package/dist/tools/workflow-folder-capture.js +47 -2
- package/dist/tools/workflow-folders.d.ts +17 -1
- package/dist/tools/workflow-folders.js +59 -6
- package/dist/tools/workflow-test-hook.d.ts +7 -0
- package/dist/tools/workflow-test-hook.js +16 -0
- package/dist/tools/workflow-test-loader.d.ts +1 -0
- package/dist/tools/workflow-test-loader.js +10 -0
- package/dist/workflows/develop-ticket.js +1 -1
- package/dist/workflows/ticket-prompts.js +5 -1
- package/package.json +46 -4
- package/templates/develop/README.md +78 -0
- package/templates/develop/develop/accept.ts +11 -0
- package/templates/develop/develop/flow-tests.ts +357 -0
- package/templates/develop/develop/local.ts +40 -0
- package/templates/develop/develop/option-tests.ts +174 -0
- package/templates/develop/develop/partial-choice.ts +29 -0
- package/templates/develop/develop/partial.ts +28 -0
- package/templates/develop/develop/pull.ts +152 -0
- package/templates/develop/develop/queue-partial.ts +39 -0
- package/templates/develop/develop/refusal-tests.ts +174 -0
- package/templates/develop/develop/report.ts +156 -0
- package/templates/develop/develop/round.ts +40 -0
- package/templates/develop/develop/scenarios.ts +87 -0
- package/templates/develop/develop/turn.ts +67 -0
- package/templates/develop/develop.declaration.json +24 -0
- package/templates/develop/develop.test.ts +287 -0
- package/templates/develop/develop.ts +30 -0
- package/templates/develop/template.json +153 -0
- package/dist/src/chats/analysis-batches.d.ts +0 -42
- package/dist/src/chats/analysis-batches.js +0 -97
- package/dist/src/chats/analysis-checkpoint.d.ts +0 -29
- package/dist/src/chats/analysis-checkpoint.js +0 -31
- package/dist/src/chats/analysis-contract.d.ts +0 -80
- package/dist/src/chats/analysis-contract.js +0 -16
- package/dist/src/chats/analysis-data.d.ts +0 -3
- package/dist/src/chats/analysis-data.js +0 -85
- package/dist/src/chats/analysis-input.d.ts +0 -18
- package/dist/src/chats/analysis-input.js +0 -97
- package/dist/src/chats/analysis-links.d.ts +0 -2
- package/dist/src/chats/analysis-links.js +0 -25
- package/dist/src/chats/analysis-merge.d.ts +0 -16
- package/dist/src/chats/analysis-merge.js +0 -134
- package/dist/src/chats/analysis-prompt.d.ts +0 -18
- package/dist/src/chats/analysis-prompt.js +0 -42
- package/dist/src/chats/analysis-proposal.d.ts +0 -4
- package/dist/src/chats/analysis-proposal.js +0 -41
- package/dist/src/chats/analysis-provenance.d.ts +0 -4
- package/dist/src/chats/analysis-provenance.js +0 -99
- package/dist/src/chats/analysis-shape.d.ts +0 -4
- package/dist/src/chats/analysis-shape.js +0 -235
- package/dist/src/chats/analysis.d.ts +0 -3
- package/dist/src/chats/analysis.js +0 -42
- package/dist/src/chats/corpus-input.d.ts +0 -5
- package/dist/src/chats/corpus-input.js +0 -288
- package/dist/src/chats/destination.d.ts +0 -4
- package/dist/src/chats/destination.js +0 -96
- package/dist/src/chats/import.d.ts +0 -15
- package/dist/src/chats/import.js +0 -243
- package/dist/src/chats/input-file.d.ts +0 -3
- package/dist/src/chats/input-file.js +0 -32
- package/dist/src/chats/normalize.d.ts +0 -29
- package/dist/src/chats/normalize.js +0 -155
- package/dist/src/chats/previous-import.d.ts +0 -5
- package/dist/src/chats/previous-import.js +0 -34
- package/dist/src/chats/reader.d.ts +0 -21
- package/dist/src/chats/reader.js +0 -118
- package/dist/src/chats/redact-import.d.ts +0 -14
- package/dist/src/chats/redact-import.js +0 -141
- package/dist/src/chats/redaction.d.ts +0 -41
- package/dist/src/chats/redaction.js +0 -161
- package/dist/src/chats/reference-mapping.d.ts +0 -16
- package/dist/src/chats/reference-mapping.js +0 -153
- package/dist/src/chats/revision-input.d.ts +0 -3
- package/dist/src/chats/revision-input.js +0 -180
- package/dist/src/chats/revision.d.ts +0 -48
- package/dist/src/chats/revision.js +0 -94
- package/dist/src/chats/selection.d.ts +0 -25
- package/dist/src/chats/selection.js +0 -109
- package/dist/src/chats/source.d.ts +0 -23
- package/dist/src/chats/source.js +0 -135
- package/dist/src/chats/structure.d.ts +0 -57
- package/dist/src/chats/structure.js +0 -216
- package/dist/src/chats/workflow-generation-projection.d.ts +0 -8
- package/dist/src/chats/workflow-generation-projection.js +0 -75
- package/dist/src/chats/workflow-generation-source.d.ts +0 -25
- package/dist/src/chats/workflow-generation-source.js +0 -124
- package/dist/src/chats/workflow-generation-text.d.ts +0 -23
- package/dist/src/chats/workflow-generation-text.js +0 -74
- package/dist/src/chats/workflow-generation.d.ts +0 -69
- package/dist/src/chats/workflow-generation.js +0 -142
- package/dist/src/daemon/analysis-launch.d.ts +0 -5
- package/dist/src/daemon/analysis-launch.js +0 -81
- package/dist/src/daemon/analysis-token.d.ts +0 -6
- package/dist/src/daemon/analysis-token.js +0 -88
- package/dist/src/daemon/analysis-worker.d.ts +0 -20
- package/dist/src/daemon/analysis-worker.js +0 -271
- package/dist/src/daemon/chats-batch-binding.d.ts +0 -23
- package/dist/src/daemon/chats-batch-binding.js +0 -99
- package/dist/src/daemon/chats-capture.d.ts +0 -18
- package/dist/src/daemon/chats-capture.js +0 -194
- package/dist/src/daemon/chats-checkpoints.d.ts +0 -41
- package/dist/src/daemon/chats-checkpoints.js +0 -186
- package/dist/src/daemon/chats-files.d.ts +0 -42
- package/dist/src/daemon/chats-files.js +0 -252
- package/dist/src/daemon/chats-follow-up.d.ts +0 -38
- package/dist/src/daemon/chats-follow-up.js +0 -180
- package/dist/src/daemon/chats-question.d.ts +0 -15
- package/dist/src/daemon/chats-question.js +0 -93
- package/dist/src/daemon/chats-worker.d.ts +0 -13
- package/dist/src/daemon/chats-worker.js +0 -201
- package/dist/workflows/analyze-chats.d.ts +0 -15
- package/dist/workflows/analyze-chats.declaration.json +0 -22
- package/dist/workflows/analyze-chats.js +0 -250
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { lstat } from "node:fs/promises";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
function kill(child) {
|
|
5
|
+
if (child.pid === undefined)
|
|
6
|
+
return;
|
|
7
|
+
try {
|
|
8
|
+
process.kill(-child.pid, "SIGKILL");
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
child.kill("SIGKILL");
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export async function retryGit(tree, parts) {
|
|
15
|
+
if (tree.signal.aborted)
|
|
16
|
+
return { text: "", code: null };
|
|
17
|
+
const child = spawn("git", ["-C", tree.directory, ...parts], {
|
|
18
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
19
|
+
detached: true,
|
|
20
|
+
env: { ...process.env, GIT_TERMINAL_PROMPT: "0" },
|
|
21
|
+
});
|
|
22
|
+
const closed = Promise.withResolvers();
|
|
23
|
+
let text = "";
|
|
24
|
+
const stop = () => {
|
|
25
|
+
kill(child);
|
|
26
|
+
child.stdout.destroy();
|
|
27
|
+
closed.resolve(null);
|
|
28
|
+
};
|
|
29
|
+
const timer = setTimeout(stop, 30_000);
|
|
30
|
+
tree.signal.addEventListener("abort", stop, { once: true });
|
|
31
|
+
child.stdout.setEncoding("utf8");
|
|
32
|
+
child.stdout.on("data", (chunk) => {
|
|
33
|
+
text += chunk;
|
|
34
|
+
if (Buffer.byteLength(text) > 1_048_576)
|
|
35
|
+
stop();
|
|
36
|
+
});
|
|
37
|
+
child.once("error", () => {
|
|
38
|
+
closed.resolve(null);
|
|
39
|
+
});
|
|
40
|
+
child.once("close", closed.resolve);
|
|
41
|
+
const code = await closed.promise;
|
|
42
|
+
clearTimeout(timer);
|
|
43
|
+
tree.signal.removeEventListener("abort", stop);
|
|
44
|
+
return { text: text.trim(), code };
|
|
45
|
+
}
|
|
46
|
+
export async function turnHead(tree) {
|
|
47
|
+
const head = await retryGit(tree, ["rev-parse", "--verify", "HEAD"]);
|
|
48
|
+
return head.code === 0 && /^[a-f0-9]{40,64}$/.test(head.text)
|
|
49
|
+
? head.text
|
|
50
|
+
: null;
|
|
51
|
+
}
|
|
52
|
+
async function remoteState(tree) {
|
|
53
|
+
const branch = await retryGit(tree, ["symbolic-ref", "--short", "HEAD"]);
|
|
54
|
+
if (branch.code !== 0 || tree.signal.aborted)
|
|
55
|
+
return "unknown";
|
|
56
|
+
const reference = `refs/heads/${branch.text}`;
|
|
57
|
+
const remote = await retryGit(tree, [
|
|
58
|
+
"ls-remote",
|
|
59
|
+
"--exit-code",
|
|
60
|
+
"--heads",
|
|
61
|
+
"origin",
|
|
62
|
+
reference,
|
|
63
|
+
]);
|
|
64
|
+
if (remote.code === 2)
|
|
65
|
+
return "not pushed";
|
|
66
|
+
if (remote.code !== 0)
|
|
67
|
+
return "unknown";
|
|
68
|
+
const tracking = `refs/remotes/origin/${branch.text}`;
|
|
69
|
+
const fetched = await retryGit(tree, [
|
|
70
|
+
"fetch",
|
|
71
|
+
"--no-tags",
|
|
72
|
+
"origin",
|
|
73
|
+
`+${reference}:${tracking}`,
|
|
74
|
+
]);
|
|
75
|
+
return fetched.code === 0 ? tracking : "unknown";
|
|
76
|
+
}
|
|
77
|
+
async function pushState(tree, evidence) {
|
|
78
|
+
const { commit, remote } = evidence;
|
|
79
|
+
if (!remote.startsWith("refs/"))
|
|
80
|
+
return remote;
|
|
81
|
+
const ancestor = await retryGit(tree, [
|
|
82
|
+
"merge-base",
|
|
83
|
+
"--is-ancestor",
|
|
84
|
+
commit,
|
|
85
|
+
remote,
|
|
86
|
+
]);
|
|
87
|
+
if (ancestor.code === 1)
|
|
88
|
+
return "not pushed";
|
|
89
|
+
return ancestor.code === 0 ? "pushed" : "unknown";
|
|
90
|
+
}
|
|
91
|
+
export async function retryEvidence(tree, startCommit) {
|
|
92
|
+
const remote = await remoteState(tree);
|
|
93
|
+
if (startCommit === null || tree.signal.aborted)
|
|
94
|
+
return "unknown: commits since the start of this turn could not be determined.";
|
|
95
|
+
const commits = await retryGit(tree, [
|
|
96
|
+
"log",
|
|
97
|
+
"--format=%H %s",
|
|
98
|
+
`${startCommit}..HEAD`,
|
|
99
|
+
"--",
|
|
100
|
+
]);
|
|
101
|
+
if (commits.code !== 0)
|
|
102
|
+
return "unknown: commits since the start of this turn could not be listed.";
|
|
103
|
+
const lines = [];
|
|
104
|
+
for (const line of commits.text.split("\n").filter(Boolean)) {
|
|
105
|
+
const commit = line.split(" ")[0] ?? "";
|
|
106
|
+
const state = await pushState(tree, { commit, remote });
|
|
107
|
+
lines.push(`${commit} ${state}${line.slice(commit.length)}`);
|
|
108
|
+
}
|
|
109
|
+
if (lines.length > 0)
|
|
110
|
+
return lines.join("\n");
|
|
111
|
+
return remote === "unknown"
|
|
112
|
+
? "unknown: remote push state could not be determined; no local commits since the start of this turn."
|
|
113
|
+
: "No commits since the start of this turn.";
|
|
114
|
+
}
|
|
115
|
+
export async function indexFailure(tree) {
|
|
116
|
+
const lookup = await retryGit(tree, [
|
|
117
|
+
"rev-parse",
|
|
118
|
+
"--git-path",
|
|
119
|
+
"index.lock",
|
|
120
|
+
]);
|
|
121
|
+
const unknown = {
|
|
122
|
+
reason: "worktree-index-unknown",
|
|
123
|
+
fix: "Check that the work tree and its git index path are accessible before starting another turn.",
|
|
124
|
+
};
|
|
125
|
+
if (lookup.code !== 0 || lookup.text === "")
|
|
126
|
+
return unknown;
|
|
127
|
+
const lockPath = resolve(tree.directory, lookup.text);
|
|
128
|
+
try {
|
|
129
|
+
await lstat(lockPath);
|
|
130
|
+
return {
|
|
131
|
+
reason: "worktree-index-locked",
|
|
132
|
+
lockPath,
|
|
133
|
+
fix: "Remove the index lock when no git process uses the work tree, then start another turn.",
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
return Reflect.get(Object(error), "code") === "ENOENT" ? null : unknown;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
@@ -6,6 +6,8 @@ export interface RetrySettings {
|
|
|
6
6
|
readonly retryDelay?: (milliseconds: number, signal: AbortSignal) => Promise<void>;
|
|
7
7
|
}
|
|
8
8
|
interface RetryOptions extends RetrySettings {
|
|
9
|
+
readonly stopping?: AbortController;
|
|
10
|
+
readonly stopMilliseconds?: number;
|
|
9
11
|
readonly metadata: Readonly<Record<string, unknown>>;
|
|
10
12
|
}
|
|
11
13
|
export declare function startRetriedTurn(start: TurnStart, options: RetryOptions): Promise<RunningTurn>;
|
|
@@ -3,10 +3,12 @@ import { mkdir } from "node:fs/promises";
|
|
|
3
3
|
import { setTimeout as delay } from "node:timers/promises";
|
|
4
4
|
import { priceOf, sumUsage, usageOf, } from "../worker-usage.js";
|
|
5
5
|
import { commandModel, replaceCommandModel, estimatedCostUsd, priceForModel, } from "../token-prices.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { capacityRefusal, retryKind, startTurn, } from "./claude-turn.js";
|
|
7
|
+
import { turnHead, retryEvidence, indexFailure } from "./retry-worktree.js";
|
|
8
8
|
import { readRecord, writeRecord } from "./operation-journal.js";
|
|
9
|
-
|
|
9
|
+
import { nativeHarness } from "../harness-defaults.js";
|
|
10
|
+
const waits = { capacity: [60_000, 180_000], network: [600_000, 2_400_000] };
|
|
11
|
+
const networkContinuation = "An earlier attempt stopped because the network was not available. Continue from the current state of the work tree. Check each earlier commit, push, review comment and message. Do not repeat a write that is done. Stop and report a write whose result is not known.";
|
|
10
12
|
const continuation = "An earlier attempt stopped because the model was at capacity; continue from the current state of the work tree.\n\n";
|
|
11
13
|
function written(folder, entry) {
|
|
12
14
|
return writeRecord(folder, { ...entry, permissions: "private" });
|
|
@@ -49,12 +51,13 @@ function controlled(attempts, start) {
|
|
|
49
51
|
}
|
|
50
52
|
function attemptCommand(attempts, attempt) {
|
|
51
53
|
const { start, options } = attempts;
|
|
52
|
-
const original = start.
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
54
|
+
const original = start.command;
|
|
55
|
+
const previous = attempts.ends[attempt - 2];
|
|
56
|
+
const fallback = previous !== undefined && kindOf(attempts, previous) === "capacity"
|
|
57
|
+
? options.fallbackModels?.[attempt - 3]
|
|
58
|
+
: undefined;
|
|
56
59
|
const command = fallback === undefined ? original : replaceCommandModel(original, fallback);
|
|
57
|
-
const model = commandModel(command);
|
|
60
|
+
const model = start.output === "text" ? null : commandModel(command);
|
|
58
61
|
return {
|
|
59
62
|
command,
|
|
60
63
|
model,
|
|
@@ -65,30 +68,66 @@ function attemptCommand(attempts, attempt) {
|
|
|
65
68
|
}
|
|
66
69
|
function attemptUsage(attempts, completion) {
|
|
67
70
|
const { end, attempt } = completion;
|
|
68
|
-
const
|
|
69
|
-
|
|
71
|
+
const result = end.result ?? {
|
|
72
|
+
model: null,
|
|
73
|
+
usage: usageOf(null),
|
|
74
|
+
costUsd: null,
|
|
75
|
+
pricingModel: undefined,
|
|
76
|
+
};
|
|
77
|
+
const model = result.model ?? attemptCommand(attempts, attempt).model;
|
|
78
|
+
const usage = result.usage;
|
|
70
79
|
return {
|
|
71
80
|
attempt,
|
|
81
|
+
retryKind: kindOf(attempts, end),
|
|
72
82
|
model,
|
|
83
|
+
...(end.result?.models === undefined ? {} : { models: end.result.models }),
|
|
73
84
|
usage,
|
|
74
|
-
costUsd:
|
|
75
|
-
estimatedCostUsd:
|
|
76
|
-
worker: attempts.start.mode === "analysis"
|
|
77
|
-
? "claude"
|
|
78
|
-
: (attempts.start.worker ?? "claude"),
|
|
79
|
-
price: priceForModel(attempts.options.tokenPrices ?? {}, model),
|
|
80
|
-
}),
|
|
85
|
+
costUsd: result.costUsd,
|
|
86
|
+
estimatedCostUsd: attemptEstimate(attempts, { end, model, usage }),
|
|
81
87
|
};
|
|
82
88
|
}
|
|
83
|
-
|
|
89
|
+
function attemptEstimate(attempts, result) {
|
|
90
|
+
const worker = attempts.start.worker ?? "claude";
|
|
91
|
+
if (!nativeHarness(worker))
|
|
92
|
+
return null;
|
|
93
|
+
const models = result.end.result?.models;
|
|
94
|
+
const prices = attempts.options.tokenPrices ?? {};
|
|
95
|
+
return estimatedCostUsd(result.usage, worker === "gemini" && models !== undefined
|
|
96
|
+
? { worker, models, prices }
|
|
97
|
+
: {
|
|
98
|
+
worker,
|
|
99
|
+
price: priceForModel(prices, result.end.result?.pricingModel === undefined
|
|
100
|
+
? result.model
|
|
101
|
+
: result.end.result.pricingModel),
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
function kindOf(attempts, end) {
|
|
105
|
+
const { worker, output } = attempts.start;
|
|
106
|
+
if (output === "text" || !["claude", "codex"].includes(worker ?? "claude"))
|
|
107
|
+
return null;
|
|
108
|
+
if (worker !== "codex")
|
|
109
|
+
return retryKind(end.result);
|
|
110
|
+
return capacityRefusal(end.result) ? "capacity" : null;
|
|
111
|
+
}
|
|
112
|
+
async function promptOf(attempts) {
|
|
113
|
+
const { start, ends, stopping, turnStartCommit } = attempts;
|
|
114
|
+
if (ends.length === 0)
|
|
115
|
+
return start.prompt;
|
|
116
|
+
if (!ends.some((end) => kindOf(attempts, end) === "network"))
|
|
117
|
+
return continuation + start.prompt;
|
|
118
|
+
const evidence = await retryEvidence({ directory: start.directory, signal: stopping.signal }, turnStartCommit);
|
|
119
|
+
return `${networkContinuation}\n\nCommits since the start of this turn:\n${evidence}\n\n${start.prompt}`;
|
|
120
|
+
}
|
|
121
|
+
async function launched(attempts, prompt = attempts.start.prompt) {
|
|
84
122
|
const { start, options, ends } = attempts;
|
|
85
123
|
const attempt = ends.length + 1;
|
|
86
124
|
const selected = attemptCommand(attempts, attempt);
|
|
87
|
-
const folder =
|
|
125
|
+
const folder = attempt === 1
|
|
88
126
|
? start.folder
|
|
89
127
|
: join(start.folder, `attempt-${String(attempt)}`);
|
|
90
128
|
const entry = {
|
|
91
129
|
...options.metadata,
|
|
130
|
+
turnStartCommit: attempts.turnStartCommit,
|
|
92
131
|
model: selected.model,
|
|
93
132
|
...(selected.fallbackReason === undefined
|
|
94
133
|
? {}
|
|
@@ -113,9 +152,7 @@ async function launched(attempts) {
|
|
|
113
152
|
command: selected.command,
|
|
114
153
|
folder,
|
|
115
154
|
...(attempt === 1 ? {} : { activityFolder: start.folder }),
|
|
116
|
-
prompt
|
|
117
|
-
? start.prompt
|
|
118
|
-
: continuation + start.prompt,
|
|
155
|
+
prompt,
|
|
119
156
|
});
|
|
120
157
|
try {
|
|
121
158
|
const value = { ...entry, phase: "running", processId: turn.processId };
|
|
@@ -149,6 +186,7 @@ async function recordedEnd(attempts, completion) {
|
|
|
149
186
|
name,
|
|
150
187
|
value: {
|
|
151
188
|
...options.metadata,
|
|
189
|
+
turnStartCommit: attempts.turnStartCommit,
|
|
152
190
|
...attemptUsage(attempts, { end, attempt }),
|
|
153
191
|
...(selected.fallbackReason === undefined
|
|
154
192
|
? {}
|
|
@@ -168,6 +206,7 @@ async function waited(attempts, milliseconds) {
|
|
|
168
206
|
name: "started.json",
|
|
169
207
|
value: {
|
|
170
208
|
...options.metadata,
|
|
209
|
+
turnStartCommit: attempts.turnStartCommit,
|
|
171
210
|
startedAt: attempts.startedAt,
|
|
172
211
|
attempt: ends.length,
|
|
173
212
|
phase: "waiting",
|
|
@@ -183,6 +222,27 @@ async function waited(attempts, milliseconds) {
|
|
|
183
222
|
throw error;
|
|
184
223
|
});
|
|
185
224
|
}
|
|
225
|
+
async function preparedRetry(attempts) {
|
|
226
|
+
const prompt = await promptOf(attempts);
|
|
227
|
+
const failure = await indexFailure({
|
|
228
|
+
directory: attempts.start.directory,
|
|
229
|
+
signal: attempts.stopping.signal,
|
|
230
|
+
});
|
|
231
|
+
if (cancelled(attempts))
|
|
232
|
+
return { ...combined(attempts), stopped: true };
|
|
233
|
+
if (failure !== null) {
|
|
234
|
+
await written(attempts.start.folder, {
|
|
235
|
+
name: "retry-failure.json",
|
|
236
|
+
value: failure,
|
|
237
|
+
});
|
|
238
|
+
return {
|
|
239
|
+
...combined(attempts),
|
|
240
|
+
reason: failure.reason,
|
|
241
|
+
detail: `${failure.fix}${failure.lockPath === undefined ? "" : ` Lock: ${failure.lockPath}`}`,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
return prompt;
|
|
245
|
+
}
|
|
186
246
|
async function finished(attempts, first) {
|
|
187
247
|
const { ends } = attempts;
|
|
188
248
|
let turn = first;
|
|
@@ -190,15 +250,17 @@ async function finished(attempts, first) {
|
|
|
190
250
|
const end = await turn.ended;
|
|
191
251
|
ends.push(end);
|
|
192
252
|
await recordedEnd(attempts, { processId: turn.processId, end });
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
milliseconds === undefined)
|
|
253
|
+
const kind = kindOf(attempts, end);
|
|
254
|
+
const milliseconds = kind === null ? undefined : waits[kind][ends.length - 1];
|
|
255
|
+
if (cancelled(attempts) || milliseconds === undefined)
|
|
197
256
|
break;
|
|
198
257
|
await waited(attempts, milliseconds);
|
|
199
258
|
if (cancelled(attempts))
|
|
200
259
|
return { ...combined(attempts), stopped: true };
|
|
201
|
-
|
|
260
|
+
const prepared = await preparedRetry(attempts);
|
|
261
|
+
if (typeof prepared !== "string")
|
|
262
|
+
return prepared;
|
|
263
|
+
turn = await launched(attempts, prepared);
|
|
202
264
|
}
|
|
203
265
|
return {
|
|
204
266
|
...combined(attempts),
|
|
@@ -209,17 +271,33 @@ function cancelled(attempts) {
|
|
|
209
271
|
return attempts.stopping.signal.aborted;
|
|
210
272
|
}
|
|
211
273
|
export async function startRetriedTurn(start, options) {
|
|
274
|
+
const stopping = options.stopping ?? new AbortController();
|
|
275
|
+
const turnStartCommit = await turnHead({
|
|
276
|
+
directory: start.directory,
|
|
277
|
+
signal: stopping.signal,
|
|
278
|
+
});
|
|
212
279
|
const attempts = {
|
|
280
|
+
turnStartCommit,
|
|
213
281
|
start,
|
|
214
282
|
startedAt: new Date().toISOString(),
|
|
215
283
|
options,
|
|
216
|
-
stopping
|
|
284
|
+
stopping,
|
|
217
285
|
ends: [],
|
|
218
|
-
grace: { milliseconds: 2_000 },
|
|
286
|
+
grace: { milliseconds: options.stopMilliseconds ?? 2_000 },
|
|
219
287
|
};
|
|
220
288
|
const turn = await launched(attempts);
|
|
221
289
|
if (turn === undefined)
|
|
222
|
-
|
|
290
|
+
return {
|
|
291
|
+
processId: null,
|
|
292
|
+
ended: Promise.resolve({
|
|
293
|
+
exitCode: null,
|
|
294
|
+
result: undefined,
|
|
295
|
+
stopped: true,
|
|
296
|
+
}),
|
|
297
|
+
stop: () => {
|
|
298
|
+
stopping.abort();
|
|
299
|
+
},
|
|
300
|
+
};
|
|
223
301
|
return {
|
|
224
302
|
processId: turn.processId,
|
|
225
303
|
ended: finished(attempts, turn),
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Fields } from "../protocol.ts";
|
|
2
|
+
export type PendingSlot = {
|
|
3
|
+
readonly kind: "run";
|
|
4
|
+
readonly input: Fields;
|
|
5
|
+
} | {
|
|
6
|
+
readonly kind: "skip";
|
|
7
|
+
readonly runId: string;
|
|
8
|
+
};
|
|
9
|
+
export interface ScheduleProgress {
|
|
10
|
+
readonly everySeconds: number;
|
|
11
|
+
readonly nextAt: number;
|
|
12
|
+
readonly lastSlot: number;
|
|
13
|
+
readonly activeCommandId?: string;
|
|
14
|
+
readonly pending?: PendingSlot;
|
|
15
|
+
}
|
|
16
|
+
export declare function scheduleJournal(directory: string): Promise<{
|
|
17
|
+
readonly entries: Map<string, ScheduleProgress>;
|
|
18
|
+
readonly save: () => Promise<void>;
|
|
19
|
+
}>;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { readFile, rename, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { record } from "../protocol.js";
|
|
4
|
+
import { isCommandId, isRecordKey } from "../authority/commands.js";
|
|
5
|
+
function pendingSlot(value) {
|
|
6
|
+
const fields = record(value);
|
|
7
|
+
if (fields?.["kind"] === "run")
|
|
8
|
+
return record(fields["input"]) !== undefined;
|
|
9
|
+
return fields?.["kind"] === "skip" && isRecordKey(fields["runId"]);
|
|
10
|
+
}
|
|
11
|
+
function whole(value) {
|
|
12
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
13
|
+
}
|
|
14
|
+
function timing(fields) {
|
|
15
|
+
const { everySeconds, nextAt, lastSlot } = fields;
|
|
16
|
+
return (whole(everySeconds) &&
|
|
17
|
+
everySeconds >= 60 &&
|
|
18
|
+
everySeconds <= 86400 &&
|
|
19
|
+
whole(nextAt) &&
|
|
20
|
+
whole(lastSlot));
|
|
21
|
+
}
|
|
22
|
+
function isProgress(value) {
|
|
23
|
+
const fields = record(value);
|
|
24
|
+
if (fields === undefined)
|
|
25
|
+
return false;
|
|
26
|
+
const { activeCommandId, pending } = fields;
|
|
27
|
+
return (timing(fields) &&
|
|
28
|
+
(activeCommandId === undefined || isCommandId(activeCommandId)) &&
|
|
29
|
+
(pending === undefined || pendingSlot(pending)));
|
|
30
|
+
}
|
|
31
|
+
export async function scheduleJournal(directory) {
|
|
32
|
+
const file = join(directory, "schedules.json");
|
|
33
|
+
const text = await readFile(file, "utf8").catch((error) => {
|
|
34
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
35
|
+
return "{}";
|
|
36
|
+
throw error;
|
|
37
|
+
});
|
|
38
|
+
const parsed = record(JSON.parse(text));
|
|
39
|
+
if (parsed === undefined)
|
|
40
|
+
throw new Error("invalid-schedule-state");
|
|
41
|
+
const entries = new Map();
|
|
42
|
+
for (const [workflowId, value] of Object.entries(parsed)) {
|
|
43
|
+
if (!isProgress(value))
|
|
44
|
+
throw new Error("invalid-schedule-state");
|
|
45
|
+
entries.set(workflowId, value);
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
entries,
|
|
49
|
+
save: async () => {
|
|
50
|
+
await writeFile(`${file}.tmp`, JSON.stringify(Object.fromEntries(entries)) + "\n", {
|
|
51
|
+
mode: 0o600,
|
|
52
|
+
flush: true,
|
|
53
|
+
});
|
|
54
|
+
await rename(`${file}.tmp`, file);
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ChildProcessWithoutNullStreams } from "node:child_process";
|
|
2
|
+
import type { WriteStream } from "node:fs";
|
|
3
|
+
export declare function textOutput(child: ChildProcessWithoutNullStreams, options: {
|
|
4
|
+
readonly output: WriteStream;
|
|
5
|
+
readonly limit: number;
|
|
6
|
+
}): (exitCode: number | null) => Promise<{
|
|
7
|
+
text: string;
|
|
8
|
+
failed: boolean;
|
|
9
|
+
model: null;
|
|
10
|
+
costUsd: null;
|
|
11
|
+
usage: import("../worker-usage.ts").WorkerUsage;
|
|
12
|
+
sessionId: null;
|
|
13
|
+
turns: null;
|
|
14
|
+
reviewFeedback?: string;
|
|
15
|
+
reviewVerdict: import("../review-subject.ts").ReviewVerdict | null;
|
|
16
|
+
ticketStatus: import("../ticket-status.ts").TicketStatus;
|
|
17
|
+
ticketStatusTooLarge?: true;
|
|
18
|
+
}>;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { usageOf } from "../worker-usage.js";
|
|
2
|
+
import { reviewReportStream } from "../review-subject.js";
|
|
3
|
+
import { ticketStatusStream } from "../ticket-status-stream.js";
|
|
4
|
+
export function textOutput(child, options) {
|
|
5
|
+
const { output, limit } = options;
|
|
6
|
+
const status = ticketStatusStream(limit);
|
|
7
|
+
const verdict = reviewReportStream(limit);
|
|
8
|
+
let text = "";
|
|
9
|
+
let error = "";
|
|
10
|
+
child.stderr.setEncoding("utf8");
|
|
11
|
+
child.stderr.on("data", (chunk) => {
|
|
12
|
+
error = (error + chunk).slice(-limit);
|
|
13
|
+
});
|
|
14
|
+
child.stdout.setEncoding("utf8");
|
|
15
|
+
child.stdout.on("data", (chunk) => {
|
|
16
|
+
text = (text + chunk).slice(-limit);
|
|
17
|
+
status.write(chunk);
|
|
18
|
+
verdict.write(chunk);
|
|
19
|
+
if (!output.write(chunk)) {
|
|
20
|
+
child.stdout.pause();
|
|
21
|
+
output.once("drain", () => {
|
|
22
|
+
child.stdout.resume();
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
return async (exitCode) => {
|
|
27
|
+
await new Promise((resolve) => output.end(resolve));
|
|
28
|
+
const review = verdict.result();
|
|
29
|
+
return {
|
|
30
|
+
...status.result(),
|
|
31
|
+
reviewVerdict: review.reviewVerdict,
|
|
32
|
+
...(review.reviewVerdict === null
|
|
33
|
+
? {}
|
|
34
|
+
: { reviewFeedback: review.feedback }),
|
|
35
|
+
text: exitCode === 0 ? text : error,
|
|
36
|
+
failed: exitCode !== 0,
|
|
37
|
+
model: null,
|
|
38
|
+
costUsd: null,
|
|
39
|
+
usage: usageOf(null),
|
|
40
|
+
sessionId: null,
|
|
41
|
+
turns: null,
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type DeclaredWorkflow } from "../workflow-declaration.ts";
|
|
2
2
|
import type { Resolver, WorkflowRegistration } from "../service/registry.ts";
|
|
3
|
+
import type { LocalCommands } from "../command-settings.ts";
|
|
3
4
|
export declare const ticketWorkflow: "develop-ticket";
|
|
4
5
|
export declare const promptWorkflow: "develop-prompt";
|
|
5
6
|
export declare const issueWorkflow: "develop-issue";
|
|
@@ -18,15 +19,10 @@ export interface TicketSource {
|
|
|
18
19
|
readonly githubCommand?: readonly string[] | undefined;
|
|
19
20
|
readonly skipTickets?: readonly string[];
|
|
20
21
|
}
|
|
21
|
-
export interface TicketRegistration {
|
|
22
|
-
readonly workflowId: string;
|
|
22
|
+
export interface TicketRegistration extends Omit<WorkflowRegistration, "manifest" | "availability" | "admission"> {
|
|
23
23
|
readonly functionName: string;
|
|
24
|
-
readonly resolver: Resolver;
|
|
25
|
-
readonly submission: WorkflowRegistration["submission"];
|
|
26
24
|
readonly effectLimit: number;
|
|
27
25
|
readonly capabilities?: readonly string[];
|
|
28
|
-
readonly stages?: readonly WorkflowStage[];
|
|
29
|
-
readonly handoffs?: readonly string[];
|
|
30
26
|
}
|
|
31
27
|
export declare function ticketResolver(source: TicketSource): Resolver;
|
|
32
28
|
export declare function issueResolver(source: TicketSource): Resolver;
|
|
@@ -34,4 +30,6 @@ export declare function promptResolver(repository: string): Resolver;
|
|
|
34
30
|
export declare function ticketRegistrationTable(source: TicketSource, declarations?: readonly DeclaredWorkflow[]): readonly TicketRegistration[];
|
|
35
31
|
export declare function ticketRegistrations(manifests: Readonly<Record<string, string | undefined>>, options: {
|
|
36
32
|
readonly table: readonly TicketRegistration[];
|
|
33
|
+
readonly bundleDigest?: string;
|
|
34
|
+
readonly commands?: LocalCommands;
|
|
37
35
|
}): Promise<TicketRegistrations>;
|