cloving 1.3.0 → 1.5.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 +329 -215
- 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-health.d.ts +9 -0
- package/dist/src/broker/actor/authority-health.js +24 -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-runtime.d.ts +4 -2
- package/dist/src/broker/actor/authority-runtime.js +29 -20
- package/dist/src/broker/actor/authority-session.d.ts +6 -19
- package/dist/src/broker/actor/authority-session.js +66 -88
- package/dist/src/broker/actor/authority-settings.d.ts +2 -1
- package/dist/src/broker/actor/authority-settings.js +6 -3
- package/dist/src/broker/actor/authority-upgrades.d.ts +23 -2
- package/dist/src/broker/actor/authority-upgrades.js +8 -2
- package/dist/src/broker/actor/authority-watchdog.d.ts +6 -2
- package/dist/src/broker/actor/authority-watchdog.js +31 -9
- package/dist/src/broker/actor/authority.js +3 -1
- 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/projection-memory.d.ts +43 -0
- package/dist/src/broker/actor/projection-memory.js +207 -0
- package/dist/src/broker/actor/runtime-parts.d.ts +5 -0
- package/dist/src/broker/actor/runtime-parts.js +8 -3
- 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 +3 -0
- package/dist/src/broker/effect-upgrade.js +11 -2
- package/dist/src/cli/arguments.d.ts +13 -0
- package/dist/src/cli/arguments.js +43 -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 +7 -2
- package/dist/src/cli/client.js +13 -7
- package/dist/src/cli/command-requests.d.ts +46 -0
- package/dist/src/cli/command-requests.js +84 -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 +70 -88
- package/dist/src/cli/config-file.d.ts +2 -2
- package/dist/src/cli/config-file.js +4 -2
- package/dist/src/cli/config-notice.js +5 -2
- package/dist/src/cli/doctor-retention.d.ts +2 -0
- package/dist/src/cli/doctor-retention.js +93 -0
- 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 +11 -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 +242 -0
- package/dist/src/cli/queue-arguments.d.ts +15 -0
- package/dist/src/cli/queue-arguments.js +31 -0
- package/dist/src/cli/queue-render.d.ts +3 -0
- package/dist/src/cli/queue-render.js +26 -0
- package/dist/src/cli/reload-render.d.ts +2 -0
- package/dist/src/cli/reload-render.js +12 -0
- package/dist/src/cli/render.d.ts +1 -1
- package/dist/src/cli/render.js +54 -38
- 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 +18 -3
- package/dist/src/cli/runtime-arguments.js +29 -20
- 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/toolchain.d.ts +1 -0
- package/dist/src/cli/toolchain.js +1 -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 +2 -2
- package/dist/src/cli/usage.js +89 -11
- package/dist/src/cli/watch-actions.js +2 -2
- package/dist/src/cli/watch-api-document.d.ts +430 -0
- package/dist/src/cli/watch-api-document.js +291 -0
- package/dist/src/cli/watch-api-run.d.ts +56 -0
- package/dist/src/cli/watch-api-run.js +112 -0
- package/dist/src/cli/watch-api.d.ts +17 -0
- package/dist/src/cli/watch-api.js +230 -0
- 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 +1 -5
- package/dist/src/cli/watch-header-view.js +17 -21
- package/dist/src/cli/watch-model.d.ts +5 -1
- package/dist/src/cli/watch-model.js +20 -11
- package/dist/src/cli/watch-page.js +15 -15
- 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 +3 -0
- package/dist/src/cli/watch-reads.js +22 -20
- package/dist/src/cli/watch-render.d.ts +15 -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 +24 -10
- package/dist/src/cli/watch-view.d.ts +0 -3
- package/dist/src/cli/watch-view.js +13 -13
- package/dist/src/cli.js +73 -12
- 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-display.js +2 -0
- package/dist/src/configuration-schema.d.ts +14 -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 +208 -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 +5 -4
- package/dist/src/daemon/claude-worker.js +127 -126
- package/dist/src/daemon/daemon-adapters.d.ts +9 -0
- package/dist/src/daemon/daemon-adapters.js +33 -5
- package/dist/src/daemon/daemon-loops.d.ts +5 -1
- package/dist/src/daemon/daemon-loops.js +18 -10
- package/dist/src/daemon/daemon.js +80 -61
- package/dist/src/daemon/github-attach.d.ts +2 -0
- package/dist/src/daemon/github-attach.js +222 -0
- package/dist/src/daemon/github-calls.js +1 -1
- 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 +18 -4
- 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 +4 -1
- package/dist/src/daemon/issue-queue.js +76 -78
- package/dist/src/daemon/merge-turns.d.ts +10 -0
- package/dist/src/daemon/merge-turns.js +37 -0
- 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-control.d.ts +13 -0
- package/dist/src/daemon/queue-control.js +86 -0
- package/dist/src/daemon/queue-journal.d.ts +20 -0
- package/dist/src/daemon/queue-journal.js +89 -0
- package/dist/src/daemon/queue-status.d.ts +9 -3
- package/dist/src/daemon/queue-status.js +17 -4
- package/dist/src/daemon/record-archive.d.ts +19 -0
- package/dist/src/daemon/record-archive.js +82 -0
- package/dist/src/daemon/record-sweep.d.ts +24 -0
- package/dist/src/daemon/record-sweep.js +147 -0
- 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/settings-reload.d.ts +26 -0
- package/dist/src/daemon/settings-reload.js +82 -0
- 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-details.d.ts +4 -0
- package/dist/src/daemon/turn-details.js +33 -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 +9 -0
- package/dist/src/daemon/worker-profile.js +44 -0
- package/dist/src/daemon/workflow-generations.d.ts +7 -4
- package/dist/src/daemon/workflow-generations.js +22 -14
- package/dist/src/daemon/workflow-reload.d.ts +41 -0
- package/dist/src/daemon/workflow-reload.js +244 -0
- package/dist/src/daemon/workflow-replay.d.ts +2 -1
- package/dist/src/daemon/workflow-replay.js +7 -3
- 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 +4 -6
- package/dist/src/doctor-report.js +8 -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 +71 -0
- package/dist/src/project-config.schema.json +40 -0
- package/dist/src/project-settings.d.ts +16 -2
- package/dist/src/project-settings.js +35 -1
- package/dist/src/queue-spend.d.ts +4 -0
- package/dist/src/queue-spend.js +21 -0
- package/dist/src/queue-state.d.ts +26 -0
- package/dist/src/queue-state.js +34 -0
- package/dist/src/record-retention.d.ts +46 -0
- package/dist/src/record-retention.js +81 -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 +11 -6
- package/dist/src/service/command-waits.d.ts +34 -0
- package/dist/src/service/command-waits.js +86 -0
- package/dist/src/service/dispatcher.d.ts +4 -0
- package/dist/src/service/dispatcher.js +33 -0
- package/dist/src/service/expiry.js +2 -0
- package/dist/src/service/gateway.js +3 -1
- package/dist/src/service/queue-handlers.d.ts +4 -0
- package/dist/src/service/queue-handlers.js +32 -0
- package/dist/src/service/queue-spend.d.ts +6 -0
- package/dist/src/service/queue-spend.js +68 -0
- package/dist/src/service/registry.d.ts +28 -2
- package/dist/src/service/registry.js +48 -0
- package/dist/src/service/replies.d.ts +22 -8
- package/dist/src/service/replies.js +16 -2
- package/dist/src/service/run-handlers.js +37 -12
- 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 +11 -3
- package/dist/src/service/service.js +22 -37
- 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 +6 -0
- package/dist/src/service/worker-totals.js +8 -1
- package/dist/src/service/workflow-reload.d.ts +35 -0
- package/dist/src/service/workflow-reload.js +52 -0
- 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 -2
- package/dist/src/storage/decision-snapshots.js +16 -8
- package/dist/src/storage/domain-changes.d.ts +3 -1
- package/dist/src/storage/domain-changes.js +4 -0
- package/dist/src/storage/domain-schema.d.ts +16 -1
- package/dist/src/storage/domain-schema.js +35 -4
- package/dist/src/storage/effect-schema.d.ts +2 -0
- package/dist/src/storage/effect-schema.js +9 -0
- package/dist/src/storage/projection-changes.d.ts +12 -0
- package/dist/src/storage/projection-changes.js +194 -0
- package/dist/src/storage/projection-lookups.d.ts +7 -0
- package/dist/src/storage/projection-lookups.js +30 -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-declaration.d.ts +1 -0
- package/dist/src/workflow-declaration.js +3 -0
- 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/compile-workflows.js +3 -0
- package/dist/tools/project-configuration.d.ts +7 -2
- package/dist/tools/project-configuration.js +30 -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 +69 -26
- package/dist/tools/self-host-project.d.ts +2 -0
- package/dist/tools/self-host-project.js +30 -77
- package/dist/tools/self-host-runtime.js +1 -1
- package/dist/tools/self-host.js +76 -34
- 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-program.d.ts +4 -2
- package/dist/tools/workflow-candidate-program.js +30 -11
- 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.d.ts +1 -0
- package/dist/tools/workflow-candidate-source.js +26 -4
- 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 +17 -9
- package/templates/develop/README.md +93 -4
- package/templates/develop/develop/flow-tests.ts +38 -1
- package/templates/develop/develop/interruption-tests.ts +157 -0
- package/templates/develop/develop/local.ts +1 -0
- package/templates/develop/develop/option-tests.ts +138 -9
- package/templates/develop/develop/pull.ts +5 -1
- package/templates/develop/develop/red-green.ts +55 -0
- package/templates/develop/develop/refusal-tests.ts +77 -0
- package/templates/develop/develop/report.ts +31 -11
- package/templates/develop/develop/round.ts +1 -0
- package/templates/develop/develop/scenarios.ts +27 -0
- package/templates/develop/develop/turn.ts +28 -7
- package/templates/develop/develop.declaration.json +1 -1
- package/templates/develop/develop.test.ts +4 -0
- package/templates/develop/template.json +29 -2
- 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
|
-
export declare const
|
|
1
|
+
export declare const shellRunScript = "\nif [ -n \"${ZSH_VERSION-}\" ] && (( ${+aliases[$1]} )); then\n alias_command=\"${aliases[$1]}\"\n builtin unalias -- \"$1\"\n shift\n eval -- \"$alias_command\"' \"$@\"'\nelif [ -n \"${BASH_VERSION-}\" ] && alias_value=$(builtin alias -- \"$1\" 2>/dev/null); then\n eval -- \"alias_command=${alias_value#*=}\"\n builtin unalias -- \"$1\"\n shift\n eval -- \"$alias_command\"' \"$@\"'\nelse\n \"$@\"\nfi\n";
|
|
2
|
+
export declare const shellTurnScript = "\nset +m\nbuiltin unset GH_TOKEN GITHUB_TOKEN GH_ENTERPRISE_TOKEN GITHUB_ENTERPRISE_TOKEN || exit\nbuiltin export GH_CONFIG_DIR=\"$1\" || exit\nshift\n\nif [ -n \"${ZSH_VERSION-}\" ] && (( ${+aliases[$1]} )); then\n alias_command=\"${aliases[$1]}\"\n builtin unalias -- \"$1\"\n shift\n eval -- \"$alias_command\"' \"$@\"'\nelif [ -n \"${BASH_VERSION-}\" ] && alias_value=$(builtin alias -- \"$1\" 2>/dev/null); then\n eval -- \"alias_command=${alias_value#*=}\"\n builtin unalias -- \"$1\"\n shift\n eval -- \"$alias_command\"' \"$@\"'\nelse\n \"$@\"\nfi\n\n";
|
|
2
3
|
export declare const shellDiscoveryScript = "\nset +m\nif [ -z \"${ZSH_VERSION-}\" ] && [ -z \"${BASH_VERSION-}\" ]; then exit 64; fi\nprintf '__CLOVING_HARNESS_START_-1__\\n%s\\n\\n__CLOVING_HARNESS_END_-1__\\n' \"${BASH_VERSION:+bash}\"\nindex=0\nfor name in \"$@\"; do\n printf '__CLOVING_HARNESS_START_%s__\\n' \"$index\"\n if [ -n \"${ZSH_VERSION-}\" ]; then\n kind=$(whence -w -- \"$name\" 2>/dev/null) || kind=\n printf '%s\\n' \"${kind##*: }\"\n file=$(whence -p -- \"$name\" 2>/dev/null) || file=\n else\n kind=$(builtin type -t -- \"$name\" 2>/dev/null) || kind=\n printf '%s\\n' \"$kind\"\n file=$(builtin type -P -- \"$name\" 2>/dev/null) || file=\n fi\n case \"$file\" in /*|\"\") ;; *) file=\"$PWD/$file\" ;; esac\n printf '%s\\n' \"$file\"\n printf '\\n__CLOVING_HARNESS_END_%s__\\n' \"$index\"\n index=$((index + 1))\ndone\nexit 0\n";
|
|
3
4
|
export declare const shellProbeScript = "\nset +m\nprintf '__CLOVING_HARNESS_START_0__\\n'\nif [ \"$2\" = file ]; then\n command -- \"$1\" --version\nelif [ -n \"${ZSH_VERSION-}\" ] && (( ${+aliases[$1]} )); then\n alias_command=\"${aliases[$1]}\"\n builtin unalias -- \"$1\"\n eval -- \"$alias_command\"' --version'\nelif [ -n \"${BASH_VERSION-}\" ] && alias_value=$(builtin alias -- \"$1\" 2>/dev/null); then\n eval -- \"alias_command=${alias_value#*=}\"\n builtin unalias -- \"$1\"\n eval -- \"$alias_command\"' --version'\nelif [ -n \"${ZSH_VERSION-}\" ] || [ -n \"${BASH_VERSION-}\" ]; then\n \"$1\" --version\nelse\n exit 64\nfi\nprobe_status=$?\nprintf '\\n__CLOVING_HARNESS_END_0__\\n'\nexit \"$probe_status\"\n";
|
|
4
5
|
export declare function shellBlock(output: string, index: number): string | null;
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
export const
|
|
2
|
-
set +m
|
|
3
|
-
builtin unset GH_TOKEN GITHUB_TOKEN GH_ENTERPRISE_TOKEN GITHUB_ENTERPRISE_TOKEN || exit
|
|
4
|
-
builtin export GH_CONFIG_DIR="$1" || exit
|
|
5
|
-
shift
|
|
1
|
+
export const shellRunScript = `
|
|
6
2
|
if [ -n "\${ZSH_VERSION-}" ] && (( \${+aliases[$1]} )); then
|
|
7
3
|
alias_command="\${aliases[$1]}"
|
|
8
4
|
builtin unalias -- "$1"
|
|
@@ -17,6 +13,13 @@ else
|
|
|
17
13
|
"$@"
|
|
18
14
|
fi
|
|
19
15
|
`;
|
|
16
|
+
export const shellTurnScript = `
|
|
17
|
+
set +m
|
|
18
|
+
builtin unset GH_TOKEN GITHUB_TOKEN GH_ENTERPRISE_TOKEN GITHUB_ENTERPRISE_TOKEN || exit
|
|
19
|
+
builtin export GH_CONFIG_DIR="$1" || exit
|
|
20
|
+
shift
|
|
21
|
+
${shellRunScript}
|
|
22
|
+
`;
|
|
20
23
|
export const shellDiscoveryScript = `
|
|
21
24
|
set +m
|
|
22
25
|
if [ -z "\${ZSH_VERSION-}" ] && [ -z "\${BASH_VERSION-}" ]; then exit 64; fi
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type CommandWaitState } from "./command-waits.ts";
|
|
2
|
+
import { type Handler } from "./reduction-state.ts";
|
|
3
|
+
export declare function commandWaitCheckId(wait: CommandWaitState): string;
|
|
4
|
+
export declare function commandWaitCheckRefusal(wait: CommandWaitState | undefined, check: {
|
|
5
|
+
readonly runStatus: string;
|
|
6
|
+
readonly recordedAt: string;
|
|
7
|
+
}): string | undefined;
|
|
8
|
+
export declare const checkedCommandWait: Handler;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { instantMilliseconds, isInstant } from "./instants.js";
|
|
2
|
+
import { commandWaitKey } from "./command-waits.js";
|
|
3
|
+
import { withOperation } from "./operations.js";
|
|
4
|
+
import { applied, invalid, identity } from "./reduction-state.js";
|
|
5
|
+
export function commandWaitCheckId(wait) {
|
|
6
|
+
return identity({
|
|
7
|
+
run: wait.runId,
|
|
8
|
+
phase: "command-wait",
|
|
9
|
+
operation: wait.name,
|
|
10
|
+
round: wait.checkCount + 1,
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
export function commandWaitCheckRefusal(wait, check) {
|
|
14
|
+
if (!isInstant(check.recordedAt))
|
|
15
|
+
return "invalid-recorded-time";
|
|
16
|
+
if (wait === undefined)
|
|
17
|
+
return "unknown-command-wait";
|
|
18
|
+
const now = instantMilliseconds(check.recordedAt);
|
|
19
|
+
if (now >= wait.deadline)
|
|
20
|
+
return "command-wait-timeout";
|
|
21
|
+
if (check.runStatus !== "running")
|
|
22
|
+
return "command-wait-run-not-running";
|
|
23
|
+
if (wait.state !== "waiting")
|
|
24
|
+
return "command-wait-ended";
|
|
25
|
+
if (wait.checkOperation !== null)
|
|
26
|
+
return "command-wait-check-in-flight";
|
|
27
|
+
if (wait.nextCheckAt === null || now < wait.nextCheckAt)
|
|
28
|
+
return "command-wait-check-not-due";
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
function operation(wait, check) {
|
|
32
|
+
return {
|
|
33
|
+
runId: wait.runId,
|
|
34
|
+
operationId: commandWaitCheckId(wait),
|
|
35
|
+
capability: "command",
|
|
36
|
+
method: `run:${wait.command}`,
|
|
37
|
+
target: wait.command,
|
|
38
|
+
payload: wait.inputDigest,
|
|
39
|
+
inputDigest: check.inputDigest,
|
|
40
|
+
units: 1,
|
|
41
|
+
recoveryLimit: 1,
|
|
42
|
+
leaseKey: commandWaitCheckId(wait),
|
|
43
|
+
status: "waiting",
|
|
44
|
+
reason: "ready",
|
|
45
|
+
attempts: 0,
|
|
46
|
+
receipt: null,
|
|
47
|
+
worker: null,
|
|
48
|
+
result: null,
|
|
49
|
+
requestedSequence: check.sequence,
|
|
50
|
+
waitSequence: check.sequence,
|
|
51
|
+
settledSequence: null,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
export const checkedCommandWait = (state, recorded) => {
|
|
55
|
+
const { event, run } = recorded;
|
|
56
|
+
const waits = state.commandWaits ?? {};
|
|
57
|
+
const key = commandWaitKey(event.runId, event.payload["waitName"] ?? "");
|
|
58
|
+
const wait = waits[key];
|
|
59
|
+
const reason = commandWaitCheckRefusal(wait, {
|
|
60
|
+
runStatus: run.status,
|
|
61
|
+
recordedAt: event.recordedAt,
|
|
62
|
+
});
|
|
63
|
+
if (reason !== undefined || wait === undefined)
|
|
64
|
+
return invalid(reason ?? "unknown-command-wait");
|
|
65
|
+
const check = operation(wait, {
|
|
66
|
+
sequence: event.sequence,
|
|
67
|
+
inputDigest: event.payload["inputDigest"] ?? "",
|
|
68
|
+
});
|
|
69
|
+
if (state.effects.operations[check.operationId] !== undefined)
|
|
70
|
+
return invalid("command-wait-operation-conflict");
|
|
71
|
+
return applied(state, {
|
|
72
|
+
...recorded,
|
|
73
|
+
commandWaits: {
|
|
74
|
+
...waits,
|
|
75
|
+
[key]: {
|
|
76
|
+
...wait,
|
|
77
|
+
checkCount: wait.checkCount + 1,
|
|
78
|
+
checkOperation: check.operationId,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
effects: withOperation(state.effects, check),
|
|
82
|
+
disposition: {
|
|
83
|
+
operationId: check.operationId,
|
|
84
|
+
disposition: "admitted",
|
|
85
|
+
reason: null,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type CommandWaitsState } from "./command-waits.ts";
|
|
2
|
+
import type { AuthorityState } from "./transitions.ts";
|
|
3
|
+
import { type EffectChange, type Operation } from "./operations.ts";
|
|
4
|
+
import type { AuthorityEvent } from "./transitions.ts";
|
|
5
|
+
export declare function settledCommandWaits(waits: CommandWaitsState, check: {
|
|
6
|
+
readonly event: AuthorityEvent;
|
|
7
|
+
readonly operation: Operation | undefined;
|
|
8
|
+
}): CommandWaitsState;
|
|
9
|
+
export declare function waitEffectTime(waits: CommandWaitsState, event: AuthorityEvent): boolean;
|
|
10
|
+
export declare function waitEffectChange(state: AuthorityState, settlement: {
|
|
11
|
+
readonly event: AuthorityEvent;
|
|
12
|
+
readonly result: EffectChange;
|
|
13
|
+
}): {
|
|
14
|
+
readonly commandWaits?: CommandWaitsState;
|
|
15
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { instantMilliseconds, isInstant } from "./instants.js";
|
|
2
|
+
import { timedOut, } from "./command-waits.js";
|
|
3
|
+
import { isFinal } from "./operations.js";
|
|
4
|
+
function output(text) {
|
|
5
|
+
try {
|
|
6
|
+
const value = JSON.parse(text ?? "");
|
|
7
|
+
if (value === null || typeof value !== "object" || Array.isArray(value))
|
|
8
|
+
return { kind: "failed", reason: "command-wait-invalid-output" };
|
|
9
|
+
const ready = Reflect.get(value, "ready");
|
|
10
|
+
if (ready === false)
|
|
11
|
+
return { kind: "pending" };
|
|
12
|
+
if (ready === true)
|
|
13
|
+
return {
|
|
14
|
+
kind: "ready",
|
|
15
|
+
value: JSON.stringify(Reflect.get(value, "value") ?? null),
|
|
16
|
+
};
|
|
17
|
+
return { kind: "failed", reason: "command-wait-invalid-output" };
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return { kind: "failed", reason: "command-wait-invalid-output" };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function settled(wait, check) {
|
|
24
|
+
const { event, operation } = check;
|
|
25
|
+
const now = instantMilliseconds(event.recordedAt);
|
|
26
|
+
const recorded = { ...wait, checkOperation: null, lastCheckSettledAt: now };
|
|
27
|
+
if (now >= wait.deadline)
|
|
28
|
+
return timedOut(recorded);
|
|
29
|
+
const result = operation.status === "completed"
|
|
30
|
+
? output(event.payload["commandOutput"])
|
|
31
|
+
: { kind: "failed", reason: operation.reason ?? "command-interrupted" };
|
|
32
|
+
if (result.kind === "pending")
|
|
33
|
+
return { ...recorded, nextCheckAt: now + wait.pollEverySeconds * 1000 };
|
|
34
|
+
return {
|
|
35
|
+
...recorded,
|
|
36
|
+
state: result.kind === "ready" ? "completed" : "failed",
|
|
37
|
+
settledAt: now,
|
|
38
|
+
nextCheckAt: null,
|
|
39
|
+
result: result.kind === "ready" ? result.value : null,
|
|
40
|
+
reason: result.kind === "failed" ? result.reason : null,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export function settledCommandWaits(waits, check) {
|
|
44
|
+
const { event, operation } = check;
|
|
45
|
+
if (operation === undefined ||
|
|
46
|
+
!isFinal(operation) ||
|
|
47
|
+
!isInstant(event.recordedAt))
|
|
48
|
+
return waits;
|
|
49
|
+
return Object.fromEntries(Object.entries(waits).map(([key, wait]) => [
|
|
50
|
+
key,
|
|
51
|
+
wait.runId === event.runId &&
|
|
52
|
+
wait.checkOperation === operation.operationId &&
|
|
53
|
+
wait.state === "waiting"
|
|
54
|
+
? settled(wait, { event, operation })
|
|
55
|
+
: wait,
|
|
56
|
+
]));
|
|
57
|
+
}
|
|
58
|
+
export function waitEffectTime(waits, event) {
|
|
59
|
+
const check = Object.values(waits).some((wait) => wait.runId === event.runId &&
|
|
60
|
+
wait.checkOperation === event.payload["operationId"]);
|
|
61
|
+
return !check || isInstant(event.recordedAt);
|
|
62
|
+
}
|
|
63
|
+
export function waitEffectChange(state, settlement) {
|
|
64
|
+
if (state.commandWaits === undefined ||
|
|
65
|
+
settlement.result.disposition?.disposition !== "applied")
|
|
66
|
+
return {};
|
|
67
|
+
return {
|
|
68
|
+
commandWaits: settledCommandWaits(state.commandWaits, {
|
|
69
|
+
event: settlement.event,
|
|
70
|
+
operation: settlement.result.effects.operations[settlement.event.payload["operationId"] ?? ""],
|
|
71
|
+
}),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type CommandWaitState, type CommandWaitsState } from "./command-waits.ts";
|
|
2
|
+
import type { CommandWaits } from "../workflow-declaration.ts";
|
|
3
|
+
export interface CommandWaitView<Time = string> {
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly command: string;
|
|
6
|
+
readonly state: string;
|
|
7
|
+
readonly maximumWaitSeconds: number;
|
|
8
|
+
readonly startedAt: Time | null;
|
|
9
|
+
readonly deadline: Time | null;
|
|
10
|
+
readonly nextCheckAt: Time | null;
|
|
11
|
+
readonly checkCount: number;
|
|
12
|
+
readonly remainingSeconds: number;
|
|
13
|
+
readonly reason: string | null;
|
|
14
|
+
}
|
|
15
|
+
export declare function commandWaitView(wait: CommandWaitState, now: number): CommandWaitView<number>;
|
|
16
|
+
export declare function commandWaitViews(input: {
|
|
17
|
+
readonly runId: string;
|
|
18
|
+
readonly declarations: CommandWaits;
|
|
19
|
+
readonly waits: CommandWaitsState;
|
|
20
|
+
readonly now: number;
|
|
21
|
+
}): readonly CommandWaitView<number>[];
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { commandWaitKey, } from "./command-waits.js";
|
|
2
|
+
export function commandWaitView(wait, now) {
|
|
3
|
+
return {
|
|
4
|
+
name: wait.name,
|
|
5
|
+
command: wait.command,
|
|
6
|
+
state: wait.state,
|
|
7
|
+
maximumWaitSeconds: wait.maximumWaitSeconds,
|
|
8
|
+
startedAt: wait.startedAt,
|
|
9
|
+
deadline: wait.deadline,
|
|
10
|
+
nextCheckAt: wait.nextCheckAt,
|
|
11
|
+
checkCount: wait.checkCount,
|
|
12
|
+
remainingSeconds: Math.max(0, Math.ceil((wait.deadline - (wait.settledAt ?? now)) / 1000)),
|
|
13
|
+
reason: wait.reason,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export function commandWaitViews(input) {
|
|
17
|
+
return Object.entries(input.declarations).map(([name, declaration]) => {
|
|
18
|
+
const wait = input.waits[commandWaitKey(input.runId, name)];
|
|
19
|
+
return wait === undefined
|
|
20
|
+
? {
|
|
21
|
+
name,
|
|
22
|
+
command: declaration.command,
|
|
23
|
+
state: "not-started",
|
|
24
|
+
maximumWaitSeconds: declaration.maximumWaitSeconds,
|
|
25
|
+
startedAt: null,
|
|
26
|
+
deadline: null,
|
|
27
|
+
nextCheckAt: null,
|
|
28
|
+
checkCount: 0,
|
|
29
|
+
remainingSeconds: declaration.maximumWaitSeconds,
|
|
30
|
+
reason: null,
|
|
31
|
+
}
|
|
32
|
+
: commandWaitView(wait, input.now);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
interface WaitEvent {
|
|
2
|
+
readonly type: string;
|
|
3
|
+
readonly runId: string;
|
|
4
|
+
readonly recordedAt: string;
|
|
5
|
+
readonly payload: Readonly<Record<string, string>>;
|
|
6
|
+
}
|
|
7
|
+
export interface CommandWaitState {
|
|
8
|
+
readonly runId: string;
|
|
9
|
+
readonly name: string;
|
|
10
|
+
readonly command: string;
|
|
11
|
+
readonly inputDigest: string;
|
|
12
|
+
readonly maximumWaitSeconds: number;
|
|
13
|
+
readonly pollEverySeconds: number;
|
|
14
|
+
readonly startedAt: number;
|
|
15
|
+
readonly deadline: number;
|
|
16
|
+
readonly nextCheckAt: number | null;
|
|
17
|
+
readonly state: "waiting" | "timed-out" | "cancelled" | "completed" | "failed";
|
|
18
|
+
readonly checkCount: number;
|
|
19
|
+
readonly checkOperation: string | null;
|
|
20
|
+
readonly lastCheckSettledAt: number | null;
|
|
21
|
+
readonly result: string | null;
|
|
22
|
+
readonly settledAt: number | null;
|
|
23
|
+
readonly reason: string | null;
|
|
24
|
+
}
|
|
25
|
+
export type CommandWaitsState = Readonly<Record<string, CommandWaitState>>;
|
|
26
|
+
export declare function endedCommandWaitCheck(waits: CommandWaitsState, operationId: string): boolean;
|
|
27
|
+
export declare function commandWaitKey(runId: string, name: string): string;
|
|
28
|
+
type WaitChange = {
|
|
29
|
+
readonly kind: "updated";
|
|
30
|
+
readonly waits: CommandWaitsState;
|
|
31
|
+
} | {
|
|
32
|
+
readonly kind: "invalid";
|
|
33
|
+
readonly reason: string;
|
|
34
|
+
};
|
|
35
|
+
export declare function timedOut(wait: CommandWaitState): CommandWaitState;
|
|
36
|
+
export declare function validCommandWaitTime(waits: CommandWaitsState, event: WaitEvent): boolean;
|
|
37
|
+
export declare function closedCommandWaits(waits: CommandWaitsState, event: WaitEvent): CommandWaitsState;
|
|
38
|
+
export declare function commandWaitsAfter(waits: CommandWaitsState, event: WaitEvent): WaitChange;
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { isInstant, instantMilliseconds } from "./instants.js";
|
|
2
|
+
export function endedCommandWaitCheck(waits, operationId) {
|
|
3
|
+
return Object.values(waits).some((wait) => wait.state !== "waiting" && wait.checkOperation === operationId);
|
|
4
|
+
}
|
|
5
|
+
export function commandWaitKey(runId, name) {
|
|
6
|
+
return JSON.stringify([runId, name]);
|
|
7
|
+
}
|
|
8
|
+
function openedCommandWait(event) {
|
|
9
|
+
const startedAt = instantMilliseconds(event.recordedAt);
|
|
10
|
+
const maximumWaitSeconds = Number(event.payload["maximumWaitSeconds"]);
|
|
11
|
+
return {
|
|
12
|
+
runId: event.runId,
|
|
13
|
+
name: event.payload["waitName"] ?? "",
|
|
14
|
+
command: event.payload["target"] ?? "",
|
|
15
|
+
inputDigest: event.payload["payload"] ?? "",
|
|
16
|
+
maximumWaitSeconds,
|
|
17
|
+
pollEverySeconds: Number(event.payload["pollEverySeconds"]),
|
|
18
|
+
startedAt,
|
|
19
|
+
deadline: startedAt + maximumWaitSeconds * 1000,
|
|
20
|
+
nextCheckAt: startedAt,
|
|
21
|
+
state: "waiting",
|
|
22
|
+
checkCount: 0,
|
|
23
|
+
checkOperation: null,
|
|
24
|
+
lastCheckSettledAt: null,
|
|
25
|
+
result: null,
|
|
26
|
+
settledAt: null,
|
|
27
|
+
reason: null,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export function timedOut(wait) {
|
|
31
|
+
return {
|
|
32
|
+
...wait,
|
|
33
|
+
state: "timed-out",
|
|
34
|
+
settledAt: wait.deadline,
|
|
35
|
+
nextCheckAt: null,
|
|
36
|
+
reason: "command-wait-timeout",
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export function validCommandWaitTime(waits, event) {
|
|
40
|
+
if (!["run.completed", "run.failed", "run.cancelled"].includes(event.type))
|
|
41
|
+
return true;
|
|
42
|
+
return Object.values(waits).every((wait) => wait.runId !== event.runId ||
|
|
43
|
+
wait.state !== "waiting" ||
|
|
44
|
+
(isInstant(event.recordedAt) &&
|
|
45
|
+
instantMilliseconds(event.recordedAt) >= wait.startedAt));
|
|
46
|
+
}
|
|
47
|
+
export function closedCommandWaits(waits, event) {
|
|
48
|
+
if (!["run.completed", "run.failed", "run.cancelled"].includes(event.type))
|
|
49
|
+
return waits;
|
|
50
|
+
return Object.fromEntries(Object.entries(waits).map(([key, wait]) => {
|
|
51
|
+
if (wait.runId !== event.runId || wait.state !== "waiting")
|
|
52
|
+
return [key, wait];
|
|
53
|
+
if (instantMilliseconds(event.recordedAt) >= wait.deadline)
|
|
54
|
+
return [key, timedOut(wait)];
|
|
55
|
+
return [
|
|
56
|
+
key,
|
|
57
|
+
{
|
|
58
|
+
...wait,
|
|
59
|
+
state: "cancelled",
|
|
60
|
+
nextCheckAt: null,
|
|
61
|
+
settledAt: instantMilliseconds(event.recordedAt),
|
|
62
|
+
reason: "command-wait-run-ended",
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
67
|
+
function opened(waits, event) {
|
|
68
|
+
const key = commandWaitKey(event.runId, event.payload["waitName"] ?? "");
|
|
69
|
+
const previous = waits[key];
|
|
70
|
+
const candidate = openedCommandWait(event);
|
|
71
|
+
if (previous !== undefined && previous.inputDigest !== candidate.inputDigest)
|
|
72
|
+
return { kind: "invalid", reason: "command-wait-input-mismatch" };
|
|
73
|
+
const wait = previous ?? candidate;
|
|
74
|
+
const expired = wait.state === "waiting" &&
|
|
75
|
+
instantMilliseconds(event.recordedAt) >= wait.deadline;
|
|
76
|
+
return {
|
|
77
|
+
kind: "updated",
|
|
78
|
+
waits: { ...waits, [key]: expired ? timedOut(wait) : wait },
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
export function commandWaitsAfter(waits, event) {
|
|
82
|
+
if (event.type.startsWith("command-wait.") && !isInstant(event.recordedAt))
|
|
83
|
+
return { kind: "invalid", reason: "invalid-recorded-time" };
|
|
84
|
+
if (event.type === "command-wait.opened")
|
|
85
|
+
return opened(waits, event);
|
|
86
|
+
if (event.type !== "command-wait.expired")
|
|
87
|
+
return { kind: "updated", waits: closedCommandWaits(waits, event) };
|
|
88
|
+
const key = commandWaitKey(event.runId, event.payload["waitName"] ?? "");
|
|
89
|
+
const previous = waits[key];
|
|
90
|
+
if (previous === undefined)
|
|
91
|
+
return { kind: "invalid", reason: "unknown-command-wait" };
|
|
92
|
+
if (previous.state !== "waiting")
|
|
93
|
+
return { kind: "updated", waits };
|
|
94
|
+
if (instantMilliseconds(event.recordedAt) < previous.deadline)
|
|
95
|
+
return { kind: "invalid", reason: "command-wait-not-expired" };
|
|
96
|
+
return { kind: "updated", waits: { ...waits, [key]: timedOut(previous) } };
|
|
97
|
+
}
|
|
@@ -8,6 +8,9 @@ const digest = /^sha256:[0-9a-f]{64}$/;
|
|
|
8
8
|
const operation = /^[\x20-\x7e]{1,512}$/;
|
|
9
9
|
export const commandEvents = {
|
|
10
10
|
"admit-run": "run.created",
|
|
11
|
+
"open-command-wait": "command-wait.opened",
|
|
12
|
+
"check-command-wait": "command-wait.checked",
|
|
13
|
+
"expire-command-wait": "command-wait.expired",
|
|
11
14
|
"mark-started": "run.started",
|
|
12
15
|
"open-gate": "gate.opened",
|
|
13
16
|
"register-wait": "gate.wait-registered",
|
|
@@ -29,6 +32,19 @@ export const commandEvents = {
|
|
|
29
32
|
};
|
|
30
33
|
const revised = { required: ["expectedRevision"] };
|
|
31
34
|
const shapes = {
|
|
35
|
+
"expire-command-wait": { required: ["waitName"] },
|
|
36
|
+
"check-command-wait": { required: ["waitName", "inputDigest"] },
|
|
37
|
+
"open-command-wait": {
|
|
38
|
+
required: [
|
|
39
|
+
"waitName",
|
|
40
|
+
"target",
|
|
41
|
+
"payload",
|
|
42
|
+
"maximumWaitSeconds",
|
|
43
|
+
"pollEverySeconds",
|
|
44
|
+
],
|
|
45
|
+
consistent: (fields) => Number(fields["pollEverySeconds"]) <=
|
|
46
|
+
Number(fields["maximumWaitSeconds"]),
|
|
47
|
+
},
|
|
32
48
|
"record-schedule-skip": {
|
|
33
49
|
required: ["workflowId", "slot"],
|
|
34
50
|
validators: { slot: positive },
|
|
@@ -141,7 +157,7 @@ const shapes = {
|
|
|
141
157
|
"worker",
|
|
142
158
|
"outcome",
|
|
143
159
|
],
|
|
144
|
-
optional: ["result", "reason", "evidence"],
|
|
160
|
+
optional: ["result", "reason", "evidence", "commandOutput"],
|
|
145
161
|
consistent: (fields) => reportedOutcomes.includes(String(fields["outcome"])) &&
|
|
146
162
|
(fields["outcome"] === "failed" ||
|
|
147
163
|
(fields["result"] !== undefined) ===
|
|
@@ -157,6 +173,7 @@ const shapes = {
|
|
|
157
173
|
"result",
|
|
158
174
|
"reason",
|
|
159
175
|
"evidence",
|
|
176
|
+
"commandOutput",
|
|
160
177
|
],
|
|
161
178
|
},
|
|
162
179
|
};
|
|
@@ -264,6 +281,10 @@ export function isCapabilityList(value) {
|
|
|
264
281
|
JSON.stringify(list) === value);
|
|
265
282
|
}
|
|
266
283
|
const validators = {
|
|
284
|
+
commandOutput: (value) => typeof value === "string",
|
|
285
|
+
waitName: (value) => typeof value === "string" && /^[A-Za-z0-9-]{1,64}$/.test(value),
|
|
286
|
+
maximumWaitSeconds: (value) => whole(value) && value >= 60 && value <= 2_592_000,
|
|
287
|
+
pollEverySeconds: (value) => whole(value) && value >= 60 && value <= 86_400,
|
|
267
288
|
expectedRevision: positive,
|
|
268
289
|
expectedObservation: whole,
|
|
269
290
|
generation: positive,
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
+
import type { CommandWaitState } from "./command-waits.ts";
|
|
1
2
|
export interface DispatchRead {
|
|
3
|
+
readonly commandWait?: {
|
|
4
|
+
readonly wait: CommandWaitState;
|
|
5
|
+
readonly declared: boolean;
|
|
6
|
+
};
|
|
2
7
|
readonly attempt: {
|
|
3
8
|
readonly outcome: string | null;
|
|
4
9
|
readonly inputDigest: string;
|
|
@@ -12,6 +17,9 @@ export interface DispatchRead {
|
|
|
12
17
|
readonly status: string;
|
|
13
18
|
readonly capability: string;
|
|
14
19
|
readonly units: number;
|
|
20
|
+
readonly method?: string;
|
|
21
|
+
readonly target?: string;
|
|
22
|
+
readonly payload?: string;
|
|
15
23
|
} | undefined;
|
|
16
24
|
readonly budget: {
|
|
17
25
|
readonly limit: number;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { operationPhase } from "../operation-identity.js";
|
|
2
|
+
import { instantMilliseconds } from "./instants.js";
|
|
1
3
|
import { authorizeEffect } from "../effect-authorization.js";
|
|
2
4
|
import { isAfter } from "./instants.js";
|
|
3
5
|
function bound(read, intent) {
|
|
@@ -39,12 +41,35 @@ function authorized(read) {
|
|
|
39
41
|
});
|
|
40
42
|
return result.kind === "authorized";
|
|
41
43
|
}
|
|
44
|
+
function authorizedWait(read, check) {
|
|
45
|
+
const { commandWait, operation } = read;
|
|
46
|
+
if (commandWait === undefined || operation === undefined)
|
|
47
|
+
return false;
|
|
48
|
+
const { wait, declared } = commandWait;
|
|
49
|
+
const now = instantMilliseconds(check.now);
|
|
50
|
+
return [
|
|
51
|
+
declared,
|
|
52
|
+
wait.state === "waiting",
|
|
53
|
+
wait.checkOperation === check.intent.operationId,
|
|
54
|
+
wait.nextCheckAt !== null && now >= wait.nextCheckAt,
|
|
55
|
+
now < wait.deadline,
|
|
56
|
+
read.budget?.capabilities.includes("command"),
|
|
57
|
+
operation.capability === "command",
|
|
58
|
+
operation.units === 1,
|
|
59
|
+
operation.method === `run:${wait.command}`,
|
|
60
|
+
operation.target === wait.command,
|
|
61
|
+
operation.payload === wait.inputDigest,
|
|
62
|
+
].every(Boolean);
|
|
63
|
+
}
|
|
42
64
|
export function dispatchDecision(read, check) {
|
|
43
65
|
if (!bound(read, check.intent))
|
|
44
66
|
return "stale";
|
|
45
67
|
if (!sendable(read, check))
|
|
46
68
|
return "withheld";
|
|
47
|
-
|
|
69
|
+
const allowed = operationPhase(check.intent.operationId) === "command-wait"
|
|
70
|
+
? authorizedWait(read, check)
|
|
71
|
+
: authorized(read);
|
|
72
|
+
if (!allowed)
|
|
48
73
|
return "refused";
|
|
49
74
|
return read.pinned ? "send" : "blocked";
|
|
50
75
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { operationScope } from "../operation-identity.js";
|
|
1
|
+
import { operationScope, operationPhase } from "../operation-identity.js";
|
|
2
2
|
import { authorization } from "./budgets.js";
|
|
3
3
|
import { current, ownedLease } from "./leases.js";
|
|
4
4
|
import { cancelledOperation, count, field, rejected, runOperations, withOperation, } from "./operations.js";
|
|
@@ -18,7 +18,8 @@ function refusal(context) {
|
|
|
18
18
|
if (!admittingStatuses.includes(runStatus))
|
|
19
19
|
return "run-not-running";
|
|
20
20
|
const scope = operationScope(field(event, "operationId"));
|
|
21
|
-
if (scope?.run !== event.runId
|
|
21
|
+
if (scope?.run !== event.runId ||
|
|
22
|
+
operationPhase(field(event, "operationId")) === "command-wait")
|
|
22
23
|
return "operation-scope-mismatch";
|
|
23
24
|
if (runOperations.includes(scope.operation))
|
|
24
25
|
return "operation-scope-mismatch";
|
|
@@ -62,7 +63,9 @@ function requestedOperation(event, outcome) {
|
|
|
62
63
|
function withoutWaits(operations, event) {
|
|
63
64
|
return Object.fromEntries(Object.entries(operations).map(([operationId, operation]) => [
|
|
64
65
|
operationId,
|
|
65
|
-
operation.runId === event.runId &&
|
|
66
|
+
operation.runId === event.runId &&
|
|
67
|
+
operation.status === "waiting" &&
|
|
68
|
+
operationPhase(operation.operationId) !== "command-wait"
|
|
66
69
|
? cancelledOperation(operation, {
|
|
67
70
|
reason: "budget-exhausted",
|
|
68
71
|
sequence: event.sequence,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { operationPhase } from "../operation-identity.js";
|
|
1
2
|
import { current, ownedLease } from "./leases.js";
|
|
2
3
|
import { cancelledOperation, count, field, isFinal, isHolding, namesRunIntent, rejected, withOperation, } from "./operations.js";
|
|
3
4
|
const terminalStatuses = ["completed", "failed", "cancelled"];
|
|
@@ -135,8 +136,9 @@ function statedReason(event) {
|
|
|
135
136
|
}
|
|
136
137
|
function notStarted(effects, subject) {
|
|
137
138
|
const { operation, event, runStatus } = subject;
|
|
138
|
-
const exhausted = (
|
|
139
|
-
|
|
139
|
+
const exhausted = field(event, "reason") === "budget-exhausted" ||
|
|
140
|
+
(operationPhase(operation.operationId) !== "command-wait" &&
|
|
141
|
+
(effects.budgets[operation.runId]?.exhaustedSequence ?? null) !== null);
|
|
140
142
|
const ended = terminalStatuses.includes(runStatus);
|
|
141
143
|
const waiting = {
|
|
142
144
|
...operation,
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { AuthorityState } from "./transitions.ts";
|
|
2
2
|
export declare class HistoryState {
|
|
3
3
|
private state;
|
|
4
|
+
private readonly commandWaits;
|
|
4
5
|
private readonly runs;
|
|
5
6
|
private readonly commands;
|
|
6
7
|
private readonly details;
|
|
7
8
|
private readonly gates;
|
|
8
9
|
private readonly budgets;
|
|
10
|
+
private readonly runWaits;
|
|
9
11
|
private readonly runGates;
|
|
10
12
|
private readonly intents;
|
|
11
13
|
private readonly pending;
|
|
@@ -6,11 +6,13 @@ function entry(values, key) {
|
|
|
6
6
|
}
|
|
7
7
|
export class HistoryState {
|
|
8
8
|
state = emptyAuthority;
|
|
9
|
+
commandWaits = {};
|
|
9
10
|
runs = {};
|
|
10
11
|
commands = {};
|
|
11
12
|
details = {};
|
|
12
13
|
gates = {};
|
|
13
14
|
budgets = {};
|
|
15
|
+
runWaits = new Map();
|
|
14
16
|
runGates = new Map();
|
|
15
17
|
intents = new Map();
|
|
16
18
|
pending = new Set();
|
|
@@ -20,6 +22,9 @@ export class HistoryState {
|
|
|
20
22
|
return this.state;
|
|
21
23
|
return {
|
|
22
24
|
...this.state,
|
|
25
|
+
...(this.runWaits.has(event.runId)
|
|
26
|
+
? { commandWaits: this.runWaits.get(event.runId) ?? {} }
|
|
27
|
+
: {}),
|
|
23
28
|
runs: entry(this.runs, event.runId),
|
|
24
29
|
commands: entry(this.commands, event.commandId),
|
|
25
30
|
details: entry(this.details, event.runId),
|
|
@@ -32,6 +37,10 @@ export class HistoryState {
|
|
|
32
37
|
};
|
|
33
38
|
}
|
|
34
39
|
record(state, runId) {
|
|
40
|
+
const { commandWaits, ...baseState } = state;
|
|
41
|
+
Object.assign(this.commandWaits, commandWaits);
|
|
42
|
+
if (commandWaits !== undefined)
|
|
43
|
+
this.runWaits.set(runId, commandWaits);
|
|
35
44
|
Object.assign(this.runs, state.runs);
|
|
36
45
|
Object.assign(this.commands, state.commands);
|
|
37
46
|
Object.assign(this.details, state.details);
|
|
@@ -45,11 +54,14 @@ export class HistoryState {
|
|
|
45
54
|
for (const intent of remaining)
|
|
46
55
|
this.pending.add(intent);
|
|
47
56
|
this.intents.set(runId, state.intents);
|
|
48
|
-
this.state =
|
|
57
|
+
this.state = baseState;
|
|
49
58
|
}
|
|
50
59
|
finish() {
|
|
51
60
|
return {
|
|
52
61
|
...this.state,
|
|
62
|
+
...(Object.keys(this.commandWaits).length === 0
|
|
63
|
+
? {}
|
|
64
|
+
: { commandWaits: this.commandWaits }),
|
|
53
65
|
runs: this.runs,
|
|
54
66
|
commands: this.commands,
|
|
55
67
|
details: this.details,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export declare function isInstant(value: unknown): value is string;
|
|
2
2
|
export declare function notBefore(value: string, bound: string): boolean;
|
|
3
3
|
export declare function isAfter(value: string, bound: string): boolean;
|
|
4
|
+
export declare function instantMilliseconds(value: string): number;
|