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,53 @@
|
|
|
1
|
+
import { issueIdentity } from "../issue-identity.js";
|
|
2
|
+
import { record } from "../protocol.js";
|
|
3
|
+
export async function outcomeOf(context, view) {
|
|
4
|
+
if (view.state !== "completed")
|
|
5
|
+
return null;
|
|
6
|
+
const event = await context.authority.queries.latestCompletion({
|
|
7
|
+
runId: view.runId,
|
|
8
|
+
atOrBefore: view.latestSequence,
|
|
9
|
+
});
|
|
10
|
+
const payload = event?.payload ?? {};
|
|
11
|
+
const kind = payload["outcome"];
|
|
12
|
+
if (kind === undefined)
|
|
13
|
+
return null;
|
|
14
|
+
const { ticketStatus, promotionId, outcomeReason, issueUpdate } = payload;
|
|
15
|
+
return {
|
|
16
|
+
kind,
|
|
17
|
+
reason: outcomeReason ?? null,
|
|
18
|
+
...(promotionId === undefined ? {} : { promotionId }),
|
|
19
|
+
...(ticketStatus === undefined ? {} : { ticketStatus }),
|
|
20
|
+
...(issueUpdate === "failed" ? { issueUpdate } : {}),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function titleOf(input, workflowId) {
|
|
24
|
+
const ticket = input?.["ticket"];
|
|
25
|
+
if (typeof ticket !== "string")
|
|
26
|
+
return null;
|
|
27
|
+
const fallback = `Cloving task ${String(input?.["cycleId"])}`;
|
|
28
|
+
const lines = ticket.split("\n");
|
|
29
|
+
if (workflowId === "develop-prompt") {
|
|
30
|
+
const first = lines.find((line) => /\S/.test(line));
|
|
31
|
+
return first === undefined
|
|
32
|
+
? fallback
|
|
33
|
+
: first.replace(/^# /, "").trim().slice(0, 200);
|
|
34
|
+
}
|
|
35
|
+
const first = lines[0] ?? "";
|
|
36
|
+
return first.startsWith("# ")
|
|
37
|
+
? first.slice(2).trim().slice(0, 200)
|
|
38
|
+
: fallback;
|
|
39
|
+
}
|
|
40
|
+
export async function metadataOf(context, source) {
|
|
41
|
+
const document = source.digest
|
|
42
|
+
? await context.authority.queries.document(source.digest)
|
|
43
|
+
: undefined;
|
|
44
|
+
const input = record(JSON.parse(document ?? "null"));
|
|
45
|
+
const ticketId = input?.["ticketId"];
|
|
46
|
+
return {
|
|
47
|
+
ticketId: typeof ticketId === "string" && ticketId !== "" ? ticketId : null,
|
|
48
|
+
title: titleOf(input, source.workflowId),
|
|
49
|
+
...(source.workflowId === "develop-issue"
|
|
50
|
+
? { issueIdentity: issueIdentity(input?.["ticket"]) }
|
|
51
|
+
: {}),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
function outcomeOf(event, status) {
|
|
2
|
+
if (event === undefined)
|
|
3
|
+
return null;
|
|
4
|
+
return {
|
|
5
|
+
kind: event.payload["outcome"] ?? status,
|
|
6
|
+
reason: event.payload["outcomeReason"] ?? null,
|
|
7
|
+
promotionId: event.payload["promotionId"] ?? null,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
async function settled(authority, run) {
|
|
11
|
+
if (run.status !== "cancelled")
|
|
12
|
+
return ["completed", "failed"].includes(run.status);
|
|
13
|
+
const closure = await authority.effects.closure(run.runId);
|
|
14
|
+
return (!closure.open &&
|
|
15
|
+
closure.closure === "cancelled" &&
|
|
16
|
+
closure.unresolved.length === 0);
|
|
17
|
+
}
|
|
18
|
+
export async function runWaitTarget(authority, runId) {
|
|
19
|
+
const run = await authority.queries.run(runId);
|
|
20
|
+
const origin = (await authority.queries.runOrigins())[runId];
|
|
21
|
+
if (run === undefined || origin === undefined)
|
|
22
|
+
return undefined;
|
|
23
|
+
const terminal = await settled(authority, run);
|
|
24
|
+
const event = terminal
|
|
25
|
+
? await authority.queries.latestCompletion({
|
|
26
|
+
runId,
|
|
27
|
+
atOrBefore: run.sequence,
|
|
28
|
+
terminal: true,
|
|
29
|
+
})
|
|
30
|
+
: undefined;
|
|
31
|
+
const endedAt = event === undefined ? null : Date.parse(event.recordedAt);
|
|
32
|
+
const stoppedAt = run.status === "cancelled" && terminal
|
|
33
|
+
? await authority.effects.settledAt(runId)
|
|
34
|
+
: null;
|
|
35
|
+
return {
|
|
36
|
+
parentRunId: origin.parentRunId,
|
|
37
|
+
status: run.status,
|
|
38
|
+
endedAt: endedAt === null ? null : Math.max(endedAt, stoppedAt ?? endedAt),
|
|
39
|
+
outcome: outcomeOf(event, run.status),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { type Authority, type AuthorityTiming, type Delivery, type EffectSettings, type Refusal } from "../broker/actor/authority.ts";
|
|
2
2
|
import { type WorkflowRefusal } from "../workflow-refusals.ts";
|
|
3
|
-
import { type WorkflowRegistration } from "./registry.ts";
|
|
3
|
+
import { type Registry, type WorkflowRegistration, type WorkflowBundleStore } from "./registry.ts";
|
|
4
|
+
import { type ServiceContext } from "./replies.ts";
|
|
4
5
|
import { type WorkerPort } from "./worker-port.ts";
|
|
6
|
+
import type { RunWaitTarget } from "../run-wait.ts";
|
|
7
|
+
import type { CommandEffects } from "../command-settings.ts";
|
|
5
8
|
export type { WorkflowRegistration } from "./registry.ts";
|
|
6
9
|
export type { EffectReply, EffectReport, EffectRequest, WorkerPort, } from "./worker-port.ts";
|
|
7
10
|
export interface ServiceTiming {
|
|
@@ -24,22 +27,35 @@ export interface ServiceHost {
|
|
|
24
27
|
readonly reports?: () => readonly unknown[];
|
|
25
28
|
}
|
|
26
29
|
export interface HostPorts {
|
|
30
|
+
readonly runWait?: {
|
|
31
|
+
readonly target: (runId: string) => Promise<RunWaitTarget | undefined>;
|
|
32
|
+
readonly observe: WorkerPort["observe"];
|
|
33
|
+
};
|
|
27
34
|
readonly state: Authority["state"];
|
|
28
35
|
readonly submit: WorkerPort["submit"];
|
|
29
36
|
readonly input: (runId: string) => Promise<string | undefined>;
|
|
30
37
|
readonly document: (digest: string) => Promise<string | undefined>;
|
|
31
|
-
readonly
|
|
38
|
+
readonly workflow: {
|
|
39
|
+
readonly id: (runId: string) => Promise<string | undefined>;
|
|
40
|
+
readonly manifest: Authority["queries"]["manifest"];
|
|
41
|
+
readonly available: (runId: string, workflowId?: string) => Promise<boolean>;
|
|
42
|
+
};
|
|
32
43
|
readonly requestEffect: WorkerPort["requestEffect"];
|
|
33
44
|
readonly operation: Authority["effects"]["operation"];
|
|
45
|
+
readonly operations: Authority["effects"]["operations"];
|
|
34
46
|
readonly reportEffect: WorkerPort["reportEffect"];
|
|
35
47
|
readonly openGate: WorkerPort["openGate"];
|
|
36
48
|
readonly registerWait: WorkerPort["registerWait"];
|
|
37
49
|
}
|
|
38
50
|
export interface ServiceOptions {
|
|
51
|
+
readonly workerHarness?: ServiceContext["workerHarness"];
|
|
52
|
+
readonly commandEffects?: CommandEffects;
|
|
39
53
|
readonly stateDirectory: string;
|
|
40
54
|
readonly runtimeDirectory: string;
|
|
41
55
|
readonly workflows: readonly WorkflowRegistration[];
|
|
42
56
|
readonly retainedWorkflows?: readonly WorkflowRegistration[];
|
|
57
|
+
readonly workflowBundles?: WorkflowBundleStore;
|
|
58
|
+
readonly retainedWorkflow?: Registry["available"];
|
|
43
59
|
readonly workflowRefusals?: readonly WorkflowRefusal[];
|
|
44
60
|
readonly delivery: Delivery;
|
|
45
61
|
readonly host?: (ports: HostPorts) => Promise<ServiceHost>;
|
|
@@ -2,18 +2,19 @@ import { lstat, rm } from "node:fs/promises";
|
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { authorityTiming, openAuthority, } from "../broker/actor/authority.js";
|
|
4
4
|
import { socketAddress } from "../broker/socket-address.js";
|
|
5
|
-
import {
|
|
5
|
+
import {} from "../workflow-refusals.js";
|
|
6
6
|
import { changeSignal } from "./changes.js";
|
|
7
7
|
import { decision, questions } from "./decision-handler.js";
|
|
8
8
|
import { events } from "./event-handler.js";
|
|
9
9
|
import { expiryScan } from "./expiry.js";
|
|
10
10
|
import { commandGateway, workerCommandBound } from "./gateway.js";
|
|
11
11
|
import { workflowRegistry, } from "./registry.js";
|
|
12
|
-
import { failed } from "./replies.js";
|
|
12
|
+
import { failed, queryMetadata } from "./replies.js";
|
|
13
13
|
import { runCommand, status } from "./run-handlers.js";
|
|
14
14
|
import { submissionHandler } from "./submission-handler.js";
|
|
15
15
|
import { connectionLimits, listen, reachable } from "./transport.js";
|
|
16
16
|
import { workerPort } from "./worker-port.js";
|
|
17
|
+
import { runWaitTarget } from "./run-waits.js";
|
|
17
18
|
export const serviceTiming = {
|
|
18
19
|
authority: authorityTiming,
|
|
19
20
|
expiryScanMilliseconds: 1_000,
|
|
@@ -88,7 +89,7 @@ async function started(authority, setup) {
|
|
|
88
89
|
handle: dispatcher({
|
|
89
90
|
authority,
|
|
90
91
|
registry,
|
|
91
|
-
|
|
92
|
+
...queryMetadata(options),
|
|
92
93
|
gateway,
|
|
93
94
|
clock,
|
|
94
95
|
changed: changes.next,
|
|
@@ -135,7 +136,7 @@ export async function startService(options) {
|
|
|
135
136
|
if (typeof path !== "string")
|
|
136
137
|
return path;
|
|
137
138
|
const timing = options.timing ?? serviceTiming;
|
|
138
|
-
const registry = workflowRegistry(options.workflows, options
|
|
139
|
+
const registry = workflowRegistry(options.workflows, options);
|
|
139
140
|
const opening = await openAuthority(options.stateDirectory, {
|
|
140
141
|
delivery: options.delivery,
|
|
141
142
|
timing: timing.authority,
|
|
@@ -148,7 +149,7 @@ export async function startService(options) {
|
|
|
148
149
|
const { authority } = opening;
|
|
149
150
|
const gateway = serviceGateway(authority, { options, registry });
|
|
150
151
|
const worker = workerPort({ gateway, authority });
|
|
151
|
-
const host = await hosted(options, hostPorts(authority, worker));
|
|
152
|
+
const host = await hosted(options, hostPorts(authority, { worker, registry }));
|
|
152
153
|
if (host.kind === "refused") {
|
|
153
154
|
await authority.close();
|
|
154
155
|
return host;
|
|
@@ -182,8 +183,13 @@ function serviceGateway(authority, parts) {
|
|
|
182
183
|
pendingWorkerCommands: limits.pendingWorkerCommands,
|
|
183
184
|
});
|
|
184
185
|
}
|
|
185
|
-
function hostPorts(authority,
|
|
186
|
+
function hostPorts(authority, parts) {
|
|
187
|
+
const { worker, registry } = parts;
|
|
186
188
|
return {
|
|
189
|
+
runWait: {
|
|
190
|
+
target: (runId) => runWaitTarget(authority, runId),
|
|
191
|
+
observe: worker.observe,
|
|
192
|
+
},
|
|
187
193
|
state: authority.state,
|
|
188
194
|
submit: worker.submit,
|
|
189
195
|
input: async (runId) => {
|
|
@@ -198,7 +204,17 @@ function hostPorts(authority, worker) {
|
|
|
198
204
|
openGate: worker.openGate,
|
|
199
205
|
registerWait: worker.registerWait,
|
|
200
206
|
operation: authority.effects.operation,
|
|
201
|
-
|
|
207
|
+
operations: authority.effects.operations,
|
|
208
|
+
workflow: {
|
|
209
|
+
id: async (runId) => (await authority.queries.workflowIds())[runId],
|
|
210
|
+
manifest: authority.queries.manifest,
|
|
211
|
+
available: async (runId, workflowId) => {
|
|
212
|
+
const manifest = await authority.queries.manifest(runId);
|
|
213
|
+
return (manifest !== undefined &&
|
|
214
|
+
(workflowId === undefined || manifest.workflowId === workflowId) &&
|
|
215
|
+
(await registry.available(manifest)) !== undefined);
|
|
216
|
+
},
|
|
217
|
+
},
|
|
202
218
|
};
|
|
203
219
|
}
|
|
204
220
|
function message(error) {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { type Fields, type Reply } from "../protocol.ts";
|
|
2
2
|
import { type ServiceContext } from "./replies.ts";
|
|
3
3
|
export declare function runIdentity(commandId: string): string;
|
|
4
|
-
export declare function queueOverview(context: ServiceContext): Promise<Fields>;
|
|
5
4
|
export declare function submissionHandler(context: ServiceContext): (parameters: Fields) => Promise<Reply>;
|
|
@@ -5,7 +5,8 @@ import { setTimeout as delay } from "node:timers/promises";
|
|
|
5
5
|
import { isCommandId, isIdentifier as isWorkflowIdentifier, } from "../authority/commands.js";
|
|
6
6
|
import { documentDigest } from "../broker/decision-restore.js";
|
|
7
7
|
import { record } from "../protocol.js";
|
|
8
|
-
import { checkResolution, checkSubmission, normalizedRequest, } from "../submission.js";
|
|
8
|
+
import { checkResolution, checkSubmission, hasTicketField, normalizedRequest, } from "../submission.js";
|
|
9
|
+
import { activeWorkflow } from "./active-tickets.js";
|
|
9
10
|
import { committed, failed, invalidRequest, publicReceipt, rejection, result, } from "./replies.js";
|
|
10
11
|
export function runIdentity(commandId) {
|
|
11
12
|
return `run-${createHash("sha256").update(commandId).digest("hex").slice(0, 32)}`;
|
|
@@ -156,14 +157,15 @@ async function admit(context, admission) {
|
|
|
156
157
|
}
|
|
157
158
|
function admissionRefusal(workflow, request) {
|
|
158
159
|
const { workflowId, commandId, submission, activeTickets } = request;
|
|
159
|
-
|
|
160
|
+
const tickets = workflowId === "develop-issue" || hasTicketField(workflow.submission);
|
|
161
|
+
if (tickets &&
|
|
160
162
|
typeof submission["ticket"] === "string" &&
|
|
161
163
|
activeTickets.some((input) => input["ticketId"] === submission["ticket"]))
|
|
162
164
|
return failed("ticket-active", {
|
|
163
165
|
commandId,
|
|
164
166
|
detail: "An active run already works on this ticket.",
|
|
165
167
|
});
|
|
166
|
-
if (
|
|
168
|
+
if (tickets && submission["ticket"] !== "next")
|
|
167
169
|
return undefined;
|
|
168
170
|
return capacityRefusal(workflow, request);
|
|
169
171
|
}
|
|
@@ -228,43 +230,13 @@ async function submitted(context, parameters) {
|
|
|
228
230
|
activeTickets,
|
|
229
231
|
});
|
|
230
232
|
}
|
|
231
|
-
async function activeWorkflow(context, workflowId) {
|
|
232
|
-
const workflows = await context.authority.queries.workflowIds();
|
|
233
|
-
const state = await context.authority.state();
|
|
234
|
-
const runs = Object.values(state.runs).filter((run) => workflows[run.runId] === workflowId &&
|
|
235
|
-
!["completed", "failed", "cancelled"].includes(run.status));
|
|
236
|
-
return Promise.all(runs.map(async (run) => {
|
|
237
|
-
const digest = state.details[run.runId]?.input;
|
|
238
|
-
const text = digest
|
|
239
|
-
? await context.authority.queries.document(digest)
|
|
240
|
-
: undefined;
|
|
241
|
-
return record(JSON.parse(text ?? "null")) ?? {};
|
|
242
|
-
}));
|
|
243
|
-
}
|
|
244
|
-
export async function queueOverview(context) {
|
|
245
|
-
const workflow = context.registry.byId("develop-issue");
|
|
246
|
-
if (workflow?.admission === undefined)
|
|
247
|
-
return {};
|
|
248
|
-
const active = await activeWorkflow(context, "develop-issue");
|
|
249
|
-
return {
|
|
250
|
-
queue: {
|
|
251
|
-
lanes: workflow.admission === "when-idle" ? 1 : workflow.admission,
|
|
252
|
-
busy: active.length,
|
|
253
|
-
skipped: [
|
|
254
|
-
...active.flatMap((input) => typeof input["ticketId"] === "string"
|
|
255
|
-
? [{ ticketId: input["ticketId"], reason: "ticket-active" }]
|
|
256
|
-
: []),
|
|
257
|
-
...(workflow.resolver.skippedTickets?.() ?? []),
|
|
258
|
-
],
|
|
259
|
-
},
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
233
|
export function submissionHandler(context) {
|
|
263
234
|
const pending = new Map();
|
|
264
235
|
return (parameters) => {
|
|
265
236
|
const keys = [`command:${String(parameters["commandId"])}`];
|
|
266
237
|
const workflowId = String(parameters["workflowId"]);
|
|
267
238
|
if (workflowId === "develop-issue" ||
|
|
239
|
+
hasTicketField(context.registry.byId(workflowId)?.submission) ||
|
|
268
240
|
context.registry.byId(workflowId)?.admission !== undefined)
|
|
269
241
|
keys.push(`workflow:${workflowId}`);
|
|
270
242
|
const next = () => submitted(context, parameters);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { record } from "../protocol.js";
|
|
2
|
-
import { priceOf, usageOf,
|
|
2
|
+
import { priceOf, usageOf, attemptsOf, workerTotals, } from "../worker-usage.js";
|
|
3
3
|
function reportFields(text) {
|
|
4
4
|
try {
|
|
5
5
|
return record(JSON.parse(text ?? "null")) ?? {};
|
|
@@ -8,28 +8,6 @@ function reportFields(text) {
|
|
|
8
8
|
return {};
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
|
-
function attemptsOf(value) {
|
|
12
|
-
if (!Array.isArray(value))
|
|
13
|
-
return undefined;
|
|
14
|
-
return value.flatMap((entry) => {
|
|
15
|
-
const fields = record(entry) ?? {};
|
|
16
|
-
const attempt = tokenCount(fields["attempt"]);
|
|
17
|
-
const model = fields["model"];
|
|
18
|
-
if (attempt === null ||
|
|
19
|
-
attempt === 0 ||
|
|
20
|
-
(model !== null && typeof model !== "string"))
|
|
21
|
-
return [];
|
|
22
|
-
return [
|
|
23
|
-
{
|
|
24
|
-
attempt,
|
|
25
|
-
model,
|
|
26
|
-
usage: usageOf(fields["usage"]),
|
|
27
|
-
costUsd: priceOf(fields["costUsd"]),
|
|
28
|
-
estimatedCostUsd: priceOf(fields["estimatedCostUsd"]),
|
|
29
|
-
},
|
|
30
|
-
];
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
11
|
export async function usageTotals(context, runId) {
|
|
34
12
|
const { effects, queries } = context.authority;
|
|
35
13
|
const operations = (await effects.operations(runId)).filter((operation) => operation.capability === "claude" &&
|
|
@@ -40,7 +18,14 @@ export async function usageTotals(context, runId) {
|
|
|
40
18
|
? undefined
|
|
41
19
|
: await queries.document(operation.result));
|
|
42
20
|
const attempts = attemptsOf(report["attempts"]);
|
|
21
|
+
const model = report["model"];
|
|
22
|
+
const summary = report["summary"];
|
|
23
|
+
const harness = report["harness"] ??
|
|
24
|
+
(await context.workerHarness?.(operation.operationId));
|
|
43
25
|
turns.push({
|
|
26
|
+
...(typeof model === "string" ? { model } : {}),
|
|
27
|
+
...(typeof summary === "string" ? { summary } : {}),
|
|
28
|
+
...(typeof harness === "string" ? { harness } : {}),
|
|
44
29
|
...(attempts === undefined ? {} : { attempts }),
|
|
45
30
|
operationId: operation.operationId,
|
|
46
31
|
usage: usageOf(report["usage"]),
|
|
@@ -41,6 +41,13 @@ export interface GateRequest {
|
|
|
41
41
|
readonly prompt: string;
|
|
42
42
|
readonly expiresAt?: string;
|
|
43
43
|
}
|
|
44
|
+
export interface DecisionResult {
|
|
45
|
+
readonly decision: "approved" | "denied" | "answered" | "expired";
|
|
46
|
+
readonly answer: string | null;
|
|
47
|
+
}
|
|
48
|
+
export type DecisionWait = {
|
|
49
|
+
readonly token: string;
|
|
50
|
+
} | DecisionResult;
|
|
44
51
|
export type HandoffValue = string | number | boolean | null | readonly HandoffValue[] | {
|
|
45
52
|
readonly [key: string]: HandoffValue;
|
|
46
53
|
};
|
|
@@ -48,6 +55,20 @@ export interface HandoffRequest {
|
|
|
48
55
|
readonly workflowId: string;
|
|
49
56
|
readonly input: Readonly<Record<string, HandoffValue>>;
|
|
50
57
|
}
|
|
58
|
+
export interface RunWaitRequest {
|
|
59
|
+
readonly runId: string;
|
|
60
|
+
readonly maximumWaitSeconds: number;
|
|
61
|
+
}
|
|
62
|
+
export interface RunWaitOutcome {
|
|
63
|
+
readonly kind: string;
|
|
64
|
+
readonly reason: string | null;
|
|
65
|
+
readonly promotionId: string | null;
|
|
66
|
+
}
|
|
67
|
+
export interface CommandRequest {
|
|
68
|
+
readonly scope: ProtectedScope;
|
|
69
|
+
readonly name: string;
|
|
70
|
+
readonly input: HandoffValue;
|
|
71
|
+
}
|
|
51
72
|
export type GateResult = {
|
|
52
73
|
readonly kind: "opened";
|
|
53
74
|
readonly decisionId: string;
|
|
@@ -61,6 +82,8 @@ export type GateResult = {
|
|
|
61
82
|
export interface StepBridge {
|
|
62
83
|
readonly effect: (request: ProtectedRequest) => Promise<ProtectedResult>;
|
|
63
84
|
readonly gate: (request: GateRequest) => Promise<GateResult>;
|
|
85
|
+
readonly waitForDecision?: (request: GateRequest) => Promise<DecisionWait>;
|
|
64
86
|
readonly handoff?: (request: HandoffRequest) => Promise<ProtectedResult>;
|
|
87
|
+
readonly waitForRun?: (request: RunWaitRequest) => Promise<RunWaitOutcome>;
|
|
65
88
|
}
|
|
66
89
|
export declare function isStepBridge(value: unknown): value is StepBridge;
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import { type GateRequest, type GateResult } from "../step-bridge.ts";
|
|
1
|
+
import { type GateRequest, type GateResult, type DecisionWait } from "../step-bridge.ts";
|
|
2
2
|
export declare function decisionGate(request: GateRequest): Promise<GateResult>;
|
|
3
|
+
export declare function openDecisionWait(request: GateRequest): Promise<DecisionWait>;
|
|
@@ -6,3 +6,10 @@ export async function decisionGate(request) {
|
|
|
6
6
|
return { kind: "unavailable", reason: "cloving-host-unavailable" };
|
|
7
7
|
return await bridge.gate(request);
|
|
8
8
|
}
|
|
9
|
+
export async function openDecisionWait(request) {
|
|
10
|
+
"use step";
|
|
11
|
+
const bridge = Reflect.get(globalThis, Symbol.for(stepBridgeKey));
|
|
12
|
+
if (!isStepBridge(bridge) || bridge.waitForDecision === undefined)
|
|
13
|
+
throw new Error("cloving-host-unavailable");
|
|
14
|
+
return await bridge.waitForDecision(request);
|
|
15
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { mergeRequest, } from "../merge-request.js";
|
|
2
|
+
import { mergeWhenGreen } from "./merge-when-green.js";
|
|
3
|
+
import { waitForDecision } from "./wait-for-decision.js";
|
|
4
|
+
export async function mergeByPerson(request) {
|
|
5
|
+
const { pull, check, round } = mergeRequest(request);
|
|
6
|
+
const decision = await waitForDecision({
|
|
7
|
+
gateId: `merge:${String(pull.number)}:${pull.commit}`,
|
|
8
|
+
kind: "approval",
|
|
9
|
+
prompt: `Merge pull request #${String(pull.number)} (${pull.url}) at commit ${pull.commit} ${check === null ? "with no local check" : `after the local check ${check}`}.`,
|
|
10
|
+
});
|
|
11
|
+
if (decision.decision !== "approved")
|
|
12
|
+
return {
|
|
13
|
+
merged: false,
|
|
14
|
+
reason: "not-approved",
|
|
15
|
+
output: decision.answer ?? "",
|
|
16
|
+
};
|
|
17
|
+
return await mergeWhenGreen({ pull, check, round });
|
|
18
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { mergeRequest, } from "../merge-request.js";
|
|
2
|
+
import { record } from "../protocol.js";
|
|
3
|
+
import { protectedEffect } from "./protected-effect.js";
|
|
4
|
+
const repairReasons = [
|
|
5
|
+
"check-failed",
|
|
6
|
+
"merge-conflict",
|
|
7
|
+
"ci-failed",
|
|
8
|
+
"ci-pending",
|
|
9
|
+
];
|
|
10
|
+
export async function mergeWhenGreen(request) {
|
|
11
|
+
const { pull, check, round } = mergeRequest(request);
|
|
12
|
+
const effect = await protectedEffect({
|
|
13
|
+
capability: "github",
|
|
14
|
+
method: "merge",
|
|
15
|
+
target: pull.target,
|
|
16
|
+
payload: JSON.stringify({
|
|
17
|
+
number: pull.number,
|
|
18
|
+
commit: pull.commit,
|
|
19
|
+
check,
|
|
20
|
+
}),
|
|
21
|
+
scope: {
|
|
22
|
+
phase: "merge",
|
|
23
|
+
operation: "merge",
|
|
24
|
+
round,
|
|
25
|
+
key: `${String(pull.number)}:${pull.commit}`,
|
|
26
|
+
},
|
|
27
|
+
units: 1,
|
|
28
|
+
});
|
|
29
|
+
return mergeOutcome(effect, pull);
|
|
30
|
+
}
|
|
31
|
+
function mergeOutcome(effect, pull) {
|
|
32
|
+
if (effect.kind !== "completed")
|
|
33
|
+
return notMerged(effect);
|
|
34
|
+
const result = parsedResult(effect.result);
|
|
35
|
+
const reason = repairReasons.find((name) => name === result["reason"]);
|
|
36
|
+
if (reason !== undefined && typeof result["output"] === "string")
|
|
37
|
+
return { merged: false, reason, output: result["output"] };
|
|
38
|
+
if (result["reason"] !== undefined ||
|
|
39
|
+
result["number"] !== pull.number ||
|
|
40
|
+
result["commit"] !== pull.commit ||
|
|
41
|
+
typeof result["merged"] !== "string")
|
|
42
|
+
throw new Error("invalid-merge-result");
|
|
43
|
+
return { merged: true, reason: null, output: "" };
|
|
44
|
+
}
|
|
45
|
+
function notMerged(effect) {
|
|
46
|
+
if (effect.kind === "failed" && effect.reason === "check-not-configured")
|
|
47
|
+
return { merged: false, reason: "check-not-configured", output: "" };
|
|
48
|
+
throw new Error(effect.reason ?? effect.kind);
|
|
49
|
+
}
|
|
50
|
+
function parsedResult(text) {
|
|
51
|
+
let parsed;
|
|
52
|
+
try {
|
|
53
|
+
parsed = JSON.parse(text ?? "null");
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
throw new Error("invalid-merge-result");
|
|
57
|
+
}
|
|
58
|
+
const result = record(parsed);
|
|
59
|
+
if (result === undefined)
|
|
60
|
+
throw new Error("invalid-merge-result");
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { record } from "../protocol.js";
|
|
2
|
+
import { protectedEffect } from "./protected-effect.js";
|
|
3
|
+
import { snapshotReviewSubject } from "./review-subject.js";
|
|
4
|
+
export async function reviewByAgent(request) {
|
|
5
|
+
const reviewer = selectedReviewer(request.reviewer);
|
|
6
|
+
const subject = { ...request.subject };
|
|
7
|
+
const snapshot = await snapshotReviewSubject(subject);
|
|
8
|
+
const effect = await protectedEffect({
|
|
9
|
+
...reviewEffect({ subject, snapshot, reviewer }),
|
|
10
|
+
scope: {
|
|
11
|
+
phase: "review",
|
|
12
|
+
operation: reviewer.kind === "greptile" ? "greptile" : `turn:${reviewer.profile}`,
|
|
13
|
+
round: 1,
|
|
14
|
+
key: snapshot.subjectDigest,
|
|
15
|
+
},
|
|
16
|
+
units: 1,
|
|
17
|
+
});
|
|
18
|
+
if (effect.kind !== "completed")
|
|
19
|
+
throw new Error(effect.reason ?? effect.kind);
|
|
20
|
+
let parsed;
|
|
21
|
+
try {
|
|
22
|
+
parsed = JSON.parse(effect.result ?? "null");
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
throw new Error("invalid-review-result");
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
...(reviewer.kind === "turn"
|
|
29
|
+
? turnResult(parsed)
|
|
30
|
+
: greptileFeedback(parsed, subject)),
|
|
31
|
+
commit: snapshot.commit,
|
|
32
|
+
subjectDigest: snapshot.subjectDigest,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function selectedReviewer(value) {
|
|
36
|
+
const reviewer = record(value);
|
|
37
|
+
if (reviewer?.["kind"] === "greptile")
|
|
38
|
+
return { kind: "greptile" };
|
|
39
|
+
if (reviewer?.["kind"] === "turn" &&
|
|
40
|
+
typeof reviewer["profile"] === "string" &&
|
|
41
|
+
/^[A-Za-z0-9_-]{1,119}$/.test(reviewer["profile"]))
|
|
42
|
+
return { kind: "turn", profile: reviewer["profile"] };
|
|
43
|
+
throw new Error("invalid-reviewer");
|
|
44
|
+
}
|
|
45
|
+
function reviewEffect(input) {
|
|
46
|
+
const { subject, snapshot, reviewer } = input;
|
|
47
|
+
if (reviewer.kind === "turn")
|
|
48
|
+
return {
|
|
49
|
+
capability: "claude",
|
|
50
|
+
method: `run-turn:${reviewer.profile}`,
|
|
51
|
+
target: "draft" in subject ? snapshot.subjectDigest : subject.target,
|
|
52
|
+
payload: `Review only this immutable subject. Do not change it. For a commit, inspect that exact commit, not the current branch head.\n${snapshot.prompt}\nEnd your report with exactly one of these lines:\nReview verdict: accept\nReview verdict: change`,
|
|
53
|
+
};
|
|
54
|
+
if ("draft" in subject ||
|
|
55
|
+
!Number.isSafeInteger(subject.number) ||
|
|
56
|
+
Number(subject.number) < 1)
|
|
57
|
+
throw new Error("invalid-greptile-subject");
|
|
58
|
+
return {
|
|
59
|
+
capability: "github",
|
|
60
|
+
method: "wait-review",
|
|
61
|
+
target: subject.target,
|
|
62
|
+
payload: JSON.stringify({ number: subject.number, commit: subject.commit }),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function turnResult(parsed) {
|
|
66
|
+
const result = record(parsed);
|
|
67
|
+
if (result &&
|
|
68
|
+
(result["reviewVerdict"] === null || result["reviewVerdict"] === undefined))
|
|
69
|
+
return {
|
|
70
|
+
accepted: false,
|
|
71
|
+
feedback: "The review turn has no verdict line.",
|
|
72
|
+
};
|
|
73
|
+
if (!result ||
|
|
74
|
+
typeof result["summary"] !== "string" ||
|
|
75
|
+
(result["reviewVerdict"] !== "accept" &&
|
|
76
|
+
result["reviewVerdict"] !== "change"))
|
|
77
|
+
throw new Error("invalid-review-result");
|
|
78
|
+
return {
|
|
79
|
+
accepted: result["reviewVerdict"] === "accept",
|
|
80
|
+
feedback: result["summary"],
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function greptileFeedback(parsed, subject) {
|
|
84
|
+
if ("draft" in subject)
|
|
85
|
+
throw new Error("invalid-greptile-subject");
|
|
86
|
+
const result = greptileResult(parsed, subject);
|
|
87
|
+
return {
|
|
88
|
+
accepted: result.score === 5,
|
|
89
|
+
feedback: [result.summary, ...result.findings].filter(Boolean).join("\n\n"),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function greptileResult(parsed, subject) {
|
|
93
|
+
const result = record(parsed);
|
|
94
|
+
if (!result)
|
|
95
|
+
throw new Error("invalid-review-result");
|
|
96
|
+
const score = result["score"];
|
|
97
|
+
const summary = result["summary"];
|
|
98
|
+
const findings = result["findings"];
|
|
99
|
+
if (result["number"] !== subject.number ||
|
|
100
|
+
result["commit"] !== subject.commit ||
|
|
101
|
+
typeof score !== "number" ||
|
|
102
|
+
!Number.isInteger(score) ||
|
|
103
|
+
score < 0 ||
|
|
104
|
+
score > 5 ||
|
|
105
|
+
typeof summary !== "string" ||
|
|
106
|
+
!Array.isArray(findings))
|
|
107
|
+
throw new Error("invalid-review-result");
|
|
108
|
+
return {
|
|
109
|
+
score,
|
|
110
|
+
summary,
|
|
111
|
+
findings: findings.map((value) => {
|
|
112
|
+
const finding = record(value);
|
|
113
|
+
if (!finding)
|
|
114
|
+
throw new Error("invalid-review-result");
|
|
115
|
+
const { path, line, body } = finding;
|
|
116
|
+
if (typeof path !== "string" ||
|
|
117
|
+
typeof body !== "string" ||
|
|
118
|
+
!(line === null ||
|
|
119
|
+
(typeof line === "number" && Number.isSafeInteger(line) && line > 0)))
|
|
120
|
+
throw new Error("invalid-review-result");
|
|
121
|
+
return `${path}${line === null ? "" : `:${String(line)}`}\n${body}`;
|
|
122
|
+
}),
|
|
123
|
+
};
|
|
124
|
+
}
|