cloving 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +584 -144
- package/assets/watch-fonts/fira-code-OFL.md +93 -0
- package/assets/watch-fonts/fira-code-latin-400-normal.woff2 +0 -0
- package/assets/watch-fonts/fira-code-latin-500-normal.woff2 +0 -0
- package/assets/watch-fonts/heebo-OFL.md +93 -0
- package/assets/watch-fonts/heebo-latin-500-normal.woff2 +0 -0
- package/assets/watch-fonts/heebo-latin-700-normal.woff2 +0 -0
- package/assets/watch-fonts/heebo-latin-800-normal.woff2 +0 -0
- package/assets/watch-fonts/manifest.json +112 -0
- package/assets/watch-fonts/space-grotesk-OFL.md +93 -0
- package/assets/watch-fonts/space-grotesk-latin-400-normal.woff2 +0 -0
- package/assets/watch-fonts/space-grotesk-latin-500-normal.woff2 +0 -0
- package/assets/watch-fonts/space-grotesk-latin-600-normal.woff2 +0 -0
- package/assets/watch-fonts/space-grotesk-latin-700-normal.woff2 +0 -0
- package/dist/src/agent-harness-shell.d.ts +12 -0
- package/dist/src/agent-harness-shell.js +90 -0
- package/dist/src/agent-harness-versions.d.ts +8 -0
- package/dist/src/agent-harness-versions.js +49 -0
- package/dist/src/agent-harnesses.d.ts +4 -0
- package/dist/src/agent-harnesses.js +13 -0
- package/dist/src/authority/commands.d.ts +2 -0
- package/dist/src/authority/commands.js +49 -8
- package/dist/src/authority/dispatch-decision.d.ts +1 -0
- package/dist/src/authority/dispatch-decision.js +7 -4
- package/dist/src/authority/events.js +2 -2
- package/dist/src/authority/gate-reduction.d.ts +1 -0
- package/dist/src/authority/gate-reduction.js +18 -3
- package/dist/src/authority/gates.d.ts +2 -1
- package/dist/src/authority/gates.js +5 -1
- package/dist/src/authority/handoff-chain.d.ts +24 -0
- package/dist/src/authority/handoff-chain.js +46 -0
- package/dist/src/authority/operations.js +1 -1
- package/dist/src/authority/reconciliation.d.ts +1 -0
- package/dist/src/authority/reconciliation.js +18 -11
- package/dist/src/authority/reduction.d.ts +1 -1
- package/dist/src/authority/reduction.js +6 -1
- package/dist/src/authority/status-input.d.ts +1 -1
- package/dist/src/authority/status.d.ts +1 -0
- package/dist/src/authority/status.js +27 -3
- package/dist/src/authority/transitions.d.ts +5 -5
- package/dist/src/authority/transitions.js +9 -0
- package/dist/src/broker/actor/authority-delivery.js +1 -0
- package/dist/src/broker/actor/authority-queries.d.ts +11 -1
- package/dist/src/broker/actor/authority-queries.js +67 -3
- package/dist/src/broker/actor/authority-receipts.js +11 -1
- package/dist/src/broker/actor/authority-session.js +2 -2
- package/dist/src/broker/actor/authority-settings.js +4 -0
- package/dist/src/broker/actor/delivery-intents.d.ts +3 -1
- package/dist/src/broker/actor/delivery-intents.js +4 -4
- package/dist/src/broker/actor/effect-delivery.js +13 -1
- package/dist/src/broker/actor/effect-queries.d.ts +1 -0
- package/dist/src/broker/actor/effect-queries.js +7 -0
- package/dist/src/broker/actor/pin-check.js +1 -1
- package/dist/src/broker/actor/stop-plan.js +1 -1
- package/dist/src/broker/actor/turn-state.js +1 -1
- package/dist/src/broker/authority-admission.js +26 -5
- package/dist/src/broker/authority-restore.js +1 -0
- package/dist/src/broker/decision-restore.js +4 -4
- package/dist/src/broker/socket-address.d.ts +3 -1
- package/dist/src/broker/socket-address.js +2 -2
- package/dist/src/cli/arguments.d.ts +11 -13
- package/dist/src/cli/arguments.js +37 -107
- package/dist/src/cli/command-effects.d.ts +7 -0
- package/dist/src/cli/command-effects.js +39 -0
- package/dist/src/cli/commands.js +11 -4
- package/dist/src/cli/config-arguments.d.ts +11 -0
- package/dist/src/cli/config-arguments.js +59 -0
- package/dist/src/cli/config-command.d.ts +2 -0
- package/dist/src/cli/config-command.js +105 -0
- package/dist/src/cli/config-file.d.ts +3 -0
- package/dist/src/cli/config-file.js +50 -0
- package/dist/src/cli/config-lock.d.ts +7 -0
- package/dist/src/cli/config-lock.js +61 -0
- package/dist/src/cli/config-notice.d.ts +5 -0
- package/dist/src/cli/config-notice.js +46 -0
- package/dist/src/cli/doctor-github.d.ts +9 -0
- package/dist/src/cli/doctor-github.js +138 -0
- package/dist/src/cli/doctor-harness.d.ts +13 -0
- package/dist/src/cli/doctor-harness.js +242 -0
- package/dist/src/cli/doctor-local.d.ts +18 -0
- package/dist/src/cli/doctor-local.js +77 -0
- package/dist/src/cli/doctor-runtime.d.ts +15 -0
- package/dist/src/cli/doctor-runtime.js +176 -0
- package/dist/src/cli/doctor-service.d.ts +1 -0
- package/dist/src/cli/doctor-service.js +11 -0
- package/dist/src/cli/doctor-workflows.d.ts +3 -0
- package/dist/src/cli/doctor-workflows.js +45 -0
- package/dist/src/cli/doctor.d.ts +15 -0
- package/dist/src/cli/doctor.js +190 -0
- package/dist/src/cli/github-ci-progress.d.ts +8 -0
- package/dist/src/cli/github-ci-progress.js +83 -0
- package/dist/src/cli/github-retry.d.ts +6 -0
- package/dist/src/cli/github-retry.js +47 -0
- package/dist/src/cli/harness-probes.d.ts +22 -0
- package/dist/src/cli/harness-probes.js +183 -0
- package/dist/src/cli/main.d.ts +7 -1
- package/dist/src/cli/main.js +39 -61
- package/dist/src/cli/phone-arguments.d.ts +14 -0
- package/dist/src/cli/phone-arguments.js +37 -0
- package/dist/src/cli/phone-client.d.ts +2 -0
- package/dist/src/cli/phone-client.js +32 -0
- package/dist/src/cli/phone-command.d.ts +13 -0
- package/dist/src/cli/phone-command.js +101 -0
- package/dist/src/cli/probe-command.d.ts +36 -0
- package/dist/src/cli/probe-command.js +59 -0
- package/dist/src/cli/project-settings.d.ts +4 -0
- package/dist/src/cli/project-settings.js +33 -0
- package/dist/src/cli/render.d.ts +3 -1
- package/dist/src/cli/render.js +102 -39
- package/dist/src/cli/report-github.d.ts +18 -0
- package/dist/src/cli/report-github.js +200 -0
- package/dist/src/cli/report.d.ts +17 -0
- package/dist/src/cli/report.js +192 -0
- package/dist/src/cli/repository-arguments.d.ts +5 -0
- package/dist/src/cli/repository-arguments.js +34 -0
- package/dist/src/cli/runtime-arguments.d.ts +4 -0
- package/dist/src/cli/runtime-arguments.js +15 -0
- package/dist/src/cli/runtime-directory.d.ts +6 -2
- package/dist/src/cli/runtime-directory.js +72 -14
- package/dist/src/cli/toolchain.d.ts +2 -0
- package/dist/src/cli/toolchain.js +22 -2
- package/dist/src/cli/usage-render.d.ts +5 -0
- package/dist/src/cli/usage-render.js +40 -1
- package/dist/src/cli/usage.d.ts +3 -3
- package/dist/src/cli/usage.js +74 -45
- package/dist/src/cli/watch-actions.d.ts +2 -0
- package/dist/src/cli/watch-actions.js +4 -4
- package/dist/src/cli/watch-board-view.d.ts +12 -1
- package/dist/src/cli/watch-board-view.js +64 -12
- package/dist/src/cli/watch-board.d.ts +7 -1
- package/dist/src/cli/watch-board.js +61 -16
- package/dist/src/cli/watch-card-forms.js +2 -2
- package/dist/src/cli/watch-client.d.ts +1 -1
- package/dist/src/cli/watch-client.js +12 -3
- package/dist/src/cli/watch-header-view.d.ts +27 -0
- package/dist/src/cli/watch-header-view.js +116 -0
- package/dist/src/cli/watch-model.d.ts +10 -4
- package/dist/src/cli/watch-model.js +49 -59
- package/dist/src/cli/watch-page.js +67 -14
- package/dist/src/cli/watch-phases.js +3 -3
- package/dist/src/cli/watch-phone-client.d.ts +1 -0
- package/dist/src/cli/watch-phone-client.js +84 -0
- package/dist/src/cli/watch-phone-view.d.ts +56 -0
- package/dist/src/cli/watch-phone-view.js +113 -0
- package/dist/src/cli/watch-phone.d.ts +5 -0
- package/dist/src/cli/watch-phone.js +53 -0
- package/dist/src/cli/watch-pr-command.d.ts +5 -2
- package/dist/src/cli/watch-pr-command.js +41 -4
- package/dist/src/cli/watch-pr-identity.d.ts +14 -2
- package/dist/src/cli/watch-pr-identity.js +25 -0
- package/dist/src/cli/watch-pr-observer.d.ts +1 -0
- package/dist/src/cli/watch-pr-observer.js +48 -6
- package/dist/src/cli/watch-pull-request.d.ts +12 -0
- package/dist/src/cli/watch-pull-request.js +134 -0
- package/dist/src/cli/watch-reads.d.ts +7 -1
- package/dist/src/cli/watch-reads.js +42 -20
- package/dist/src/cli/watch-render.d.ts +23 -2
- package/dist/src/cli/watch-render.js +2 -1
- package/dist/src/cli/watch-server.js +56 -7
- package/dist/src/cli/watch-turn.d.ts +4 -1
- package/dist/src/cli/watch-turn.js +38 -2
- package/dist/src/cli/watch-usage.js +5 -1
- package/dist/src/cli/watch-view.d.ts +10 -17
- package/dist/src/cli/watch-view.js +33 -77
- package/dist/src/cli.js +106 -23
- package/dist/src/command-settings.d.ts +16 -0
- package/dist/src/command-settings.js +42 -0
- package/dist/src/configuration-change.d.ts +11 -0
- package/dist/src/configuration-change.js +62 -0
- package/dist/src/configuration-display.d.ts +21 -0
- package/dist/src/configuration-display.js +69 -0
- package/dist/src/configuration-schema.d.ts +49 -0
- package/dist/src/configuration-schema.js +159 -0
- package/dist/src/daemon/claude-turn.d.ts +20 -5
- package/dist/src/daemon/claude-turn.js +116 -53
- package/dist/src/daemon/claude-worker.d.ts +3 -5
- package/dist/src/daemon/claude-worker.js +64 -80
- package/dist/src/daemon/command-journal.d.ts +5 -0
- package/dist/src/daemon/command-journal.js +50 -0
- package/dist/src/daemon/command-process.d.ts +28 -0
- package/dist/src/daemon/command-process.js +164 -0
- package/dist/src/daemon/command-worker.d.ts +19 -0
- package/dist/src/daemon/command-worker.js +182 -0
- package/dist/src/daemon/cursor-stream.d.ts +4 -0
- package/dist/src/daemon/cursor-stream.js +154 -0
- package/dist/src/daemon/daemon-adapters.d.ts +58 -0
- package/dist/src/daemon/daemon-adapters.js +102 -0
- package/dist/src/daemon/daemon-loops.d.ts +14 -0
- package/dist/src/daemon/daemon-loops.js +39 -0
- package/dist/src/daemon/daemon.d.ts +3 -30
- package/dist/src/daemon/daemon.js +132 -110
- package/dist/src/daemon/declared-input.d.ts +3 -0
- package/dist/src/daemon/declared-input.js +9 -0
- package/dist/src/daemon/delivery-router.js +7 -1
- package/dist/src/daemon/gemini-stream.d.ts +4 -0
- package/dist/src/daemon/gemini-stream.js +129 -0
- package/dist/src/daemon/github-calls.d.ts +4 -0
- package/dist/src/daemon/github-calls.js +16 -7
- package/dist/src/daemon/github-ci-rerun.d.ts +26 -0
- package/dist/src/daemon/github-ci-rerun.js +92 -0
- package/dist/src/daemon/github-ci.d.ts +6 -0
- package/dist/src/daemon/github-ci.js +251 -0
- package/dist/src/daemon/github-merge-call.d.ts +16 -0
- package/dist/src/daemon/github-merge-call.js +73 -0
- package/dist/src/daemon/github-merge.d.ts +3 -5
- package/dist/src/daemon/github-merge.js +59 -98
- package/dist/src/daemon/github-methods.d.ts +28 -0
- package/dist/src/daemon/github-methods.js +90 -16
- package/dist/src/daemon/github-operation.d.ts +3 -0
- package/dist/src/daemon/github-retry.d.ts +6 -0
- package/dist/src/daemon/github-retry.js +13 -0
- package/dist/src/daemon/github-ticket-status.js +27 -1
- package/dist/src/daemon/github-worker.js +2 -1
- package/dist/src/daemon/handoff-worker.d.ts +10 -0
- package/dist/src/daemon/handoff-worker.js +232 -0
- package/dist/src/daemon/issue-queue.d.ts +2 -0
- package/dist/src/daemon/issue-queue.js +92 -63
- package/dist/src/daemon/notify-journal.d.ts +18 -0
- package/dist/src/daemon/notify-journal.js +108 -0
- package/dist/src/daemon/notify-message.js +2 -1
- package/dist/src/daemon/notify.js +177 -37
- package/dist/src/daemon/opencode-stream.d.ts +5 -0
- package/dist/src/daemon/opencode-stream.js +87 -0
- package/dist/src/daemon/queue-status.d.ts +4 -0
- package/dist/src/daemon/queue-status.js +38 -0
- package/dist/src/daemon/retry-worktree.d.ts +18 -0
- package/dist/src/daemon/retry-worktree.js +139 -0
- package/dist/src/daemon/retrying-turn.d.ts +5 -0
- package/dist/src/daemon/retrying-turn.js +145 -21
- package/dist/src/daemon/schedule-journal.d.ts +19 -0
- package/dist/src/daemon/schedule-journal.js +57 -0
- package/dist/src/daemon/text-output.d.ts +18 -0
- package/dist/src/daemon/text-output.js +44 -0
- package/dist/src/daemon/ticket-dependency-waits.d.ts +18 -0
- package/dist/src/daemon/ticket-dependency-waits.js +60 -0
- package/dist/src/daemon/ticket-registration.d.ts +10 -8
- package/dist/src/daemon/ticket-registration.js +146 -47
- package/dist/src/daemon/ticket-source.d.ts +4 -1
- package/dist/src/daemon/ticket-source.js +8 -2
- package/dist/src/daemon/turn-command.d.ts +10 -0
- package/dist/src/daemon/turn-command.js +33 -0
- package/dist/src/daemon/turn-report.d.ts +18 -0
- package/dist/src/daemon/turn-report.js +79 -0
- package/dist/src/daemon/work-tree.d.ts +2 -1
- package/dist/src/daemon/work-tree.js +15 -12
- package/dist/src/daemon/workflow-generations.d.ts +32 -0
- package/dist/src/daemon/workflow-generations.js +57 -0
- package/dist/src/daemon/workflow-replay.d.ts +16 -0
- package/dist/src/daemon/workflow-replay.js +58 -0
- package/dist/src/daemon/workflow-schedules.d.ts +27 -0
- package/dist/src/daemon/workflow-schedules.js +185 -0
- package/dist/src/decision-visibility.d.ts +2 -0
- package/dist/src/decision-visibility.js +10 -0
- package/dist/src/decision-wait.d.ts +1 -0
- package/dist/src/decision-wait.js +3 -0
- package/dist/src/delivery-backoff.d.ts +1 -0
- package/dist/src/delivery-backoff.js +3 -0
- package/dist/src/doctor-report.d.ts +24 -0
- package/dist/src/doctor-report.js +70 -0
- package/dist/src/execution-pin.d.ts +9 -0
- package/dist/src/execution-pin.js +86 -2
- package/dist/src/grok-result.d.ts +12 -0
- package/dist/src/grok-result.js +61 -0
- package/dist/src/harness-defaults.d.ts +35 -0
- package/dist/src/harness-defaults.js +121 -0
- package/dist/src/host/decision-resume.d.ts +35 -0
- package/dist/src/host/decision-resume.js +86 -0
- package/dist/src/host/gate-bridge.d.ts +48 -0
- package/dist/src/host/gate-bridge.js +124 -0
- package/dist/src/host/run-wait.d.ts +26 -0
- package/dist/src/host/run-wait.js +37 -0
- package/dist/src/host/start-delivery.d.ts +3 -2
- package/dist/src/host/start-delivery.js +11 -4
- package/dist/src/host/step-bridge-host.d.ts +6 -19
- package/dist/src/host/step-bridge-host.js +57 -55
- package/dist/src/host/world-reconciliation.d.ts +1 -0
- package/dist/src/host/world-reconciliation.js +3 -0
- package/dist/src/host/world-runs.js +5 -0
- package/dist/src/issue-identity.d.ts +6 -0
- package/dist/src/issue-identity.js +23 -0
- package/dist/src/merge-request.d.ts +19 -0
- package/dist/src/merge-request.js +32 -0
- package/dist/src/phone/canonical-json.d.ts +1 -0
- package/dist/src/phone/canonical-json.js +16 -0
- package/dist/src/phone/phone-link.d.ts +7 -0
- package/dist/src/phone/phone-link.js +21 -0
- package/dist/src/phone/qr-data.d.ts +8 -0
- package/dist/src/phone/qr-data.js +133 -0
- package/dist/src/phone/qr-matrix.d.ts +6 -0
- package/dist/src/phone/qr-matrix.js +175 -0
- package/dist/src/phone/qr-penalty.d.ts +3 -0
- package/dist/src/phone/qr-penalty.js +67 -0
- package/dist/src/phone/qr-picture.d.ts +5 -0
- package/dist/src/phone/qr-picture.js +24 -0
- package/dist/src/private-config.schema.json +263 -0
- package/dist/src/project-config.schema.json +65 -0
- package/dist/src/project-settings.d.ts +19 -0
- package/dist/src/project-settings.js +131 -0
- package/dist/src/relay/answer-check.d.ts +24 -0
- package/dist/src/relay/answer-check.js +145 -0
- package/dist/src/relay/answer-inbox.d.ts +15 -0
- package/dist/src/relay/answer-inbox.js +173 -0
- package/dist/src/relay/daemon-keys.d.ts +16 -0
- package/dist/src/relay/daemon-keys.js +75 -0
- package/dist/src/relay/decision-check.d.ts +3 -0
- package/dist/src/relay/decision-check.js +77 -0
- package/dist/src/relay/decision-close.d.ts +6 -0
- package/dist/src/relay/decision-close.js +72 -0
- package/dist/src/relay/decision-envelopes.d.ts +29 -0
- package/dist/src/relay/decision-envelopes.js +93 -0
- package/dist/src/relay/decision-watch.d.ts +14 -0
- package/dist/src/relay/decision-watch.js +68 -0
- package/dist/src/relay/envelope-post.d.ts +8 -0
- package/dist/src/relay/envelope-post.js +71 -0
- package/dist/src/relay/envelope.d.ts +28 -0
- package/dist/src/relay/envelope.js +53 -0
- package/dist/src/relay/hpke.d.ts +25 -0
- package/dist/src/relay/hpke.js +108 -0
- package/dist/src/relay/pairing-checks.d.ts +42 -0
- package/dist/src/relay/pairing-checks.js +172 -0
- package/dist/src/relay/pairing-follow.d.ts +8 -0
- package/dist/src/relay/pairing-follow.js +95 -0
- package/dist/src/relay/pairing-session.d.ts +29 -0
- package/dist/src/relay/pairing-session.js +87 -0
- package/dist/src/relay/phone-delivery.d.ts +51 -0
- package/dist/src/relay/phone-delivery.js +139 -0
- package/dist/src/relay/phone-devices.d.ts +36 -0
- package/dist/src/relay/phone-devices.js +46 -0
- package/dist/src/relay/phone-inbox.d.ts +18 -0
- package/dist/src/relay/phone-inbox.js +17 -0
- package/dist/src/relay/phone-operations.d.ts +18 -0
- package/dist/src/relay/phone-operations.js +121 -0
- package/dist/src/relay/phone-outbox.d.ts +21 -0
- package/dist/src/relay/phone-outbox.js +25 -0
- package/dist/src/relay/phone-socket.d.ts +6 -0
- package/dist/src/relay/phone-socket.js +63 -0
- package/dist/src/relay/relay-control.d.ts +7 -0
- package/dist/src/relay/relay-control.js +24 -0
- package/dist/src/relay/relay-files.d.ts +2 -0
- package/dist/src/relay/relay-files.js +23 -0
- package/dist/src/relay/relay-heartbeat.d.ts +17 -0
- package/dist/src/relay/relay-heartbeat.js +81 -0
- package/dist/src/relay/relay-http.d.ts +14 -0
- package/dist/src/relay/relay-http.js +63 -0
- package/dist/src/relay/relay-registration.d.ts +15 -0
- package/dist/src/relay/relay-registration.js +63 -0
- package/dist/src/relay/relay-service.d.ts +25 -0
- package/dist/src/relay/relay-service.js +216 -0
- package/dist/src/relay/relay-store.d.ts +48 -0
- package/dist/src/relay/relay-store.js +131 -0
- package/dist/src/relay/sealed-post.d.ts +25 -0
- package/dist/src/relay/sealed-post.js +52 -0
- package/dist/src/relay.d.ts +1 -0
- package/dist/src/relay.js +8 -0
- package/dist/src/report-statistics.d.ts +50 -0
- package/dist/src/report-statistics.js +70 -0
- package/dist/src/report.d.ts +171 -0
- package/dist/src/report.js +119 -0
- package/dist/src/repository-identity.d.ts +4 -0
- package/dist/src/repository-identity.js +4 -0
- package/dist/src/review-subject.d.ts +41 -0
- package/dist/src/review-subject.js +91 -0
- package/dist/src/run-wait.d.ts +23 -0
- package/dist/src/run-wait.js +20 -0
- package/dist/src/service/active-tickets.d.ts +4 -0
- package/dist/src/service/active-tickets.js +49 -0
- package/dist/src/service/command-effects.d.ts +4 -0
- package/dist/src/service/command-effects.js +16 -0
- package/dist/src/service/decision-handler.d.ts +4 -0
- package/dist/src/service/decision-handler.js +39 -4
- package/dist/src/service/gateway.js +18 -3
- package/dist/src/service/queue-runs.d.ts +3 -0
- package/dist/src/service/queue-runs.js +39 -0
- package/dist/src/service/registry.d.ts +22 -3
- package/dist/src/service/registry.js +51 -8
- package/dist/src/service/replies.d.ts +10 -0
- package/dist/src/service/replies.js +12 -0
- package/dist/src/service/run-handlers.js +45 -54
- package/dist/src/service/run-metadata.d.ts +8 -0
- package/dist/src/service/run-metadata.js +53 -0
- package/dist/src/service/run-waits.d.ts +3 -0
- package/dist/src/service/run-waits.js +41 -0
- package/dist/src/service/service.d.ts +21 -2
- package/dist/src/service/service.js +23 -5
- package/dist/src/service/submission-handler.js +70 -19
- package/dist/src/service/worker-port.d.ts +1 -0
- package/dist/src/service/worker-totals.js +10 -1
- package/dist/src/step-bridge.d.ts +32 -0
- package/dist/src/steps/decision-gate.d.ts +2 -1
- package/dist/src/steps/decision-gate.js +7 -0
- package/dist/src/steps/handoff.d.ts +2 -0
- package/dist/src/steps/handoff.js +13 -0
- package/dist/src/steps/merge-by-person.d.ts +2 -0
- package/dist/src/steps/merge-by-person.js +18 -0
- package/dist/src/steps/merge-when-green.d.ts +2 -0
- package/dist/src/steps/merge-when-green.js +62 -0
- package/dist/src/steps/review-by-agent.d.ts +5 -0
- package/dist/src/steps/review-by-agent.js +124 -0
- package/dist/src/steps/review-by-person.d.ts +4 -0
- package/dist/src/steps/review-by-person.js +16 -0
- package/dist/src/steps/review-subject.d.ts +2 -0
- package/dist/src/steps/review-subject.js +11 -0
- package/dist/src/steps/run-command.d.ts +2 -0
- package/dist/src/steps/run-command.js +15 -0
- package/dist/src/steps/sleep.d.ts +3 -0
- package/dist/src/steps/sleep.js +19 -0
- package/dist/src/steps/wait-for-decision.d.ts +2 -0
- package/dist/src/steps/wait-for-decision.js +71 -0
- package/dist/src/steps/wait-for-run.d.ts +5 -0
- package/dist/src/steps/wait-for-run.js +9 -0
- package/dist/src/storage/decision-snapshots.d.ts +1 -0
- package/dist/src/storage/decision-snapshots.js +7 -1
- package/dist/src/submission.d.ts +4 -0
- package/dist/src/submission.js +6 -2
- package/dist/src/testing.d.ts +29 -0
- package/dist/src/testing.js +264 -0
- package/dist/src/ticket-dependencies.d.ts +1 -0
- package/dist/src/ticket-dependencies.js +15 -0
- package/dist/src/ticket-status-stream.d.ts +9 -0
- package/dist/src/ticket-status-stream.js +94 -0
- package/dist/src/ticket-status.js +7 -4
- package/dist/src/token-prices.d.ts +14 -4
- package/dist/src/token-prices.js +56 -11
- package/dist/src/turn-profile.d.ts +1 -0
- package/dist/src/turn-profile.js +8 -1
- package/dist/src/worker-usage.d.ts +25 -0
- package/dist/src/worker-usage.js +58 -1
- package/dist/src/workflow-admission.d.ts +6 -0
- package/dist/src/workflow-candidate.d.ts +7 -2
- package/dist/src/workflow-candidate.js +48 -5
- package/dist/src/workflow-contracts.d.ts +2 -0
- package/dist/src/workflow-contracts.js +8 -3
- package/dist/src/workflow-declaration.d.ts +31 -2
- package/dist/src/workflow-declaration.js +140 -16
- package/dist/src/workflow-discovery.d.ts +19 -0
- package/dist/src/workflow-discovery.js +36 -0
- package/dist/src/workflow-refusals.d.ts +6 -0
- package/dist/src/workflow-refusals.js +42 -0
- package/dist/src/workflow-schedule.d.ts +22 -0
- package/dist/src/workflow-schedule.js +53 -0
- package/dist/src/workflows.d.ts +12 -1
- package/dist/src/workflows.js +9 -0
- package/dist/tools/admit-workflow.d.ts +14 -0
- package/dist/tools/admit-workflow.js +107 -0
- package/dist/tools/doctor-adoption.d.ts +1 -0
- package/dist/tools/doctor-adoption.js +11 -0
- package/dist/tools/project-configuration.d.ts +4 -0
- package/dist/tools/project-configuration.js +47 -0
- package/dist/tools/self-host-processes.d.ts +1 -0
- package/dist/tools/self-host-processes.js +33 -22
- package/dist/tools/self-host-project.d.ts +21 -0
- package/dist/tools/self-host-project.js +224 -0
- package/dist/tools/self-host-runtime.d.ts +16 -0
- package/dist/tools/self-host-runtime.js +60 -0
- package/dist/tools/self-host-workflows.d.ts +1 -0
- package/dist/tools/self-host-workflows.js +36 -1
- package/dist/tools/self-host.js +106 -135
- package/dist/tools/workflow-bundle-dependencies.d.ts +5 -0
- package/dist/tools/workflow-bundle-dependencies.js +93 -0
- package/dist/tools/workflow-bundles.d.ts +20 -0
- package/dist/tools/workflow-bundles.js +173 -0
- package/dist/tools/workflow-candidate-counts.d.ts +12 -0
- package/dist/tools/workflow-candidate-counts.js +266 -0
- package/dist/tools/workflow-candidate-fields.d.ts +5 -0
- package/dist/tools/workflow-candidate-fields.js +24 -0
- package/dist/tools/workflow-candidate-helper-counts.d.ts +10 -0
- package/dist/tools/workflow-candidate-helper-counts.js +129 -0
- package/dist/tools/workflow-candidate-program.d.ts +13 -0
- package/dist/tools/workflow-candidate-program.js +106 -0
- package/dist/tools/workflow-candidate-source.d.ts +6 -0
- package/dist/tools/workflow-candidate-source.js +169 -0
- package/dist/tools/workflow-candidate-syntax.d.ts +21 -0
- package/dist/tools/workflow-candidate-syntax.js +263 -0
- package/dist/tools/workflow-command.d.ts +1 -0
- package/dist/tools/workflow-command.js +143 -0
- package/dist/tools/workflow-folder-capture.d.ts +18 -0
- package/dist/tools/workflow-folder-capture.js +261 -0
- package/dist/tools/workflow-folders.d.ts +49 -0
- package/dist/tools/workflow-folders.js +203 -0
- package/dist/tools/workflow-source-effects.d.ts +10 -0
- package/dist/tools/workflow-source-effects.js +213 -0
- package/dist/tools/workflow-test-hook.d.ts +7 -0
- package/dist/tools/workflow-test-hook.js +16 -0
- package/dist/tools/workflow-test-loader.d.ts +1 -0
- package/dist/tools/workflow-test-loader.js +10 -0
- package/dist/workflows/develop-prd.js +71 -3
- package/dist/workflows/develop-ticket.js +6 -1
- package/dist/workflows/ticket-prompts.js +17 -3
- package/package.json +66 -6
- package/templates/develop/README.md +78 -0
- package/templates/develop/develop/accept.ts +11 -0
- package/templates/develop/develop/flow-tests.ts +357 -0
- package/templates/develop/develop/local.ts +40 -0
- package/templates/develop/develop/option-tests.ts +174 -0
- package/templates/develop/develop/partial-choice.ts +29 -0
- package/templates/develop/develop/partial.ts +28 -0
- package/templates/develop/develop/pull.ts +152 -0
- package/templates/develop/develop/queue-partial.ts +39 -0
- package/templates/develop/develop/refusal-tests.ts +174 -0
- package/templates/develop/develop/report.ts +156 -0
- package/templates/develop/develop/round.ts +40 -0
- package/templates/develop/develop/scenarios.ts +87 -0
- package/templates/develop/develop/turn.ts +67 -0
- package/templates/develop/develop.declaration.json +24 -0
- package/templates/develop/develop.test.ts +287 -0
- package/templates/develop/develop.ts +30 -0
- package/templates/develop/template.json +153 -0
- package/dist/src/chats/analysis-batches.d.ts +0 -24
- package/dist/src/chats/analysis-batches.js +0 -83
- package/dist/src/chats/analysis-contract.d.ts +0 -80
- package/dist/src/chats/analysis-contract.js +0 -16
- package/dist/src/chats/analysis-data.d.ts +0 -3
- package/dist/src/chats/analysis-data.js +0 -85
- package/dist/src/chats/analysis-input.d.ts +0 -12
- package/dist/src/chats/analysis-input.js +0 -83
- package/dist/src/chats/analysis-links.d.ts +0 -2
- package/dist/src/chats/analysis-links.js +0 -25
- package/dist/src/chats/analysis-prompt.d.ts +0 -10
- package/dist/src/chats/analysis-prompt.js +0 -16
- package/dist/src/chats/analysis-proposal.d.ts +0 -2
- package/dist/src/chats/analysis-proposal.js +0 -32
- package/dist/src/chats/analysis-provenance.d.ts +0 -4
- package/dist/src/chats/analysis-provenance.js +0 -99
- package/dist/src/chats/analysis-shape.d.ts +0 -3
- package/dist/src/chats/analysis-shape.js +0 -228
- package/dist/src/chats/analysis.d.ts +0 -3
- package/dist/src/chats/analysis.js +0 -42
- package/dist/src/chats/corpus-input.d.ts +0 -5
- package/dist/src/chats/corpus-input.js +0 -288
- package/dist/src/chats/destination.d.ts +0 -4
- package/dist/src/chats/destination.js +0 -96
- package/dist/src/chats/import.d.ts +0 -15
- package/dist/src/chats/import.js +0 -243
- package/dist/src/chats/input-file.d.ts +0 -3
- package/dist/src/chats/input-file.js +0 -32
- package/dist/src/chats/normalize.d.ts +0 -29
- package/dist/src/chats/normalize.js +0 -155
- package/dist/src/chats/previous-import.d.ts +0 -5
- package/dist/src/chats/previous-import.js +0 -34
- package/dist/src/chats/reader.d.ts +0 -21
- package/dist/src/chats/reader.js +0 -118
- package/dist/src/chats/redact-import.d.ts +0 -14
- package/dist/src/chats/redact-import.js +0 -141
- package/dist/src/chats/redaction.d.ts +0 -41
- package/dist/src/chats/redaction.js +0 -161
- package/dist/src/chats/revision-input.d.ts +0 -3
- package/dist/src/chats/revision-input.js +0 -180
- package/dist/src/chats/revision.d.ts +0 -48
- package/dist/src/chats/revision.js +0 -94
- package/dist/src/chats/selection.d.ts +0 -25
- package/dist/src/chats/selection.js +0 -109
- package/dist/src/chats/source.d.ts +0 -23
- package/dist/src/chats/source.js +0 -135
- package/dist/src/chats/structure.d.ts +0 -57
- package/dist/src/chats/structure.js +0 -216
- package/dist/src/daemon/analysis-launch.d.ts +0 -5
- package/dist/src/daemon/analysis-launch.js +0 -81
- package/dist/src/daemon/analysis-token.d.ts +0 -6
- package/dist/src/daemon/analysis-token.js +0 -88
- package/dist/src/daemon/analysis-worker.d.ts +0 -22
- package/dist/src/daemon/analysis-worker.js +0 -219
- package/dist/src/daemon/chats-files.d.ts +0 -15
- package/dist/src/daemon/chats-files.js +0 -113
- package/dist/src/daemon/chats-worker.d.ts +0 -12
- package/dist/src/daemon/chats-worker.js +0 -200
- package/dist/workflows/analyze-chats.d.ts +0 -10
- package/dist/workflows/analyze-chats.declaration.json +0 -9
- package/dist/workflows/analyze-chats.js +0 -73
package/dist/src/worker-usage.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
export function modelUsageOf(value) {
|
|
2
|
+
if (!Array.isArray(value))
|
|
3
|
+
return undefined;
|
|
4
|
+
return value.flatMap((entry) => {
|
|
5
|
+
if (typeof entry !== "object" || entry === null)
|
|
6
|
+
return [];
|
|
7
|
+
const model = Reflect.get(entry, "model");
|
|
8
|
+
if (typeof model !== "string")
|
|
9
|
+
return [];
|
|
10
|
+
return [{ model, usage: usageOf(Reflect.get(entry, "usage")) }];
|
|
11
|
+
});
|
|
12
|
+
}
|
|
1
13
|
export function priceOf(value) {
|
|
2
14
|
return typeof value === "number" && Number.isFinite(value) && value >= 0
|
|
3
15
|
? value
|
|
@@ -11,6 +23,11 @@ export function tokenCount(value) {
|
|
|
11
23
|
export function usageOf(value) {
|
|
12
24
|
const fields = typeof value === "object" && value !== null ? value : {};
|
|
13
25
|
return {
|
|
26
|
+
...(Object.hasOwn(fields, "cache_creation_input_tokens")
|
|
27
|
+
? {
|
|
28
|
+
cache_creation_input_tokens: tokenCount(Reflect.get(fields, "cache_creation_input_tokens")),
|
|
29
|
+
}
|
|
30
|
+
: {}),
|
|
14
31
|
input_tokens: tokenCount(Reflect.get(fields, "input_tokens")),
|
|
15
32
|
cache_read_input_tokens: tokenCount(Reflect.get(fields, "cache_read_input_tokens")),
|
|
16
33
|
output_tokens: tokenCount(Reflect.get(fields, "output_tokens")),
|
|
@@ -23,12 +40,17 @@ function total(values) {
|
|
|
23
40
|
}
|
|
24
41
|
export function sumUsage(values) {
|
|
25
42
|
return {
|
|
43
|
+
...(values.some((value) => Object.hasOwn(value, "cache_creation_input_tokens"))
|
|
44
|
+
? {
|
|
45
|
+
cache_creation_input_tokens: total(values.map((value) => value.cache_creation_input_tokens ?? null)),
|
|
46
|
+
}
|
|
47
|
+
: {}),
|
|
26
48
|
input_tokens: total(values.map((value) => value.input_tokens)),
|
|
27
49
|
cache_read_input_tokens: total(values.map((value) => value.cache_read_input_tokens)),
|
|
28
50
|
output_tokens: total(values.map((value) => value.output_tokens)),
|
|
29
51
|
};
|
|
30
52
|
}
|
|
31
|
-
function sumPrices(values) {
|
|
53
|
+
export function sumPrices(values) {
|
|
32
54
|
const prices = values.map(priceOf);
|
|
33
55
|
if (prices.length === 0 || prices.includes(null))
|
|
34
56
|
return null;
|
|
@@ -42,3 +64,38 @@ export function workerTotals(workerTurns) {
|
|
|
42
64
|
estimatedCostUsd: sumPrices(workerTurns.map((turn) => turn.estimatedCostUsd)),
|
|
43
65
|
};
|
|
44
66
|
}
|
|
67
|
+
function retryKindField(value) {
|
|
68
|
+
return value === null || value === "capacity" || value === "network"
|
|
69
|
+
? { retryKind: value }
|
|
70
|
+
: {};
|
|
71
|
+
}
|
|
72
|
+
export function attemptsOf(value) {
|
|
73
|
+
if (!Array.isArray(value))
|
|
74
|
+
return undefined;
|
|
75
|
+
return value.flatMap((entry) => {
|
|
76
|
+
const fields = typeof entry === "object" && entry !== null ? entry : {};
|
|
77
|
+
const field = (name) => Reflect.get(fields, name);
|
|
78
|
+
const attempt = tokenCount(field("attempt"));
|
|
79
|
+
const model = field("model");
|
|
80
|
+
const models = modelUsageOf(field("models"));
|
|
81
|
+
if (attempt === null ||
|
|
82
|
+
attempt === 0 ||
|
|
83
|
+
(model !== null && typeof model !== "string"))
|
|
84
|
+
return [];
|
|
85
|
+
return [
|
|
86
|
+
{
|
|
87
|
+
...retryKindField(field("retryKind")),
|
|
88
|
+
attempt,
|
|
89
|
+
model,
|
|
90
|
+
...(models === undefined ? {} : { models }),
|
|
91
|
+
usage: usageOf(field("usage")),
|
|
92
|
+
costUsd: priceOf(field("costUsd")),
|
|
93
|
+
estimatedCostUsd: priceOf(field("estimatedCostUsd")),
|
|
94
|
+
},
|
|
95
|
+
];
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
export function attemptFields(value) {
|
|
99
|
+
const attempts = attemptsOf(value);
|
|
100
|
+
return attempts === undefined ? {} : { attempts };
|
|
101
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CommandWaits } from "./workflow-declaration.ts";
|
|
1
2
|
export interface ToolchainIdentity {
|
|
2
3
|
readonly sdk: string;
|
|
3
4
|
readonly world: string;
|
|
@@ -23,10 +24,15 @@ export interface AdmissionPolicy {
|
|
|
23
24
|
readonly capabilities: readonly string[];
|
|
24
25
|
}
|
|
25
26
|
export interface ExecutionManifest {
|
|
27
|
+
readonly queue?: boolean;
|
|
26
28
|
readonly name: string;
|
|
27
29
|
readonly workflowId: string;
|
|
28
30
|
readonly steps: readonly string[];
|
|
29
31
|
readonly capabilities: readonly string[];
|
|
32
|
+
readonly handoffs?: readonly string[];
|
|
33
|
+
readonly commands?: readonly string[];
|
|
34
|
+
readonly commandWaits?: CommandWaits;
|
|
35
|
+
readonly bundleDigest?: string;
|
|
30
36
|
readonly artifacts: Readonly<Record<string, string>>;
|
|
31
37
|
readonly resources: Readonly<Record<string, string>>;
|
|
32
38
|
readonly toolchain: ToolchainIdentity;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type WorkflowDeclaration } from "./workflow-declaration.ts";
|
|
1
|
+
import { type WorkflowQueueCode, type WorkflowDeclaration } from "./workflow-declaration.ts";
|
|
2
2
|
export interface CandidateDeclaration {
|
|
3
3
|
readonly workflow: WorkflowDeclaration;
|
|
4
4
|
readonly methods: Readonly<Record<string, readonly string[]>>;
|
|
@@ -6,12 +6,14 @@ export interface CandidateDeclaration {
|
|
|
6
6
|
export interface CandidateImport {
|
|
7
7
|
readonly module: string;
|
|
8
8
|
readonly names: readonly string[];
|
|
9
|
+
readonly source?: string;
|
|
9
10
|
}
|
|
10
11
|
export interface CandidateEffect {
|
|
11
12
|
readonly capability: string | null;
|
|
12
13
|
readonly method: string | null;
|
|
13
14
|
}
|
|
14
15
|
export interface CandidateAnalysis {
|
|
16
|
+
readonly localSources?: readonly string[];
|
|
15
17
|
readonly imports: readonly CandidateImport[];
|
|
16
18
|
readonly effects: readonly CandidateEffect[];
|
|
17
19
|
readonly directEffects: readonly string[];
|
|
@@ -20,10 +22,13 @@ export interface CandidateAnalysis {
|
|
|
20
22
|
readonly knownUnitTotal: number;
|
|
21
23
|
}
|
|
22
24
|
export type InstalledWorkflowExports = Readonly<Record<string, readonly string[]>>;
|
|
23
|
-
export type WorkflowCandidateCode = "invalid-declaration" | "forbidden-import" | "missing-export" | "unsupported-source" | "dynamic-effect" | "undeclared-effect" | "effect-limit" | "direct-effect";
|
|
25
|
+
export type WorkflowCandidateCode = WorkflowQueueCode | "invalid-declaration" | "forbidden-import" | "missing-export" | "unsupported-source" | "dynamic-effect" | "undeclared-effect" | "effect-limit" | "direct-effect";
|
|
24
26
|
export interface WorkflowCandidateInput {
|
|
25
27
|
readonly declaration: unknown;
|
|
26
28
|
readonly analysis: CandidateAnalysis;
|
|
27
29
|
readonly installedExports: InstalledWorkflowExports;
|
|
28
30
|
}
|
|
31
|
+
export declare function workflowHelperPath(source: string, imported: string): string | undefined;
|
|
32
|
+
export declare function isCandidateDeclaration(value: unknown): value is CandidateDeclaration;
|
|
29
33
|
export declare function checkWorkflowCandidate(input: WorkflowCandidateInput): readonly WorkflowCandidateCode[];
|
|
34
|
+
export declare function candidateDeclarationRefusals(value: unknown): readonly WorkflowCandidateCode[];
|
|
@@ -1,21 +1,58 @@
|
|
|
1
1
|
import { record } from "./protocol.js";
|
|
2
|
-
import { isWorkflowDeclaration, } from "./workflow-declaration.js";
|
|
2
|
+
import { isWorkflowDeclaration, workflowQueueRefusals, } from "./workflow-declaration.js";
|
|
3
3
|
const workflowModules = [
|
|
4
4
|
"cloving/workflows",
|
|
5
5
|
"cloving/workflows/steps/decision-gate",
|
|
6
|
+
"cloving/workflows/steps/wait-for-decision",
|
|
7
|
+
"cloving/workflows/steps/review-by-person",
|
|
8
|
+
"cloving/workflows/steps/review-by-agent",
|
|
9
|
+
"cloving/workflows/steps/merge-by-person",
|
|
10
|
+
"cloving/workflows/steps/merge-when-green",
|
|
11
|
+
"cloving/workflows/steps/review-subject",
|
|
6
12
|
"cloving/workflows/steps/load-cycle",
|
|
7
13
|
"cloving/workflows/steps/protected-effect",
|
|
14
|
+
"cloving/workflows/steps/handoff",
|
|
15
|
+
"cloving/workflows/steps/wait-for-run",
|
|
16
|
+
"cloving/workflows/steps/run-command",
|
|
17
|
+
"cloving/workflows/steps/sleep",
|
|
8
18
|
];
|
|
19
|
+
export function workflowHelperPath(source, imported) {
|
|
20
|
+
if (!imported.startsWith("./"))
|
|
21
|
+
return undefined;
|
|
22
|
+
const parts = [
|
|
23
|
+
...source.split("/").slice(0, -1),
|
|
24
|
+
...imported.slice(2).split("/"),
|
|
25
|
+
];
|
|
26
|
+
if (parts.length < 2 ||
|
|
27
|
+
parts.some((part) => part.length === 0 ||
|
|
28
|
+
part === "." ||
|
|
29
|
+
part === ".." ||
|
|
30
|
+
part.toUpperCase() === "NODE_MODULES" ||
|
|
31
|
+
/[\\:\0]/.test(part) ||
|
|
32
|
+
part.startsWith("~")))
|
|
33
|
+
return undefined;
|
|
34
|
+
const path = parts.join("/");
|
|
35
|
+
return path.endsWith(".ts") && !path.endsWith(".d.ts") ? path : undefined;
|
|
36
|
+
}
|
|
37
|
+
function allowedImport(entry, analysis) {
|
|
38
|
+
if (workflowModules.includes(entry.module))
|
|
39
|
+
return true;
|
|
40
|
+
const path = workflowHelperPath(entry.source ?? "candidate.ts", entry.module);
|
|
41
|
+
return path !== undefined && (analysis.localSources ?? []).includes(path);
|
|
42
|
+
}
|
|
9
43
|
function isMethodList(value) {
|
|
10
44
|
return (Array.isArray(value) &&
|
|
11
45
|
value.length > 0 &&
|
|
12
46
|
Array.from(value).every((method) => typeof method === "string" && method.trim().length > 0) &&
|
|
13
47
|
new Set(value).size === value.length);
|
|
14
48
|
}
|
|
15
|
-
function isCandidateDeclaration(value) {
|
|
49
|
+
export function isCandidateDeclaration(value) {
|
|
16
50
|
const fields = record(value);
|
|
17
51
|
if (!fields ||
|
|
18
|
-
Object.keys(fields).some((key) =>
|
|
52
|
+
Object.keys(fields).some((key) => !["workflow", "methods", "template"].includes(key)) ||
|
|
53
|
+
(Object.hasOwn(fields, "template") &&
|
|
54
|
+
(typeof fields["template"] !== "string" ||
|
|
55
|
+
!/^[a-z][a-z0-9-]{0,63}$/.test(fields["template"]))))
|
|
19
56
|
return false;
|
|
20
57
|
const workflow = fields["workflow"];
|
|
21
58
|
const methods = record(fields["methods"]);
|
|
@@ -27,10 +64,10 @@ function isCandidateDeclaration(value) {
|
|
|
27
64
|
}
|
|
28
65
|
export function checkWorkflowCandidate(input) {
|
|
29
66
|
if (!isCandidateDeclaration(input.declaration))
|
|
30
|
-
return
|
|
67
|
+
return candidateDeclarationRefusals(input.declaration);
|
|
31
68
|
const { analysis, declaration, installedExports } = input;
|
|
32
69
|
const codes = [];
|
|
33
|
-
if (analysis.imports.some((entry) => !
|
|
70
|
+
if (analysis.imports.some((entry) => !allowedImport(entry, analysis)))
|
|
34
71
|
codes.push("forbidden-import");
|
|
35
72
|
if (analysis.imports.some((entry) => {
|
|
36
73
|
if (!workflowModules.includes(entry.module))
|
|
@@ -57,3 +94,9 @@ export function checkWorkflowCandidate(input) {
|
|
|
57
94
|
codes.push("unsupported-source");
|
|
58
95
|
return [...new Set(codes)].sort();
|
|
59
96
|
}
|
|
97
|
+
export function candidateDeclarationRefusals(value) {
|
|
98
|
+
if (isCandidateDeclaration(value))
|
|
99
|
+
return [];
|
|
100
|
+
const codes = workflowQueueRefusals(record(value)?.["workflow"]);
|
|
101
|
+
return codes.length > 0 ? codes : ["invalid-declaration"];
|
|
102
|
+
}
|
|
@@ -16,6 +16,7 @@ export type CycleOutcome = {
|
|
|
16
16
|
readonly promotionId: string;
|
|
17
17
|
readonly ticketStatus?: "complete" | "partial";
|
|
18
18
|
readonly issueUpdate?: "failed";
|
|
19
|
+
readonly reason?: string;
|
|
19
20
|
};
|
|
20
21
|
export type Validation<Value> = {
|
|
21
22
|
readonly kind: "valid";
|
|
@@ -24,6 +25,7 @@ export type Validation<Value> = {
|
|
|
24
25
|
readonly kind: "invalid";
|
|
25
26
|
readonly reason: string;
|
|
26
27
|
};
|
|
28
|
+
export declare function isPromotionId(value: unknown): value is string;
|
|
27
29
|
export declare function isBlockedReason(value: unknown): value is string;
|
|
28
30
|
export declare function validateDevelopmentInput(value: unknown): Validation<DevelopmentInput>;
|
|
29
31
|
export declare function validateCycleOutcome(value: unknown, input: DevelopmentInput): Validation<CycleOutcome>;
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { isTicketStatus } from "./ticket-status.js";
|
|
2
2
|
const identifier = /^[A-Za-z0-9._:-]{1,128}$/;
|
|
3
3
|
const reason = /^\S[\s\S]{0,255}$/;
|
|
4
|
+
export function isPromotionId(value) {
|
|
5
|
+
return typeof value === "string" && identifier.test(value);
|
|
6
|
+
}
|
|
4
7
|
export function isBlockedReason(value) {
|
|
5
8
|
return typeof value === "string" && reason.test(value);
|
|
6
9
|
}
|
|
@@ -40,7 +43,7 @@ const outcomes = {
|
|
|
40
43
|
},
|
|
41
44
|
handoff_requested: {
|
|
42
45
|
keys: ["cycleId", "kind", "promotionId"],
|
|
43
|
-
optional: ["ticketStatus", "issueUpdate"],
|
|
46
|
+
optional: ["ticketStatus", "issueUpdate", "reason"],
|
|
44
47
|
parse: (fields) => {
|
|
45
48
|
const cycleId = textField(fields, {
|
|
46
49
|
key: "cycleId",
|
|
@@ -54,16 +57,18 @@ const outcomes = {
|
|
|
54
57
|
return null;
|
|
55
58
|
const ticketStatus = fields["ticketStatus"];
|
|
56
59
|
const issueUpdate = fields["issueUpdate"];
|
|
60
|
+
const reason = fields["reason"];
|
|
57
61
|
if (issueUpdate !== undefined && issueUpdate !== "failed")
|
|
58
62
|
return null;
|
|
59
63
|
if (ticketStatus !== undefined && !isTicketStatus(ticketStatus))
|
|
60
64
|
return null;
|
|
65
|
+
if (reason !== undefined && !isBlockedReason(reason))
|
|
66
|
+
return null;
|
|
61
67
|
return {
|
|
62
68
|
kind: "handoff_requested",
|
|
63
69
|
cycleId,
|
|
64
70
|
promotionId,
|
|
65
|
-
...(issueUpdate
|
|
66
|
-
...(ticketStatus === undefined ? {} : { ticketStatus }),
|
|
71
|
+
...Object.fromEntries(Object.entries({ issueUpdate, ticketStatus, reason }).filter(([, value]) => value !== undefined)),
|
|
67
72
|
};
|
|
68
73
|
},
|
|
69
74
|
},
|
|
@@ -1,11 +1,40 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type SubmissionContract } from "./submission.ts";
|
|
2
|
+
import { type WorkflowSchedule } from "./workflow-schedule.ts";
|
|
3
|
+
export interface WorkflowStage {
|
|
4
|
+
readonly name: string;
|
|
5
|
+
readonly label: string;
|
|
6
|
+
readonly operations?: readonly string[];
|
|
7
|
+
readonly gateKinds?: readonly ("approval" | "question")[];
|
|
8
|
+
readonly gateIds?: readonly string[];
|
|
9
|
+
}
|
|
10
|
+
export type WorkflowStages = Readonly<Record<string, readonly WorkflowStage[]>>;
|
|
11
|
+
export interface CommandWaitDeclaration {
|
|
12
|
+
readonly command: string;
|
|
13
|
+
readonly maximumWaitSeconds: number;
|
|
14
|
+
readonly pollEverySeconds: number;
|
|
15
|
+
}
|
|
16
|
+
export type CommandWaits = Readonly<Record<string, CommandWaitDeclaration>>;
|
|
2
17
|
export interface WorkflowDeclaration {
|
|
3
18
|
readonly workflowId: string;
|
|
4
19
|
readonly effectLimit: number;
|
|
5
|
-
readonly capabilities: readonly ("claude" | "github" | "
|
|
20
|
+
readonly capabilities: readonly ("claude" | "github" | "command")[];
|
|
6
21
|
readonly input: SubmissionContract;
|
|
22
|
+
readonly stages?: readonly WorkflowStage[];
|
|
23
|
+
readonly handoffs?: readonly string[];
|
|
24
|
+
readonly commands?: readonly string[];
|
|
25
|
+
readonly commandWaits?: CommandWaits;
|
|
26
|
+
readonly queue?: boolean;
|
|
27
|
+
readonly schedule?: WorkflowSchedule;
|
|
7
28
|
}
|
|
8
29
|
export interface DeclaredWorkflow extends WorkflowDeclaration {
|
|
9
30
|
readonly functionName: string;
|
|
10
31
|
}
|
|
32
|
+
export type WorkflowQueueCode = "queue-needs-ticket-field" | "queue-input-incomplete";
|
|
33
|
+
export declare function workflowQueueRefusals(value: unknown): readonly WorkflowQueueCode[];
|
|
34
|
+
export declare function isWorkflowStages(value: unknown): value is readonly WorkflowStage[];
|
|
35
|
+
export declare function isWorkflowNames(value: unknown): value is readonly string[];
|
|
36
|
+
export declare function isCommandWaits(value: unknown, permissions: {
|
|
37
|
+
readonly capabilities: readonly string[];
|
|
38
|
+
readonly commands: readonly string[];
|
|
39
|
+
}): value is CommandWaits;
|
|
11
40
|
export declare function isWorkflowDeclaration(value: unknown): value is WorkflowDeclaration;
|
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { record } from "./protocol.js";
|
|
2
|
+
import { hasTicketField, } from "./submission.js";
|
|
3
|
+
import { checkWorkflowSchedule, } from "./workflow-schedule.js";
|
|
4
|
+
export function workflowQueueRefusals(value) {
|
|
5
|
+
const declaration = record(value);
|
|
6
|
+
if (declaration?.["queue"] !== true || !isInput(declaration["input"]))
|
|
7
|
+
return [];
|
|
8
|
+
const input = declaration["input"];
|
|
9
|
+
if (!hasTicketField(input))
|
|
10
|
+
return ["queue-needs-ticket-field"];
|
|
11
|
+
return Object.entries(input.fields).some(([name, rule]) => name !== "ticket" && (rule === "string" || rule.optional !== true))
|
|
12
|
+
? ["queue-input-incomplete"]
|
|
13
|
+
: [];
|
|
14
|
+
}
|
|
2
15
|
function keys(fields, allowed) {
|
|
3
|
-
return
|
|
16
|
+
return (fields !== undefined &&
|
|
17
|
+
Object.keys(fields).every((key) => allowed.includes(key)));
|
|
4
18
|
}
|
|
5
19
|
function integer(value, bounds) {
|
|
6
20
|
return (typeof value === "number" &&
|
|
@@ -20,40 +34,150 @@ function integerBounds(fields) {
|
|
|
20
34
|
}
|
|
21
35
|
function isField(value) {
|
|
22
36
|
const fields = record(value);
|
|
23
|
-
if (fields
|
|
24
|
-
!keys(fields, ["type", "optional", "minimum", "maximum"]))
|
|
37
|
+
if (!keys(fields, ["type", "optional", "minimum", "maximum"]))
|
|
25
38
|
return false;
|
|
26
39
|
if (fields["optional"] !== undefined &&
|
|
27
40
|
typeof fields["optional"] !== "boolean")
|
|
28
41
|
return false;
|
|
29
42
|
if (fields["type"] === "integer")
|
|
30
43
|
return integerBounds(fields);
|
|
31
|
-
return ((fields["type"] === "string" ||
|
|
44
|
+
return ((fields["type"] === "string" ||
|
|
45
|
+
fields["type"] === "boolean" ||
|
|
46
|
+
fields["type"] === "ticket") &&
|
|
32
47
|
!Object.hasOwn(fields, "minimum") &&
|
|
33
48
|
!Object.hasOwn(fields, "maximum"));
|
|
34
49
|
}
|
|
35
50
|
function isInput(value) {
|
|
36
51
|
const input = record(value);
|
|
37
|
-
if (
|
|
52
|
+
if (!keys(input, ["maximumBytes", "fields"]))
|
|
38
53
|
return false;
|
|
39
54
|
const fields = record(input["fields"]);
|
|
40
55
|
return (integer(input["maximumBytes"], { minimum: 1, maximum: 1_048_576 }) &&
|
|
41
56
|
fields !== undefined &&
|
|
42
|
-
Object.
|
|
57
|
+
Object.entries(fields).every(([name, rule]) => isField(rule) && (rule.type !== "ticket" || name === "ticket")));
|
|
58
|
+
}
|
|
59
|
+
function matches(value, pattern) {
|
|
60
|
+
return typeof value === "string" && pattern.test(value);
|
|
61
|
+
}
|
|
62
|
+
function selectors(value, pattern) {
|
|
63
|
+
return (Array.isArray(value) &&
|
|
64
|
+
Array.from(value).every((item) => matches(item, pattern)));
|
|
65
|
+
}
|
|
66
|
+
function isStageLabel(label) {
|
|
67
|
+
return (typeof label === "string" &&
|
|
68
|
+
/^[^\p{C}\p{Zl}\p{Zp}]{1,40}$/u.test(label) &&
|
|
69
|
+
label.trim() === label &&
|
|
70
|
+
!["Other", "Done", "Stopped"].includes(label));
|
|
71
|
+
}
|
|
72
|
+
function isStage(value) {
|
|
73
|
+
const stage = record(value);
|
|
74
|
+
if (!keys(stage, ["name", "label", "operations", "gateKinds", "gateIds"]))
|
|
75
|
+
return false;
|
|
76
|
+
const { name, label } = stage;
|
|
77
|
+
const operations = Object.hasOwn(stage, "operations")
|
|
78
|
+
? stage["operations"]
|
|
79
|
+
: [];
|
|
80
|
+
const gateKinds = Object.hasOwn(stage, "gateKinds") ? stage["gateKinds"] : [];
|
|
81
|
+
const gateIds = Object.hasOwn(stage, "gateIds") ? stage["gateIds"] : [];
|
|
82
|
+
return (matches(name, /^[A-Za-z0-9-]{1,64}$/) &&
|
|
83
|
+
isStageLabel(label) &&
|
|
84
|
+
selectors(operations, /^[A-Za-z0-9._:/-]{1,128}$/) &&
|
|
85
|
+
selectors(gateKinds, /^(approval|question)$/) &&
|
|
86
|
+
selectors(gateIds, /^[A-Za-z0-9._:/-]{1,128}$/) &&
|
|
87
|
+
operations.length + gateKinds.length + gateIds.length > 0);
|
|
88
|
+
}
|
|
89
|
+
function unique(values) {
|
|
90
|
+
return new Set(values).size === values.length;
|
|
91
|
+
}
|
|
92
|
+
export function isWorkflowStages(value) {
|
|
93
|
+
if (!Array.isArray(value) || value.length < 1 || value.length > 12)
|
|
94
|
+
return false;
|
|
95
|
+
const stages = Array.from(value);
|
|
96
|
+
if (!stages.every(isStage))
|
|
97
|
+
return false;
|
|
98
|
+
return (unique(stages.map((stage) => stage.name)) &&
|
|
99
|
+
unique(stages.map((stage) => stage.label)) &&
|
|
100
|
+
unique(stages.flatMap((stage) => stage.operations ?? [])) &&
|
|
101
|
+
unique(stages.flatMap((stage) => stage.gateKinds ?? [])) &&
|
|
102
|
+
unique(stages.flatMap((stage) => stage.gateIds ?? [])));
|
|
103
|
+
}
|
|
104
|
+
function isCapabilities(value) {
|
|
105
|
+
return (Array.isArray(value) &&
|
|
106
|
+
value.length > 0 &&
|
|
107
|
+
value.every((capability) => capability === "claude" ||
|
|
108
|
+
capability === "github" ||
|
|
109
|
+
capability === "command"));
|
|
110
|
+
}
|
|
111
|
+
export function isWorkflowNames(value) {
|
|
112
|
+
return selectors(value, /^[A-Za-z0-9-]{1,64}$/) && unique(value);
|
|
113
|
+
}
|
|
114
|
+
function declaredCommands(declaration, capabilities) {
|
|
115
|
+
const commands = declaration["commands"];
|
|
116
|
+
if (Object.hasOwn(declaration, "commands") && !isWorkflowNames(commands))
|
|
117
|
+
return false;
|
|
118
|
+
return ((!capabilities.includes("command") ||
|
|
119
|
+
(Array.isArray(commands) && commands.length > 0)) &&
|
|
120
|
+
declaredCommandWaits(declaration, capabilities));
|
|
121
|
+
}
|
|
122
|
+
function isCommandWait(value) {
|
|
123
|
+
const wait = record(value);
|
|
124
|
+
if (!keys(wait, ["command", "maximumWaitSeconds", "pollEverySeconds"]))
|
|
125
|
+
return false;
|
|
126
|
+
return (typeof wait["command"] === "string" &&
|
|
127
|
+
integer(wait["maximumWaitSeconds"], { minimum: 60, maximum: 2_592_000 }) &&
|
|
128
|
+
integer(wait["pollEverySeconds"], { minimum: 60, maximum: 86_400 }) &&
|
|
129
|
+
Number(wait["pollEverySeconds"]) <= Number(wait["maximumWaitSeconds"]));
|
|
130
|
+
}
|
|
131
|
+
export function isCommandWaits(value, permissions) {
|
|
132
|
+
const waits = record(value);
|
|
133
|
+
if (waits === undefined)
|
|
134
|
+
return false;
|
|
135
|
+
return Object.entries(waits).every(([name, wait]) => matches(name, /^[A-Za-z0-9-]{1,64}$/) &&
|
|
136
|
+
name.trim() === name &&
|
|
137
|
+
isCommandWait(wait) &&
|
|
138
|
+
permissions.capabilities.includes("command") &&
|
|
139
|
+
permissions.commands.includes(wait.command));
|
|
140
|
+
}
|
|
141
|
+
function declaredCommandWaits(declaration, capabilities) {
|
|
142
|
+
if (!Object.hasOwn(declaration, "commandWaits"))
|
|
143
|
+
return true;
|
|
144
|
+
const commands = declaration["commands"];
|
|
145
|
+
return isCommandWaits(declaration["commandWaits"], {
|
|
146
|
+
capabilities,
|
|
147
|
+
commands: isWorkflowNames(commands) ? commands : [],
|
|
148
|
+
});
|
|
43
149
|
}
|
|
44
150
|
export function isWorkflowDeclaration(value) {
|
|
45
151
|
const declaration = record(value);
|
|
46
|
-
if (declaration
|
|
47
|
-
|
|
152
|
+
if (!keys(declaration, [
|
|
153
|
+
"workflowId",
|
|
154
|
+
"effectLimit",
|
|
155
|
+
"capabilities",
|
|
156
|
+
"input",
|
|
157
|
+
"stages",
|
|
158
|
+
"handoffs",
|
|
159
|
+
"commands",
|
|
160
|
+
"commandWaits",
|
|
161
|
+
"queue",
|
|
162
|
+
"schedule",
|
|
163
|
+
]))
|
|
48
164
|
return false;
|
|
49
165
|
const { workflowId, effectLimit, capabilities, input } = declaration;
|
|
50
|
-
return (
|
|
51
|
-
/^[A-Za-z0-9-]{1,64}$/.test(workflowId) &&
|
|
166
|
+
return (matches(workflowId, /^[A-Za-z0-9-]{1,64}$/) &&
|
|
52
167
|
integer(effectLimit, { minimum: 1, maximum: 100 }) &&
|
|
53
|
-
|
|
54
|
-
capabilities
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
168
|
+
isCapabilities(capabilities) &&
|
|
169
|
+
declaredCommands(declaration, capabilities) &&
|
|
170
|
+
isInput(input) &&
|
|
171
|
+
declaredOptions(declaration, input));
|
|
172
|
+
}
|
|
173
|
+
function declaredOptions(declaration, input) {
|
|
174
|
+
return ((!Object.hasOwn(declaration, "queue") ||
|
|
175
|
+
typeof declaration["queue"] === "boolean") &&
|
|
176
|
+
workflowQueueRefusals(declaration).length === 0 &&
|
|
177
|
+
(!Object.hasOwn(declaration, "stages") ||
|
|
178
|
+
isWorkflowStages(declaration["stages"])) &&
|
|
179
|
+
(!Object.hasOwn(declaration, "handoffs") ||
|
|
180
|
+
isWorkflowNames(declaration["handoffs"])) &&
|
|
181
|
+
(!Object.hasOwn(declaration, "schedule") ||
|
|
182
|
+
checkWorkflowSchedule(input, declaration["schedule"]).kind === "valid"));
|
|
59
183
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface WorkflowReservation {
|
|
2
|
+
readonly baseName?: string;
|
|
3
|
+
readonly workflowId?: string;
|
|
4
|
+
readonly functionName?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface WorkflowDiscoveryIdentity {
|
|
7
|
+
readonly queue?: boolean;
|
|
8
|
+
readonly baseName: string;
|
|
9
|
+
readonly workflowId: string | undefined;
|
|
10
|
+
readonly functionNames: readonly string[];
|
|
11
|
+
}
|
|
12
|
+
export type WorkflowConflictCode = "workflow-conflict" | "bundled-name-reserved" | "queue-workflow-conflict";
|
|
13
|
+
export declare function workflowConflicts(candidates: readonly WorkflowDiscoveryIdentity[], bundled: readonly WorkflowReservation[]): readonly (readonly WorkflowConflictCode[])[];
|
|
14
|
+
export declare const bundledWorkflowIds: {
|
|
15
|
+
readonly ticket: "develop-ticket";
|
|
16
|
+
readonly issue: "develop-issue";
|
|
17
|
+
readonly prompt: "develop-prompt";
|
|
18
|
+
readonly prd: "develop-prd";
|
|
19
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
function identityKeys(identity) {
|
|
2
|
+
return [
|
|
3
|
+
...(identity.baseName === undefined ? [] : [`base:${identity.baseName}`]),
|
|
4
|
+
...(identity.workflowId === undefined ? [] : [`id:${identity.workflowId}`]),
|
|
5
|
+
...identity.functionNames.map((name) => `function:${name}`),
|
|
6
|
+
];
|
|
7
|
+
}
|
|
8
|
+
export function workflowConflicts(candidates, bundled) {
|
|
9
|
+
const keys = candidates.map(identityKeys);
|
|
10
|
+
const counts = new Map();
|
|
11
|
+
for (const names of keys) {
|
|
12
|
+
for (const name of new Set(names))
|
|
13
|
+
counts.set(name, (counts.get(name) ?? 0) + 1);
|
|
14
|
+
}
|
|
15
|
+
const reserved = new Set(bundled.flatMap((entry) => identityKeys({
|
|
16
|
+
...entry,
|
|
17
|
+
functionNames: entry.functionName === undefined ? [] : [entry.functionName],
|
|
18
|
+
})));
|
|
19
|
+
const queued = candidates.filter((candidate) => candidate.queue === true);
|
|
20
|
+
return keys.map((names, index) => {
|
|
21
|
+
const codes = [];
|
|
22
|
+
if (queued.length > 1 && candidates[index]?.queue === true)
|
|
23
|
+
codes.push("queue-workflow-conflict");
|
|
24
|
+
if (names.some((name) => reserved.has(name)))
|
|
25
|
+
codes.push("bundled-name-reserved");
|
|
26
|
+
if (names.some((name) => (counts.get(name) ?? 0) > 1))
|
|
27
|
+
codes.push("workflow-conflict");
|
|
28
|
+
return codes;
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
export const bundledWorkflowIds = {
|
|
32
|
+
ticket: "develop-ticket",
|
|
33
|
+
issue: "develop-issue",
|
|
34
|
+
prompt: "develop-prompt",
|
|
35
|
+
prd: "develop-prd",
|
|
36
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { record } from "./protocol.js";
|
|
2
|
+
const refusalCodes = new Set([
|
|
3
|
+
"invalid-declaration",
|
|
4
|
+
"queue-needs-ticket-field",
|
|
5
|
+
"queue-input-incomplete",
|
|
6
|
+
"queue-workflow-conflict",
|
|
7
|
+
"forbidden-import",
|
|
8
|
+
"missing-export",
|
|
9
|
+
"unsupported-source",
|
|
10
|
+
"dynamic-effect",
|
|
11
|
+
"undeclared-effect",
|
|
12
|
+
"effect-limit",
|
|
13
|
+
"direct-effect",
|
|
14
|
+
"workflow-conflict",
|
|
15
|
+
"bundled-name-reserved",
|
|
16
|
+
"unsafe-workflow-path",
|
|
17
|
+
"workflow-read-failed",
|
|
18
|
+
"workflow-source-changed",
|
|
19
|
+
"compile-failed",
|
|
20
|
+
]);
|
|
21
|
+
function refusal(value) {
|
|
22
|
+
const { scope, label, codes } = record(value) ?? {};
|
|
23
|
+
if ((scope !== "project" && scope !== "user") ||
|
|
24
|
+
typeof label !== "string" ||
|
|
25
|
+
/^(?:[A-Za-z0-9][A-Za-z0-9._-]{0,127}\.ts|file-[a-f0-9]{16}|workflows\/)$/u.exec(label)?.[0] !== label ||
|
|
26
|
+
!Array.isArray(codes) ||
|
|
27
|
+
codes.length === 0)
|
|
28
|
+
return [];
|
|
29
|
+
const known = codes.filter((code) => typeof code === "string" && refusalCodes.has(code));
|
|
30
|
+
if (known.length !== codes.length)
|
|
31
|
+
return [];
|
|
32
|
+
return [{ scope, label, codes: [...new Set(known)].sort() }];
|
|
33
|
+
}
|
|
34
|
+
export function workflowRefusals(value) {
|
|
35
|
+
if (!Array.isArray(value))
|
|
36
|
+
return [];
|
|
37
|
+
return value.flatMap(refusal).sort((left, right) => {
|
|
38
|
+
const a = `${left.scope}\0${left.label}`;
|
|
39
|
+
const b = `${right.scope}\0${right.label}`;
|
|
40
|
+
return a < b ? -1 : Number(a > b);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type Fields } from "./protocol.ts";
|
|
2
|
+
import { type SubmissionContract } from "./submission.ts";
|
|
3
|
+
export interface WorkflowSchedule {
|
|
4
|
+
readonly everySeconds: number;
|
|
5
|
+
readonly input: Fields;
|
|
6
|
+
}
|
|
7
|
+
export type ScheduleCheck = {
|
|
8
|
+
readonly kind: "valid";
|
|
9
|
+
readonly schedule: WorkflowSchedule;
|
|
10
|
+
} | {
|
|
11
|
+
readonly kind: "rejected";
|
|
12
|
+
readonly code: string;
|
|
13
|
+
};
|
|
14
|
+
interface ScheduleSource {
|
|
15
|
+
readonly workflowId: string;
|
|
16
|
+
readonly input: SubmissionContract;
|
|
17
|
+
readonly schedule?: WorkflowSchedule;
|
|
18
|
+
}
|
|
19
|
+
export declare function parseSchedulesSetting(value: string | undefined): unknown;
|
|
20
|
+
export declare function configuredSchedules(declarations: readonly ScheduleSource[], overrides: unknown): Readonly<Record<string, WorkflowSchedule>>;
|
|
21
|
+
export declare function checkWorkflowSchedule(contract: SubmissionContract, value: unknown): ScheduleCheck;
|
|
22
|
+
export {};
|