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,92 @@
|
|
|
1
|
+
import { field, repositoryPath } from "./github-operation.js";
|
|
2
|
+
import { githubRead } from "./github-retry.js";
|
|
3
|
+
import { operationKey, writeRecord } from "./operation-journal.js";
|
|
4
|
+
import { readFile } from "node:fs/promises";
|
|
5
|
+
import { join } from "node:path";
|
|
6
|
+
function isRerun(value) {
|
|
7
|
+
return (typeof field(value, "run") === "string" &&
|
|
8
|
+
/^\d+$/.test(String(field(value, "run"))) &&
|
|
9
|
+
typeof field(value, "requestedAt") === "number" &&
|
|
10
|
+
typeof field(value, "output") === "string");
|
|
11
|
+
}
|
|
12
|
+
export async function ciWait(operation, commit) {
|
|
13
|
+
const text = await readFile(join(operation.folder, `ci-${operationKey(commit)}.json`), "utf8").catch((error) => {
|
|
14
|
+
if (field(error, "code") === "ENOENT")
|
|
15
|
+
return undefined;
|
|
16
|
+
throw error;
|
|
17
|
+
});
|
|
18
|
+
if (text === undefined)
|
|
19
|
+
return { commit, startedAt: Date.now(), reruns: [] };
|
|
20
|
+
const stored = JSON.parse(text);
|
|
21
|
+
const startedAt = field(stored, "startedAt");
|
|
22
|
+
const reruns = field(stored, "reruns");
|
|
23
|
+
if (field(stored, "commit") !== commit ||
|
|
24
|
+
typeof startedAt !== "number" ||
|
|
25
|
+
!Array.isArray(reruns) ||
|
|
26
|
+
!reruns.every(isRerun))
|
|
27
|
+
throw new Error("github-call-failed");
|
|
28
|
+
return { commit, startedAt, reruns };
|
|
29
|
+
}
|
|
30
|
+
export async function workflowAttempt(operation, run) {
|
|
31
|
+
const value = JSON.parse(await githubRead(operation, [
|
|
32
|
+
"api",
|
|
33
|
+
`${repositoryPath}/actions/runs/${run}`,
|
|
34
|
+
]));
|
|
35
|
+
const attempt = field(value, "run_attempt");
|
|
36
|
+
const status = field(value, "status");
|
|
37
|
+
if (typeof attempt !== "number" ||
|
|
38
|
+
!Number.isSafeInteger(attempt) ||
|
|
39
|
+
attempt < 1 ||
|
|
40
|
+
typeof status !== "string")
|
|
41
|
+
throw new Error("github-call-failed");
|
|
42
|
+
return { attempt, status };
|
|
43
|
+
}
|
|
44
|
+
export async function attemptChecks(operation, workflow) {
|
|
45
|
+
const pages = JSON.parse(await githubRead(operation, [
|
|
46
|
+
"api",
|
|
47
|
+
"--paginate",
|
|
48
|
+
"--slurp",
|
|
49
|
+
`${repositoryPath}/actions/runs/${workflow.run}/attempts/${String(workflow.attempt)}/jobs?per_page=100`,
|
|
50
|
+
]));
|
|
51
|
+
if (!Array.isArray(pages) || pages.length === 0)
|
|
52
|
+
throw new Error("github-call-failed");
|
|
53
|
+
const ids = new Set();
|
|
54
|
+
for (const page of pages) {
|
|
55
|
+
const jobs = field(page, "jobs");
|
|
56
|
+
if (!Array.isArray(jobs))
|
|
57
|
+
throw new Error("github-call-failed");
|
|
58
|
+
for (const job of jobs) {
|
|
59
|
+
const id = /\/check-runs\/(\d+)$/.exec(String(field(job, "check_run_url")))?.[1];
|
|
60
|
+
if (id === undefined)
|
|
61
|
+
throw new Error("github-call-failed");
|
|
62
|
+
ids.add(Number(id));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return ids;
|
|
66
|
+
}
|
|
67
|
+
export async function rerunCi(operation, request) {
|
|
68
|
+
const { wait, rerun } = request;
|
|
69
|
+
wait.reruns.push(rerun);
|
|
70
|
+
await writeRecord(operation.folder, {
|
|
71
|
+
name: `ci-${operationKey(wait.commit)}.json`,
|
|
72
|
+
value: wait,
|
|
73
|
+
permissions: "private",
|
|
74
|
+
});
|
|
75
|
+
if (Date.now() >= request.deadline)
|
|
76
|
+
return;
|
|
77
|
+
try {
|
|
78
|
+
await operation.calls.gh(["run", "rerun", rerun.run, "--failed"]);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
operation.signal.throwIfAborted();
|
|
82
|
+
throw Object.assign(new Error("github-network-failed", { cause: error }), {
|
|
83
|
+
detail: field(error, "detail"),
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
export function attemptOutput(attempts) {
|
|
88
|
+
const allowance = Math.floor(6_000 / attempts.length) - 40;
|
|
89
|
+
return attempts
|
|
90
|
+
.map((output, index) => `Attempt ${String(index + 1)}:\n${output.length <= allowance ? output : output.slice(0, 400) + "\n…\n" + output.slice(-(allowance - 404))}`)
|
|
91
|
+
.join("\n");
|
|
92
|
+
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { settingsEnvironment } from "../cli/project-settings.js";
|
|
1
2
|
import { setTimeout as delay } from "node:timers/promises";
|
|
2
3
|
import { githubText } from "./github-calls.js";
|
|
3
4
|
import { githubRead } from "./github-retry.js";
|
|
5
|
+
import { ciWait, workflowAttempt, attemptChecks, rerunCi, attemptOutput, } from "./github-ci-rerun.js";
|
|
4
6
|
import { field, githubTiming, repositoryPath, } from "./github-operation.js";
|
|
5
7
|
function isCheckRun(value) {
|
|
6
8
|
const conclusion = field(value, "conclusion");
|
|
@@ -117,12 +119,18 @@ async function failedOutput(operation, checks) {
|
|
|
117
119
|
.join("\n")
|
|
118
120
|
.slice(0, 6_000);
|
|
119
121
|
}
|
|
122
|
+
function requiredCheckNames(operation) {
|
|
123
|
+
if (operation.settings.requiredChecks !== undefined)
|
|
124
|
+
return operation.settings.requiredChecks === null
|
|
125
|
+
? undefined
|
|
126
|
+
: operation.settings.requiredChecks;
|
|
127
|
+
const setting = settingsEnvironment({ ...process.env, ...operation.settings.environment }, operation.settings.repository)["CLOVING_REQUIRED_CHECKS"];
|
|
128
|
+
return setting === undefined ? undefined : JSON.parse(setting);
|
|
129
|
+
}
|
|
120
130
|
function requiredChecks(operation) {
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
if (setting === undefined)
|
|
131
|
+
const names = requiredCheckNames(operation);
|
|
132
|
+
if (names === undefined)
|
|
124
133
|
return undefined;
|
|
125
|
-
const names = JSON.parse(setting);
|
|
126
134
|
if (!Array.isArray(names) ||
|
|
127
135
|
!names.every((name) => typeof name === "string" && name.trim() !== ""))
|
|
128
136
|
throw new Error("invalid-payload");
|
|
@@ -131,6 +139,70 @@ function requiredChecks(operation) {
|
|
|
131
139
|
function pendingChecks(checks, names) {
|
|
132
140
|
return [...names].filter((name) => !checks.some((check) => check.name === name && check.status === "completed"));
|
|
133
141
|
}
|
|
142
|
+
function runOf(check) {
|
|
143
|
+
return check.app?.slug === "github-actions"
|
|
144
|
+
? /\/actions\/runs\/(\d+)/.exec(check.details_url ?? "")?.[1]
|
|
145
|
+
: undefined;
|
|
146
|
+
}
|
|
147
|
+
async function rerunBeforeDeadline(operation, request) {
|
|
148
|
+
if (Date.now() >= request.deadline)
|
|
149
|
+
return;
|
|
150
|
+
const output = await failedOutput(operation, request.checks);
|
|
151
|
+
const requestedAt = Date.now();
|
|
152
|
+
if (requestedAt >= request.deadline)
|
|
153
|
+
return;
|
|
154
|
+
await rerunCi(operation, {
|
|
155
|
+
wait: request.wait,
|
|
156
|
+
rerun: { run: request.run, requestedAt, output },
|
|
157
|
+
deadline: request.deadline,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
async function rerunFailedChecks(operation, input) {
|
|
161
|
+
const { wait, failed } = input;
|
|
162
|
+
const failures = failed.filter((check) => runOf(check) === undefined);
|
|
163
|
+
const pending = [];
|
|
164
|
+
const runs = new Set(failed.flatMap((check) => runOf(check) ?? []));
|
|
165
|
+
for (const run of runs) {
|
|
166
|
+
const checks = failed.filter((check) => runOf(check) === run);
|
|
167
|
+
const recorded = wait.reruns.find((rerun) => rerun.run === run);
|
|
168
|
+
const workflow = await workflowAttempt(operation, run);
|
|
169
|
+
if (workflow.attempt === 1 &&
|
|
170
|
+
recorded === undefined &&
|
|
171
|
+
workflow.status === "completed")
|
|
172
|
+
await rerunBeforeDeadline(operation, {
|
|
173
|
+
wait,
|
|
174
|
+
run,
|
|
175
|
+
checks,
|
|
176
|
+
deadline: input.deadline,
|
|
177
|
+
});
|
|
178
|
+
if (workflow.attempt === 1) {
|
|
179
|
+
pending.push(`workflow ${run} rerun`);
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
const ids = await attemptChecks(operation, {
|
|
183
|
+
run,
|
|
184
|
+
attempt: workflow.attempt,
|
|
185
|
+
});
|
|
186
|
+
const current = checks.filter((check) => ids.has(check.id));
|
|
187
|
+
if (current.length === 0) {
|
|
188
|
+
pending.push(`workflow ${run} rerun`);
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
failures.push(...current);
|
|
192
|
+
}
|
|
193
|
+
return { failures, pending };
|
|
194
|
+
}
|
|
195
|
+
async function ciFailureOutput(operation, input) {
|
|
196
|
+
const { wait, failed } = input;
|
|
197
|
+
const previous = wait.reruns.filter((rerun) => failed.some((check) => runOf(check) === rerun.run));
|
|
198
|
+
const current = await failedOutput(operation, failed);
|
|
199
|
+
return previous.length === 0
|
|
200
|
+
? current
|
|
201
|
+
: attemptOutput([
|
|
202
|
+
previous.map((rerun) => rerun.output).join("\n"),
|
|
203
|
+
current,
|
|
204
|
+
]);
|
|
205
|
+
}
|
|
134
206
|
export async function waitForCi(operation, commit) {
|
|
135
207
|
const { pollMilliseconds: poll, ciGraceMilliseconds: grace, ciLimitMilliseconds: limit, } = {
|
|
136
208
|
...githubTiming,
|
|
@@ -138,7 +210,8 @@ export async function waitForCi(operation, commit) {
|
|
|
138
210
|
ciLimitMilliseconds: 5_400_000,
|
|
139
211
|
...operation.settings.timing,
|
|
140
212
|
};
|
|
141
|
-
const
|
|
213
|
+
const wait = await ciWait(operation, commit);
|
|
214
|
+
const started = wait.startedAt;
|
|
142
215
|
const required = requiredChecks(operation);
|
|
143
216
|
const names = new Set(required);
|
|
144
217
|
for (;;) {
|
|
@@ -146,12 +219,20 @@ export async function waitForCi(operation, commit) {
|
|
|
146
219
|
for (const check of checks)
|
|
147
220
|
names.add(check.name);
|
|
148
221
|
const failed = checks.filter((check) => check.status === "completed" && !passing.has(check.conclusion ?? ""));
|
|
149
|
-
|
|
222
|
+
const retried = await rerunFailedChecks(operation, {
|
|
223
|
+
wait,
|
|
224
|
+
failed,
|
|
225
|
+
deadline: started + limit,
|
|
226
|
+
});
|
|
227
|
+
if (retried.failures.length > 0)
|
|
150
228
|
return {
|
|
151
229
|
reason: "ci-failed",
|
|
152
|
-
output: await
|
|
230
|
+
output: await ciFailureOutput(operation, {
|
|
231
|
+
wait,
|
|
232
|
+
failed: retried.failures,
|
|
233
|
+
}),
|
|
153
234
|
};
|
|
154
|
-
const pending = pendingChecks(checks, names);
|
|
235
|
+
const pending = [...pendingChecks(checks, names), ...retried.pending];
|
|
155
236
|
if (pending.length === 0 &&
|
|
156
237
|
(required !== undefined ||
|
|
157
238
|
names.size > 0 ||
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { type Operation } from "./github-operation.ts";
|
|
2
|
+
export type MergeCheck = "beforeMerge" | null;
|
|
2
3
|
export interface ReviewedPull {
|
|
3
4
|
readonly number: number;
|
|
4
5
|
readonly commit: string;
|
|
6
|
+
readonly check?: MergeCheck | undefined;
|
|
5
7
|
}
|
|
6
8
|
export declare function knownMerge(operation: Operation, expected: ReviewedPull & {
|
|
7
9
|
readonly updated: string;
|
|
@@ -69,12 +69,13 @@ async function updatedTree(operation, place) {
|
|
|
69
69
|
async function checked(operation, place) {
|
|
70
70
|
await changeChecked(operation, place);
|
|
71
71
|
const head = await headOf(operation, place.tree);
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
const command = place.check === null ? undefined : operation.settings.check;
|
|
73
|
+
if (command !== undefined)
|
|
74
|
+
await operation.calls.run(command, place.tree.path);
|
|
74
75
|
await clean(operation, place.tree);
|
|
75
76
|
if ((await headOf(operation, place.tree)) !== head)
|
|
76
77
|
throw new Error("uncommitted-change");
|
|
77
|
-
if (head !== place.commit &&
|
|
78
|
+
if (head !== place.commit && command === undefined && place.check !== null)
|
|
78
79
|
throw new Error("check-required");
|
|
79
80
|
return head;
|
|
80
81
|
}
|
|
@@ -139,6 +140,7 @@ async function readyHead(operation, pull) {
|
|
|
139
140
|
tree,
|
|
140
141
|
commit: pull.commit,
|
|
141
142
|
recorded,
|
|
143
|
+
check: pull.check,
|
|
142
144
|
});
|
|
143
145
|
if (updated !== pull.commit && recorded !== updated)
|
|
144
146
|
await writeRecord(operation.folder, {
|
|
@@ -175,6 +177,8 @@ function commandOutput(cause) {
|
|
|
175
177
|
.join("");
|
|
176
178
|
}
|
|
177
179
|
export async function merge(operation, pull) {
|
|
180
|
+
if (pull.check === "beforeMerge" && operation.settings.check === undefined)
|
|
181
|
+
throw new Error("check-not-configured");
|
|
178
182
|
try {
|
|
179
183
|
return await completedMerge(operation, pull);
|
|
180
184
|
}
|
|
@@ -21,6 +21,7 @@ export const methodReasons = new Set([
|
|
|
21
21
|
"check-failed",
|
|
22
22
|
"merge-conflict",
|
|
23
23
|
"check-required",
|
|
24
|
+
"check-not-configured",
|
|
24
25
|
"base-moved",
|
|
25
26
|
"head-not-updated",
|
|
26
27
|
"uncommitted-change",
|
|
@@ -37,6 +38,14 @@ function integer(operation, name) {
|
|
|
37
38
|
throw new Error("invalid-payload");
|
|
38
39
|
return value;
|
|
39
40
|
}
|
|
41
|
+
function mergeCheck(operation) {
|
|
42
|
+
if (!Object.hasOwn(operation.payload, "check"))
|
|
43
|
+
return undefined;
|
|
44
|
+
const value = operation.payload["check"];
|
|
45
|
+
if (value === null || value === "beforeMerge")
|
|
46
|
+
return value;
|
|
47
|
+
throw new Error("invalid-payload");
|
|
48
|
+
}
|
|
40
49
|
async function prepare(operation) {
|
|
41
50
|
const { settings, calls, target, signal } = operation;
|
|
42
51
|
await calls.git(settings.repository, ["fetch", "--quiet", "origin"]);
|
|
@@ -261,6 +270,7 @@ export const methods = new Map([
|
|
|
261
270
|
(operation) => merge(operation, {
|
|
262
271
|
number: integer(operation, "number"),
|
|
263
272
|
commit: text(operation, "commit"),
|
|
273
|
+
check: mergeCheck(operation),
|
|
264
274
|
}),
|
|
265
275
|
],
|
|
266
276
|
]);
|
|
@@ -10,6 +10,7 @@ export declare const githubTiming: GithubTiming;
|
|
|
10
10
|
export interface MethodSettings extends CallSettings {
|
|
11
11
|
readonly worktrees: string;
|
|
12
12
|
readonly timing?: GithubTiming;
|
|
13
|
+
readonly requiredChecks?: readonly string[] | null;
|
|
13
14
|
readonly check?: readonly string[];
|
|
14
15
|
}
|
|
15
16
|
export interface Operation {
|
|
@@ -1,49 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
function
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
const status = field(error, "status");
|
|
10
|
-
if ([500, 502, 503, 504].includes(Number(status)))
|
|
11
|
-
return true;
|
|
12
|
-
return ((status === undefined ||
|
|
13
|
-
(typeof status === "number" && Number.isNaN(status))) &&
|
|
14
|
-
/TLS handshake timeout|connection reset|i\/o timeout|\bEOF\b/i.test(detail));
|
|
15
|
-
}
|
|
16
|
-
function retryFactor(error, retry) {
|
|
17
|
-
const network = transient(error);
|
|
18
|
-
if (!network && !retry.statuses.includes(Number(field(error, "status"))))
|
|
19
|
-
throw error;
|
|
20
|
-
if (retry.attempt < 2)
|
|
21
|
-
return network ? retry.attempt + 1 : 1;
|
|
22
|
-
if (!network)
|
|
23
|
-
throw error;
|
|
24
|
-
throw Object.assign(new Error("github-network-failed", { cause: error }), {
|
|
25
|
-
detail: field(error, "detail"),
|
|
1
|
+
import { githubRetry } from "../cli/github-retry.js";
|
|
2
|
+
import { githubTiming } from "./github-operation.js";
|
|
3
|
+
export function retryGithub(operation, retry) {
|
|
4
|
+
return githubRetry({
|
|
5
|
+
...retry,
|
|
6
|
+
signal: operation.signal,
|
|
7
|
+
pollMilliseconds: (operation.settings.timing ?? githubTiming)
|
|
8
|
+
.pollMilliseconds,
|
|
26
9
|
});
|
|
27
10
|
}
|
|
28
|
-
export async function retryGithub(operation, retry) {
|
|
29
|
-
const timing = operation.settings.timing ?? githubTiming;
|
|
30
|
-
for (let attempt = 0;; attempt += 1) {
|
|
31
|
-
operation.signal.throwIfAborted();
|
|
32
|
-
try {
|
|
33
|
-
return await retry.action(attempt);
|
|
34
|
-
}
|
|
35
|
-
catch (error) {
|
|
36
|
-
operation.signal.throwIfAborted();
|
|
37
|
-
const factor = retryFactor(error, {
|
|
38
|
-
attempt,
|
|
39
|
-
statuses: retry.statuses ?? [],
|
|
40
|
-
});
|
|
41
|
-
await delay(timing.pollMilliseconds * factor, undefined, {
|
|
42
|
-
signal: operation.signal,
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
11
|
export function githubRead(operation, parts) {
|
|
48
12
|
return retryGithub(operation, { action: () => operation.calls.gh(parts) });
|
|
49
13
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { activeQueueRuns } from "./queue-status.js";
|
|
1
2
|
import { randomUUID } from "node:crypto";
|
|
2
3
|
import { readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
3
4
|
import { join } from "node:path";
|
|
@@ -147,30 +148,6 @@ async function completed(settings, pending) {
|
|
|
147
148
|
await retired(pending, ending);
|
|
148
149
|
return pendingRuns;
|
|
149
150
|
}
|
|
150
|
-
async function active(runtimeDirectory) {
|
|
151
|
-
let count = 0;
|
|
152
|
-
let after = "";
|
|
153
|
-
do {
|
|
154
|
-
const reply = await send(runtimeDirectory, {
|
|
155
|
-
operation: "status",
|
|
156
|
-
parameters: { after, limit: 500 },
|
|
157
|
-
});
|
|
158
|
-
if (reply.kind === "error")
|
|
159
|
-
throw new Error(reply.error.code);
|
|
160
|
-
const runs = reply.result["runs"];
|
|
161
|
-
if (!Array.isArray(runs))
|
|
162
|
-
throw new Error("invalid-run-list");
|
|
163
|
-
count += runs.filter((value) => {
|
|
164
|
-
const run = record(value);
|
|
165
|
-
return run?.["workflowId"] === "develop-issue" && !terminal(run);
|
|
166
|
-
}).length;
|
|
167
|
-
const next = reply.result["next"];
|
|
168
|
-
if (next !== null && (typeof next !== "string" || next <= after))
|
|
169
|
-
throw new Error("invalid-run-page");
|
|
170
|
-
after = next;
|
|
171
|
-
} while (after !== null);
|
|
172
|
-
return count;
|
|
173
|
-
}
|
|
174
151
|
async function submit(settings, pending) {
|
|
175
152
|
const commandId = pending.retryCommandId ?? randomUUID();
|
|
176
153
|
pending.commands.add(commandId);
|
|
@@ -178,7 +155,7 @@ async function submit(settings, pending) {
|
|
|
178
155
|
const reply = await send(settings.runtimeDirectory, {
|
|
179
156
|
operation: "run",
|
|
180
157
|
parameters: {
|
|
181
|
-
workflowId: "develop-issue",
|
|
158
|
+
workflowId: settings.workflowId ?? "develop-issue",
|
|
182
159
|
source: "ticket",
|
|
183
160
|
submission: { ticket: "next" },
|
|
184
161
|
commandId,
|
|
@@ -279,7 +256,7 @@ async function cycle(settings, signal) {
|
|
|
279
256
|
await holding(pendingRuns);
|
|
280
257
|
continue;
|
|
281
258
|
}
|
|
282
|
-
const activeRuns = await
|
|
259
|
+
const activeRuns = await activeQueueRuns(settings);
|
|
283
260
|
const held = await holding(activeRuns);
|
|
284
261
|
if (activeRuns >= lanes || activeRuns < pendingRuns)
|
|
285
262
|
continue;
|
|
@@ -2,6 +2,7 @@ import { recordedNotifications, saveNotifications, } from "./notify-journal.js";
|
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { send } from "../cli/client.js";
|
|
5
|
+
import { deliveryBackoffMilliseconds } from "../delivery-backoff.js";
|
|
5
6
|
import { record } from "../protocol.js";
|
|
6
7
|
import { decisionNotification, outcomeNotification, } from "./notify-message.js";
|
|
7
8
|
const retentionMilliseconds = 7 * 24 * 60 * 60_000;
|
|
@@ -132,7 +133,7 @@ async function prepareDelivery(journal, entry) {
|
|
|
132
133
|
});
|
|
133
134
|
if (entry.attempts === 5)
|
|
134
135
|
return undefined;
|
|
135
|
-
const backoff = [
|
|
136
|
+
const backoff = deliveryBackoffMilliseconds[entry.attempts] ?? 0;
|
|
136
137
|
if (entry.lastAttemptAt !== null &&
|
|
137
138
|
Date.now() - entry.lastAttemptAt < backoff)
|
|
138
139
|
return undefined;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { record } from "../protocol.js";
|
|
2
|
+
import { sumUsage, usageOf, tokenCount, } from "../worker-usage.js";
|
|
3
|
+
function parsed(line) {
|
|
4
|
+
try {
|
|
5
|
+
return record(JSON.parse(line)) ?? {};
|
|
6
|
+
}
|
|
7
|
+
catch {
|
|
8
|
+
return {};
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function tokens(value) {
|
|
12
|
+
const counts = record(value) ?? {};
|
|
13
|
+
const cache = record(counts["cache"]) ?? {};
|
|
14
|
+
const output = tokenCount(counts["output"]);
|
|
15
|
+
const reasoning = tokenCount(counts["reasoning"]);
|
|
16
|
+
return usageOf({
|
|
17
|
+
input_tokens: counts["input"],
|
|
18
|
+
cache_read_input_tokens: cache["read"],
|
|
19
|
+
output_tokens: output === null || reasoning === null ? null : output + reasoning,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function errorMessage(value) {
|
|
23
|
+
const error = record(value) ?? {};
|
|
24
|
+
const data = record(error["data"]) ?? {};
|
|
25
|
+
const message = data["message"] ?? error["name"];
|
|
26
|
+
return typeof message === "string" ? message : "opencode error";
|
|
27
|
+
}
|
|
28
|
+
function translated(line, state) {
|
|
29
|
+
const event = parsed(line);
|
|
30
|
+
const part = record(event["part"]) ?? {};
|
|
31
|
+
if (typeof event["sessionID"] === "string")
|
|
32
|
+
state.sessionId = event["sessionID"];
|
|
33
|
+
if (typeof event["model"] === "string")
|
|
34
|
+
state.model = event["model"];
|
|
35
|
+
if (event["type"] === "error")
|
|
36
|
+
state.error = errorMessage(event["error"]);
|
|
37
|
+
if (event["type"] === "step_finish") {
|
|
38
|
+
state.steps.push(tokens(part["tokens"]));
|
|
39
|
+
state.reason = part["reason"];
|
|
40
|
+
}
|
|
41
|
+
if (event["type"] !== "text" || typeof part["text"] !== "string")
|
|
42
|
+
return [];
|
|
43
|
+
state.message = part["text"];
|
|
44
|
+
return [
|
|
45
|
+
JSON.stringify({
|
|
46
|
+
type: "assistant",
|
|
47
|
+
message: { content: [{ type: "text", text: state.message }] },
|
|
48
|
+
}),
|
|
49
|
+
];
|
|
50
|
+
}
|
|
51
|
+
function result(exitCode, state) {
|
|
52
|
+
const success = exitCode === 0 && state.error === null && state.reason === "stop";
|
|
53
|
+
const failure = exitCode === 0
|
|
54
|
+
? "opencode ended without a final stop step"
|
|
55
|
+
: `opencode ended with the code ${String(exitCode)}`;
|
|
56
|
+
return JSON.stringify({
|
|
57
|
+
type: "result",
|
|
58
|
+
subtype: success ? "success" : "error_during_execution",
|
|
59
|
+
is_error: !success,
|
|
60
|
+
result: success
|
|
61
|
+
? state.message
|
|
62
|
+
: state.error || state.stderr.trim() || failure,
|
|
63
|
+
total_cost_usd: null,
|
|
64
|
+
model: state.model,
|
|
65
|
+
usage: sumUsage(state.steps),
|
|
66
|
+
session_id: state.sessionId,
|
|
67
|
+
num_turns: state.steps.length,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
export function opencodeStream() {
|
|
71
|
+
const state = {
|
|
72
|
+
steps: [],
|
|
73
|
+
message: "",
|
|
74
|
+
sessionId: null,
|
|
75
|
+
model: null,
|
|
76
|
+
reason: null,
|
|
77
|
+
error: null,
|
|
78
|
+
stderr: "",
|
|
79
|
+
};
|
|
80
|
+
return {
|
|
81
|
+
line: (line) => translated(line, state),
|
|
82
|
+
stderr: (chunk) => {
|
|
83
|
+
state.stderr = (state.stderr + chunk).slice(-16_000);
|
|
84
|
+
},
|
|
85
|
+
result: (exitCode) => result(exitCode, state),
|
|
86
|
+
};
|
|
87
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { send } from "../cli/client.js";
|
|
2
|
+
import { record } from "../protocol.js";
|
|
3
|
+
function queueBusy(value) {
|
|
4
|
+
const busy = record(value)?.["busy"];
|
|
5
|
+
if (typeof busy !== "number")
|
|
6
|
+
return undefined;
|
|
7
|
+
if (!Number.isSafeInteger(busy) || busy < 0)
|
|
8
|
+
throw new Error("invalid-queue-status");
|
|
9
|
+
return busy;
|
|
10
|
+
}
|
|
11
|
+
export async function activeQueueRuns(settings) {
|
|
12
|
+
let count = 0;
|
|
13
|
+
let after = "";
|
|
14
|
+
do {
|
|
15
|
+
const reply = await send(settings.runtimeDirectory, {
|
|
16
|
+
operation: "status",
|
|
17
|
+
parameters: { after, limit: 500 },
|
|
18
|
+
});
|
|
19
|
+
if (reply.kind === "error")
|
|
20
|
+
throw new Error(reply.error.code);
|
|
21
|
+
const busy = queueBusy(reply.result["queue"]);
|
|
22
|
+
if (busy !== undefined)
|
|
23
|
+
return busy;
|
|
24
|
+
const runs = reply.result["runs"];
|
|
25
|
+
if (!Array.isArray(runs))
|
|
26
|
+
throw new Error("invalid-run-list");
|
|
27
|
+
count += runs.filter((value) => {
|
|
28
|
+
const run = record(value);
|
|
29
|
+
return (run?.["workflowId"] === (settings.workflowId ?? "develop-issue") &&
|
|
30
|
+
!["completed", "failed", "cancelled"].includes(String(run["state"])));
|
|
31
|
+
}).length;
|
|
32
|
+
const next = reply.result["next"];
|
|
33
|
+
if (next !== null && (typeof next !== "string" || next <= after))
|
|
34
|
+
throw new Error("invalid-run-page");
|
|
35
|
+
after = next;
|
|
36
|
+
} while (after !== null);
|
|
37
|
+
return count;
|
|
38
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface RetryTree {
|
|
2
|
+
readonly directory: string;
|
|
3
|
+
readonly signal: AbortSignal;
|
|
4
|
+
}
|
|
5
|
+
interface GitResult {
|
|
6
|
+
readonly text: string;
|
|
7
|
+
readonly code: number | null;
|
|
8
|
+
}
|
|
9
|
+
export declare function retryGit(tree: RetryTree, parts: readonly string[]): Promise<GitResult>;
|
|
10
|
+
export declare function turnHead(tree: RetryTree): Promise<string | null>;
|
|
11
|
+
export declare function retryEvidence(tree: RetryTree, startCommit: string | null): Promise<string>;
|
|
12
|
+
export interface IndexFailure {
|
|
13
|
+
readonly reason: "worktree-index-unknown" | "worktree-index-locked";
|
|
14
|
+
readonly lockPath?: string;
|
|
15
|
+
readonly fix: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function indexFailure(tree: RetryTree): Promise<IndexFailure | null>;
|
|
18
|
+
export {};
|