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,200 @@
|
|
|
1
|
+
export async function readReportGithub(input) {
|
|
2
|
+
const reader = await repositoryReader(input).catch(() => null);
|
|
3
|
+
if (reader === null)
|
|
4
|
+
return {
|
|
5
|
+
observedSince: null,
|
|
6
|
+
issues: null,
|
|
7
|
+
pulls: null,
|
|
8
|
+
sources: {
|
|
9
|
+
issues: { status: "unavailable", reason: "configuration-or-identity" },
|
|
10
|
+
pulls: { status: "unavailable", reason: "configuration-or-identity" },
|
|
11
|
+
history: { status: "unavailable", reason: "configuration-or-identity" },
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
const [issues, pulls, history] = await Promise.allSettled([
|
|
15
|
+
issuesOf(reader, input.since),
|
|
16
|
+
pullsOf(reader, input.since),
|
|
17
|
+
repositoryCreatedAt(reader),
|
|
18
|
+
]);
|
|
19
|
+
return {
|
|
20
|
+
observedSince: history.status === "fulfilled" ? history.value : null,
|
|
21
|
+
issues: issues.status === "fulfilled" ? issues.value : null,
|
|
22
|
+
pulls: pulls.status === "fulfilled" ? pulls.value : null,
|
|
23
|
+
sources: {
|
|
24
|
+
issues: source(issues),
|
|
25
|
+
pulls: source(pulls),
|
|
26
|
+
history: source(history),
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
import { record } from "../protocol.js";
|
|
31
|
+
import { githubRetry } from "./github-retry.js";
|
|
32
|
+
import { prRepository } from "./watch-pr-identity.js";
|
|
33
|
+
function commandOf(value) {
|
|
34
|
+
const command = JSON.parse(value ?? '["gh"]');
|
|
35
|
+
if (!Array.isArray(command) ||
|
|
36
|
+
command.length === 0 ||
|
|
37
|
+
!command.every((part) => typeof part === "string" && part !== "" && !part.includes("\0")))
|
|
38
|
+
throw new Error("configuration");
|
|
39
|
+
return command.map(String);
|
|
40
|
+
}
|
|
41
|
+
function rows(value) {
|
|
42
|
+
if (!Array.isArray(value))
|
|
43
|
+
throw new Error("response");
|
|
44
|
+
return value.map((item) => {
|
|
45
|
+
const row = record(item);
|
|
46
|
+
if (row === undefined)
|
|
47
|
+
throw new Error("response");
|
|
48
|
+
return row;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function identity(row, context) {
|
|
52
|
+
const { repository, kind } = context;
|
|
53
|
+
const number = row["number"];
|
|
54
|
+
const url = row["html_url"];
|
|
55
|
+
if (typeof number !== "number" ||
|
|
56
|
+
!Number.isSafeInteger(number) ||
|
|
57
|
+
number <= 0 ||
|
|
58
|
+
typeof url !== "string" ||
|
|
59
|
+
url.toLowerCase() !==
|
|
60
|
+
`https://${repository.host}/${repository.owner}/${repository.repository}/${kind}/${String(number)}`)
|
|
61
|
+
throw new Error("identity");
|
|
62
|
+
return number;
|
|
63
|
+
}
|
|
64
|
+
function timestamp(value) {
|
|
65
|
+
if (typeof value !== "string" || !Number.isFinite(Date.parse(value)))
|
|
66
|
+
throw new Error("response");
|
|
67
|
+
return Date.parse(value);
|
|
68
|
+
}
|
|
69
|
+
async function issuesOf(reader, since) {
|
|
70
|
+
const result = [];
|
|
71
|
+
const seen = new Set();
|
|
72
|
+
for (let page = 1;; page += 1) {
|
|
73
|
+
const values = rows(await reader.read(`issues?state=closed&since=${encodeURIComponent(since)}&per_page=100&page=${String(page)}`, [
|
|
74
|
+
"--jq",
|
|
75
|
+
'map({number, html_url, closed_at, state, state_reason} + (if has("pull_request") then {pull_request: {}} else {} end))',
|
|
76
|
+
]));
|
|
77
|
+
for (const row of values) {
|
|
78
|
+
if (Object.hasOwn(row, "pull_request"))
|
|
79
|
+
continue;
|
|
80
|
+
const number = identity(row, {
|
|
81
|
+
repository: reader.repository,
|
|
82
|
+
kind: "issues",
|
|
83
|
+
});
|
|
84
|
+
if (seen.has(number))
|
|
85
|
+
throw new Error("response");
|
|
86
|
+
seen.add(number);
|
|
87
|
+
if (!completedIssue(row))
|
|
88
|
+
continue;
|
|
89
|
+
result.push({
|
|
90
|
+
at: timestamp(row["closed_at"]),
|
|
91
|
+
value: 1,
|
|
92
|
+
evidence: { issue: number },
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
if (values.length < 100)
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
async function pullsOf(reader, since) {
|
|
100
|
+
const result = [];
|
|
101
|
+
const seen = new Set();
|
|
102
|
+
for (let page = 1;; page += 1) {
|
|
103
|
+
const values = rows(await reader.read(`pulls?state=closed&sort=updated&direction=desc&per_page=100&page=${String(page)}`));
|
|
104
|
+
for (const row of values) {
|
|
105
|
+
const number = identity(row, {
|
|
106
|
+
repository: reader.repository,
|
|
107
|
+
kind: "pull",
|
|
108
|
+
});
|
|
109
|
+
if (seen.has(number))
|
|
110
|
+
throw new Error("response");
|
|
111
|
+
seen.add(number);
|
|
112
|
+
timestamp(row["updated_at"]);
|
|
113
|
+
if (row["merged_at"] === null)
|
|
114
|
+
continue;
|
|
115
|
+
result.push({
|
|
116
|
+
at: timestamp(row["merged_at"]),
|
|
117
|
+
value: 1,
|
|
118
|
+
evidence: { pullRequest: number },
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
if (values.length < 100 ||
|
|
122
|
+
values.some((row) => Date.parse(String(row["updated_at"])) < Date.parse(since)))
|
|
123
|
+
return result;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async function repositoryReader(input) {
|
|
127
|
+
const settings = input.settings;
|
|
128
|
+
if (settings?.repository === undefined)
|
|
129
|
+
throw new Error("configuration");
|
|
130
|
+
const command = commandOf(settings.githubCommand);
|
|
131
|
+
const signal = AbortSignal.timeout(120_000);
|
|
132
|
+
const origin = await settings.execute({
|
|
133
|
+
command: ["git", "config", "--local", "--get-all", "remote.origin.url"],
|
|
134
|
+
directory: settings.repository,
|
|
135
|
+
signal,
|
|
136
|
+
});
|
|
137
|
+
const repository = origin.status === 0 && origin.errorCode === null
|
|
138
|
+
? prRepository(origin.stdout)
|
|
139
|
+
: null;
|
|
140
|
+
if (repository === null)
|
|
141
|
+
throw new Error("identity");
|
|
142
|
+
const directory = settings.repository;
|
|
143
|
+
return {
|
|
144
|
+
repository,
|
|
145
|
+
read: async (endpoint, flags = []) => {
|
|
146
|
+
const output = await githubRetry({
|
|
147
|
+
signal,
|
|
148
|
+
pollMilliseconds: input.retryMilliseconds ?? 30_000,
|
|
149
|
+
action: async () => {
|
|
150
|
+
const output = await settings.execute({
|
|
151
|
+
directory,
|
|
152
|
+
signal,
|
|
153
|
+
command: [
|
|
154
|
+
...command,
|
|
155
|
+
"api",
|
|
156
|
+
"--method",
|
|
157
|
+
"GET",
|
|
158
|
+
"--hostname",
|
|
159
|
+
repository.host,
|
|
160
|
+
`repos/${repository.owner}/${repository.repository}${endpoint === "" ? "" : `/${endpoint}`}`,
|
|
161
|
+
...flags,
|
|
162
|
+
],
|
|
163
|
+
});
|
|
164
|
+
if (output.status !== 0 || output.errorCode !== null)
|
|
165
|
+
throw Object.assign(new Error("github-call-failed"), {
|
|
166
|
+
status: Number(/\(HTTP (\d{3})\)/.exec(output.stderr)?.[1]),
|
|
167
|
+
detail: output.stderr,
|
|
168
|
+
});
|
|
169
|
+
return output.stdout;
|
|
170
|
+
},
|
|
171
|
+
});
|
|
172
|
+
const parsed = JSON.parse(output);
|
|
173
|
+
return parsed;
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function source(result) {
|
|
178
|
+
if (result.status === "fulfilled")
|
|
179
|
+
return { status: "available" };
|
|
180
|
+
const reason = result.reason instanceof Error &&
|
|
181
|
+
result.reason.message === "github-network-failed"
|
|
182
|
+
? "github-network-failed"
|
|
183
|
+
: "read-failed";
|
|
184
|
+
return { status: "unavailable", reason };
|
|
185
|
+
}
|
|
186
|
+
async function repositoryCreatedAt(reader) {
|
|
187
|
+
const repository = record(await reader.read(""));
|
|
188
|
+
const name = repository?.["full_name"];
|
|
189
|
+
if (typeof name !== "string" ||
|
|
190
|
+
name.toLowerCase() !==
|
|
191
|
+
`${reader.repository.owner}/${reader.repository.repository}`)
|
|
192
|
+
throw new Error("identity");
|
|
193
|
+
return timestamp(repository?.["created_at"]);
|
|
194
|
+
}
|
|
195
|
+
function completedIssue(row) {
|
|
196
|
+
if (row["state"] !== "closed" ||
|
|
197
|
+
!["completed", "not_planned", "duplicate"].includes(String(row["state_reason"])))
|
|
198
|
+
throw new Error("response");
|
|
199
|
+
return row["state_reason"] === "completed";
|
|
200
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type Fields } from "../protocol.ts";
|
|
2
|
+
import { type ReportCompletion } from "../report.ts";
|
|
3
|
+
import type { WatchPrSettings } from "./watch-pr-settings.ts";
|
|
4
|
+
interface ReportEnvironment {
|
|
5
|
+
readonly runtimeDirectory: string;
|
|
6
|
+
readonly workingDirectory: string;
|
|
7
|
+
readonly watchPr?: WatchPrSettings;
|
|
8
|
+
readonly terminal: {
|
|
9
|
+
readonly out: (text: string) => void;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export declare function reportCommand(invocation: {
|
|
13
|
+
readonly since: number;
|
|
14
|
+
readonly json: boolean;
|
|
15
|
+
}, environment: ReportEnvironment): Promise<number>;
|
|
16
|
+
export declare function reportCompletion(event: Fields): ReportCompletion | null;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { record } from "../protocol.js";
|
|
2
|
+
import { loopReport, } from "../report.js";
|
|
3
|
+
import { send } from "./client.js";
|
|
4
|
+
import { readReportGithub } from "./report-github.js";
|
|
5
|
+
function reportRecord(value, after) {
|
|
6
|
+
const event = record(value) ?? {};
|
|
7
|
+
const sequence = event["sequence"];
|
|
8
|
+
const at = event["recordedAt"];
|
|
9
|
+
if (typeof sequence !== "number" ||
|
|
10
|
+
!Number.isSafeInteger(sequence) ||
|
|
11
|
+
sequence <= after ||
|
|
12
|
+
typeof at !== "string" ||
|
|
13
|
+
!Number.isFinite(Date.parse(at)))
|
|
14
|
+
throw new Error("invalid-report-cursor");
|
|
15
|
+
return { event, sequence, at: Date.parse(at) };
|
|
16
|
+
}
|
|
17
|
+
function appendEvents(snapshot, values) {
|
|
18
|
+
for (const value of values) {
|
|
19
|
+
const parsed = reportRecord(value, snapshot.after);
|
|
20
|
+
if (snapshot.latest !== null && parsed.sequence > snapshot.latest)
|
|
21
|
+
break;
|
|
22
|
+
snapshot.after = parsed.sequence;
|
|
23
|
+
if (snapshot.observedSince === null || parsed.at < snapshot.observedSince)
|
|
24
|
+
snapshot.observedSince = parsed.at;
|
|
25
|
+
const completion = reportCompletion(parsed.event);
|
|
26
|
+
if (completion === null)
|
|
27
|
+
continue;
|
|
28
|
+
if (snapshot.completions.has(completion.runId))
|
|
29
|
+
throw new Error("duplicate-report-completion");
|
|
30
|
+
snapshot.completions.set(completion.runId, completion);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async function daemonReport(runtime) {
|
|
34
|
+
const snapshot = {
|
|
35
|
+
after: 0,
|
|
36
|
+
latest: null,
|
|
37
|
+
observedSince: null,
|
|
38
|
+
completions: new Map(),
|
|
39
|
+
};
|
|
40
|
+
for (;;) {
|
|
41
|
+
const reply = await send(runtime, {
|
|
42
|
+
operation: "events",
|
|
43
|
+
parameters: { after: snapshot.after, limit: 1000 },
|
|
44
|
+
});
|
|
45
|
+
if (reply.kind === "error")
|
|
46
|
+
throw new Error(reply.error.code);
|
|
47
|
+
const latest = reply.result["latestSequence"];
|
|
48
|
+
if (typeof latest !== "number" ||
|
|
49
|
+
!Number.isSafeInteger(latest) ||
|
|
50
|
+
latest < snapshot.after)
|
|
51
|
+
throw new Error("invalid-report-snapshot");
|
|
52
|
+
snapshot.latest ??= latest;
|
|
53
|
+
const events = reply.result["events"];
|
|
54
|
+
if (!Array.isArray(events))
|
|
55
|
+
throw new Error("invalid-report-events");
|
|
56
|
+
appendEvents(snapshot, events);
|
|
57
|
+
if (snapshot.after >= snapshot.latest)
|
|
58
|
+
return {
|
|
59
|
+
completions: [...snapshot.completions.values()],
|
|
60
|
+
observedSince: snapshot.observedSince,
|
|
61
|
+
};
|
|
62
|
+
if (events.length < 1000)
|
|
63
|
+
throw new Error("incomplete-report-snapshot");
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function settledSpending(run) {
|
|
67
|
+
const condition = run["condition"];
|
|
68
|
+
const effects = run["effects"];
|
|
69
|
+
return (["completed", "failed", "cancelled"].includes(String(condition)) &&
|
|
70
|
+
Array.isArray(effects) &&
|
|
71
|
+
effects.every((value) => ["completed", "failed", "stopped", "cancelled", "refused"].includes(String(record(value)?.["state"]))));
|
|
72
|
+
}
|
|
73
|
+
async function runCost(runtime, runId) {
|
|
74
|
+
const reply = await send(runtime, {
|
|
75
|
+
operation: "status",
|
|
76
|
+
parameters: { runId },
|
|
77
|
+
});
|
|
78
|
+
if (reply.kind === "error")
|
|
79
|
+
return { runId, turns: null };
|
|
80
|
+
const run = record(reply.result["run"]);
|
|
81
|
+
const turns = run?.["workerTurns"];
|
|
82
|
+
if (run?.["runId"] !== runId ||
|
|
83
|
+
!Array.isArray(turns) ||
|
|
84
|
+
!settledSpending(run))
|
|
85
|
+
return { runId, turns: null };
|
|
86
|
+
const parsed = turns.map((value) => {
|
|
87
|
+
const turn = record(value);
|
|
88
|
+
const operationId = turn?.["operationId"];
|
|
89
|
+
const costUsd = turn?.["costUsd"];
|
|
90
|
+
return typeof operationId === "string" &&
|
|
91
|
+
(costUsd === null ||
|
|
92
|
+
(typeof costUsd === "number" &&
|
|
93
|
+
Number.isFinite(costUsd) &&
|
|
94
|
+
costUsd >= 0))
|
|
95
|
+
? { operationId, costUsd }
|
|
96
|
+
: null;
|
|
97
|
+
});
|
|
98
|
+
return {
|
|
99
|
+
runId,
|
|
100
|
+
turns: parsed.some((turn) => turn === null)
|
|
101
|
+
? null
|
|
102
|
+
: parsed.filter((turn) => turn !== null),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function textReport(report) {
|
|
106
|
+
const lines = [`Loop report ${JSON.stringify(report["window"])}`];
|
|
107
|
+
for (const [name, value] of Object.entries(record(report["metrics"]) ?? {})) {
|
|
108
|
+
const metric = record(value) ?? {};
|
|
109
|
+
lines.push(`${name}: ${metric["status"] === "unavailable" ? "unavailable" : String(metric["value"])}`);
|
|
110
|
+
const baseline = record(metric["baseline"]) ?? {};
|
|
111
|
+
lines.push(` history: ${String(baseline["history"])}; median: ${String(baseline["median"])}; band: ${JSON.stringify(baseline["band"])}${metric["mark"] === "outside" ? "; outside" : ""}`);
|
|
112
|
+
lines.push(` comparison value: ${String(metric["comparisonValue"])}`);
|
|
113
|
+
lines.push(` evidence: ${JSON.stringify(metric["evidence"])}`);
|
|
114
|
+
lines.push(` baseline evidence: ${JSON.stringify(baseline["evidence"])}`);
|
|
115
|
+
}
|
|
116
|
+
lines.push(`Run costs (USD): ${JSON.stringify(report["runCosts"])}`);
|
|
117
|
+
lines.push(`Sources: ${JSON.stringify(report["sources"])}`);
|
|
118
|
+
lines.push(`Coverage: ${JSON.stringify(report["coverage"])}`);
|
|
119
|
+
return lines.join("\n") + "\n";
|
|
120
|
+
}
|
|
121
|
+
export async function reportCommand(invocation, environment) {
|
|
122
|
+
const now = Date.now();
|
|
123
|
+
const since = new Date(now - (invocation.since + 168) * 3_600_000).toISOString();
|
|
124
|
+
const settings = environment.watchPr === undefined ? {} : { settings: environment.watchPr };
|
|
125
|
+
const [daemonRead, githubRead] = await Promise.allSettled([
|
|
126
|
+
daemonReport(environment.runtimeDirectory),
|
|
127
|
+
readReportGithub({ since, ...settings }),
|
|
128
|
+
]);
|
|
129
|
+
const daemon = daemonRead.status === "fulfilled"
|
|
130
|
+
? daemonRead.value
|
|
131
|
+
: { completions: null, observedSince: null };
|
|
132
|
+
const github = githubRead.status === "fulfilled" ? { github: githubRead.value } : {};
|
|
133
|
+
const costs = [];
|
|
134
|
+
for (const event of daemon.completions ?? [])
|
|
135
|
+
if (event.at >= now - (invocation.since + 168) * 3_600_000 &&
|
|
136
|
+
event.at < now)
|
|
137
|
+
costs.push(await runCost(environment.runtimeDirectory, event.runId));
|
|
138
|
+
const calculated = loopReport({
|
|
139
|
+
since: invocation.since,
|
|
140
|
+
now,
|
|
141
|
+
...daemon,
|
|
142
|
+
costs,
|
|
143
|
+
...github,
|
|
144
|
+
});
|
|
145
|
+
const report = {
|
|
146
|
+
...calculated,
|
|
147
|
+
window: {
|
|
148
|
+
...calculated.window,
|
|
149
|
+
start: new Date(calculated.window.start).toISOString(),
|
|
150
|
+
end: new Date(now).toISOString(),
|
|
151
|
+
},
|
|
152
|
+
runCosts: calculated.runCosts.map((cost) => ({
|
|
153
|
+
...cost,
|
|
154
|
+
completedAt: new Date(cost.completedAt).toISOString(),
|
|
155
|
+
})),
|
|
156
|
+
};
|
|
157
|
+
environment.terminal.out(invocation.json ? `${JSON.stringify(report)}\n` : textReport(report));
|
|
158
|
+
return 0;
|
|
159
|
+
}
|
|
160
|
+
function outcomeOf(event) {
|
|
161
|
+
if (event["type"] === "run.failed")
|
|
162
|
+
return "failed";
|
|
163
|
+
if (event["type"] === "run.cancelled")
|
|
164
|
+
return "cancelled";
|
|
165
|
+
if (event["type"] !== "run.completed")
|
|
166
|
+
return null;
|
|
167
|
+
const payload = record(event["payload"]) ?? {};
|
|
168
|
+
if (payload["outcome"] === "handoff_requested" &&
|
|
169
|
+
payload["ticketStatus"] === "partial")
|
|
170
|
+
return "partial";
|
|
171
|
+
const outcome = payload["outcome"];
|
|
172
|
+
if (outcome === undefined || outcome === "handoff_requested")
|
|
173
|
+
return "completed";
|
|
174
|
+
return outcome === "blocked" ? "blocked" : null;
|
|
175
|
+
}
|
|
176
|
+
export function reportCompletion(event) {
|
|
177
|
+
const terminal = ["run.completed", "run.failed", "run.cancelled"].includes(String(event["type"]));
|
|
178
|
+
if (!terminal)
|
|
179
|
+
return null;
|
|
180
|
+
const outcome = outcomeOf(event);
|
|
181
|
+
if (outcome === null)
|
|
182
|
+
throw new Error("invalid-report-event");
|
|
183
|
+
const runId = event["runId"];
|
|
184
|
+
const sequence = event["sequence"];
|
|
185
|
+
const at = event["recordedAt"];
|
|
186
|
+
if (typeof runId !== "string" ||
|
|
187
|
+
typeof sequence !== "number" ||
|
|
188
|
+
typeof at !== "string" ||
|
|
189
|
+
!Number.isFinite(Date.parse(at)))
|
|
190
|
+
throw new Error("invalid-report-event");
|
|
191
|
+
return { runId, sequence, at: Date.parse(at), outcome };
|
|
192
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type ParseArgsConfig } from "node:util";
|
|
2
|
+
export declare function repositoryArguments(argumentsList: readonly string[], options: NonNullable<ParseArgsConfig["options"]>): {
|
|
3
|
+
readonly argumentsList: readonly string[];
|
|
4
|
+
readonly repository: string | undefined;
|
|
5
|
+
} | string;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { parseArgs } from "node:util";
|
|
2
|
+
export function repositoryArguments(argumentsList, options) {
|
|
3
|
+
if (!argumentsList.some((argument) => argument === "--repository" || argument.startsWith("--repository=")))
|
|
4
|
+
return { argumentsList, repository: undefined };
|
|
5
|
+
try {
|
|
6
|
+
const parsed = parseArgs({
|
|
7
|
+
args: [...argumentsList],
|
|
8
|
+
options: {
|
|
9
|
+
...options,
|
|
10
|
+
repository: { type: "string" },
|
|
11
|
+
},
|
|
12
|
+
tokens: true,
|
|
13
|
+
allowPositionals: true,
|
|
14
|
+
strict: false,
|
|
15
|
+
});
|
|
16
|
+
const selectors = parsed.tokens.filter((token) => token.kind === "option" && token.name === "repository");
|
|
17
|
+
if (selectors.length > 1)
|
|
18
|
+
return "repeated-option";
|
|
19
|
+
const removed = new Set(selectors.flatMap((token) => token.kind === "option" && !token.inlineValue
|
|
20
|
+
? [token.index, token.index + 1]
|
|
21
|
+
: [token.index]));
|
|
22
|
+
const repository = parsed.values["repository"];
|
|
23
|
+
if (selectors.length > 0 &&
|
|
24
|
+
(typeof repository !== "string" || repository === ""))
|
|
25
|
+
return "missing-value";
|
|
26
|
+
return {
|
|
27
|
+
argumentsList: argumentsList.filter((_, index) => !removed.has(index)),
|
|
28
|
+
repository: typeof repository === "string" ? repository : undefined,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return "missing-value";
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -11,6 +11,10 @@ export type RunSource = {
|
|
|
11
11
|
type DecisionCommand = "answer" | "approve" | "deny";
|
|
12
12
|
type RunCommand = "pause" | "resume" | "drop";
|
|
13
13
|
export type RuntimeInvocation = {
|
|
14
|
+
readonly kind: "report";
|
|
15
|
+
readonly since: number;
|
|
16
|
+
readonly json: boolean;
|
|
17
|
+
} | {
|
|
14
18
|
readonly kind: "command-help";
|
|
15
19
|
readonly command: string;
|
|
16
20
|
} | {
|
|
@@ -51,6 +51,15 @@ const shapes = new Map([
|
|
|
51
51
|
build: events,
|
|
52
52
|
},
|
|
53
53
|
],
|
|
54
|
+
[
|
|
55
|
+
"report",
|
|
56
|
+
{
|
|
57
|
+
subject: "none",
|
|
58
|
+
required: [],
|
|
59
|
+
allowed: () => ["since", "json"],
|
|
60
|
+
build: report,
|
|
61
|
+
},
|
|
62
|
+
],
|
|
54
63
|
[
|
|
55
64
|
"watch",
|
|
56
65
|
{
|
|
@@ -246,3 +255,9 @@ function events(request) {
|
|
|
246
255
|
const json = given(request, "json");
|
|
247
256
|
return { kind: "events", runId, after: after ?? 0, limit, follow, json };
|
|
248
257
|
}
|
|
258
|
+
function report(request) {
|
|
259
|
+
const since = whole(valueOf(request, "since"), { minimum: 1, maximum: 168 });
|
|
260
|
+
if (since === invalid)
|
|
261
|
+
return "invalid-option-value";
|
|
262
|
+
return { kind: "report", since: since ?? 24, json: given(request, "json") };
|
|
263
|
+
}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
type Environment = Readonly<Record<string, string | undefined>>;
|
|
2
|
-
export declare function
|
|
3
|
-
export declare function
|
|
2
|
+
export declare function shellArgument(value: string): string;
|
|
3
|
+
export declare function clientCommand(environment: Environment, repository?: string): string;
|
|
4
|
+
export declare function repositoryRuntimeName(repository: string): string;
|
|
5
|
+
export declare function adoptionRecordPath(environment: Environment, repository: string): string | undefined;
|
|
6
|
+
export declare function legacyRuntimeDirectory(environment: Environment): string | undefined;
|
|
7
|
+
export declare function runtimeDirectory(environment: Environment, repository?: string): string | undefined;
|
|
4
8
|
export {};
|
|
@@ -1,25 +1,83 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { repositoryFileName } from "../repository-identity.js";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { readFileSync, realpathSync } from "node:fs";
|
|
4
|
+
import { basename, isAbsolute, join } from "node:path";
|
|
5
|
+
import { record } from "../protocol.js";
|
|
2
6
|
function given(value) {
|
|
3
7
|
return value !== undefined && value.length > 0;
|
|
4
8
|
}
|
|
5
|
-
export function
|
|
9
|
+
export function shellArgument(value) {
|
|
10
|
+
return /^[A-Za-z0-9_./-]+$/.test(value)
|
|
11
|
+
? value
|
|
12
|
+
: `'${value.replaceAll("'", "'\\''")}'`;
|
|
13
|
+
}
|
|
14
|
+
export function clientCommand(environment, repository) {
|
|
6
15
|
const explicit = environment["CLOVING_RUNTIME_DIR"];
|
|
7
16
|
return given(explicit)
|
|
8
|
-
? `CLOVING_RUNTIME_DIR=${explicit} cloving`
|
|
9
|
-
:
|
|
17
|
+
? `CLOVING_RUNTIME_DIR=${shellArgument(explicit)} cloving`
|
|
18
|
+
: `cloving${repository === undefined ? "" : ` --repository ${shellArgument(repository)}`}`;
|
|
19
|
+
}
|
|
20
|
+
function stateRoot(environment) {
|
|
21
|
+
const state = environment["XDG_STATE_HOME"];
|
|
22
|
+
if (given(state))
|
|
23
|
+
return state;
|
|
24
|
+
const home = environment["HOME"];
|
|
25
|
+
return given(home) ? join(home, ".local", "state") : undefined;
|
|
26
|
+
}
|
|
27
|
+
export function repositoryRuntimeName(repository) {
|
|
28
|
+
const canonical = realpathSync(repository);
|
|
29
|
+
return repositoryFileName({
|
|
30
|
+
name: basename(canonical),
|
|
31
|
+
sha256: createHash("sha256").update(canonical).digest("hex"),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
export function adoptionRecordPath(environment, repository) {
|
|
35
|
+
const state = stateRoot(environment);
|
|
36
|
+
return state === undefined
|
|
37
|
+
? undefined
|
|
38
|
+
: join(state, "cloving", "adopted-runtime", `${repositoryRuntimeName(repository)}.json`);
|
|
39
|
+
}
|
|
40
|
+
export function legacyRuntimeDirectory(environment) {
|
|
41
|
+
const runtime = environment["XDG_RUNTIME_DIR"];
|
|
42
|
+
if (given(runtime))
|
|
43
|
+
return join(runtime, "cloving");
|
|
44
|
+
const state = stateRoot(environment);
|
|
45
|
+
return state === undefined ? undefined : join(state, "cloving", "run");
|
|
46
|
+
}
|
|
47
|
+
function adoptedRuntime(environment, repository) {
|
|
48
|
+
const path = adoptionRecordPath(environment, repository);
|
|
49
|
+
if (path === undefined)
|
|
50
|
+
return undefined;
|
|
51
|
+
try {
|
|
52
|
+
return runtimeRecord(path, repository);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
56
|
+
return undefined;
|
|
57
|
+
throw error;
|
|
58
|
+
}
|
|
10
59
|
}
|
|
11
|
-
|
|
60
|
+
function runtimeRecord(path, repository) {
|
|
61
|
+
const value = record(JSON.parse(readFileSync(path, "utf8")));
|
|
62
|
+
if (value?.["schemaVersion"] === 1 &&
|
|
63
|
+
value["repository"] === realpathSync(repository) &&
|
|
64
|
+
typeof value["runtimeDirectory"] === "string" &&
|
|
65
|
+
isAbsolute(value["runtimeDirectory"]))
|
|
66
|
+
return value["runtimeDirectory"];
|
|
67
|
+
throw new Error("invalid-runtime-record");
|
|
68
|
+
}
|
|
69
|
+
export function runtimeDirectory(environment, repository) {
|
|
12
70
|
const explicit = environment["CLOVING_RUNTIME_DIR"];
|
|
13
71
|
if (given(explicit))
|
|
14
72
|
return explicit;
|
|
73
|
+
if (repository === undefined)
|
|
74
|
+
return undefined;
|
|
75
|
+
const adopted = adoptedRuntime(environment, repository);
|
|
76
|
+
if (adopted !== undefined)
|
|
77
|
+
return adopted;
|
|
15
78
|
const runtime = environment["XDG_RUNTIME_DIR"];
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return join(state, "cloving", "run");
|
|
21
|
-
const home = environment["HOME"];
|
|
22
|
-
return given(home)
|
|
23
|
-
? join(home, ".local", "state", "cloving", "run")
|
|
24
|
-
: undefined;
|
|
79
|
+
const root = given(runtime) ? runtime : stateRoot(environment);
|
|
80
|
+
return root === undefined
|
|
81
|
+
? undefined
|
|
82
|
+
: join(root, "cloving", repositoryRuntimeName(repository), "run");
|
|
25
83
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { ToolchainIdentity } from "../workflow-admission.ts";
|
|
2
|
+
export declare const supportedNodes: string;
|
|
3
|
+
export declare function supportedNode(version: string): boolean;
|
|
2
4
|
export declare function observedToolchain(start: string): Promise<ToolchainIdentity>;
|
|
3
5
|
export declare function qualifiedToolchain(observed: ToolchainIdentity, start: string): Promise<ToolchainIdentity>;
|
|
@@ -3,7 +3,27 @@ import { createHash } from "node:crypto";
|
|
|
3
3
|
import { access, readFile, realpath } from "node:fs/promises";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import packageMetadata from "#package" with { type: "json" };
|
|
6
|
-
const
|
|
6
|
+
export const supportedNodes = packageMetadata.engines.node;
|
|
7
|
+
export function supportedNode(version) {
|
|
8
|
+
const release = /^v(\d+)\.(\d+)\.(\d+)$/.exec(version);
|
|
9
|
+
if (release === null)
|
|
10
|
+
return false;
|
|
11
|
+
const observed = release.slice(1).map(Number);
|
|
12
|
+
return supportedNodes.split(" || ").some((range) => {
|
|
13
|
+
const bounds = /^>=(\d+)\.(\d+)\.(\d+) <(\d+)$/
|
|
14
|
+
.exec(range)
|
|
15
|
+
?.slice(1)
|
|
16
|
+
.map(Number);
|
|
17
|
+
if (bounds === undefined)
|
|
18
|
+
return false;
|
|
19
|
+
return (atLeast(observed, bounds.slice(0, 3)) &&
|
|
20
|
+
(observed[0] ?? 0) < (bounds[3] ?? 0));
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function atLeast(observed, minimum) {
|
|
24
|
+
const index = observed.findIndex((part, position) => part !== minimum[position]);
|
|
25
|
+
return index === -1 || (observed[index] ?? 0) > (minimum[index] ?? 0);
|
|
26
|
+
}
|
|
7
27
|
export async function observedToolchain(start) {
|
|
8
28
|
const root = await projectRoot(start);
|
|
9
29
|
const sdk = await packageDirectory(start, "workflow");
|
|
@@ -29,7 +49,7 @@ export async function qualifiedToolchain(observed, start) {
|
|
|
29
49
|
sdk: `workflow@${packageMetadata.dependencies.workflow}`,
|
|
30
50
|
world: `@workflow/world-local@${typeof declared === "string" ? declared : "undeclared"}`,
|
|
31
51
|
builder: `@workflow/builders@${packageMetadata.dependencies["@workflow/builders"]}`,
|
|
32
|
-
node:
|
|
52
|
+
node: supportedNode(observed.node) ? observed.node : supportedNodes,
|
|
33
53
|
dependencies: observed.dependencies,
|
|
34
54
|
};
|
|
35
55
|
}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import { type WorkerAttemptUsage } from "../worker-usage.ts";
|
|
1
2
|
export declare function priceText(value: unknown, estimate?: unknown): string;
|
|
2
3
|
export declare function usageText(value: unknown): string;
|
|
3
4
|
export declare function totalsSuffix(state: unknown): string;
|
|
5
|
+
export declare function statusJson(result: Fields): Fields;
|
|
6
|
+
import { type Fields } from "../protocol.ts";
|
|
7
|
+
export declare function attemptText(attempt: WorkerAttemptUsage): string;
|
|
8
|
+
export declare function attemptTexts(value: unknown): readonly string[];
|