cloving 1.3.0 → 1.4.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 +235 -206
- package/dist/src/agent-harness-shell.d.ts +2 -1
- package/dist/src/agent-harness-shell.js +8 -5
- package/dist/src/authority/command-wait-checks.d.ts +8 -0
- package/dist/src/authority/command-wait-checks.js +88 -0
- package/dist/src/authority/command-wait-results.d.ts +15 -0
- package/dist/src/authority/command-wait-results.js +73 -0
- package/dist/src/authority/command-wait-view.d.ts +21 -0
- package/dist/src/authority/command-wait-view.js +34 -0
- package/dist/src/authority/command-waits.d.ts +39 -0
- package/dist/src/authority/command-waits.js +97 -0
- package/dist/src/authority/commands.js +22 -1
- package/dist/src/authority/dispatch-decision.d.ts +8 -0
- package/dist/src/authority/dispatch-decision.js +26 -1
- package/dist/src/authority/effect-requests.js +6 -3
- package/dist/src/authority/effect-results.js +4 -2
- package/dist/src/authority/history-state.d.ts +2 -0
- package/dist/src/authority/history-state.js +13 -1
- package/dist/src/authority/instants.d.ts +1 -0
- package/dist/src/authority/instants.js +21 -0
- package/dist/src/authority/reduction-state.d.ts +2 -0
- package/dist/src/authority/reduction-state.js +5 -0
- package/dist/src/authority/reduction.js +24 -0
- package/dist/src/authority/status-input.d.ts +2 -0
- package/dist/src/authority/status.d.ts +2 -0
- package/dist/src/authority/status.js +1 -0
- package/dist/src/authority/stop-sequence.d.ts +1 -0
- package/dist/src/authority/stop-sequence.js +2 -1
- package/dist/src/authority/transitions.d.ts +6 -4
- package/dist/src/authority/transitions.js +7 -0
- package/dist/src/broker/actor/authority-queries.d.ts +2 -1
- package/dist/src/broker/actor/authority-queries.js +14 -5
- package/dist/src/broker/actor/authority-receipts.js +1 -1
- package/dist/src/broker/actor/authority-settings.js +2 -2
- package/dist/src/broker/actor/authority-upgrades.d.ts +19 -2
- package/dist/src/broker/actor/authority-upgrades.js +7 -2
- package/dist/src/broker/actor/delivery-intents.js +2 -0
- package/dist/src/broker/actor/effect-delivery.d.ts +1 -1
- package/dist/src/broker/actor/effect-delivery.js +15 -2
- package/dist/src/broker/actor/effect-plan.js +11 -2
- package/dist/src/broker/actor/effect-queries.d.ts +4 -0
- package/dist/src/broker/actor/effect-queries.js +9 -1
- package/dist/src/broker/actor/effect-turn.js +2 -0
- package/dist/src/broker/actor/stop-plan.js +9 -3
- package/dist/src/broker/actor/stop-turn.d.ts +2 -0
- package/dist/src/broker/actor/stop-turn.js +24 -11
- package/dist/src/broker/actor/turn-draft.d.ts +1 -0
- package/dist/src/broker/actor/turn-draft.js +4 -0
- package/dist/src/broker/actor/turn-state.js +5 -1
- package/dist/src/broker/authority-admission.js +60 -0
- package/dist/src/broker/authority-restore.d.ts +2 -0
- package/dist/src/broker/authority-restore.js +35 -1
- package/dist/src/broker/command-wait-restore.d.ts +31 -0
- package/dist/src/broker/command-wait-restore.js +86 -0
- package/dist/src/broker/decision-restore.d.ts +1 -1
- package/dist/src/broker/decision-restore.js +1 -0
- package/dist/src/broker/effect-upgrade.d.ts +2 -0
- package/dist/src/broker/effect-upgrade.js +8 -2
- package/dist/src/cli/arguments.d.ts +13 -0
- package/dist/src/cli/arguments.js +42 -3
- package/dist/src/cli/chat-stores.d.ts +2 -0
- package/dist/src/cli/chat-stores.js +113 -0
- package/dist/src/cli/client.d.ts +4 -1
- package/dist/src/cli/client.js +9 -3
- package/dist/src/cli/command-requests.d.ts +17 -0
- package/dist/src/cli/command-requests.js +43 -0
- package/dist/src/cli/command-waits.d.ts +9 -0
- package/dist/src/cli/command-waits.js +51 -0
- package/dist/src/cli/commands.js +14 -41
- package/dist/src/cli/config-file.d.ts +2 -2
- package/dist/src/cli/config-file.js +4 -2
- package/dist/src/cli/doctor-workflows.d.ts +5 -2
- package/dist/src/cli/doctor-workflows.js +12 -7
- package/dist/src/cli/doctor.js +6 -9
- package/dist/src/cli/harness-probes.d.ts +2 -0
- package/dist/src/cli/harness-probes.js +1 -1
- package/dist/src/cli/harness-processes.d.ts +6 -0
- package/dist/src/cli/harness-processes.js +36 -0
- package/dist/src/cli/init-command.d.ts +9 -0
- package/dist/src/cli/init-command.js +52 -0
- package/dist/src/cli/init-prompt-command.d.ts +10 -0
- package/dist/src/cli/init-prompt-command.js +145 -0
- package/dist/src/cli/init-prompt.d.ts +35 -0
- package/dist/src/cli/init-prompt.js +74 -0
- package/dist/src/cli/init-selection.d.ts +13 -0
- package/dist/src/cli/init-selection.js +75 -0
- package/dist/src/cli/main.d.ts +2 -0
- package/dist/src/cli/main.js +37 -7
- package/dist/src/cli/mcp-server.d.ts +1 -0
- package/dist/src/cli/mcp-server.js +156 -0
- package/dist/src/cli/mcp-tools.d.ts +15 -0
- package/dist/src/cli/mcp-tools.js +80 -0
- package/dist/src/cli/render.d.ts +1 -1
- package/dist/src/cli/render.js +17 -30
- package/dist/src/cli/report-ci-jobs.d.ts +23 -0
- package/dist/src/cli/report-ci-jobs.js +103 -0
- package/dist/src/cli/report-ci-usage.d.ts +9 -0
- package/dist/src/cli/report-ci-usage.js +185 -0
- package/dist/src/cli/report-ci.d.ts +13 -0
- package/dist/src/cli/report-ci.js +74 -0
- package/dist/src/cli/report-closures.d.ts +6 -0
- package/dist/src/cli/report-closures.js +97 -0
- package/dist/src/cli/report-flow.d.ts +7 -0
- package/dist/src/cli/report-flow.js +122 -0
- package/dist/src/cli/report-github-reader.d.ts +29 -0
- package/dist/src/cli/report-github-reader.js +157 -0
- package/dist/src/cli/report-github.d.ts +15 -8
- package/dist/src/cli/report-github.js +131 -150
- package/dist/src/cli/report-operator.d.ts +3 -0
- package/dist/src/cli/report-operator.js +40 -0
- package/dist/src/cli/report-ready.d.ts +3 -0
- package/dist/src/cli/report-ready.js +96 -0
- package/dist/src/cli/report-text.d.ts +9 -0
- package/dist/src/cli/report-text.js +33 -0
- package/dist/src/cli/report.d.ts +1 -0
- package/dist/src/cli/report.js +104 -27
- package/dist/src/cli/runtime-arguments.d.ts +2 -1
- package/dist/src/cli/runtime-arguments.js +7 -2
- package/dist/src/cli/schedule-arguments.d.ts +14 -0
- package/dist/src/cli/schedule-arguments.js +26 -0
- package/dist/src/cli/schedule-render.d.ts +22 -0
- package/dist/src/cli/schedule-render.js +73 -0
- package/dist/src/cli/terminal-text.d.ts +3 -0
- package/dist/src/cli/terminal-text.js +28 -0
- package/dist/src/cli/usage-render.d.ts +1 -0
- package/dist/src/cli/usage-render.js +28 -1
- package/dist/src/cli/usage.d.ts +1 -1
- package/dist/src/cli/usage.js +50 -7
- package/dist/src/cli/watch-actions.js +2 -2
- package/dist/src/cli/watch-board-view.js +19 -2
- package/dist/src/cli/watch-board.d.ts +4 -2
- package/dist/src/cli/watch-board.js +53 -43
- package/dist/src/cli/watch-card-forms.d.ts +1 -1
- package/dist/src/cli/watch-card-forms.js +11 -10
- package/dist/src/cli/watch-client.d.ts +1 -1
- package/dist/src/cli/watch-client.js +2 -11
- package/dist/src/cli/watch-header-view.d.ts +0 -5
- package/dist/src/cli/watch-header-view.js +8 -20
- package/dist/src/cli/watch-model.d.ts +4 -1
- package/dist/src/cli/watch-model.js +17 -11
- package/dist/src/cli/watch-page.js +12 -14
- package/dist/src/cli/watch-phases.d.ts +12 -3
- package/dist/src/cli/watch-phases.js +68 -11
- package/dist/src/cli/watch-pr-board.js +1 -1
- package/dist/src/cli/watch-pr-command.d.ts +1 -0
- package/dist/src/cli/watch-pull-request.js +18 -8
- package/dist/src/cli/watch-reads.d.ts +2 -0
- package/dist/src/cli/watch-reads.js +17 -16
- package/dist/src/cli/watch-render.d.ts +14 -0
- package/dist/src/cli/watch-run-input.d.ts +0 -1
- package/dist/src/cli/watch-run-input.js +0 -13
- package/dist/src/cli/watch-server.js +6 -6
- package/dist/src/cli/watch-view.d.ts +0 -3
- package/dist/src/cli/watch-view.js +13 -13
- package/dist/src/cli.js +59 -5
- package/dist/src/command-wait.d.ts +4 -0
- package/dist/src/command-wait.js +45 -0
- package/dist/src/configuration-change.d.ts +7 -0
- package/dist/src/configuration-change.js +14 -0
- package/dist/src/configuration-schema.d.ts +9 -0
- package/dist/src/configuration-schema.js +6 -2
- package/dist/src/daemon/attachment-file.d.ts +6 -0
- package/dist/src/daemon/attachment-file.js +86 -0
- package/dist/src/daemon/attachments.d.ts +14 -0
- package/dist/src/daemon/attachments.js +17 -0
- package/dist/src/daemon/claude-recovery.d.ts +50 -0
- package/dist/src/daemon/claude-recovery.js +204 -0
- package/dist/src/daemon/claude-stream.d.ts +27 -0
- package/dist/src/daemon/claude-stream.js +63 -0
- package/dist/src/daemon/claude-turn.d.ts +11 -25
- package/dist/src/daemon/claude-turn.js +64 -81
- package/dist/src/daemon/claude-worker.d.ts +2 -1
- package/dist/src/daemon/claude-worker.js +124 -122
- package/dist/src/daemon/daemon-adapters.d.ts +2 -0
- package/dist/src/daemon/daemon-adapters.js +26 -2
- package/dist/src/daemon/daemon-loops.d.ts +3 -1
- package/dist/src/daemon/daemon-loops.js +3 -1
- package/dist/src/daemon/daemon.js +14 -6
- package/dist/src/daemon/github-attach.d.ts +2 -0
- package/dist/src/daemon/github-attach.js +149 -0
- package/dist/src/daemon/github-ci-filters.d.ts +6 -0
- package/dist/src/daemon/github-ci-filters.js +138 -0
- package/dist/src/daemon/github-ci-workflows.d.ts +10 -0
- package/dist/src/daemon/github-ci-workflows.js +148 -0
- package/dist/src/daemon/github-ci.js +22 -4
- package/dist/src/daemon/github-issue-methods.d.ts +2 -0
- package/dist/src/daemon/github-issue-methods.js +37 -2
- package/dist/src/daemon/github-merge-call.d.ts +2 -1
- package/dist/src/daemon/github-merge-call.js +10 -3
- package/dist/src/daemon/github-merge.js +52 -24
- package/dist/src/daemon/github-methods.js +12 -2
- package/dist/src/daemon/github-operation.d.ts +4 -0
- package/dist/src/daemon/github-operation.js +6 -0
- package/dist/src/daemon/github-worker.d.ts +4 -0
- package/dist/src/daemon/github-worker.js +6 -0
- package/dist/src/daemon/issue-queue.d.ts +1 -1
- package/dist/src/daemon/issue-queue.js +16 -11
- package/dist/src/daemon/notify-events.d.ts +6 -0
- package/dist/src/daemon/notify-events.js +84 -0
- package/dist/src/daemon/notify-journal.js +1 -1
- package/dist/src/daemon/notify-message.d.ts +4 -1
- package/dist/src/daemon/notify-message.js +36 -0
- package/dist/src/daemon/notify.d.ts +1 -1
- package/dist/src/daemon/notify.js +5 -77
- package/dist/src/daemon/operation-journal.d.ts +1 -0
- package/dist/src/daemon/queue-status.d.ts +9 -3
- package/dist/src/daemon/queue-status.js +17 -4
- package/dist/src/daemon/resume-index-lock.d.ts +13 -0
- package/dist/src/daemon/resume-index-lock.js +160 -0
- package/dist/src/daemon/resume-worktree.d.ts +7 -0
- package/dist/src/daemon/resume-worktree.js +29 -0
- package/dist/src/daemon/retrying-turn.d.ts +2 -12
- package/dist/src/daemon/retrying-turn.js +98 -172
- package/dist/src/daemon/schedule-control.d.ts +26 -0
- package/dist/src/daemon/schedule-control.js +110 -0
- package/dist/src/daemon/schedule-journal.d.ts +2 -15
- package/dist/src/daemon/schedule-journal.js +67 -4
- package/dist/src/daemon/ticket-registration.d.ts +2 -7
- package/dist/src/daemon/ticket-registration.js +15 -81
- package/dist/src/daemon/turn-attempt-journal.d.ts +38 -0
- package/dist/src/daemon/turn-attempt-journal.js +136 -0
- package/dist/src/daemon/turn-attempts.d.ts +47 -0
- package/dist/src/daemon/turn-attempts.js +166 -0
- package/dist/src/daemon/turn-report.d.ts +8 -1
- package/dist/src/daemon/turn-report.js +39 -0
- package/dist/src/daemon/work-tree.d.ts +9 -0
- package/dist/src/daemon/work-tree.js +20 -0
- package/dist/src/daemon/worker-profile.d.ts +8 -0
- package/dist/src/daemon/worker-profile.js +40 -0
- package/dist/src/daemon/workflow-schedules.d.ts +3 -0
- package/dist/src/daemon/workflow-schedules.js +98 -45
- package/dist/src/daemon/worktree-processes.d.ts +9 -0
- package/dist/src/daemon/worktree-processes.js +151 -0
- package/dist/src/doctor-report.d.ts +3 -5
- package/dist/src/doctor-report.js +6 -13
- package/dist/src/harness-start.d.ts +15 -0
- package/dist/src/harness-start.js +37 -0
- package/dist/src/host/command-wait.d.ts +38 -0
- package/dist/src/host/command-wait.js +115 -0
- package/dist/src/host/start-delivery.d.ts +5 -7
- package/dist/src/host/start-delivery.js +3 -15
- package/dist/src/host/step-bridge-host.d.ts +2 -0
- package/dist/src/host/step-bridge-host.js +21 -0
- package/dist/src/operation-identity.d.ts +1 -0
- package/dist/src/operation-identity.js +4 -0
- package/dist/src/private-config.schema.json +40 -0
- package/dist/src/project-config.schema.json +40 -0
- package/dist/src/project-settings.d.ts +2 -2
- package/dist/src/project-settings.js +3 -1
- package/dist/src/queue-spend.d.ts +4 -0
- package/dist/src/queue-spend.js +21 -0
- package/dist/src/relay/relay-service.d.ts +3 -0
- package/dist/src/relay/relay-service.js +5 -3
- package/dist/src/report-ci.d.ts +164 -0
- package/dist/src/report-ci.js +32 -0
- package/dist/src/report-effects.d.ts +15 -0
- package/dist/src/report-effects.js +212 -0
- package/dist/src/report-flow-types.d.ts +38 -0
- package/dist/src/report-flow-types.js +7 -0
- package/dist/src/report-flow.d.ts +43 -0
- package/dist/src/report-flow.js +193 -0
- package/dist/src/report-operator.d.ts +67 -0
- package/dist/src/report-operator.js +25 -0
- package/dist/src/report-quality.d.ts +221 -0
- package/dist/src/report-quality.js +94 -0
- package/dist/src/report-ready.d.ts +23 -0
- package/dist/src/report-ready.js +117 -0
- package/dist/src/report-statistics.d.ts +2 -1
- package/dist/src/report-statistics.js +40 -4
- package/dist/src/report.d.ts +588 -47
- package/dist/src/report.js +156 -41
- package/dist/src/schedule-progress.d.ts +33 -0
- package/dist/src/schedule-progress.js +45 -0
- package/dist/src/service/active-tickets.js +6 -6
- package/dist/src/service/command-waits.d.ts +34 -0
- package/dist/src/service/command-waits.js +86 -0
- package/dist/src/service/expiry.js +2 -0
- package/dist/src/service/gateway.js +3 -1
- package/dist/src/service/queue-spend.d.ts +6 -0
- package/dist/src/service/queue-spend.js +68 -0
- package/dist/src/service/replies.d.ts +8 -1
- package/dist/src/service/replies.js +11 -0
- package/dist/src/service/run-handlers.js +22 -2
- package/dist/src/service/run-metadata.d.ts +15 -1
- package/dist/src/service/run-metadata.js +93 -8
- package/dist/src/service/service.d.ts +4 -0
- package/dist/src/service/service.js +8 -8
- package/dist/src/service/submission-handler.js +18 -4
- package/dist/src/service/worker-port.js +9 -1
- package/dist/src/service/worker-totals.d.ts +2 -0
- package/dist/src/service/worker-totals.js +1 -1
- package/dist/src/step-bridge.d.ts +20 -0
- package/dist/src/steps/command-wait.d.ts +12 -0
- package/dist/src/steps/command-wait.js +26 -0
- package/dist/src/steps/open-decision-wait.d.ts +2 -0
- package/dist/src/steps/{decision-gate.js → open-decision-wait.js} +0 -7
- package/dist/src/steps/review-by-person.js +4 -1
- package/dist/src/steps/wait-for-command.d.ts +3 -0
- package/dist/src/steps/wait-for-command.js +17 -0
- package/dist/src/steps/wait-for-decision.js +1 -1
- package/dist/src/storage/command-wait-rows.d.ts +30 -0
- package/dist/src/storage/command-wait-rows.js +96 -0
- package/dist/src/storage/decision-snapshots.d.ts +8 -1
- package/dist/src/storage/decision-snapshots.js +15 -1
- package/dist/src/storage/domain-changes.d.ts +2 -0
- package/dist/src/storage/domain-changes.js +3 -0
- package/dist/src/storage/domain-schema.d.ts +13 -1
- package/dist/src/storage/domain-schema.js +31 -4
- package/dist/src/storage/effect-schema.d.ts +1 -0
- package/dist/src/storage/effect-schema.js +5 -0
- package/dist/src/testing-requests.d.ts +15 -0
- package/dist/src/testing-requests.js +93 -0
- package/dist/src/testing.d.ts +4 -10
- package/dist/src/testing.js +33 -86
- package/dist/src/worker-usage.d.ts +1 -0
- package/dist/src/worker-usage.js +3 -0
- package/dist/src/workflow-candidate.d.ts +1 -0
- package/dist/src/workflow-candidate.js +12 -1
- package/dist/src/workflow-contracts.d.ts +1 -0
- package/dist/src/workflow-contracts.js +9 -2
- package/dist/src/workflow-discovery.d.ts +2 -13
- package/dist/src/workflow-discovery.js +1 -13
- package/dist/src/workflow-refusals.js +0 -1
- package/dist/src/workflows.d.ts +1 -1
- package/dist/src/workflows.js +1 -1
- package/dist/tools/red-green-command.d.ts +1 -0
- package/dist/tools/red-green-command.js +174 -0
- package/dist/tools/red-green-process.d.ts +10 -0
- package/dist/tools/red-green-process.js +59 -0
- package/dist/tools/self-host-processes.d.ts +2 -0
- package/dist/tools/self-host-processes.js +32 -13
- package/dist/tools/self-host-project.js +13 -78
- package/dist/tools/self-host-runtime.js +1 -1
- package/dist/tools/self-host.js +42 -10
- package/dist/tools/template-command.d.ts +1 -0
- package/dist/tools/template-command.js +160 -0
- package/dist/tools/template-copy.d.ts +11 -0
- package/dist/tools/template-copy.js +130 -0
- package/dist/tools/template-files.d.ts +17 -0
- package/dist/tools/template-files.js +74 -0
- package/dist/tools/workflow-bundles.js +1 -0
- package/dist/tools/workflow-candidate-counts.js +2 -2
- package/dist/tools/workflow-candidate-shape.d.ts +3 -0
- package/dist/tools/workflow-candidate-shape.js +90 -0
- package/dist/tools/workflow-candidate-source.js +15 -1
- package/dist/tools/workflow-candidate-syntax.d.ts +2 -2
- package/dist/tools/workflow-candidate-syntax.js +24 -94
- package/dist/tools/workflow-command.js +1 -2
- package/dist/tools/workflow-folders.d.ts +2 -3
- package/dist/tools/workflow-folders.js +1 -1
- package/package.json +16 -8
- package/templates/develop/README.md +12 -0
- package/templates/develop/develop/flow-tests.ts +37 -0
- package/templates/develop/develop/pull.ts +5 -1
- package/templates/develop/develop/refusal-tests.ts +77 -0
- package/templates/develop/develop/turn.ts +2 -1
- package/templates/idea-to-issue/README.md +27 -0
- package/templates/idea-to-issue/idea-to-issue/effects.ts +52 -0
- package/templates/idea-to-issue/idea-to-issue/leave.ts +10 -0
- package/templates/idea-to-issue/idea-to-issue/next.ts +29 -0
- package/templates/idea-to-issue/idea-to-issue/post-person.ts +18 -0
- package/templates/idea-to-issue/idea-to-issue/post.ts +50 -0
- package/templates/idea-to-issue/idea-to-issue/queue.ts +27 -0
- package/templates/idea-to-issue/idea-to-issue/review.ts +42 -0
- package/templates/idea-to-issue/idea-to-issue/scenarios.ts +50 -0
- package/templates/idea-to-issue/idea-to-issue/turn.ts +40 -0
- package/templates/idea-to-issue/idea-to-issue.declaration.json +16 -0
- package/templates/idea-to-issue/idea-to-issue.test.ts +79 -0
- package/templates/idea-to-issue/idea-to-issue.ts +49 -0
- package/templates/idea-to-issue/template.json +81 -0
- package/templates/review-day/README.md +97 -0
- package/templates/review-day/review-day/critique.ts +58 -0
- package/templates/review-day/review-day/decision.ts +29 -0
- package/templates/review-day/review-day/facts.ts +69 -0
- package/templates/review-day/review-day/label.ts +29 -0
- package/templates/review-day/review-day/next.ts +28 -0
- package/templates/review-day/review-day/post.ts +27 -0
- package/templates/review-day/review-day/report.ts +98 -0
- package/templates/review-day/review-day/rules.ts +12 -0
- package/templates/review-day/review-day/scenarios.ts +76 -0
- package/templates/review-day/review-day/turn.ts +73 -0
- package/templates/review-day/review-day.declaration.json +16 -0
- package/templates/review-day/review-day.test.ts +362 -0
- package/templates/review-day/review-day.ts +37 -0
- package/templates/review-day/template.json +56 -0
- package/dist/src/cli/watch-start-view.d.ts +0 -18
- package/dist/src/cli/watch-start-view.js +0 -77
- package/dist/src/steps/decision-gate.d.ts +0 -3
- package/dist/workflows/develop-prd.d.ts +0 -7
- package/dist/workflows/develop-prd.js +0 -165
- package/dist/workflows/develop-ticket.d.ts +0 -9
- package/dist/workflows/develop-ticket.js +0 -207
- package/dist/workflows/issue-labels.d.ts +0 -16
- package/dist/workflows/issue-labels.js +0 -70
- package/dist/workflows/ticket-prompts.d.ts +0 -35
- package/dist/workflows/ticket-prompts.js +0 -147
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { commandWaitDisplay } from "./command-waits.js";
|
|
2
|
+
import { scheduleMetadata, scheduledMetadata, metadataOf, outcomeOf, ticketMetadataPage, workflowMetadata, } from "./run-metadata.js";
|
|
2
3
|
import { linksOf } from "../authority/handoff-chain.js";
|
|
3
4
|
import { runView, unresolvedEffects, } from "../authority/status.js";
|
|
4
5
|
import { record } from "../protocol.js";
|
|
@@ -13,6 +14,7 @@ async function snapshot(context) {
|
|
|
13
14
|
const state = await authority.state();
|
|
14
15
|
const sequences = await authority.queries.sequences();
|
|
15
16
|
return {
|
|
17
|
+
now: context.clock(),
|
|
16
18
|
links: await authority.queries.runLinks(),
|
|
17
19
|
state,
|
|
18
20
|
operations: await authority.operations(),
|
|
@@ -64,9 +66,16 @@ async function viewOf(context, scope) {
|
|
|
64
66
|
if (run === undefined)
|
|
65
67
|
return undefined;
|
|
66
68
|
const details = state.details[run.runId];
|
|
69
|
+
const workflowId = scope.snapshot.workflowIds[run.runId] ?? run.workflow;
|
|
67
70
|
const effects = await effectInput(context, run.runId);
|
|
68
71
|
const input = {
|
|
69
72
|
...effects,
|
|
73
|
+
commandWaits: await commandWaitDisplay({
|
|
74
|
+
authority: context.authority,
|
|
75
|
+
runId: run.runId,
|
|
76
|
+
waits: state.commandWaits,
|
|
77
|
+
now: scope.snapshot.now,
|
|
78
|
+
}),
|
|
70
79
|
closure: run.status === "cancelled"
|
|
71
80
|
? await context.authority.effects.closure(run.runId)
|
|
72
81
|
: null,
|
|
@@ -84,10 +93,14 @@ async function viewOf(context, scope) {
|
|
|
84
93
|
};
|
|
85
94
|
return {
|
|
86
95
|
...runView(input),
|
|
96
|
+
...(await scheduledMetadata(context, {
|
|
97
|
+
runId: run.runId,
|
|
98
|
+
workflowId,
|
|
99
|
+
})),
|
|
87
100
|
commandOperations: effects.commandOperations,
|
|
88
101
|
...linksOf({ runId: run.runId, ...scope.snapshot.links[run.runId] }),
|
|
89
102
|
input: await submittedInput(context, details?.submission),
|
|
90
|
-
workflowId
|
|
103
|
+
workflowId,
|
|
91
104
|
latestAt: times[run.runId] ?? null,
|
|
92
105
|
unresolvedEffects: unresolvedEffects(input),
|
|
93
106
|
feedback: await feedbackOf(context, { state, runId: run.runId }),
|
|
@@ -96,6 +109,7 @@ async function viewOf(context, scope) {
|
|
|
96
109
|
function summary(view) {
|
|
97
110
|
return {
|
|
98
111
|
runId: view.runId,
|
|
112
|
+
...(view.scheduled === undefined ? {} : { scheduled: view.scheduled }),
|
|
99
113
|
...linksOf(view),
|
|
100
114
|
input: view.input,
|
|
101
115
|
workflowId: view.workflowId,
|
|
@@ -106,6 +120,7 @@ function summary(view) {
|
|
|
106
120
|
latestSequence: view.latestSequence,
|
|
107
121
|
latestAt: view.latestAt,
|
|
108
122
|
pendingDecisions: view.pendingDecisions,
|
|
123
|
+
commandWaits: view.commandWaits,
|
|
109
124
|
};
|
|
110
125
|
}
|
|
111
126
|
function full(view) {
|
|
@@ -145,6 +160,7 @@ async function listed(context, page) {
|
|
|
145
160
|
const runs = views.filter((view) => view !== undefined).map(summary);
|
|
146
161
|
return result("run-list", {
|
|
147
162
|
...(await queueOverview(context)),
|
|
163
|
+
...(await scheduleMetadata(context)),
|
|
148
164
|
workflows: context.registry.workflowIds,
|
|
149
165
|
workflowRefusals: context.workflowRefusals ?? [],
|
|
150
166
|
...(Object.keys(context.registry.workflowStages).length === 0
|
|
@@ -165,12 +181,16 @@ function listParameters(parameters) {
|
|
|
165
181
|
return { after, limit };
|
|
166
182
|
}
|
|
167
183
|
export async function status(context, parameters) {
|
|
184
|
+
if (parameters["metadata"] === "workflows")
|
|
185
|
+
return workflowMetadata(context, parameters["runIds"]);
|
|
168
186
|
if (parameters["runIds"] !== undefined)
|
|
169
187
|
return queueRunStatuses(context, parameters["runIds"]);
|
|
170
188
|
const { runId } = parameters;
|
|
171
189
|
const page = listParameters(parameters);
|
|
172
190
|
if (page === undefined)
|
|
173
191
|
return invalidRequest("The status request is not valid.");
|
|
192
|
+
if (parameters["metadata"] === "tickets")
|
|
193
|
+
return ticketMetadataPage(context, page);
|
|
174
194
|
const current = await snapshot(context);
|
|
175
195
|
if (runId === undefined)
|
|
176
196
|
return listed(context, { snapshot: current, ...page });
|
|
@@ -1,8 +1,22 @@
|
|
|
1
1
|
import { type Fields } from "../protocol.ts";
|
|
2
2
|
import type { RunView } from "../authority/status.ts";
|
|
3
|
-
import type
|
|
3
|
+
import { type ServiceContext } from "./replies.ts";
|
|
4
|
+
export declare function workflowMetadata(context: ServiceContext, runIds: unknown): Promise<import("../protocol.ts").Reply>;
|
|
5
|
+
export declare function ticketMetadataPage(context: ServiceContext, page: {
|
|
6
|
+
readonly after: string;
|
|
7
|
+
readonly limit: number;
|
|
8
|
+
}): Promise<import("../protocol.ts").Reply>;
|
|
4
9
|
export declare function outcomeOf(context: ServiceContext, view: Pick<RunView, "state" | "runId" | "latestSequence">): Promise<Fields | null>;
|
|
5
10
|
export declare function metadataOf(context: ServiceContext, source: {
|
|
6
11
|
readonly workflowId: string;
|
|
7
12
|
readonly digest: string | null | undefined;
|
|
8
13
|
}): Promise<Fields>;
|
|
14
|
+
export declare function scheduleMetadata(context: ServiceContext): Promise<Fields>;
|
|
15
|
+
export declare function scheduledMetadata(context: ServiceContext, run: {
|
|
16
|
+
readonly runId: string;
|
|
17
|
+
readonly workflowId: string;
|
|
18
|
+
}): Promise<{
|
|
19
|
+
readonly scheduled?: {
|
|
20
|
+
readonly slot: number;
|
|
21
|
+
};
|
|
22
|
+
}>;
|
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
import { issueIdentity } from "../issue-identity.js";
|
|
2
2
|
import { record } from "../protocol.js";
|
|
3
|
+
import { invalidRequest, isIdentifier, result, } from "./replies.js";
|
|
4
|
+
export async function workflowMetadata(context, runIds) {
|
|
5
|
+
if (!Array.isArray(runIds) ||
|
|
6
|
+
runIds.length === 0 ||
|
|
7
|
+
runIds.length > 500 ||
|
|
8
|
+
!runIds.every(isIdentifier) ||
|
|
9
|
+
new Set(runIds).size !== runIds.length)
|
|
10
|
+
return invalidRequest("Workflow metadata needs one to 500 distinct run IDs.");
|
|
11
|
+
const identities = await context.authority.queries.workflowIds(runIds);
|
|
12
|
+
return result("run-workflow-metadata", {
|
|
13
|
+
runs: runIds.map((runId) => ({
|
|
14
|
+
runId,
|
|
15
|
+
workflowId: identities[runId] ?? null,
|
|
16
|
+
})),
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
export async function ticketMetadataPage(context, page) {
|
|
20
|
+
const state = await context.authority.state();
|
|
21
|
+
const identifiers = Object.keys(state.runs)
|
|
22
|
+
.sort()
|
|
23
|
+
.filter((runId) => runId > page.after);
|
|
24
|
+
const shown = identifiers.slice(0, page.limit);
|
|
25
|
+
const runs = [];
|
|
26
|
+
for (const runId of shown) {
|
|
27
|
+
const digest = state.details[runId]?.input;
|
|
28
|
+
const document = digest
|
|
29
|
+
? await context.authority.queries.document(digest)
|
|
30
|
+
: "{}";
|
|
31
|
+
const input = record(JSON.parse(document ?? "null"));
|
|
32
|
+
if (input === undefined)
|
|
33
|
+
throw new Error("report-ticket-metadata-unavailable");
|
|
34
|
+
runs.push({ runId, ticketId: ticketIdOf(input) });
|
|
35
|
+
}
|
|
36
|
+
return result("run-ticket-metadata", {
|
|
37
|
+
runs,
|
|
38
|
+
next: identifiers.length > shown.length ? shown.at(-1) : null,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
3
41
|
export async function outcomeOf(context, view) {
|
|
4
42
|
if (view.state !== "completed")
|
|
5
43
|
return null;
|
|
@@ -20,13 +58,22 @@ export async function outcomeOf(context, view) {
|
|
|
20
58
|
...(issueUpdate === "failed" ? { issueUpdate } : {}),
|
|
21
59
|
};
|
|
22
60
|
}
|
|
61
|
+
function ticketOf(input) {
|
|
62
|
+
const declared = record(record(input?.["input"])?.["ticket"]);
|
|
63
|
+
const id = declared === undefined ? input?.["ticketId"] : declared["id"];
|
|
64
|
+
const text = declared === undefined ? input?.["ticket"] : declared["text"];
|
|
65
|
+
return {
|
|
66
|
+
id: typeof id === "string" ? id : undefined,
|
|
67
|
+
text: typeof text === "string" ? text : undefined,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
23
70
|
function titleOf(input, workflowId) {
|
|
24
|
-
const ticket = input
|
|
25
|
-
if (
|
|
71
|
+
const ticket = ticketOf(input).text;
|
|
72
|
+
if (ticket === undefined)
|
|
26
73
|
return null;
|
|
27
74
|
const fallback = `Cloving task ${String(input?.["cycleId"])}`;
|
|
28
75
|
const lines = ticket.split("\n");
|
|
29
|
-
if (workflowId === "develop-prompt") {
|
|
76
|
+
if (workflowId === "develop-prompt" && !Object.hasOwn(input ?? {}, "input")) {
|
|
30
77
|
const first = lines.find((line) => /\S/.test(line));
|
|
31
78
|
return first === undefined
|
|
32
79
|
? fallback
|
|
@@ -42,12 +89,50 @@ export async function metadataOf(context, source) {
|
|
|
42
89
|
? await context.authority.queries.document(source.digest)
|
|
43
90
|
: undefined;
|
|
44
91
|
const input = record(JSON.parse(document ?? "null"));
|
|
45
|
-
const ticketId = input?.["ticketId"];
|
|
46
92
|
return {
|
|
47
|
-
ticketId:
|
|
93
|
+
ticketId: ticketIdOf(input),
|
|
48
94
|
title: titleOf(input, source.workflowId),
|
|
49
|
-
...(
|
|
50
|
-
? {
|
|
51
|
-
: {}),
|
|
95
|
+
...(ticketOf(input).text === undefined
|
|
96
|
+
? {}
|
|
97
|
+
: { issueIdentity: issueIdentity(ticketOf(input).text) }),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function ticketIdOf(input) {
|
|
101
|
+
const ticketId = ticketOf(input).id;
|
|
102
|
+
return ticketId === undefined || ticketId === "" ? null : ticketId;
|
|
103
|
+
}
|
|
104
|
+
export async function scheduleMetadata(context) {
|
|
105
|
+
if (context.schedule === undefined)
|
|
106
|
+
return {};
|
|
107
|
+
const reply = await context.schedule({ action: "list" });
|
|
108
|
+
if (reply.kind !== "result" || !Array.isArray(reply.result["schedules"]))
|
|
109
|
+
return { schedules: { status: "unavailable" } };
|
|
110
|
+
const schedules = reply.result["schedules"];
|
|
111
|
+
if (schedules.length === 0)
|
|
112
|
+
return {};
|
|
113
|
+
return {
|
|
114
|
+
schedules: schedules.map((value) => {
|
|
115
|
+
const schedule = record(value) ?? {};
|
|
116
|
+
return Object.fromEntries([
|
|
117
|
+
"workflowId",
|
|
118
|
+
"everySeconds",
|
|
119
|
+
"state",
|
|
120
|
+
"failuresInRow",
|
|
121
|
+
"nextAt",
|
|
122
|
+
"stoppedAt",
|
|
123
|
+
].map((name) => [name, schedule[name]]));
|
|
124
|
+
}),
|
|
52
125
|
};
|
|
53
126
|
}
|
|
127
|
+
export async function scheduledMetadata(context, run) {
|
|
128
|
+
const commandId = (await context.authority.queries.run(run.runId))
|
|
129
|
+
?.admissionCommandId;
|
|
130
|
+
const prefix = `schedule:${run.workflowId}:`;
|
|
131
|
+
if (typeof commandId !== "string" || !commandId.startsWith(prefix))
|
|
132
|
+
return {};
|
|
133
|
+
const suffix = commandId.slice(prefix.length);
|
|
134
|
+
const slot = Number(suffix);
|
|
135
|
+
return /^(0|[1-9][0-9]*)$/.test(suffix) && Number.isSafeInteger(slot)
|
|
136
|
+
? { scheduled: { slot } }
|
|
137
|
+
: {};
|
|
138
|
+
}
|
|
@@ -5,6 +5,7 @@ import { type ServiceContext } from "./replies.ts";
|
|
|
5
5
|
import { type WorkerPort } from "./worker-port.ts";
|
|
6
6
|
import type { RunWaitTarget } from "../run-wait.ts";
|
|
7
7
|
import type { CommandEffects } from "../command-settings.ts";
|
|
8
|
+
import { type CommandWaitPort } from "./command-waits.ts";
|
|
8
9
|
export type { WorkflowRegistration } from "./registry.ts";
|
|
9
10
|
export type { EffectReply, EffectReport, EffectRequest, WorkerPort, } from "./worker-port.ts";
|
|
10
11
|
export interface ServiceTiming {
|
|
@@ -27,6 +28,7 @@ export interface ServiceHost {
|
|
|
27
28
|
readonly reports?: () => readonly unknown[];
|
|
28
29
|
}
|
|
29
30
|
export interface HostPorts {
|
|
31
|
+
readonly commandWait: CommandWaitPort;
|
|
30
32
|
readonly runWait?: {
|
|
31
33
|
readonly target: (runId: string) => Promise<RunWaitTarget | undefined>;
|
|
32
34
|
readonly observe: WorkerPort["observe"];
|
|
@@ -48,6 +50,8 @@ export interface HostPorts {
|
|
|
48
50
|
readonly registerWait: WorkerPort["registerWait"];
|
|
49
51
|
}
|
|
50
52
|
export interface ServiceOptions {
|
|
53
|
+
readonly schedule?: NonNullable<ServiceContext["schedule"]>;
|
|
54
|
+
readonly queueDailySpendLimitUsd?: number;
|
|
51
55
|
readonly workerHarness?: ServiceContext["workerHarness"];
|
|
52
56
|
readonly commandEffects?: CommandEffects;
|
|
53
57
|
readonly stateDirectory: string;
|
|
@@ -9,12 +9,13 @@ 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, queryMetadata } from "./replies.js";
|
|
12
|
+
import { errorMessage, failed, queryMetadata, scheduleRequest, } 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
17
|
import { runWaitTarget } from "./run-waits.js";
|
|
18
|
+
import { commandWaitPort } from "./command-waits.js";
|
|
18
19
|
export const serviceTiming = {
|
|
19
20
|
authority: authorityTiming,
|
|
20
21
|
expiryScanMilliseconds: 1_000,
|
|
@@ -59,6 +60,7 @@ function dispatcher(context) {
|
|
|
59
60
|
const run = submissionHandler(context);
|
|
60
61
|
const operations = new Map([
|
|
61
62
|
["run", (request) => run(request.parameters)],
|
|
63
|
+
["schedule", (request) => scheduleRequest(context, request.parameters)],
|
|
62
64
|
["status", (request) => status(context, request.parameters)],
|
|
63
65
|
["questions", (request) => questions(context, request.parameters)],
|
|
64
66
|
["decision", (request) => decision(context, request.parameters)],
|
|
@@ -149,7 +151,7 @@ export async function startService(options) {
|
|
|
149
151
|
const { authority } = opening;
|
|
150
152
|
const gateway = serviceGateway(authority, { options, registry });
|
|
151
153
|
const worker = workerPort({ gateway, authority });
|
|
152
|
-
const host = await hosted(options, hostPorts(authority, { worker, registry }));
|
|
154
|
+
const host = await hosted(options, hostPorts(authority, { worker, registry, gateway }));
|
|
153
155
|
if (host.kind === "refused") {
|
|
154
156
|
await authority.close();
|
|
155
157
|
return host;
|
|
@@ -169,8 +171,8 @@ export async function startService(options) {
|
|
|
169
171
|
};
|
|
170
172
|
}
|
|
171
173
|
catch (error) {
|
|
172
|
-
const unclosed = await released(authority, host.host).then(() => "", (failure) => `; the close failed: ${
|
|
173
|
-
return refused("transport-failure", `${
|
|
174
|
+
const unclosed = await released(authority, host.host).then(() => "", (failure) => `; the close failed: ${errorMessage(failure)}`);
|
|
175
|
+
return refused("transport-failure", `${errorMessage(error)}${unclosed}`);
|
|
174
176
|
}
|
|
175
177
|
}
|
|
176
178
|
function serviceGateway(authority, parts) {
|
|
@@ -186,6 +188,7 @@ function serviceGateway(authority, parts) {
|
|
|
186
188
|
function hostPorts(authority, parts) {
|
|
187
189
|
const { worker, registry } = parts;
|
|
188
190
|
return {
|
|
191
|
+
commandWait: commandWaitPort({ authority, gateway: parts.gateway }),
|
|
189
192
|
runWait: {
|
|
190
193
|
target: (runId) => runWaitTarget(authority, runId),
|
|
191
194
|
observe: worker.observe,
|
|
@@ -217,14 +220,11 @@ function hostPorts(authority, parts) {
|
|
|
217
220
|
},
|
|
218
221
|
};
|
|
219
222
|
}
|
|
220
|
-
function message(error) {
|
|
221
|
-
return String(Reflect.get(Object(error), "message"));
|
|
222
|
-
}
|
|
223
223
|
async function hosted(options, ports) {
|
|
224
224
|
try {
|
|
225
225
|
return { kind: "started", host: await options.host?.(ports) };
|
|
226
226
|
}
|
|
227
227
|
catch (error) {
|
|
228
|
-
return refused("host-unavailable",
|
|
228
|
+
return refused("host-unavailable", errorMessage(error));
|
|
229
229
|
}
|
|
230
230
|
}
|
|
@@ -7,6 +7,7 @@ import { documentDigest } from "../broker/decision-restore.js";
|
|
|
7
7
|
import { record } from "../protocol.js";
|
|
8
8
|
import { checkResolution, checkSubmission, hasTicketField, normalizedRequest, } from "../submission.js";
|
|
9
9
|
import { activeWorkflow } from "./active-tickets.js";
|
|
10
|
+
import { queueSpend } from "./queue-spend.js";
|
|
10
11
|
import { committed, failed, invalidRequest, publicReceipt, rejection, result, } from "./replies.js";
|
|
11
12
|
export function runIdentity(commandId) {
|
|
12
13
|
return `run-${createHash("sha256").update(commandId).digest("hex").slice(0, 32)}`;
|
|
@@ -125,6 +126,9 @@ async function admit(context, admission) {
|
|
|
125
126
|
const { input } = resolution;
|
|
126
127
|
if (Buffer.byteLength(input) > context.documentBytes)
|
|
127
128
|
return unresolved(context, { kind: "failure", commandId });
|
|
129
|
+
const held = await spendRefusal(context, admission);
|
|
130
|
+
if (held !== undefined)
|
|
131
|
+
return held;
|
|
128
132
|
const receipt = await context.gateway.execute({
|
|
129
133
|
principal: "operator",
|
|
130
134
|
command: {
|
|
@@ -155,9 +159,20 @@ async function admit(context, admission) {
|
|
|
155
159
|
replayed: receipt.kind === "duplicate",
|
|
156
160
|
});
|
|
157
161
|
}
|
|
162
|
+
async function spendRefusal(context, admission) {
|
|
163
|
+
if (admission.workflow.manifest.queue !== true)
|
|
164
|
+
return undefined;
|
|
165
|
+
const spend = record((await queueSpend(context))["spend"]);
|
|
166
|
+
return spend?.["holding"] === true
|
|
167
|
+
? failed("queue-spend-limit", {
|
|
168
|
+
commandId: admission.commandId,
|
|
169
|
+
detail: "Queue holding for spend limit.",
|
|
170
|
+
})
|
|
171
|
+
: undefined;
|
|
172
|
+
}
|
|
158
173
|
function admissionRefusal(workflow, request) {
|
|
159
|
-
const {
|
|
160
|
-
const tickets =
|
|
174
|
+
const { commandId, submission, activeTickets } = request;
|
|
175
|
+
const tickets = hasTicketField(workflow.submission);
|
|
161
176
|
if (tickets &&
|
|
162
177
|
typeof submission["ticket"] === "string" &&
|
|
163
178
|
activeTickets.some((input) => input["ticketId"] === submission["ticket"]))
|
|
@@ -235,8 +250,7 @@ export function submissionHandler(context) {
|
|
|
235
250
|
return (parameters) => {
|
|
236
251
|
const keys = [`command:${String(parameters["commandId"])}`];
|
|
237
252
|
const workflowId = String(parameters["workflowId"]);
|
|
238
|
-
if (workflowId
|
|
239
|
-
hasTicketField(context.registry.byId(workflowId)?.submission) ||
|
|
253
|
+
if (hasTicketField(context.registry.byId(workflowId)?.submission) ||
|
|
240
254
|
context.registry.byId(workflowId)?.admission !== undefined)
|
|
241
255
|
keys.push(`workflow:${workflowId}`);
|
|
242
256
|
const next = () => submitted(context, parameters);
|
|
@@ -86,7 +86,7 @@ function effectPort(parts) {
|
|
|
86
86
|
command: {
|
|
87
87
|
kind: "report-effect",
|
|
88
88
|
...rest,
|
|
89
|
-
...(
|
|
89
|
+
...reportedResult({ result, worker: report.worker }),
|
|
90
90
|
},
|
|
91
91
|
documents: result === undefined ? [] : [result],
|
|
92
92
|
epoch: epoch ?? authority.epoch,
|
|
@@ -124,3 +124,11 @@ export function workerPort(parts) {
|
|
|
124
124
|
...effectPort(parts),
|
|
125
125
|
};
|
|
126
126
|
}
|
|
127
|
+
function reportedResult(report) {
|
|
128
|
+
if (report.result === undefined)
|
|
129
|
+
return {};
|
|
130
|
+
return {
|
|
131
|
+
result: documentDigest(report.result),
|
|
132
|
+
...(report.worker === "command" ? { commandOutput: report.result } : {}),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type Fields } from "../protocol.ts";
|
|
1
2
|
import { type WorkerTotals } from "../worker-usage.ts";
|
|
2
3
|
import type { ServiceContext } from "./replies.ts";
|
|
4
|
+
export declare function reportFields(text: string | undefined): Fields;
|
|
3
5
|
export declare function usageTotals(context: ServiceContext, runId: string): Promise<WorkerTotals>;
|
|
@@ -64,6 +64,22 @@ export interface RunWaitOutcome {
|
|
|
64
64
|
readonly reason: string | null;
|
|
65
65
|
readonly promotionId: string | null;
|
|
66
66
|
}
|
|
67
|
+
export interface CommandWaitRequest {
|
|
68
|
+
readonly name: string;
|
|
69
|
+
readonly input: HandoffValue;
|
|
70
|
+
}
|
|
71
|
+
export type CommandWaitOutcome = {
|
|
72
|
+
readonly kind: "ready";
|
|
73
|
+
readonly value: HandoffValue;
|
|
74
|
+
} | {
|
|
75
|
+
readonly kind: "timed-out" | "failed" | "refused" | "unavailable";
|
|
76
|
+
readonly reason: string;
|
|
77
|
+
};
|
|
78
|
+
export type CommandWaitProgress = CommandWaitOutcome | {
|
|
79
|
+
readonly kind: "pending";
|
|
80
|
+
readonly deadline: number;
|
|
81
|
+
readonly nextCheckAt: number;
|
|
82
|
+
};
|
|
67
83
|
export interface CommandRequest {
|
|
68
84
|
readonly scope: ProtectedScope;
|
|
69
85
|
readonly name: string;
|
|
@@ -80,6 +96,10 @@ export type GateResult = {
|
|
|
80
96
|
readonly reason: string;
|
|
81
97
|
};
|
|
82
98
|
export interface StepBridge {
|
|
99
|
+
readonly openCommandWait?: (request: CommandWaitRequest) => Promise<CommandWaitProgress>;
|
|
100
|
+
readonly checkCommandWait?: (request: {
|
|
101
|
+
readonly name: string;
|
|
102
|
+
}) => Promise<CommandWaitProgress>;
|
|
83
103
|
readonly effect: (request: ProtectedRequest) => Promise<ProtectedResult>;
|
|
84
104
|
readonly gate: (request: GateRequest) => Promise<GateResult>;
|
|
85
105
|
readonly waitForDecision?: (request: GateRequest) => Promise<DecisionWait>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type CommandWaitRequest, type CommandWaitProgress } from "../command-wait.ts";
|
|
2
|
+
export declare function openCommandWait(request: CommandWaitRequest): Promise<CommandWaitProgress>;
|
|
3
|
+
export declare namespace openCommandWait {
|
|
4
|
+
var maxRetries: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function checkCommandWait(request: {
|
|
7
|
+
readonly name: string;
|
|
8
|
+
}): Promise<CommandWaitProgress>;
|
|
9
|
+
export declare namespace checkCommandWait {
|
|
10
|
+
var maxRetries: number;
|
|
11
|
+
}
|
|
12
|
+
export declare function commandWaitDate(milliseconds: number): Date;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { isStepBridge, stepBridgeKey } from "../step-bridge.js";
|
|
2
|
+
import { isCommandWaitRequest, } from "../command-wait.js";
|
|
3
|
+
export async function openCommandWait(request) {
|
|
4
|
+
"use step";
|
|
5
|
+
if (!isCommandWaitRequest(request))
|
|
6
|
+
return { kind: "refused", reason: "invalid-command-wait-request" };
|
|
7
|
+
const bridge = Reflect.get(globalThis, Symbol.for(stepBridgeKey));
|
|
8
|
+
if (!isStepBridge(bridge) || bridge.openCommandWait === undefined)
|
|
9
|
+
return { kind: "unavailable", reason: "cloving-host-unavailable" };
|
|
10
|
+
return await bridge.openCommandWait({
|
|
11
|
+
name: request.name,
|
|
12
|
+
input: request.input,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
export async function checkCommandWait(request) {
|
|
16
|
+
"use step";
|
|
17
|
+
const bridge = Reflect.get(globalThis, Symbol.for(stepBridgeKey));
|
|
18
|
+
if (!isStepBridge(bridge) || bridge.checkCommandWait === undefined)
|
|
19
|
+
return { kind: "unavailable", reason: "cloving-host-unavailable" };
|
|
20
|
+
return await bridge.checkCommandWait({ name: request.name });
|
|
21
|
+
}
|
|
22
|
+
openCommandWait.maxRetries = 0;
|
|
23
|
+
checkCommandWait.maxRetries = 0;
|
|
24
|
+
export function commandWaitDate(milliseconds) {
|
|
25
|
+
return new Date(milliseconds);
|
|
26
|
+
}
|
|
@@ -1,11 +1,4 @@
|
|
|
1
1
|
import { isStepBridge, stepBridgeKey, } from "../step-bridge.js";
|
|
2
|
-
export async function decisionGate(request) {
|
|
3
|
-
"use step";
|
|
4
|
-
const bridge = Reflect.get(globalThis, Symbol.for(stepBridgeKey));
|
|
5
|
-
if (!isStepBridge(bridge))
|
|
6
|
-
return { kind: "unavailable", reason: "cloving-host-unavailable" };
|
|
7
|
-
return await bridge.gate(request);
|
|
8
|
-
}
|
|
9
2
|
export async function openDecisionWait(request) {
|
|
10
3
|
"use step";
|
|
11
4
|
const bridge = Reflect.get(globalThis, Symbol.for(stepBridgeKey));
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { snapshotReviewSubject } from "./review-subject.js";
|
|
2
2
|
import { waitForDecision } from "./wait-for-decision.js";
|
|
3
3
|
export async function reviewByPerson(request) {
|
|
4
|
+
let draft = "draft" in request.subject ? request.subject.draft : null;
|
|
5
|
+
if (draft !== null && request.subject.commit !== undefined)
|
|
6
|
+
draft = `${request.subject.commit}\n${draft}`;
|
|
4
7
|
const snapshot = await snapshotReviewSubject(request.subject);
|
|
5
8
|
const decision = await waitForDecision({
|
|
6
9
|
gateId: `review:${snapshot.subjectDigest}`,
|
|
7
10
|
kind: "approval",
|
|
8
|
-
prompt: `Review this subject:\n${snapshot.prompt}`,
|
|
11
|
+
prompt: `Review this subject:\n${draft ?? snapshot.prompt}`,
|
|
9
12
|
});
|
|
10
13
|
return {
|
|
11
14
|
accepted: decision.decision === "approved",
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { sleep } from "workflow";
|
|
2
|
+
import { isCommandWaitRequest, } from "../command-wait.js";
|
|
3
|
+
import { openCommandWait, checkCommandWait, commandWaitDate, } from "./command-wait.js";
|
|
4
|
+
export async function waitForCommand(request) {
|
|
5
|
+
if (!isCommandWaitRequest(request))
|
|
6
|
+
return { kind: "refused", reason: "invalid-command-wait-request" };
|
|
7
|
+
let result = await openCommandWait({
|
|
8
|
+
name: request.name,
|
|
9
|
+
input: request.input,
|
|
10
|
+
});
|
|
11
|
+
while (result.kind === "pending") {
|
|
12
|
+
result = await checkCommandWait({ name: request.name });
|
|
13
|
+
if (result.kind === "pending")
|
|
14
|
+
await sleep(commandWaitDate(Math.min(result.deadline, result.nextCheckAt)));
|
|
15
|
+
}
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
@@ -51,7 +51,7 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
51
51
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
52
|
});
|
|
53
53
|
import { createHook } from "workflow";
|
|
54
|
-
import { openDecisionWait } from "./decision-
|
|
54
|
+
import { openDecisionWait } from "./open-decision-wait.js";
|
|
55
55
|
export async function waitForDecision(request) {
|
|
56
56
|
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
57
57
|
try {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type SqlConnection } from "./domain-rows.ts";
|
|
2
|
+
import { type Statement } from "./statements.ts";
|
|
3
|
+
export declare const commandWaitSchema = "\nCREATE TABLE command_waits (\n run_id TEXT NOT NULL REFERENCES runs (run_id) DEFERRABLE INITIALLY DEFERRED,\n name TEXT NOT NULL,\n command TEXT NOT NULL,\n input_digest TEXT NOT NULL REFERENCES documents (digest) DEFERRABLE INITIALLY DEFERRED,\n maximum_wait_seconds INTEGER NOT NULL,\n poll_every_seconds INTEGER NOT NULL,\n started_at INTEGER NOT NULL,\n deadline INTEGER NOT NULL,\n next_check_at INTEGER,\n state TEXT NOT NULL,\n settled_at INTEGER,\n reason TEXT,\n PRIMARY KEY (run_id, name)\n) STRICT;\n";
|
|
4
|
+
export declare const commandWaitCheckSchema = "\nALTER TABLE command_waits ADD COLUMN check_count INTEGER NOT NULL DEFAULT 0;\nALTER TABLE command_waits ADD COLUMN check_operation TEXT;\nALTER TABLE command_waits ADD COLUMN last_check_settled_at INTEGER;\nALTER TABLE command_waits ADD COLUMN result TEXT;\n";
|
|
5
|
+
export interface CommandWaitRow {
|
|
6
|
+
readonly runId: string;
|
|
7
|
+
readonly name: string;
|
|
8
|
+
readonly command: string;
|
|
9
|
+
readonly inputDigest: string;
|
|
10
|
+
readonly maximumWaitSeconds: number;
|
|
11
|
+
readonly pollEverySeconds: number;
|
|
12
|
+
readonly startedAt: number;
|
|
13
|
+
readonly deadline: number;
|
|
14
|
+
readonly nextCheckAt: number | null;
|
|
15
|
+
readonly state: string;
|
|
16
|
+
readonly checkCount: number;
|
|
17
|
+
readonly checkOperation: string | null;
|
|
18
|
+
readonly lastCheckSettledAt: number | null;
|
|
19
|
+
readonly result: string | null;
|
|
20
|
+
readonly settledAt: number | null;
|
|
21
|
+
readonly reason: string | null;
|
|
22
|
+
}
|
|
23
|
+
export declare function commandWaitRow(value: unknown): CommandWaitRow;
|
|
24
|
+
export declare function loadCommandWaits(connection: SqlConnection, scope?: {
|
|
25
|
+
readonly runId?: string;
|
|
26
|
+
readonly version?: "opened";
|
|
27
|
+
}): Promise<readonly CommandWaitRow[]>;
|
|
28
|
+
export declare function commandWaitStatements(rows: readonly CommandWaitRow[], scope?: {
|
|
29
|
+
readonly version?: "opened";
|
|
30
|
+
}): readonly Statement[];
|