cloving 1.1.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 +584 -144
- package/assets/watch-fonts/fira-code-OFL.md +93 -0
- package/assets/watch-fonts/fira-code-latin-400-normal.woff2 +0 -0
- package/assets/watch-fonts/fira-code-latin-500-normal.woff2 +0 -0
- package/assets/watch-fonts/heebo-OFL.md +93 -0
- package/assets/watch-fonts/heebo-latin-500-normal.woff2 +0 -0
- package/assets/watch-fonts/heebo-latin-700-normal.woff2 +0 -0
- package/assets/watch-fonts/heebo-latin-800-normal.woff2 +0 -0
- package/assets/watch-fonts/manifest.json +112 -0
- package/assets/watch-fonts/space-grotesk-OFL.md +93 -0
- package/assets/watch-fonts/space-grotesk-latin-400-normal.woff2 +0 -0
- package/assets/watch-fonts/space-grotesk-latin-500-normal.woff2 +0 -0
- package/assets/watch-fonts/space-grotesk-latin-600-normal.woff2 +0 -0
- package/assets/watch-fonts/space-grotesk-latin-700-normal.woff2 +0 -0
- 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 +2 -0
- package/dist/src/authority/commands.js +49 -8
- package/dist/src/authority/dispatch-decision.d.ts +1 -0
- package/dist/src/authority/dispatch-decision.js +7 -4
- package/dist/src/authority/events.js +2 -2
- 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/handoff-chain.d.ts +24 -0
- package/dist/src/authority/handoff-chain.js +46 -0
- package/dist/src/authority/operations.js +1 -1
- package/dist/src/authority/reconciliation.d.ts +1 -0
- package/dist/src/authority/reconciliation.js +18 -11
- 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 +9 -0
- package/dist/src/broker/actor/authority-delivery.js +1 -0
- package/dist/src/broker/actor/authority-queries.d.ts +11 -1
- package/dist/src/broker/actor/authority-queries.js +67 -3
- 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 +3 -1
- package/dist/src/broker/actor/delivery-intents.js +4 -4
- package/dist/src/broker/actor/effect-delivery.js +13 -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 +26 -5
- 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 +3 -1
- package/dist/src/cli/render.js +102 -39
- 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 +74 -45
- 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 +12 -1
- package/dist/src/cli/watch-board-view.js +64 -12
- package/dist/src/cli/watch-board.d.ts +7 -1
- package/dist/src/cli/watch-board.js +61 -16
- 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 +12 -3
- 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.d.ts +10 -4
- package/dist/src/cli/watch-model.js +49 -59
- package/dist/src/cli/watch-page.js +67 -14
- package/dist/src/cli/watch-phases.js +3 -3
- 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-pr-command.d.ts +5 -2
- package/dist/src/cli/watch-pr-command.js +41 -4
- package/dist/src/cli/watch-pr-identity.d.ts +14 -2
- package/dist/src/cli/watch-pr-identity.js +25 -0
- package/dist/src/cli/watch-pr-observer.d.ts +1 -0
- package/dist/src/cli/watch-pr-observer.js +48 -6
- package/dist/src/cli/watch-pull-request.d.ts +12 -0
- package/dist/src/cli/watch-pull-request.js +134 -0
- package/dist/src/cli/watch-reads.d.ts +7 -1
- package/dist/src/cli/watch-reads.js +42 -20
- package/dist/src/cli/watch-render.d.ts +23 -2
- package/dist/src/cli/watch-render.js +2 -1
- package/dist/src/cli/watch-server.js +56 -7
- package/dist/src/cli/watch-turn.d.ts +4 -1
- package/dist/src/cli/watch-turn.js +38 -2
- package/dist/src/cli/watch-usage.js +5 -1
- package/dist/src/cli/watch-view.d.ts +10 -17
- package/dist/src/cli/watch-view.js +33 -77
- 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 +20 -5
- package/dist/src/daemon/claude-turn.js +116 -53
- package/dist/src/daemon/claude-worker.d.ts +3 -5
- package/dist/src/daemon/claude-worker.js +64 -80
- 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 +3 -30
- package/dist/src/daemon/daemon.js +132 -110
- 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 +7 -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-calls.d.ts +4 -0
- package/dist/src/daemon/github-calls.js +16 -7
- 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.d.ts +6 -0
- package/dist/src/daemon/github-ci.js +251 -0
- package/dist/src/daemon/github-merge-call.d.ts +16 -0
- package/dist/src/daemon/github-merge-call.js +73 -0
- package/dist/src/daemon/github-merge.d.ts +3 -5
- package/dist/src/daemon/github-merge.js +59 -98
- package/dist/src/daemon/github-methods.d.ts +28 -0
- package/dist/src/daemon/github-methods.js +90 -16
- package/dist/src/daemon/github-operation.d.ts +3 -0
- package/dist/src/daemon/github-retry.d.ts +6 -0
- package/dist/src/daemon/github-retry.js +13 -0
- package/dist/src/daemon/github-ticket-status.js +27 -1
- package/dist/src/daemon/github-worker.js +2 -1
- package/dist/src/daemon/handoff-worker.d.ts +10 -0
- package/dist/src/daemon/handoff-worker.js +232 -0
- package/dist/src/daemon/issue-queue.d.ts +2 -0
- package/dist/src/daemon/issue-queue.js +92 -63
- package/dist/src/daemon/notify-journal.d.ts +18 -0
- package/dist/src/daemon/notify-journal.js +108 -0
- package/dist/src/daemon/notify-message.js +2 -1
- package/dist/src/daemon/notify.js +177 -37
- 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 +5 -0
- package/dist/src/daemon/retrying-turn.js +145 -21
- 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-dependency-waits.d.ts +18 -0
- package/dist/src/daemon/ticket-dependency-waits.js +60 -0
- package/dist/src/daemon/ticket-registration.d.ts +10 -8
- package/dist/src/daemon/ticket-registration.js +146 -47
- package/dist/src/daemon/ticket-source.d.ts +4 -1
- package/dist/src/daemon/ticket-source.js +8 -2
- 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-visibility.d.ts +2 -0
- package/dist/src/decision-visibility.js +10 -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 +9 -0
- package/dist/src/execution-pin.js +86 -2
- 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 +3 -2
- package/dist/src/host/start-delivery.js +11 -4
- package/dist/src/host/step-bridge-host.d.ts +6 -19
- package/dist/src/host/step-bridge-host.js +57 -55
- package/dist/src/host/world-reconciliation.d.ts +1 -0
- package/dist/src/host/world-reconciliation.js +3 -0
- package/dist/src/host/world-runs.js +5 -0
- package/dist/src/issue-identity.d.ts +6 -0
- package/dist/src/issue-identity.js +23 -0
- 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/queue-runs.d.ts +3 -0
- package/dist/src/service/queue-runs.js +39 -0
- package/dist/src/service/registry.d.ts +22 -3
- package/dist/src/service/registry.js +51 -8
- package/dist/src/service/replies.d.ts +10 -0
- package/dist/src/service/replies.js +12 -0
- package/dist/src/service/run-handlers.js +45 -54
- 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 +21 -2
- package/dist/src/service/service.js +23 -5
- package/dist/src/service/submission-handler.js +70 -19
- package/dist/src/service/worker-port.d.ts +1 -0
- package/dist/src/service/worker-totals.js +10 -1
- package/dist/src/step-bridge.d.ts +32 -0
- package/dist/src/steps/decision-gate.d.ts +2 -1
- package/dist/src/steps/decision-gate.js +7 -0
- package/dist/src/steps/handoff.d.ts +2 -0
- package/dist/src/steps/handoff.js +13 -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-dependencies.d.ts +1 -0
- package/dist/src/ticket-dependencies.js +15 -0
- package/dist/src/ticket-status-stream.d.ts +9 -0
- package/dist/src/ticket-status-stream.js +94 -0
- package/dist/src/ticket-status.js +7 -4
- package/dist/src/token-prices.d.ts +14 -4
- package/dist/src/token-prices.js +56 -11
- package/dist/src/turn-profile.d.ts +1 -0
- package/dist/src/turn-profile.js +8 -1
- package/dist/src/worker-usage.d.ts +25 -0
- package/dist/src/worker-usage.js +58 -1
- package/dist/src/workflow-admission.d.ts +6 -0
- package/dist/src/workflow-candidate.d.ts +7 -2
- package/dist/src/workflow-candidate.js +48 -5
- package/dist/src/workflow-contracts.d.ts +2 -0
- package/dist/src/workflow-contracts.js +8 -3
- package/dist/src/workflow-declaration.d.ts +31 -2
- package/dist/src/workflow-declaration.js +140 -16
- package/dist/src/workflow-discovery.d.ts +19 -0
- package/dist/src/workflow-discovery.js +36 -0
- package/dist/src/workflow-refusals.d.ts +6 -0
- package/dist/src/workflow-refusals.js +42 -0
- package/dist/src/workflow-schedule.d.ts +22 -0
- package/dist/src/workflow-schedule.js +53 -0
- package/dist/src/workflows.d.ts +12 -1
- package/dist/src/workflows.js +9 -0
- package/dist/tools/admit-workflow.d.ts +14 -0
- package/dist/tools/admit-workflow.js +107 -0
- 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 +21 -0
- package/dist/tools/self-host-project.js +224 -0
- 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 +106 -135
- package/dist/tools/workflow-bundle-dependencies.d.ts +5 -0
- package/dist/tools/workflow-bundle-dependencies.js +93 -0
- package/dist/tools/workflow-bundles.d.ts +20 -0
- package/dist/tools/workflow-bundles.js +173 -0
- package/dist/tools/workflow-candidate-counts.d.ts +12 -0
- package/dist/tools/workflow-candidate-counts.js +266 -0
- 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 +13 -0
- package/dist/tools/workflow-candidate-program.js +106 -0
- package/dist/tools/workflow-candidate-source.d.ts +6 -0
- package/dist/tools/workflow-candidate-source.js +169 -0
- package/dist/tools/workflow-candidate-syntax.d.ts +21 -0
- package/dist/tools/workflow-candidate-syntax.js +263 -0
- 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 +18 -0
- package/dist/tools/workflow-folder-capture.js +261 -0
- package/dist/tools/workflow-folders.d.ts +49 -0
- package/dist/tools/workflow-folders.js +203 -0
- package/dist/tools/workflow-source-effects.d.ts +10 -0
- package/dist/tools/workflow-source-effects.js +213 -0
- 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-prd.js +71 -3
- package/dist/workflows/develop-ticket.js +6 -1
- package/dist/workflows/ticket-prompts.js +17 -3
- package/package.json +66 -6
- 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 -24
- package/dist/src/chats/analysis-batches.js +0 -83
- 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 -12
- package/dist/src/chats/analysis-input.js +0 -83
- package/dist/src/chats/analysis-links.d.ts +0 -2
- package/dist/src/chats/analysis-links.js +0 -25
- package/dist/src/chats/analysis-prompt.d.ts +0 -10
- package/dist/src/chats/analysis-prompt.js +0 -16
- package/dist/src/chats/analysis-proposal.d.ts +0 -2
- package/dist/src/chats/analysis-proposal.js +0 -32
- 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 -3
- package/dist/src/chats/analysis-shape.js +0 -228
- 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/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/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 -22
- package/dist/src/daemon/analysis-worker.js +0 -219
- package/dist/src/daemon/chats-files.d.ts +0 -15
- package/dist/src/daemon/chats-files.js +0 -113
- package/dist/src/daemon/chats-worker.d.ts +0 -12
- package/dist/src/daemon/chats-worker.js +0 -200
- package/dist/workflows/analyze-chats.d.ts +0 -10
- package/dist/workflows/analyze-chats.declaration.json +0 -9
- package/dist/workflows/analyze-chats.js +0 -73
|
@@ -1,10 +1,16 @@
|
|
|
1
|
+
import { turnCommand } from "./turn-command.js";
|
|
1
2
|
import { spawn } from "node:child_process";
|
|
2
3
|
import { createWriteStream, mkdtempSync, rmSync } from "node:fs";
|
|
3
4
|
import { join } from "node:path";
|
|
4
5
|
import { codexStream } from "./codex-stream.js";
|
|
5
|
-
import {
|
|
6
|
+
import { cursorStream } from "./cursor-stream.js";
|
|
7
|
+
import { opencodeStream } from "./opencode-stream.js";
|
|
8
|
+
import { textOutput } from "./text-output.js";
|
|
9
|
+
import { grokResultFields, grokUsageWarnings } from "../grok-result.js";
|
|
10
|
+
import { geminiStream } from "./gemini-stream.js";
|
|
11
|
+
import { priceOf, modelUsageOf, usageOf, } from "../worker-usage.js";
|
|
6
12
|
import { commandModel } from "../token-prices.js";
|
|
7
|
-
import {
|
|
13
|
+
import { shellTurnScript } from "../agent-harness-shell.js";
|
|
8
14
|
function parsed(line) {
|
|
9
15
|
try {
|
|
10
16
|
const value = JSON.parse(line);
|
|
@@ -20,21 +26,39 @@ function numberOf(value) {
|
|
|
20
26
|
function textOf(value) {
|
|
21
27
|
return typeof value === "string" ? value : null;
|
|
22
28
|
}
|
|
29
|
+
function networkFailure(result) {
|
|
30
|
+
return (result?.failed === true &&
|
|
31
|
+
result.text.startsWith("API Error: Can't reach the API server"));
|
|
32
|
+
}
|
|
23
33
|
export function capacityRefusal(result) {
|
|
34
|
+
if (networkFailure(result))
|
|
35
|
+
return false;
|
|
24
36
|
return (result?.failed === true &&
|
|
25
37
|
["success", "error_during_execution"].includes(result.subtype ?? "error_during_execution") &&
|
|
26
38
|
(result.text ===
|
|
27
39
|
"Selected model is at capacity. Please try a different model." ||
|
|
28
40
|
result.errorType === "overloaded"));
|
|
29
41
|
}
|
|
30
|
-
export function
|
|
42
|
+
export function retryKind(result) {
|
|
43
|
+
if (networkFailure(result))
|
|
44
|
+
return "network";
|
|
45
|
+
return capacityRefusal(result) ? "capacity" : null;
|
|
46
|
+
}
|
|
47
|
+
export function succeeded(end) {
|
|
48
|
+
return (end.reason === undefined &&
|
|
49
|
+
end.exitCode === 0 &&
|
|
50
|
+
end.result?.failed === false);
|
|
51
|
+
}
|
|
52
|
+
export function streamResult(line, worker) {
|
|
31
53
|
if (!line.includes('"result"'))
|
|
32
54
|
return undefined;
|
|
33
55
|
const record = parsed(line);
|
|
34
56
|
const field = (name) => Reflect.get(Object(record), name);
|
|
35
57
|
if (field("type") !== "result")
|
|
36
58
|
return undefined;
|
|
59
|
+
const models = modelUsageOf(field("models"));
|
|
37
60
|
return {
|
|
61
|
+
...(models === undefined ? {} : { models }),
|
|
38
62
|
...(typeof field("subtype") === "string"
|
|
39
63
|
? { subtype: String(field("subtype")) }
|
|
40
64
|
: {}),
|
|
@@ -48,6 +72,7 @@ export function streamResult(line) {
|
|
|
48
72
|
model: textOf(field("model")),
|
|
49
73
|
sessionId: textOf(field("session_id")),
|
|
50
74
|
turns: numberOf(field("num_turns")),
|
|
75
|
+
...(worker === "grok" ? grokResultFields(record) : {}),
|
|
51
76
|
};
|
|
52
77
|
}
|
|
53
78
|
function ended(stream) {
|
|
@@ -55,12 +80,7 @@ function ended(stream) {
|
|
|
55
80
|
stream.end(settle);
|
|
56
81
|
});
|
|
57
82
|
}
|
|
58
|
-
function turnEnvironment(configuration, start) {
|
|
59
|
-
if (start.mode === "analysis")
|
|
60
|
-
return {
|
|
61
|
-
...analysisEnvironment(start.folder),
|
|
62
|
-
CLAUDE_CODE_OAUTH_TOKEN: start.analysisToken,
|
|
63
|
-
};
|
|
83
|
+
export function turnEnvironment(configuration, start) {
|
|
64
84
|
const excluded = new Set([
|
|
65
85
|
"GH_TOKEN",
|
|
66
86
|
"GITHUB_TOKEN",
|
|
@@ -75,25 +95,42 @@ function turnEnvironment(configuration, start) {
|
|
|
75
95
|
if (start.turnId !== undefined)
|
|
76
96
|
environment["CLOVING_TURN_ID"] = start.turnId;
|
|
77
97
|
environment["GH_CONFIG_DIR"] = configuration;
|
|
98
|
+
if (start.worker === "opencode")
|
|
99
|
+
environment["OPENCODE_PERMISSION"] = '{"*":"allow"}';
|
|
78
100
|
return environment;
|
|
79
101
|
}
|
|
80
102
|
function spawnTurn(start) {
|
|
81
103
|
const configuration = mkdtempSync(join(start.folder, "gh-config-"));
|
|
82
|
-
const
|
|
104
|
+
const { parts, standardInput } = turnCommand(start);
|
|
105
|
+
const command = start.shell === undefined
|
|
106
|
+
? parts
|
|
107
|
+
: [
|
|
108
|
+
start.shell,
|
|
109
|
+
"-l",
|
|
110
|
+
"-i",
|
|
111
|
+
"-c",
|
|
112
|
+
shellTurnScript,
|
|
113
|
+
"cloving-harness",
|
|
114
|
+
configuration,
|
|
115
|
+
...parts,
|
|
116
|
+
];
|
|
117
|
+
const [executable = "", ...fixed] = command;
|
|
83
118
|
try {
|
|
84
119
|
const child = spawn(executable, fixed, {
|
|
85
120
|
cwd: start.directory,
|
|
86
121
|
env: turnEnvironment(configuration, start),
|
|
87
122
|
stdio: ["pipe", "pipe", "pipe"],
|
|
123
|
+
detached: start.shell !== undefined,
|
|
88
124
|
});
|
|
89
|
-
return { child, configuration };
|
|
125
|
+
return { child, configuration, standardInput };
|
|
90
126
|
}
|
|
91
127
|
catch (error) {
|
|
92
128
|
rmSync(configuration, { recursive: true, force: true });
|
|
93
129
|
throw error;
|
|
94
130
|
}
|
|
95
131
|
}
|
|
96
|
-
function receivedLines(stream,
|
|
132
|
+
function receivedLines(stream, input) {
|
|
133
|
+
const { lines, worker } = input;
|
|
97
134
|
for (const line of lines) {
|
|
98
135
|
const event = parsed(line);
|
|
99
136
|
const field = (name) => Reflect.get(Object(event), name);
|
|
@@ -102,7 +139,7 @@ function receivedLines(stream, lines) {
|
|
|
102
139
|
stream.errorType = textOf(field("error"));
|
|
103
140
|
if (type === "system" || type === "result")
|
|
104
141
|
stream.model = textOf(field("model")) ?? stream.model;
|
|
105
|
-
const result = streamResult(line);
|
|
142
|
+
const result = streamResult(line, worker);
|
|
106
143
|
if (result !== undefined) {
|
|
107
144
|
const errorType = result.errorType ?? stream.errorType;
|
|
108
145
|
stream.result = {
|
|
@@ -113,16 +150,31 @@ function receivedLines(stream, lines) {
|
|
|
113
150
|
}
|
|
114
151
|
}
|
|
115
152
|
function activityOutput(start) {
|
|
116
|
-
if (start.mode === "analysis")
|
|
117
|
-
return undefined;
|
|
118
153
|
const output = createWriteStream(join(start.activityFolder ?? start.folder, "turn.jsonl"), { flags: start.activityFolder === undefined ? "w" : "a" });
|
|
119
154
|
if (start.activityFolder !== undefined)
|
|
120
155
|
output.write("\n");
|
|
121
156
|
return output;
|
|
122
157
|
}
|
|
123
|
-
function
|
|
158
|
+
function streamAdapter(worker) {
|
|
159
|
+
if (worker === "codex")
|
|
160
|
+
return codexStream();
|
|
161
|
+
if (worker === "cursor-agent")
|
|
162
|
+
return cursorStream();
|
|
163
|
+
if (worker === "gemini")
|
|
164
|
+
return geminiStream();
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
167
|
+
function turnOutput(start, child) {
|
|
124
168
|
const output = activityOutput(start);
|
|
125
|
-
|
|
169
|
+
if (start.output === "text")
|
|
170
|
+
return textOutput(child, { output, limit: start.resultBytes ?? 48_000 });
|
|
171
|
+
const translated = start.worker === "opencode" ? opencodeStream() : undefined;
|
|
172
|
+
const adapter = translated ?? streamAdapter(start.worker);
|
|
173
|
+
const { stdout, stderr } = child;
|
|
174
|
+
if (translated !== undefined) {
|
|
175
|
+
stderr.setEncoding("utf8");
|
|
176
|
+
stderr.on("data", translated.stderr);
|
|
177
|
+
}
|
|
126
178
|
const stream = {
|
|
127
179
|
pending: "",
|
|
128
180
|
result: undefined,
|
|
@@ -130,66 +182,72 @@ function turnOutput(start, stdout) {
|
|
|
130
182
|
errorType: null,
|
|
131
183
|
};
|
|
132
184
|
const received = (lines) => {
|
|
133
|
-
receivedLines(stream,
|
|
185
|
+
receivedLines(stream, {
|
|
186
|
+
lines,
|
|
187
|
+
...(start.worker === undefined ? {} : { worker: start.worker }),
|
|
188
|
+
});
|
|
134
189
|
};
|
|
135
190
|
const written = (lines) => {
|
|
136
191
|
for (const line of lines)
|
|
137
|
-
output
|
|
192
|
+
output.write(`${line}\n`);
|
|
138
193
|
received(lines);
|
|
139
194
|
};
|
|
140
195
|
stdout.setEncoding("utf8");
|
|
141
196
|
stdout.on("data", (chunk) => {
|
|
142
|
-
if (
|
|
143
|
-
output
|
|
197
|
+
if (adapter === undefined)
|
|
198
|
+
output.write(chunk);
|
|
144
199
|
const lines = `${stream.pending}${chunk}`.split("\n");
|
|
145
200
|
stream.pending = lines.pop() ?? "";
|
|
146
|
-
if (
|
|
147
|
-
written(lines.flatMap(
|
|
201
|
+
if (adapter !== undefined) {
|
|
202
|
+
written(lines.flatMap(adapter.line));
|
|
148
203
|
return;
|
|
149
204
|
}
|
|
150
205
|
received(lines);
|
|
151
206
|
});
|
|
152
207
|
return async (exitCode) => {
|
|
153
|
-
if (
|
|
154
|
-
written(
|
|
155
|
-
written([
|
|
208
|
+
if (adapter !== undefined) {
|
|
209
|
+
written(adapter.line(stream.pending));
|
|
210
|
+
written([adapter.result(exitCode)]);
|
|
156
211
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if (codex === undefined)
|
|
212
|
+
await ended(output);
|
|
213
|
+
if (adapter === undefined)
|
|
160
214
|
received([stream.pending]);
|
|
161
215
|
const result = stream.result;
|
|
162
216
|
return result === undefined
|
|
163
217
|
? undefined
|
|
164
218
|
: {
|
|
165
219
|
...result,
|
|
166
|
-
model: result.model ??
|
|
167
|
-
stream.model ??
|
|
168
|
-
commandModel(start.mode === "analysis" ? analysisCommand() : start.command),
|
|
220
|
+
model: result.model ?? stream.model ?? commandModel(start.command),
|
|
169
221
|
};
|
|
170
222
|
};
|
|
171
223
|
}
|
|
172
|
-
function
|
|
173
|
-
const
|
|
174
|
-
if (
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
224
|
+
function signalTurn(turn, signal) {
|
|
225
|
+
const { child, start } = turn;
|
|
226
|
+
if (start.shell === undefined || child.pid === undefined) {
|
|
227
|
+
child.kill(signal);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
try {
|
|
231
|
+
process.kill(-child.pid, signal);
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
const code = Reflect.get(Object(error), "code");
|
|
235
|
+
if (code !== "ESRCH" && code !== "EPERM")
|
|
236
|
+
throw error;
|
|
237
|
+
child.kill(signal);
|
|
238
|
+
}
|
|
183
239
|
}
|
|
184
240
|
export function startTurn(start) {
|
|
185
|
-
const { child, configuration } = spawnTurn(start);
|
|
186
|
-
const output = turnOutput(start, child
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
child.stderr.
|
|
241
|
+
const { child, configuration, standardInput } = spawnTurn(start);
|
|
242
|
+
const output = turnOutput(start, child);
|
|
243
|
+
const warnings = grokUsageWarnings();
|
|
244
|
+
if (start.worker === "grok") {
|
|
245
|
+
child.stderr.setEncoding("utf8");
|
|
246
|
+
child.stderr.on("data", warnings.write);
|
|
247
|
+
}
|
|
248
|
+
child.stderr.pipe(createWriteStream(join(start.folder, "turn.stderr.log")));
|
|
191
249
|
child.stdin.on("error", () => undefined);
|
|
192
|
-
child.stdin.end(
|
|
250
|
+
child.stdin.end(standardInput);
|
|
193
251
|
const closed = new Promise((settle) => {
|
|
194
252
|
child.once("error", () => undefined);
|
|
195
253
|
child.once("close", settle);
|
|
@@ -200,17 +258,22 @@ export function startTurn(start) {
|
|
|
200
258
|
ended: closed
|
|
201
259
|
.then(async (exitCode) => {
|
|
202
260
|
timers.forEach(clearTimeout);
|
|
261
|
+
const result = await output(exitCode);
|
|
203
262
|
return {
|
|
204
263
|
exitCode,
|
|
205
|
-
result:
|
|
264
|
+
result: result !== undefined && warnings.incomplete()
|
|
265
|
+
? { ...result, usage: usageOf(null), costUsd: null }
|
|
266
|
+
: result,
|
|
206
267
|
};
|
|
207
268
|
})
|
|
208
269
|
.finally(() => {
|
|
209
270
|
rmSync(configuration, { recursive: true, force: true });
|
|
210
271
|
}),
|
|
211
272
|
stop: (graceMilliseconds) => {
|
|
212
|
-
child
|
|
213
|
-
timers.push(setTimeout(() =>
|
|
273
|
+
signalTurn({ child, start }, "SIGTERM");
|
|
274
|
+
timers.push(setTimeout(() => {
|
|
275
|
+
signalTurn({ child, start }, "SIGKILL");
|
|
276
|
+
}, graceMilliseconds).unref());
|
|
214
277
|
},
|
|
215
278
|
};
|
|
216
279
|
}
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type HarnessSettings } from "../harness-defaults.ts";
|
|
2
2
|
import { type TurnProfiles } from "../turn-profile.ts";
|
|
3
3
|
import type { Delivery } from "../broker/actor/delivery-intents.ts";
|
|
4
|
-
import { type Worker } from "./claude-turn.ts";
|
|
5
4
|
import { type RetrySettings } from "./retrying-turn.ts";
|
|
6
5
|
import { type WorkerReport } from "./operation-journal.ts";
|
|
7
|
-
export interface ClaudeWorkerSettings extends RetrySettings {
|
|
8
|
-
readonly tokenPrices?: TokenPrices;
|
|
9
|
-
readonly worker?: Worker;
|
|
6
|
+
export interface ClaudeWorkerSettings extends RetrySettings, HarnessSettings {
|
|
10
7
|
readonly profiles?: TurnProfiles;
|
|
11
8
|
readonly workflowId?: (runId: string) => Promise<string | undefined>;
|
|
12
9
|
readonly repository: string;
|
|
@@ -18,6 +15,7 @@ export interface ClaudeWorkerSettings extends RetrySettings {
|
|
|
18
15
|
readonly stopMilliseconds?: number;
|
|
19
16
|
}
|
|
20
17
|
export interface ClaudeWorker extends Delivery {
|
|
18
|
+
readonly harness: (operationId: string) => Promise<string | undefined>;
|
|
21
19
|
readonly stop: NonNullable<Delivery["stop"]>;
|
|
22
20
|
readonly close: () => Promise<void>;
|
|
23
21
|
}
|
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
import { join } from "node:path";
|
|
2
|
-
import {
|
|
3
|
-
import { analysisWorker } from "./analysis-worker.js";
|
|
4
|
-
import { analysisMethod } from "./analysis-launch.js";
|
|
5
|
-
import { estimatedCostUsd, priceForModel, } from "../token-prices.js";
|
|
2
|
+
import { turnHarness } from "../harness-defaults.js";
|
|
6
3
|
import { profileCommand, } from "../turn-profile.js";
|
|
7
|
-
import {} from "./claude-turn.js";
|
|
4
|
+
import { succeeded } from "./claude-turn.js";
|
|
5
|
+
import { turnReport } from "./turn-report.js";
|
|
8
6
|
import { startRetriedTurn } from "./retrying-turn.js";
|
|
9
7
|
import { interrupted, located, operationKey, readRecord as read, replied, reportOf, writeRecord as written, } from "./operation-journal.js";
|
|
10
|
-
import {
|
|
8
|
+
import { treeFailure, workTree } from "./work-tree.js";
|
|
11
9
|
export const claudeLimits = {
|
|
12
10
|
summaryCharacters: 16_000,
|
|
13
11
|
resultBytes: 48_000,
|
|
14
12
|
stopMilliseconds: 2_000,
|
|
15
13
|
};
|
|
16
14
|
const worker = "claude";
|
|
15
|
+
async function recordedHarness(journal, operationId) {
|
|
16
|
+
const { folder } = located(journal, operationId);
|
|
17
|
+
const started = await read(folder, "started.json").catch(() => undefined);
|
|
18
|
+
const harness = Reflect.get(Object(started), "harness");
|
|
19
|
+
return typeof harness === "string" ? harness : undefined;
|
|
20
|
+
}
|
|
17
21
|
function alive(processId) {
|
|
18
22
|
if (typeof processId !== "number")
|
|
19
23
|
return false;
|
|
@@ -41,78 +45,43 @@ async function reconciled(parts, intent) {
|
|
|
41
45
|
await written(folder, { name: "result.json", value: ending });
|
|
42
46
|
return replied({ receipt: key, worker }, ending);
|
|
43
47
|
}
|
|
44
|
-
async function resultText(tree, turn) {
|
|
45
|
-
const { result, settings } = turn;
|
|
46
|
-
const fields = {
|
|
47
|
-
ticketStatus: ticketStatus(result.text),
|
|
48
|
-
summary: result.text.slice(0, claudeLimits.summaryCharacters),
|
|
49
|
-
...(await changes(tree)),
|
|
50
|
-
worktree: tree.path,
|
|
51
|
-
costUsd: result.costUsd,
|
|
52
|
-
usage: result.usage,
|
|
53
|
-
model: result.model,
|
|
54
|
-
estimatedCostUsd: estimatedCostUsd(result.usage, {
|
|
55
|
-
worker: settings.worker ?? "claude",
|
|
56
|
-
price: priceForModel(settings.tokenPrices ?? {}, result.model),
|
|
57
|
-
}),
|
|
58
|
-
sessionId: result.sessionId,
|
|
59
|
-
turns: result.turns,
|
|
60
|
-
};
|
|
61
|
-
const text = JSON.stringify(fields);
|
|
62
|
-
const excess = Buffer.byteLength(text) - claudeLimits.resultBytes;
|
|
63
|
-
if (excess <= 0)
|
|
64
|
-
return { text };
|
|
65
|
-
const kept = Math.max(0, fields.summary.length - excess);
|
|
66
|
-
const shortened = JSON.stringify({
|
|
67
|
-
...fields,
|
|
68
|
-
summary: fields.summary.slice(0, kept),
|
|
69
|
-
});
|
|
70
|
-
if (Buffer.byteLength(shortened) <= claudeLimits.resultBytes)
|
|
71
|
-
return { text: shortened };
|
|
72
|
-
const metadata = JSON.stringify({
|
|
73
|
-
...fields,
|
|
74
|
-
ticketStatus: undefined,
|
|
75
|
-
summary: "",
|
|
76
|
-
});
|
|
77
|
-
return {
|
|
78
|
-
reason: "claude-result-too-large",
|
|
79
|
-
...(Buffer.byteLength(metadata) <= claudeLimits.resultBytes
|
|
80
|
-
? { text: metadata }
|
|
81
|
-
: {}),
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
48
|
async function outcome(running, end) {
|
|
85
49
|
const endedAt = new Date().toISOString();
|
|
86
50
|
const { result } = end;
|
|
87
51
|
const report = result === undefined
|
|
88
52
|
? {}
|
|
89
|
-
: await
|
|
53
|
+
: await turnReport({
|
|
54
|
+
tree: running.tree,
|
|
55
|
+
harness: running.harness,
|
|
56
|
+
limits: claudeLimits,
|
|
57
|
+
}, result);
|
|
90
58
|
const { text, reason } = report;
|
|
91
|
-
if (reason === undefined &&
|
|
92
|
-
text !== undefined &&
|
|
93
|
-
end.exitCode === 0 &&
|
|
94
|
-
result?.failed === false)
|
|
59
|
+
if (succeeded(end) && reason === undefined && text !== undefined)
|
|
95
60
|
return { outcome: "completed", result: text, endedAt };
|
|
96
61
|
if (running.stopping.requested)
|
|
97
62
|
return { outcome: "stopped", endedAt };
|
|
98
63
|
return {
|
|
99
64
|
outcome: "failed",
|
|
100
|
-
reason: reason ?? "claude-turn-failed",
|
|
65
|
+
reason: end.reason ?? reason ?? "claude-turn-failed",
|
|
66
|
+
...(end.detail === undefined ? {} : { detail: end.detail }),
|
|
101
67
|
...(text === undefined ? {} : { result: text }),
|
|
102
68
|
endedAt,
|
|
103
69
|
};
|
|
104
70
|
}
|
|
105
71
|
async function concluded(parts, running) {
|
|
106
72
|
const { intent, key } = running;
|
|
107
|
-
const recorded = await outcome(
|
|
73
|
+
const recorded = await outcome(running, await running.turn.ended);
|
|
108
74
|
await written(running.folder, { name: "result.json", value: recorded });
|
|
109
75
|
await parts.settings.report(reportOf({ intent, commandId: `claude-turn:${key}`, worker }, recorded));
|
|
110
76
|
}
|
|
111
77
|
async function begun(parts, start) {
|
|
112
78
|
const { intent, key, folder, tree, prompt } = start;
|
|
79
|
+
const { harness } = start;
|
|
80
|
+
const stopping = { requested: false, controller: new AbortController() };
|
|
113
81
|
const turn = startRetriedTurn({
|
|
114
|
-
|
|
115
|
-
|
|
82
|
+
...harness,
|
|
83
|
+
resultBytes: claudeLimits.resultBytes,
|
|
84
|
+
command: profileCommand(harness.command, start.profile),
|
|
116
85
|
environment: start.profile.env ?? {},
|
|
117
86
|
turnId: `${intent.runId}-${key}`,
|
|
118
87
|
directory: tree.path,
|
|
@@ -120,7 +89,9 @@ async function begun(parts, start) {
|
|
|
120
89
|
prompt,
|
|
121
90
|
}, {
|
|
122
91
|
...parts.settings,
|
|
92
|
+
stopping: stopping.controller,
|
|
123
93
|
metadata: {
|
|
94
|
+
harness: harness.worker,
|
|
124
95
|
operationId: intent.operationId,
|
|
125
96
|
target: intent.target,
|
|
126
97
|
branch: tree.branch,
|
|
@@ -128,7 +99,6 @@ async function begun(parts, start) {
|
|
|
128
99
|
startCommit: tree.startCommit,
|
|
129
100
|
},
|
|
130
101
|
});
|
|
131
|
-
const stopping = { requested: false };
|
|
132
102
|
parts.active.set(key, {
|
|
133
103
|
turn,
|
|
134
104
|
stopping,
|
|
@@ -174,16 +144,30 @@ async function runWorkflow(settings, runId) {
|
|
|
174
144
|
return undefined;
|
|
175
145
|
}
|
|
176
146
|
}
|
|
147
|
+
function unsupportedProfile(profile, harness) {
|
|
148
|
+
if (harness.output === "text" && profile.model !== undefined)
|
|
149
|
+
return "profile-model-not-supported";
|
|
150
|
+
if (harness.worker === "claude")
|
|
151
|
+
return undefined;
|
|
152
|
+
return [
|
|
153
|
+
profile.allowedTools,
|
|
154
|
+
profile.permissionMode,
|
|
155
|
+
profile.maxBudgetUsd,
|
|
156
|
+
].some((value) => value !== undefined)
|
|
157
|
+
? "profile-needs-claude"
|
|
158
|
+
: undefined;
|
|
159
|
+
}
|
|
177
160
|
async function selectedProfile(settings, intent) {
|
|
178
161
|
if (intent.method === "run-turn")
|
|
179
162
|
return {};
|
|
180
|
-
if (settings.worker === "codex")
|
|
181
|
-
return "profile-needs-claude";
|
|
182
163
|
const name = intent.method.slice("run-turn:".length);
|
|
183
164
|
const profiles = settings.profiles ?? {};
|
|
184
165
|
const profile = Object.hasOwn(profiles, name) ? profiles[name] : undefined;
|
|
185
166
|
if (profile === undefined)
|
|
186
167
|
return "unknown-profile";
|
|
168
|
+
const unsupported = unsupportedProfile(profile, turnHarness(settings, profile));
|
|
169
|
+
if (unsupported !== undefined)
|
|
170
|
+
return unsupported;
|
|
187
171
|
if (profile.workflows === undefined)
|
|
188
172
|
return profile;
|
|
189
173
|
const workflowId = await runWorkflow(settings, intent.runId);
|
|
@@ -222,11 +206,19 @@ async function delivered(parts, call) {
|
|
|
222
206
|
const first = await firstTurn(settings, { tree, intent });
|
|
223
207
|
if (aborted())
|
|
224
208
|
return failure("claude-start-aborted");
|
|
225
|
-
await begun(parts, {
|
|
209
|
+
await begun(parts, {
|
|
210
|
+
...place,
|
|
211
|
+
intent,
|
|
212
|
+
tree: first,
|
|
213
|
+
prompt,
|
|
214
|
+
profile,
|
|
215
|
+
harness: turnHarness(settings, profile),
|
|
216
|
+
});
|
|
226
217
|
return { receipt: place.key, worker };
|
|
227
218
|
}
|
|
228
219
|
async function halted(parts, active) {
|
|
229
220
|
active.stopping.requested = true;
|
|
221
|
+
active.stopping.controller.abort();
|
|
230
222
|
const turn = await active.turn.catch(() => undefined);
|
|
231
223
|
turn?.stop(parts.settings.stopMilliseconds ?? claudeLimits.stopMilliseconds);
|
|
232
224
|
await active.concluded;
|
|
@@ -241,35 +233,27 @@ async function stopped(parts, intent) {
|
|
|
241
233
|
export function claudeWorker(settings) {
|
|
242
234
|
if (settings.command.length === 0)
|
|
243
235
|
throw new Error("invalid-claude-command");
|
|
236
|
+
turnHarness(settings);
|
|
237
|
+
for (const profile of Object.values(settings.profiles ?? {}))
|
|
238
|
+
turnHarness(settings, profile);
|
|
244
239
|
const parts = {
|
|
245
240
|
settings,
|
|
246
241
|
active: new Map(),
|
|
247
242
|
stopping: new AbortController(),
|
|
248
243
|
};
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
Object.hasOwn(settings.profiles ?? {}, "analyze-chats") ||
|
|
253
|
-
(await runWorkflow(settings, intent.runId)) !== "analyze-chats")
|
|
254
|
-
return failure("analysis-worker-unavailable");
|
|
255
|
-
return run();
|
|
256
|
-
};
|
|
244
|
+
const guarded = (intent, run) => intent.method === "run-turn:analyze-chats"
|
|
245
|
+
? Promise.resolve(failure("unsupported-effect"))
|
|
246
|
+
: run();
|
|
257
247
|
return {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
? guarded(intent, () => analysis.reconcile(intent, signal))
|
|
266
|
-
: reconciled(parts, intent),
|
|
267
|
-
stop: (intent, signal) => intent.method === analysisMethod
|
|
268
|
-
? guarded(intent, () => analysis.stop(intent, signal))
|
|
269
|
-
: stopped(parts, intent),
|
|
248
|
+
harness: (operationId) => recordedHarness(settings.journal, operationId),
|
|
249
|
+
deliver: (intent, signal) => guarded(intent, () => delivered(parts, {
|
|
250
|
+
intent,
|
|
251
|
+
signal: AbortSignal.any([signal, parts.stopping.signal]),
|
|
252
|
+
})),
|
|
253
|
+
reconcile: (intent) => guarded(intent, () => reconciled(parts, intent)),
|
|
254
|
+
stop: (intent) => guarded(intent, () => stopped(parts, intent)),
|
|
270
255
|
close: async () => {
|
|
271
256
|
parts.stopping.abort();
|
|
272
|
-
await analysis.close();
|
|
273
257
|
await Promise.all([...parts.active.values()].map((active) => halted(parts, active)));
|
|
274
258
|
},
|
|
275
259
|
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { CommandEffects } from "../command-settings.ts";
|
|
2
|
+
export declare function claimCommand(folder: string): Promise<boolean>;
|
|
3
|
+
export declare function commandStarted(folder: string): Promise<boolean>;
|
|
4
|
+
export declare function recordCommandResult(folder: string, value: unknown): Promise<boolean>;
|
|
5
|
+
export declare function commandEffects(journal: string): CommandEffects;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { link, mkdir, rm, stat, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { located, readRecord } from "./operation-journal.js";
|
|
5
|
+
import { record } from "../protocol.js";
|
|
6
|
+
function alreadyExists(error) {
|
|
7
|
+
if (Reflect.get(Object(error), "code") === "EEXIST")
|
|
8
|
+
return false;
|
|
9
|
+
throw error;
|
|
10
|
+
}
|
|
11
|
+
export async function claimCommand(folder) {
|
|
12
|
+
await mkdir(dirname(folder), { recursive: true, mode: 0o700 });
|
|
13
|
+
return mkdir(folder, { mode: 0o700 }).then(() => true, alreadyExists);
|
|
14
|
+
}
|
|
15
|
+
export async function commandStarted(folder) {
|
|
16
|
+
return stat(folder).then(() => true, (error) => {
|
|
17
|
+
if (Reflect.get(Object(error), "code") === "ENOENT")
|
|
18
|
+
return false;
|
|
19
|
+
throw error;
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
export async function recordCommandResult(folder, value) {
|
|
23
|
+
const staged = join(folder, `${randomUUID()}.staged`);
|
|
24
|
+
await writeFile(staged, JSON.stringify(value), { mode: 0o600, flag: "wx" });
|
|
25
|
+
try {
|
|
26
|
+
return await link(staged, join(folder, "result.json")).then(() => true, alreadyExists);
|
|
27
|
+
}
|
|
28
|
+
finally {
|
|
29
|
+
await rm(staged);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export function commandEffects(journal) {
|
|
33
|
+
const completed = new Map();
|
|
34
|
+
return (effects) => Promise.all(effects.map(async (effect) => {
|
|
35
|
+
const { key, folder } = located(journal, effect.operationId);
|
|
36
|
+
const cached = completed.get(key);
|
|
37
|
+
if (cached !== undefined)
|
|
38
|
+
return { ...effect, ...cached };
|
|
39
|
+
const result = record(await readRecord(folder, "result.json"));
|
|
40
|
+
const exitCode = result?.["exitCode"];
|
|
41
|
+
const duration = result?.["durationMilliseconds"];
|
|
42
|
+
const metadata = {
|
|
43
|
+
exitCode: typeof exitCode === "number" ? exitCode : null,
|
|
44
|
+
durationMilliseconds: typeof duration === "number" ? duration : null,
|
|
45
|
+
};
|
|
46
|
+
if (result !== undefined)
|
|
47
|
+
completed.set(key, metadata);
|
|
48
|
+
return { ...effect, ...metadata };
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface CommandStart {
|
|
2
|
+
readonly command: readonly string[];
|
|
3
|
+
readonly directory: string;
|
|
4
|
+
readonly folder: string;
|
|
5
|
+
readonly payload: string;
|
|
6
|
+
readonly runId: string;
|
|
7
|
+
readonly operationId: string;
|
|
8
|
+
readonly seconds: number;
|
|
9
|
+
readonly deadline?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface CommandEnd {
|
|
12
|
+
readonly stdout: string;
|
|
13
|
+
readonly exitCode: number | null;
|
|
14
|
+
readonly durationMilliseconds: number;
|
|
15
|
+
readonly reason?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface RunningCommand {
|
|
18
|
+
readonly ended: Promise<CommandEnd>;
|
|
19
|
+
readonly stop: () => void;
|
|
20
|
+
}
|
|
21
|
+
export interface CommandClock {
|
|
22
|
+
readonly now: () => number;
|
|
23
|
+
readonly timer: (wait: {
|
|
24
|
+
readonly milliseconds: number;
|
|
25
|
+
readonly expired: () => void;
|
|
26
|
+
}) => () => void;
|
|
27
|
+
}
|
|
28
|
+
export declare function startCommand(start: CommandStart, clock?: CommandClock): RunningCommand;
|