cloving 0.3.19 → 1.0.1
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/{LICENSE.md → LICENSE} +1 -1
- package/README.md +475 -182
- package/dist/src/authority/budgets.d.ts +12 -0
- package/dist/src/authority/budgets.js +42 -0
- package/dist/src/authority/commands.d.ts +7 -0
- package/dist/src/authority/commands.js +263 -0
- package/dist/src/authority/details.d.ts +28 -0
- package/dist/src/authority/details.js +33 -0
- package/dist/src/authority/dispatch-decision.d.ts +40 -0
- package/dist/src/authority/dispatch-decision.js +47 -0
- package/dist/src/authority/effect-requests.d.ts +2 -0
- package/dist/src/authority/effect-requests.js +139 -0
- package/dist/src/authority/effect-results.d.ts +4 -0
- package/dist/src/authority/effect-results.js +236 -0
- package/dist/src/authority/events.d.ts +2 -0
- package/dist/src/authority/events.js +45 -0
- package/dist/src/authority/gate-reduction.d.ts +8 -0
- package/dist/src/authority/gate-reduction.js +109 -0
- package/dist/src/authority/gates.d.ts +48 -0
- package/dist/src/authority/gates.js +77 -0
- package/dist/src/authority/history-state.d.ts +15 -0
- package/dist/src/authority/history-state.js +61 -0
- package/dist/src/authority/history.d.ts +13 -0
- package/dist/src/authority/history.js +37 -0
- package/dist/src/authority/instants.d.ts +3 -0
- package/dist/src/authority/instants.js +38 -0
- package/dist/src/authority/leases.d.ts +15 -0
- package/dist/src/authority/leases.js +113 -0
- package/dist/src/authority/operations.d.ts +101 -0
- package/dist/src/authority/operations.js +75 -0
- package/dist/src/authority/reconciliation.d.ts +27 -0
- package/dist/src/authority/reconciliation.js +147 -0
- package/dist/src/authority/reducer.d.ts +41 -0
- package/dist/src/authority/reducer.js +139 -0
- package/dist/src/authority/reduction-state.d.ts +36 -0
- package/dist/src/authority/reduction-state.js +68 -0
- package/dist/src/authority/reduction.d.ts +6 -0
- package/dist/src/authority/reduction.js +160 -0
- package/dist/src/authority/status-closure.d.ts +4 -0
- package/dist/src/authority/status-closure.js +57 -0
- package/dist/src/authority/status-effects.d.ts +17 -0
- package/dist/src/authority/status-effects.js +43 -0
- package/dist/src/authority/status-input.d.ts +45 -0
- package/dist/src/authority/status-input.js +9 -0
- package/dist/src/authority/status.d.ts +32 -0
- package/dist/src/authority/status.js +256 -0
- package/dist/src/authority/stop-sequence.d.ts +37 -0
- package/dist/src/authority/stop-sequence.js +91 -0
- package/dist/src/authority/transitions.d.ts +63 -0
- package/dist/src/authority/transitions.js +122 -0
- package/dist/src/broker/actor/adapter-calls.d.ts +13 -0
- package/dist/src/broker/actor/adapter-calls.js +34 -0
- package/dist/src/broker/actor/adapter-outcomes.d.ts +28 -0
- package/dist/src/broker/actor/adapter-outcomes.js +80 -0
- package/dist/src/broker/actor/authority-actor.d.ts +25 -0
- package/dist/src/broker/actor/authority-actor.js +169 -0
- package/dist/src/broker/actor/authority-changes.d.ts +31 -0
- package/dist/src/broker/actor/authority-changes.js +46 -0
- package/dist/src/broker/actor/authority-connection.d.ts +15 -0
- package/dist/src/broker/actor/authority-connection.js +44 -0
- package/dist/src/broker/actor/authority-conversion.d.ts +10 -0
- package/dist/src/broker/actor/authority-conversion.js +72 -0
- package/dist/src/broker/actor/authority-delivery.d.ts +13 -0
- package/dist/src/broker/actor/authority-delivery.js +162 -0
- package/dist/src/broker/actor/authority-logger.d.ts +2 -0
- package/dist/src/broker/actor/authority-logger.js +19 -0
- package/dist/src/broker/actor/authority-policy.d.ts +9 -0
- package/dist/src/broker/actor/authority-policy.js +11 -0
- package/dist/src/broker/actor/authority-queries.d.ts +45 -0
- package/dist/src/broker/actor/authority-queries.js +85 -0
- package/dist/src/broker/actor/authority-receipts.d.ts +28 -0
- package/dist/src/broker/actor/authority-receipts.js +84 -0
- package/dist/src/broker/actor/authority-release.d.ts +13 -0
- package/dist/src/broker/actor/authority-release.js +69 -0
- package/dist/src/broker/actor/authority-runtime.d.ts +60 -0
- package/dist/src/broker/actor/authority-runtime.js +204 -0
- package/dist/src/broker/actor/authority-session.d.ts +65 -0
- package/dist/src/broker/actor/authority-session.js +252 -0
- package/dist/src/broker/actor/authority-settings.d.ts +33 -0
- package/dist/src/broker/actor/authority-settings.js +63 -0
- package/dist/src/broker/actor/authority-upgrades.d.ts +16 -0
- package/dist/src/broker/actor/authority-upgrades.js +12 -0
- package/dist/src/broker/actor/authority-watchdog.d.ts +14 -0
- package/dist/src/broker/actor/authority-watchdog.js +41 -0
- package/dist/src/broker/actor/authority.d.ts +14 -0
- package/dist/src/broker/actor/authority.js +115 -0
- package/dist/src/broker/actor/delivery-intents.d.ts +68 -0
- package/dist/src/broker/actor/delivery-intents.js +77 -0
- package/dist/src/broker/actor/delivery-plan.d.ts +2 -0
- package/dist/src/broker/actor/delivery-plan.js +109 -0
- package/dist/src/broker/actor/delivery-results.d.ts +11 -0
- package/dist/src/broker/actor/delivery-results.js +63 -0
- package/dist/src/broker/actor/effect-delivery.d.ts +19 -0
- package/dist/src/broker/actor/effect-delivery.js +118 -0
- package/dist/src/broker/actor/effect-plan.d.ts +41 -0
- package/dist/src/broker/actor/effect-plan.js +173 -0
- package/dist/src/broker/actor/effect-queries.d.ts +27 -0
- package/dist/src/broker/actor/effect-queries.js +80 -0
- package/dist/src/broker/actor/effect-turn.d.ts +25 -0
- package/dist/src/broker/actor/effect-turn.js +84 -0
- package/dist/src/broker/actor/pin-check.d.ts +6 -0
- package/dist/src/broker/actor/pin-check.js +12 -0
- package/dist/src/broker/actor/runtime-parts.d.ts +23 -0
- package/dist/src/broker/actor/runtime-parts.js +34 -0
- package/dist/src/broker/actor/stop-plan.d.ts +20 -0
- package/dist/src/broker/actor/stop-plan.js +46 -0
- package/dist/src/broker/actor/stop-turn.d.ts +17 -0
- package/dist/src/broker/actor/stop-turn.js +42 -0
- package/dist/src/broker/actor/turn-draft.d.ts +31 -0
- package/dist/src/broker/actor/turn-draft.js +138 -0
- package/dist/src/broker/actor/turn-plan.d.ts +17 -0
- package/dist/src/broker/actor/turn-plan.js +136 -0
- package/dist/src/broker/actor/turn-refusals.d.ts +8 -0
- package/dist/src/broker/actor/turn-refusals.js +35 -0
- package/dist/src/broker/actor/turn-staging.d.ts +78 -0
- package/dist/src/broker/actor/turn-staging.js +34 -0
- package/dist/src/broker/actor/turn-state.d.ts +34 -0
- package/dist/src/broker/actor/turn-state.js +208 -0
- package/dist/src/broker/authority-admission.d.ts +21 -0
- package/dist/src/broker/authority-admission.js +70 -0
- package/dist/src/broker/authority-restore.d.ts +30 -0
- package/dist/src/broker/authority-restore.js +165 -0
- package/dist/src/broker/decision-restore.d.ts +16 -0
- package/dist/src/broker/decision-restore.js +158 -0
- package/dist/src/broker/decision-upgrade.d.ts +3 -0
- package/dist/src/broker/decision-upgrade.js +12 -0
- package/dist/src/broker/effect-restore.d.ts +20 -0
- package/dist/src/broker/effect-restore.js +111 -0
- package/dist/src/broker/effect-upgrade.d.ts +3 -0
- package/dist/src/broker/effect-upgrade.js +9 -0
- package/dist/src/broker/operation-digest.d.ts +1 -0
- package/dist/src/broker/operation-digest.js +4 -0
- package/dist/src/broker/socket-address.d.ts +9 -0
- package/dist/src/broker/socket-address.js +14 -0
- package/dist/src/broker/workflow-pin.d.ts +2 -0
- package/dist/src/broker/workflow-pin.js +5 -0
- package/dist/src/chats/destination.d.ts +4 -0
- package/dist/src/chats/destination.js +94 -0
- package/dist/src/chats/import.d.ts +13 -0
- package/dist/src/chats/import.js +71 -0
- package/dist/src/chats/normalize.d.ts +20 -0
- package/dist/src/chats/normalize.js +139 -0
- package/dist/src/chats/reader.d.ts +15 -0
- package/dist/src/chats/reader.js +87 -0
- package/dist/src/cli/arguments.d.ts +23 -0
- package/dist/src/cli/arguments.js +154 -0
- package/dist/src/cli/client.d.ts +15 -0
- package/dist/src/cli/client.js +122 -0
- package/dist/src/cli/commands.d.ts +14 -0
- package/dist/src/cli/commands.js +253 -0
- package/dist/src/cli/main.d.ts +1 -0
- package/dist/src/cli/main.js +80 -0
- package/dist/src/cli/render.d.ts +8 -0
- package/dist/src/cli/render.js +186 -0
- package/dist/src/cli/runtime-arguments.d.ts +73 -0
- package/dist/src/cli/runtime-arguments.js +248 -0
- package/dist/src/cli/runtime-directory.d.ts +4 -0
- package/dist/src/cli/runtime-directory.js +25 -0
- package/dist/src/cli/toolchain.d.ts +3 -0
- package/dist/src/cli/toolchain.js +74 -0
- package/dist/src/cli/usage.d.ts +4 -0
- package/dist/src/cli/usage.js +124 -0
- package/dist/src/cli/validate.d.ts +38 -0
- package/dist/src/cli/validate.js +116 -0
- package/dist/src/cli/watch-board-view.d.ts +22 -0
- package/dist/src/cli/watch-board-view.js +128 -0
- package/dist/src/cli/watch-board.d.ts +15 -0
- package/dist/src/cli/watch-board.js +174 -0
- package/dist/src/cli/watch-element.d.ts +11 -0
- package/dist/src/cli/watch-element.js +6 -0
- package/dist/src/cli/watch-model.d.ts +29 -0
- package/dist/src/cli/watch-model.js +261 -0
- package/dist/src/cli/watch-navigation.d.ts +9 -0
- package/dist/src/cli/watch-navigation.js +40 -0
- package/dist/src/cli/watch-page.d.ts +1 -0
- package/dist/src/cli/watch-page.js +272 -0
- package/dist/src/cli/watch-paths.d.ts +2 -0
- package/dist/src/cli/watch-paths.js +52 -0
- package/dist/src/cli/watch-phases.d.ts +7 -0
- package/dist/src/cli/watch-phases.js +148 -0
- package/dist/src/cli/watch-reads.d.ts +28 -0
- package/dist/src/cli/watch-reads.js +244 -0
- package/dist/src/cli/watch-render.d.ts +139 -0
- package/dist/src/cli/watch-render.js +95 -0
- package/dist/src/cli/watch-server.d.ts +10 -0
- package/dist/src/cli/watch-server.js +176 -0
- package/dist/src/cli/watch-stream.d.ts +11 -0
- package/dist/src/cli/watch-stream.js +128 -0
- package/dist/src/cli/watch-turn.d.ts +29 -0
- package/dist/src/cli/watch-turn.js +130 -0
- package/dist/src/cli/watch-view.d.ts +39 -0
- package/dist/src/cli/watch-view.js +223 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +62 -0
- package/dist/src/daemon/claude-turn.d.ts +28 -0
- package/dist/src/daemon/claude-turn.js +135 -0
- package/dist/src/daemon/claude-worker.d.ts +26 -0
- package/dist/src/daemon/claude-worker.js +224 -0
- package/dist/src/daemon/codex-stream.d.ts +4 -0
- package/dist/src/daemon/codex-stream.js +113 -0
- package/dist/src/daemon/daemon.d.ts +46 -0
- package/dist/src/daemon/daemon.js +186 -0
- package/dist/src/daemon/delivery-router.d.ts +10 -0
- package/dist/src/daemon/delivery-router.js +34 -0
- package/dist/src/daemon/github-calls.d.ts +29 -0
- package/dist/src/daemon/github-calls.js +127 -0
- package/dist/src/daemon/github-issue-methods.d.ts +3 -0
- package/dist/src/daemon/github-issue-methods.js +99 -0
- package/dist/src/daemon/github-issue-privacy.d.ts +6 -0
- package/dist/src/daemon/github-issue-privacy.js +131 -0
- package/dist/src/daemon/github-merge.d.ts +18 -0
- package/dist/src/daemon/github-merge.js +259 -0
- package/dist/src/daemon/github-methods.d.ts +5 -0
- package/dist/src/daemon/github-methods.js +198 -0
- package/dist/src/daemon/github-operation.d.ts +38 -0
- package/dist/src/daemon/github-operation.js +57 -0
- package/dist/src/daemon/github-worker.d.ts +17 -0
- package/dist/src/daemon/github-worker.js +281 -0
- package/dist/src/daemon/host-environment.d.ts +8 -0
- package/dist/src/daemon/host-environment.js +14 -0
- package/dist/src/daemon/issue-queue.d.ts +9 -0
- package/dist/src/daemon/issue-queue.js +163 -0
- package/dist/src/daemon/notify-message.d.ts +14 -0
- package/dist/src/daemon/notify-message.js +48 -0
- package/dist/src/daemon/notify.d.ts +12 -0
- package/dist/src/daemon/notify.js +161 -0
- package/dist/src/daemon/operation-journal.d.ts +42 -0
- package/dist/src/daemon/operation-journal.js +53 -0
- package/dist/src/daemon/ticket-registration.d.ts +33 -0
- package/dist/src/daemon/ticket-registration.js +177 -0
- package/dist/src/daemon/ticket-source.d.ts +17 -0
- package/dist/src/daemon/ticket-source.js +36 -0
- package/dist/src/daemon/work-tree.d.ts +26 -0
- package/dist/src/daemon/work-tree.js +206 -0
- package/dist/src/effect-authorization.d.ts +21 -0
- package/dist/src/effect-authorization.js +14 -0
- package/dist/src/execution-pin.d.ts +4 -0
- package/dist/src/execution-pin.js +68 -0
- package/dist/src/host/start-delivery.d.ts +41 -0
- package/dist/src/host/start-delivery.js +68 -0
- package/dist/src/host/step-bridge-host.d.ts +79 -0
- package/dist/src/host/step-bridge-host.js +205 -0
- package/dist/src/host/step-claims.d.ts +31 -0
- package/dist/src/host/step-claims.js +85 -0
- package/dist/src/host/world-host.d.ts +21 -0
- package/dist/src/host/world-host.js +51 -0
- package/dist/src/host/world-reconciliation.d.ts +37 -0
- package/dist/src/host/world-reconciliation.js +75 -0
- package/dist/src/host/world-runs.d.ts +14 -0
- package/dist/src/host/world-runs.js +61 -0
- package/dist/src/operation-identity.d.ts +7 -0
- package/dist/src/operation-identity.js +59 -0
- package/dist/src/protocol.d.ts +35 -0
- package/dist/src/protocol.js +64 -0
- package/dist/src/resource-files.d.ts +1 -0
- package/dist/src/resource-files.js +29 -0
- package/dist/src/service/changes.d.ts +11 -0
- package/dist/src/service/changes.js +32 -0
- package/dist/src/service/decision-handler.d.ts +9 -0
- package/dist/src/service/decision-handler.js +233 -0
- package/dist/src/service/event-handler.d.ts +10 -0
- package/dist/src/service/event-handler.js +70 -0
- package/dist/src/service/expiry.d.ts +13 -0
- package/dist/src/service/expiry.js +53 -0
- package/dist/src/service/gateway.d.ts +21 -0
- package/dist/src/service/gateway.js +120 -0
- package/dist/src/service/registry.d.ts +40 -0
- package/dist/src/service/registry.js +13 -0
- package/dist/src/service/replies.d.ts +26 -0
- package/dist/src/service/replies.js +56 -0
- package/dist/src/service/run-handlers.d.ts +4 -0
- package/dist/src/service/run-handlers.js +271 -0
- package/dist/src/service/service.d.ts +58 -0
- package/dist/src/service/service.js +212 -0
- package/dist/src/service/submission-handler.d.ts +4 -0
- package/dist/src/service/submission-handler.js +206 -0
- package/dist/src/service/transport.d.ts +16 -0
- package/dist/src/service/transport.js +141 -0
- package/dist/src/service/worker-port.d.ts +85 -0
- package/dist/src/service/worker-port.js +126 -0
- package/dist/src/step-bridge.d.ts +57 -0
- package/dist/src/step-bridge.js +4 -0
- package/dist/src/steps/decision-gate.d.ts +2 -0
- package/dist/src/steps/decision-gate.js +8 -0
- package/dist/src/steps/load-cycle.d.ts +10 -0
- package/dist/src/steps/load-cycle.js +11 -0
- package/dist/src/steps/protected-effect.d.ts +2 -0
- package/dist/src/steps/protected-effect.js +8 -0
- package/dist/src/storage/decision-rows.d.ts +54 -0
- package/dist/src/storage/decision-rows.js +72 -0
- package/dist/src/storage/decision-snapshots.d.ts +17 -0
- package/dist/src/storage/decision-snapshots.js +25 -0
- package/dist/src/storage/domain-changes.d.ts +48 -0
- package/dist/src/storage/domain-changes.js +213 -0
- package/dist/src/storage/domain-rows.d.ts +85 -0
- package/dist/src/storage/domain-rows.js +129 -0
- package/dist/src/storage/domain-schema.d.ts +32 -0
- package/dist/src/storage/domain-schema.js +193 -0
- package/dist/src/storage/effect-changes.d.ts +5 -0
- package/dist/src/storage/effect-changes.js +105 -0
- package/dist/src/storage/effect-rows.d.ts +67 -0
- package/dist/src/storage/effect-rows.js +74 -0
- package/dist/src/storage/effect-schema.d.ts +1 -0
- package/dist/src/storage/effect-schema.js +59 -0
- package/dist/src/storage/statements.d.ts +9 -0
- package/dist/src/storage/statements.js +8 -0
- package/dist/src/submission.d.ts +42 -0
- package/dist/src/submission.js +71 -0
- package/dist/src/turn-profile.d.ts +13 -0
- package/dist/src/turn-profile.js +100 -0
- package/dist/src/workflow-admission.d.ts +45 -0
- package/dist/src/workflow-admission.js +151 -0
- package/dist/src/workflow-contracts.d.ts +27 -0
- package/dist/src/workflow-contracts.js +88 -0
- package/dist/src/workflow-declaration.d.ts +11 -0
- package/dist/src/workflow-declaration.js +57 -0
- package/dist/src/workflow-resources.d.ts +8 -0
- package/dist/src/workflow-resources.js +14 -0
- package/dist/src/workflows.d.ts +5 -0
- package/dist/src/workflows.js +3 -0
- package/dist/tools/compile-workflows.d.ts +1 -0
- package/dist/tools/compile-workflows.js +33 -0
- package/dist/tools/self-host-processes.d.ts +10 -0
- package/dist/tools/self-host-processes.js +151 -0
- package/dist/tools/self-host-workflows.d.ts +15 -0
- package/dist/tools/self-host-workflows.js +78 -0
- package/dist/tools/self-host.d.ts +1 -0
- package/dist/tools/self-host.js +261 -0
- package/dist/tools/self-update-host.d.ts +6 -0
- package/dist/tools/self-update-host.js +41 -0
- package/dist/tools/self-update.d.ts +10 -0
- package/dist/tools/self-update.js +105 -0
- package/dist/tools/workflow-manifest.d.ts +3 -0
- package/dist/tools/workflow-manifest.js +34 -0
- package/dist/workflows/develop-prd.d.ts +7 -0
- package/dist/workflows/develop-prd.js +97 -0
- package/dist/workflows/develop-ticket.d.ts +15 -0
- package/dist/workflows/develop-ticket.js +301 -0
- package/dist/workflows/issue-labels.d.ts +14 -0
- package/dist/workflows/issue-labels.js +36 -0
- package/package.json +82 -75
- package/.DS_Store +0 -0
- package/.aider.chat.history.md +0 -16978
- package/.aider.input.history +0 -15
- package/.aider.tags.cache.v3/cache.db +0 -0
- package/.aider.tags.cache.v3/cache.db-shm +0 -0
- package/.aider.tags.cache.v3/cache.db-wal +0 -0
- package/.cursorrules +0 -77
- package/.github/workflows/auto-release.yml +0 -83
- package/.github/workflows/ci.yml +0 -32
- package/.github/workflows/npm-publish.yml +0 -34
- package/.gitignore +0 -67
- package/.husky/_/.gitignore +0 -1
- package/.husky/_/applypatch-msg +0 -2
- package/.husky/_/commit-msg +0 -2
- package/.husky/_/h +0 -22
- package/.husky/_/husky.sh +0 -9
- package/.husky/_/post-applypatch +0 -2
- package/.husky/_/post-checkout +0 -2
- package/.husky/_/post-commit +0 -2
- package/.husky/_/post-merge +0 -2
- package/.husky/_/post-rewrite +0 -2
- package/.husky/_/pre-applypatch +0 -2
- package/.husky/_/pre-auto-gc +0 -2
- package/.husky/_/pre-commit +0 -2
- package/.husky/_/pre-merge-commit +0 -2
- package/.husky/_/pre-push +0 -2
- package/.husky/_/pre-rebase +0 -2
- package/.husky/_/prepare-commit-msg +0 -2
- package/.husky/pre-commit +0 -1
- package/.husky/pre-push +0 -1
- package/.prettierrc.json +0 -7
- package/.tool-versions +0 -2
- package/SECURITY.md +0 -15
- package/cloving.json +0 -67
- package/dist/abstract_gpt/index.js +0 -55
- package/dist/cloving_gpt/adapters/Adapter.js +0 -2
- package/dist/cloving_gpt/adapters/azureopenai.js +0 -69
- package/dist/cloving_gpt/adapters/claude.js +0 -128
- package/dist/cloving_gpt/adapters/gemini.js +0 -135
- package/dist/cloving_gpt/adapters/gpt4all.js +0 -29
- package/dist/cloving_gpt/adapters/index.js +0 -2
- package/dist/cloving_gpt/adapters/mistral.js +0 -128
- package/dist/cloving_gpt/adapters/ollama.js +0 -128
- package/dist/cloving_gpt/adapters/openai.js +0 -100
- package/dist/cloving_gpt/index.js +0 -192
- package/dist/commands/analyze.js +0 -47
- package/dist/commands/chat.js +0 -14
- package/dist/commands/check.js +0 -7
- package/dist/commands/commit.js +0 -44
- package/dist/commands/config.js +0 -167
- package/dist/commands/describe.js +0 -235
- package/dist/commands/generate/code.js +0 -21
- package/dist/commands/generate/commit.js +0 -11
- package/dist/commands/generate/context.js +0 -82
- package/dist/commands/generate/docs.js +0 -11
- package/dist/commands/generate/documentation.js +0 -11
- package/dist/commands/generate/fizzbuzz.js +0 -35
- package/dist/commands/generate/init.js +0 -15
- package/dist/commands/generate/review.js +0 -11
- package/dist/commands/generate/sh.js +0 -95
- package/dist/commands/generate/shell.js +0 -11
- package/dist/commands/generate/unit_tests.js +0 -11
- package/dist/commands/init.js +0 -13
- package/dist/commands/models.js +0 -22
- package/dist/commands/project/build.js +0 -88
- package/dist/commands/project/complete.js +0 -12
- package/dist/commands/project/init.js +0 -82
- package/dist/commands/project/plan.js +0 -108
- package/dist/commands/proxy.js +0 -11
- package/dist/commands/review.js +0 -50
- package/dist/commands/tokens.js +0 -75
- package/dist/commands/unit_tests.js +0 -150
- package/dist/commands/update.js +0 -7
- package/dist/file2.js +0 -4
- package/dist/index.js +0 -134
- package/dist/managers/BlockManager.js +0 -120
- package/dist/managers/ChatManager.js +0 -653
- package/dist/managers/ChunkManager.js +0 -32
- package/dist/managers/CodeManager.js +0 -185
- package/dist/managers/CommitManager.js +0 -64
- package/dist/managers/DocsManager.js +0 -88
- package/dist/managers/DocumentationManager.js +0 -114
- package/dist/managers/InitManager.js +0 -230
- package/dist/managers/ProxyManager.js +0 -210
- package/dist/managers/ReviewManager.js +0 -131
- package/dist/managers/ShellManager.js +0 -163
- package/dist/managers/StreamManager.js +0 -308
- package/dist/managers/UnitTestManager.js +0 -243
- package/dist/managers/src/managers/ProxyManager.js +0 -1
- package/dist/newfile.js +0 -2
- package/dist/package.json +0 -86
- package/dist/utils/command_utils.js +0 -384
- package/dist/utils/config_utils.js +0 -249
- package/dist/utils/gitUtils.js +0 -42
- package/dist/utils/git_utils.js +0 -217
- package/dist/utils/modelUtils.js +0 -7
- package/dist/utils/model_utils.js +0 -7
- package/dist/utils/prompt_utils.js +0 -333
- package/dist/utils/prompts/CODEGEN_COULDNT_APPLY.md +0 -5
- package/dist/utils/prompts/CODEGEN_EXAMPLES.md +0 -82
- package/dist/utils/prompts/CODEGEN_INSTRUCTIONS.md +0 -43
- package/dist/utils/prompts/DOCS_INSTRUCTIONS.md +0 -9
- package/dist/utils/prompts/INIT_INSTRUCTIONS.md +0 -132
- package/dist/utils/prompts/REVIEW_INSTRUCTIONS.md +0 -49
- package/dist/utils/prompts/SHELL_INSTRUCTIONS.md +0 -15
- package/dist/utils/prompts/SPECIAL_FILES.md +0 -66
- package/dist/utils/prompts/index.js +0 -27
- package/dist/utils/string_utils.js +0 -505
- package/dist/utils/types.js +0 -2
- package/jest.config.js +0 -11
- package/src/cloving_gpt/adapters/azureopenai.ts +0 -83
- package/src/cloving_gpt/adapters/claude.ts +0 -140
- package/src/cloving_gpt/adapters/gemini.ts +0 -146
- package/src/cloving_gpt/adapters/index.ts +0 -43
- package/src/cloving_gpt/adapters/mistral.ts +0 -142
- package/src/cloving_gpt/adapters/ollama.ts +0 -136
- package/src/cloving_gpt/adapters/openai.ts +0 -113
- package/src/cloving_gpt/index.ts +0 -229
- package/src/commands/chat.ts +0 -12
- package/src/commands/config.ts +0 -192
- package/src/commands/generate/code.ts +0 -18
- package/src/commands/generate/commit.ts +0 -9
- package/src/commands/generate/context.ts +0 -93
- package/src/commands/generate/docs.ts +0 -9
- package/src/commands/generate/review.ts +0 -9
- package/src/commands/generate/shell.ts +0 -9
- package/src/commands/generate/unit_tests.ts +0 -9
- package/src/commands/init.ts +0 -9
- package/src/commands/models.ts +0 -21
- package/src/commands/proxy.ts +0 -9
- package/src/commands/tokens.ts +0 -82
- package/src/index.ts +0 -197
- package/src/managers/BlockManager.ts +0 -126
- package/src/managers/ChatManager.ts +0 -755
- package/src/managers/ChunkManager.ts +0 -31
- package/src/managers/CodeManager.ts +0 -226
- package/src/managers/CommitManager.ts +0 -71
- package/src/managers/DocsManager.ts +0 -101
- package/src/managers/InitManager.ts +0 -263
- package/src/managers/ProxyManager.ts +0 -240
- package/src/managers/ReviewManager.ts +0 -154
- package/src/managers/ShellManager.ts +0 -172
- package/src/managers/StreamManager.ts +0 -353
- package/src/managers/UnitTestManager.ts +0 -293
- package/src/utils/config_utils.ts +0 -271
- package/src/utils/git_utils.ts +0 -230
- package/src/utils/model_utils.ts +0 -3
- package/src/utils/prompt_utils.ts +0 -375
- package/src/utils/prompts/CODEGEN_COULDNT_APPLY.md +0 -5
- package/src/utils/prompts/CODEGEN_EXAMPLES.md +0 -82
- package/src/utils/prompts/CODEGEN_INSTRUCTIONS.md +0 -43
- package/src/utils/prompts/DOCS_INSTRUCTIONS.md +0 -9
- package/src/utils/prompts/INIT_INSTRUCTIONS.md +0 -132
- package/src/utils/prompts/REVIEW_INSTRUCTIONS.md +0 -49
- package/src/utils/prompts/SHELL_INSTRUCTIONS.md +0 -15
- package/src/utils/prompts/SPECIAL_FILES.md +0 -66
- package/src/utils/prompts/index.ts +0 -37
- package/src/utils/string_utils.ts +0 -552
- package/src/utils/types.ts +0 -127
- package/tests/commands/generate/unit_tests.test.ts +0 -27
- package/tests/utils/git_utils.test.ts +0 -116
- package/tests/utils/model_utils.test.ts +0 -27
- package/tests/utils/prompt_utils.test.ts +0 -33
- package/tests/utils/string_utils.test.ts +0 -560
- package/tsconfig.json +0 -14
- package/yarn.lock +0 -5823
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { admitCompiled } from "../cli/validate.js";
|
|
3
|
+
import { ticketCommandText, ticketText } from "./ticket-source.js";
|
|
4
|
+
export const ticketWorkflow = "develop-ticket";
|
|
5
|
+
export const promptWorkflow = "develop-prompt";
|
|
6
|
+
export const issueWorkflow = "develop-issue";
|
|
7
|
+
export const ticketCapabilities = ["claude", "github"];
|
|
8
|
+
const ticketIdentifier = /^[A-Za-z0-9._:-]{1,64}$/;
|
|
9
|
+
function rejected(code, detail) {
|
|
10
|
+
return { kind: "rejected", code, detail };
|
|
11
|
+
}
|
|
12
|
+
function digest(commandId) {
|
|
13
|
+
return createHash("sha256").update(commandId).digest("hex");
|
|
14
|
+
}
|
|
15
|
+
async function ticket(source, request) {
|
|
16
|
+
const { command, repository } = source;
|
|
17
|
+
const ticketId = String(request.submission["ticket"]);
|
|
18
|
+
if (ticketId === "next")
|
|
19
|
+
return nextTicket(source, request);
|
|
20
|
+
if (!ticketIdentifier.test(ticketId))
|
|
21
|
+
return rejected("invalid-ticket-id", "A ticket ID has letters, digits and the characters . _ : - only.");
|
|
22
|
+
if (command === undefined)
|
|
23
|
+
return rejected("ticket-source-not-configured", "The daemon has no ticket command. Set CLOVING_TICKET_COMMAND, or use the workflow develop-prompt.");
|
|
24
|
+
const read = await ticketText(command, { ticketId, signal: request.signal });
|
|
25
|
+
if (read.kind === "failed")
|
|
26
|
+
return rejected("ticket-not-available", read.detail);
|
|
27
|
+
const name = ticketId.toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
28
|
+
return {
|
|
29
|
+
kind: "resolved",
|
|
30
|
+
input: {
|
|
31
|
+
cycleId: `${name}-${digest(request.commandId).slice(0, 8)}`,
|
|
32
|
+
ticketId,
|
|
33
|
+
ticket: read.text,
|
|
34
|
+
repository,
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
async function nextTicket(source, request) {
|
|
39
|
+
if (source.nextCommand === undefined)
|
|
40
|
+
return rejected("next-source-not-configured", "The daemon has no next-ticket command. Set CLOVING_NEXT_COMMAND.");
|
|
41
|
+
const selected = await ticketCommandText(source.nextCommand, request.signal);
|
|
42
|
+
if (selected.kind === "failed")
|
|
43
|
+
return rejected("next-ticket-not-available", selected.detail);
|
|
44
|
+
if (selected.text === "")
|
|
45
|
+
return rejected("no-ready-ticket", "The next-ticket command printed no ticket ID.");
|
|
46
|
+
if (!ticketIdentifier.test(selected.text) || selected.text === "next")
|
|
47
|
+
return rejected("invalid-ticket-id", "The next-ticket command must print one valid ticket ID other than next.");
|
|
48
|
+
return ticket(source, { ...request, submission: { ticket: selected.text } });
|
|
49
|
+
}
|
|
50
|
+
export function ticketResolver(source) {
|
|
51
|
+
return {
|
|
52
|
+
id: "ticket-command",
|
|
53
|
+
version: "1",
|
|
54
|
+
resolve: (request) => ticket(source, request),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export function issueResolver(source) {
|
|
58
|
+
return {
|
|
59
|
+
id: "issue-command",
|
|
60
|
+
version: "1",
|
|
61
|
+
resolve: async (request) => {
|
|
62
|
+
const resolution = await ticket(source, request);
|
|
63
|
+
if (resolution.kind === "rejected")
|
|
64
|
+
return resolution;
|
|
65
|
+
return {
|
|
66
|
+
kind: "resolved",
|
|
67
|
+
input: { ...Object(resolution.input), delivery: "pull-request" },
|
|
68
|
+
};
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export function promptResolver(repository) {
|
|
73
|
+
return {
|
|
74
|
+
id: "ticket-prompt",
|
|
75
|
+
version: "1",
|
|
76
|
+
resolve: (request) => Promise.resolve({
|
|
77
|
+
kind: "resolved",
|
|
78
|
+
input: {
|
|
79
|
+
cycleId: `task-${digest(request.commandId).slice(0, 12)}`,
|
|
80
|
+
ticket: String(request.submission["prompt"]),
|
|
81
|
+
repository,
|
|
82
|
+
},
|
|
83
|
+
}),
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
export function ticketRegistrationTable(source, declarations = []) {
|
|
87
|
+
return [
|
|
88
|
+
{
|
|
89
|
+
workflowId: ticketWorkflow,
|
|
90
|
+
functionName: "developTicket",
|
|
91
|
+
effectLimit: 8,
|
|
92
|
+
submission: { maximumBytes: 4_096, fields: { ticket: "string" } },
|
|
93
|
+
resolver: ticketResolver(source),
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
workflowId: issueWorkflow,
|
|
97
|
+
functionName: "developTicket",
|
|
98
|
+
effectLimit: 20,
|
|
99
|
+
submission: { maximumBytes: 4_096, fields: { ticket: "string" } },
|
|
100
|
+
resolver: issueResolver(source),
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
workflowId: "develop-prd",
|
|
104
|
+
functionName: "developPrd",
|
|
105
|
+
effectLimit: 8,
|
|
106
|
+
submission: { maximumBytes: 65_536, fields: { prompt: "string" } },
|
|
107
|
+
resolver: promptResolver(source.repository),
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
workflowId: promptWorkflow,
|
|
111
|
+
functionName: "developTicket",
|
|
112
|
+
effectLimit: 8,
|
|
113
|
+
submission: { maximumBytes: 65_536, fields: { prompt: "string" } },
|
|
114
|
+
resolver: promptResolver(source.repository),
|
|
115
|
+
},
|
|
116
|
+
...declarations.map((declaration) => ({
|
|
117
|
+
workflowId: declaration.workflowId,
|
|
118
|
+
functionName: declaration.functionName,
|
|
119
|
+
effectLimit: declaration.effectLimit,
|
|
120
|
+
capabilities: declaration.capabilities,
|
|
121
|
+
submission: declaration.input,
|
|
122
|
+
resolver: declaredResolver(source.repository),
|
|
123
|
+
})),
|
|
124
|
+
];
|
|
125
|
+
}
|
|
126
|
+
function declaredResolver(repository) {
|
|
127
|
+
return {
|
|
128
|
+
id: "declared-input",
|
|
129
|
+
version: "1",
|
|
130
|
+
resolve: (request) => Promise.resolve({
|
|
131
|
+
kind: "resolved",
|
|
132
|
+
input: {
|
|
133
|
+
cycleId: `task-${digest(request.commandId).slice(0, 12)}`,
|
|
134
|
+
repository,
|
|
135
|
+
input: request.submission,
|
|
136
|
+
},
|
|
137
|
+
}),
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
export async function ticketRegistrations(manifests, options) {
|
|
141
|
+
const ids = new Set();
|
|
142
|
+
for (const row of options.table) {
|
|
143
|
+
if (ids.has(row.workflowId))
|
|
144
|
+
return {
|
|
145
|
+
kind: "rejected",
|
|
146
|
+
detail: `duplicate-workflow-id: ${row.workflowId}`,
|
|
147
|
+
};
|
|
148
|
+
ids.add(row.workflowId);
|
|
149
|
+
}
|
|
150
|
+
const registrations = [];
|
|
151
|
+
for (const row of options.table) {
|
|
152
|
+
const manifest = manifests[row.functionName];
|
|
153
|
+
if (manifest === undefined)
|
|
154
|
+
return {
|
|
155
|
+
kind: "rejected",
|
|
156
|
+
detail: `Missing manifest for workflow function ${row.functionName}.`,
|
|
157
|
+
};
|
|
158
|
+
const admission = await admitCompiled(manifest, {
|
|
159
|
+
file: manifest,
|
|
160
|
+
capabilities: row.capabilities ?? ticketCapabilities,
|
|
161
|
+
});
|
|
162
|
+
if (admission.kind === "rejected")
|
|
163
|
+
return {
|
|
164
|
+
kind: "rejected",
|
|
165
|
+
detail: `${admission.error.code}: ${admission.error.detail}`,
|
|
166
|
+
};
|
|
167
|
+
registrations.push({
|
|
168
|
+
workflowId: row.workflowId,
|
|
169
|
+
manifest: admission.manifest,
|
|
170
|
+
availability: "available",
|
|
171
|
+
effectLimit: row.effectLimit,
|
|
172
|
+
submission: row.submission,
|
|
173
|
+
resolver: row.resolver,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
return { kind: "admitted", registrations };
|
|
177
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const ticketLimits: {
|
|
2
|
+
textBytes: number;
|
|
3
|
+
detailCharacters: number;
|
|
4
|
+
};
|
|
5
|
+
export type TicketRead = {
|
|
6
|
+
readonly kind: "read";
|
|
7
|
+
readonly text: string;
|
|
8
|
+
} | {
|
|
9
|
+
readonly kind: "failed";
|
|
10
|
+
readonly detail: string;
|
|
11
|
+
};
|
|
12
|
+
export interface TicketRequest {
|
|
13
|
+
readonly ticketId: string;
|
|
14
|
+
readonly signal: AbortSignal;
|
|
15
|
+
}
|
|
16
|
+
export declare function ticketText(command: readonly string[], request: TicketRequest): Promise<TicketRead>;
|
|
17
|
+
export declare function ticketCommandText(command: readonly string[], signal: AbortSignal): Promise<TicketRead>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
export const ticketLimits = { textBytes: 48_000, detailCharacters: 300 };
|
|
4
|
+
function failed(detail) {
|
|
5
|
+
return { kind: "failed", detail };
|
|
6
|
+
}
|
|
7
|
+
function printed(output) {
|
|
8
|
+
const text = output.trim();
|
|
9
|
+
if (text === "")
|
|
10
|
+
return failed("The ticket command printed no text.");
|
|
11
|
+
if (Buffer.byteLength(text) > ticketLimits.textBytes)
|
|
12
|
+
return failed(`The ticket text has more than ${String(ticketLimits.textBytes)} bytes.`);
|
|
13
|
+
return { kind: "read", text };
|
|
14
|
+
}
|
|
15
|
+
function ended(error) {
|
|
16
|
+
const code = Reflect.get(Object(error), "code");
|
|
17
|
+
const cause = String(Reflect.get(Object(error), "stderr"))
|
|
18
|
+
.trim()
|
|
19
|
+
.slice(0, ticketLimits.detailCharacters);
|
|
20
|
+
return typeof code === "number"
|
|
21
|
+
? failed(`The ticket command ended with the code ${String(code)}: ${cause}`)
|
|
22
|
+
: failed(`The ticket command did not complete: ${String(code)}`);
|
|
23
|
+
}
|
|
24
|
+
const executed = promisify(execFile);
|
|
25
|
+
export function ticketText(command, request) {
|
|
26
|
+
const [executable = "", ...fixed] = command;
|
|
27
|
+
return ticketCommandText([executable, ...fixed, request.ticketId], request.signal).then((result) => result.kind === "failed" ? result : printed(result.text));
|
|
28
|
+
}
|
|
29
|
+
export function ticketCommandText(command, signal) {
|
|
30
|
+
const [executable = "", ...fixed] = command;
|
|
31
|
+
return executed(executable, fixed, {
|
|
32
|
+
signal,
|
|
33
|
+
maxBuffer: 4 * ticketLimits.textBytes,
|
|
34
|
+
encoding: "utf8",
|
|
35
|
+
}).then((output) => ({ kind: "read", text: output.stdout.trim() }), ended);
|
|
36
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface WorkTree {
|
|
2
|
+
readonly path: string;
|
|
3
|
+
readonly branch: string;
|
|
4
|
+
readonly startCommit: string;
|
|
5
|
+
}
|
|
6
|
+
export interface TreeRequest {
|
|
7
|
+
readonly repository: string;
|
|
8
|
+
readonly worktrees: string;
|
|
9
|
+
readonly target: string;
|
|
10
|
+
readonly signal: AbortSignal;
|
|
11
|
+
readonly base?: string;
|
|
12
|
+
}
|
|
13
|
+
export interface Changes {
|
|
14
|
+
readonly branch: string;
|
|
15
|
+
readonly commits: readonly string[];
|
|
16
|
+
readonly files: readonly string[];
|
|
17
|
+
readonly uncommitted: readonly string[];
|
|
18
|
+
}
|
|
19
|
+
export declare function treeName(target: string): string;
|
|
20
|
+
export declare function treePlace(request: Pick<TreeRequest, "worktrees" | "target">): {
|
|
21
|
+
readonly path: string;
|
|
22
|
+
readonly branch: string;
|
|
23
|
+
};
|
|
24
|
+
export declare function workTree(request: TreeRequest): Promise<WorkTree>;
|
|
25
|
+
export declare function treeFailure(error: unknown): string;
|
|
26
|
+
export declare function changes(tree: WorkTree): Promise<Changes>;
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { execFile, spawn } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import { mkdir, realpath } from "node:fs/promises";
|
|
4
|
+
import { join, relative, resolve, sep } from "node:path";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
const executed = promisify(execFile);
|
|
7
|
+
const lineLimit = 30;
|
|
8
|
+
const lineLength = 120;
|
|
9
|
+
async function git(call) {
|
|
10
|
+
const { directory, parts, signal } = call;
|
|
11
|
+
const { stdout } = await executed("git", ["-C", directory, ...parts], {
|
|
12
|
+
...(signal === undefined ? {} : { signal }),
|
|
13
|
+
});
|
|
14
|
+
return stdout;
|
|
15
|
+
}
|
|
16
|
+
export function treeName(target) {
|
|
17
|
+
return target
|
|
18
|
+
.replace(/[^A-Za-z0-9._-]/g, "-")
|
|
19
|
+
.replace(/\.{2,}/g, "-")
|
|
20
|
+
.replace(/^\.|\.$/g, "-")
|
|
21
|
+
.replace(/\.lock$/, "-lock");
|
|
22
|
+
}
|
|
23
|
+
async function added(request, tree) {
|
|
24
|
+
const { repository, worktrees, signal } = request;
|
|
25
|
+
const call = (parts) => git({ directory: repository, parts, signal });
|
|
26
|
+
await call(["worktree", "prune"]);
|
|
27
|
+
await mkdir(worktrees, { recursive: true });
|
|
28
|
+
const known = await call([
|
|
29
|
+
"rev-parse",
|
|
30
|
+
"--verify",
|
|
31
|
+
"--quiet",
|
|
32
|
+
`refs/heads/${tree.branch}`,
|
|
33
|
+
]).then(() => true, () => false);
|
|
34
|
+
await call(known
|
|
35
|
+
? ["worktree", "add", tree.path, tree.branch]
|
|
36
|
+
: [
|
|
37
|
+
"worktree",
|
|
38
|
+
"add",
|
|
39
|
+
"-b",
|
|
40
|
+
tree.branch,
|
|
41
|
+
tree.path,
|
|
42
|
+
request.base ?? "HEAD",
|
|
43
|
+
]);
|
|
44
|
+
}
|
|
45
|
+
export function treePlace(request) {
|
|
46
|
+
const name = treeName(request.target);
|
|
47
|
+
return { path: join(request.worktrees, name), branch: `cloving/${name}` };
|
|
48
|
+
}
|
|
49
|
+
export async function workTree(request) {
|
|
50
|
+
if (request.target.startsWith("branch:"))
|
|
51
|
+
return branchTree(request).catch((error) => {
|
|
52
|
+
const reason = treeFailure(error);
|
|
53
|
+
throw new Error(reason === "work-tree-not-available"
|
|
54
|
+
? "branch-worktree-not-found"
|
|
55
|
+
: reason);
|
|
56
|
+
});
|
|
57
|
+
const { path, branch } = treePlace(request);
|
|
58
|
+
if (!existsSync(join(path, ".git")))
|
|
59
|
+
await added(request, { path, branch });
|
|
60
|
+
const head = await git({
|
|
61
|
+
directory: path,
|
|
62
|
+
parts: ["rev-parse", "HEAD"],
|
|
63
|
+
signal: request.signal,
|
|
64
|
+
});
|
|
65
|
+
return { path, branch, startCommit: head.trim() };
|
|
66
|
+
}
|
|
67
|
+
async function branchTree(request) {
|
|
68
|
+
const branch = request.target.slice("branch:".length);
|
|
69
|
+
if (branch.startsWith("cloving/"))
|
|
70
|
+
throw new Error("branch-reserved");
|
|
71
|
+
const listing = await git({
|
|
72
|
+
directory: request.repository,
|
|
73
|
+
parts: ["worktree", "list", "--porcelain", "-z"],
|
|
74
|
+
signal: request.signal,
|
|
75
|
+
});
|
|
76
|
+
const entry = listing
|
|
77
|
+
.split("\0\0")
|
|
78
|
+
.slice(1)
|
|
79
|
+
.find((record) => record.split("\0").includes(`branch refs/heads/${branch}`));
|
|
80
|
+
const path = entry?.split("\0")[0]?.slice("worktree ".length);
|
|
81
|
+
if (path === undefined)
|
|
82
|
+
throw new Error("branch-worktree-not-found");
|
|
83
|
+
await sameBranch(request, { path, branch });
|
|
84
|
+
await outsideManaged(request, path);
|
|
85
|
+
await cleanBranch({ directory: path, signal: request.signal });
|
|
86
|
+
const head = await git({
|
|
87
|
+
directory: path,
|
|
88
|
+
parts: ["rev-parse", "HEAD"],
|
|
89
|
+
signal: request.signal,
|
|
90
|
+
});
|
|
91
|
+
return { path, branch, startCommit: head.trim() };
|
|
92
|
+
}
|
|
93
|
+
async function outsideManaged(request, path) {
|
|
94
|
+
const folder = await realpath(request.worktrees).catch((error) => {
|
|
95
|
+
if (typeof error !== "object" ||
|
|
96
|
+
error === null ||
|
|
97
|
+
!("code" in error) ||
|
|
98
|
+
error.code !== "ENOENT")
|
|
99
|
+
throw error;
|
|
100
|
+
return resolve(request.worktrees);
|
|
101
|
+
});
|
|
102
|
+
const location = relative(folder, await realpath(path));
|
|
103
|
+
if (location !== ".." && !location.startsWith(`..${sep}`))
|
|
104
|
+
throw new Error("branch-reserved");
|
|
105
|
+
}
|
|
106
|
+
async function sameBranch(request, tree) {
|
|
107
|
+
const common = async (directory) => {
|
|
108
|
+
const folder = await git({
|
|
109
|
+
directory,
|
|
110
|
+
parts: ["rev-parse", "--git-common-dir"],
|
|
111
|
+
signal: request.signal,
|
|
112
|
+
});
|
|
113
|
+
return realpath(resolve(directory, folder.trim()));
|
|
114
|
+
};
|
|
115
|
+
if ((await common(request.repository)) !== (await common(tree.path)))
|
|
116
|
+
throw new Error("branch-worktree-not-found");
|
|
117
|
+
const head = await git({
|
|
118
|
+
directory: tree.path,
|
|
119
|
+
parts: ["symbolic-ref", "--quiet", "HEAD"],
|
|
120
|
+
signal: request.signal,
|
|
121
|
+
});
|
|
122
|
+
if (head.trim() !== `refs/heads/${tree.branch}`)
|
|
123
|
+
throw new Error("branch-worktree-not-found");
|
|
124
|
+
}
|
|
125
|
+
async function cleanBranch(place) {
|
|
126
|
+
await cleanOutput({
|
|
127
|
+
...place,
|
|
128
|
+
parts: [
|
|
129
|
+
"-c",
|
|
130
|
+
"core.fileMode=true",
|
|
131
|
+
"status",
|
|
132
|
+
"--porcelain",
|
|
133
|
+
"--untracked-files=all",
|
|
134
|
+
"--ignore-submodules=none",
|
|
135
|
+
],
|
|
136
|
+
}, hasOutput);
|
|
137
|
+
await cleanOutput({ ...place, parts: ["ls-files", "-v", "-z"] }, hiddenIndex);
|
|
138
|
+
}
|
|
139
|
+
async function hasOutput(output) {
|
|
140
|
+
let present = false;
|
|
141
|
+
for await (const chunk of output) {
|
|
142
|
+
if (chunk.length > 0)
|
|
143
|
+
present = true;
|
|
144
|
+
}
|
|
145
|
+
return present;
|
|
146
|
+
}
|
|
147
|
+
async function hiddenIndex(output) {
|
|
148
|
+
let entryStart = true;
|
|
149
|
+
let hidden = false;
|
|
150
|
+
for await (const chunk of output) {
|
|
151
|
+
for (const character of chunk.toString()) {
|
|
152
|
+
if (entryStart && /[a-zS]/.test(character))
|
|
153
|
+
hidden = true;
|
|
154
|
+
entryStart = character === "\0";
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return hidden;
|
|
158
|
+
}
|
|
159
|
+
async function cleanOutput(call, inspect) {
|
|
160
|
+
const child = spawn("git", ["-C", call.directory, ...call.parts], {
|
|
161
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
162
|
+
...(call.signal === undefined ? {} : { signal: call.signal }),
|
|
163
|
+
});
|
|
164
|
+
const ended = new Promise((resolve) => {
|
|
165
|
+
child.once("error", () => {
|
|
166
|
+
resolve(false);
|
|
167
|
+
});
|
|
168
|
+
child.once("close", (code) => {
|
|
169
|
+
resolve(code === 0);
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
const dirty = await inspect(child.stdout);
|
|
173
|
+
if (!(await ended))
|
|
174
|
+
throw new Error("branch-worktree-not-found");
|
|
175
|
+
if (dirty)
|
|
176
|
+
throw new Error("branch-worktree-not-clean");
|
|
177
|
+
}
|
|
178
|
+
export function treeFailure(error) {
|
|
179
|
+
const reason = error instanceof Error ? error.message : "";
|
|
180
|
+
return [
|
|
181
|
+
"branch-worktree-not-found",
|
|
182
|
+
"branch-worktree-not-clean",
|
|
183
|
+
"branch-reserved",
|
|
184
|
+
].includes(reason)
|
|
185
|
+
? reason
|
|
186
|
+
: "work-tree-not-available";
|
|
187
|
+
}
|
|
188
|
+
export async function changes(tree) {
|
|
189
|
+
const lines = async (parts) => (await git({ directory: tree.path, parts }).catch(() => ""))
|
|
190
|
+
.split("\n")
|
|
191
|
+
.filter((line) => line.trim() !== "")
|
|
192
|
+
.slice(0, lineLimit)
|
|
193
|
+
.map((line) => line.slice(0, lineLength));
|
|
194
|
+
const range = `${tree.startCommit}..HEAD`;
|
|
195
|
+
const [branch = tree.branch] = await lines([
|
|
196
|
+
"rev-parse",
|
|
197
|
+
"--abbrev-ref",
|
|
198
|
+
"HEAD",
|
|
199
|
+
]);
|
|
200
|
+
return {
|
|
201
|
+
branch,
|
|
202
|
+
commits: await lines(["log", "--oneline", range]),
|
|
203
|
+
files: await lines(["diff", "--stat", range]),
|
|
204
|
+
uncommitted: await lines(["status", "--short"]),
|
|
205
|
+
};
|
|
206
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface EffectBudget {
|
|
2
|
+
readonly limit: number;
|
|
3
|
+
readonly spent: number;
|
|
4
|
+
}
|
|
5
|
+
export interface EffectRequest {
|
|
6
|
+
readonly capability: string;
|
|
7
|
+
readonly units: number;
|
|
8
|
+
}
|
|
9
|
+
export type EffectAuthorization = {
|
|
10
|
+
readonly kind: "authorized";
|
|
11
|
+
readonly spent: number;
|
|
12
|
+
} | {
|
|
13
|
+
readonly kind: "rejected";
|
|
14
|
+
readonly reason: string;
|
|
15
|
+
};
|
|
16
|
+
export declare function authorizeEffect(manifest: {
|
|
17
|
+
readonly capabilities: readonly string[];
|
|
18
|
+
}, effect: {
|
|
19
|
+
readonly budget: EffectBudget;
|
|
20
|
+
readonly request: EffectRequest;
|
|
21
|
+
}): EffectAuthorization;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export function authorizeEffect(manifest, effect) {
|
|
2
|
+
const { budget, request } = effect;
|
|
3
|
+
if (![budget.limit, budget.spent].every((value) => Number.isSafeInteger(value) && value >= 0) ||
|
|
4
|
+
!Number.isSafeInteger(request.units) ||
|
|
5
|
+
request.units < 1 ||
|
|
6
|
+
budget.spent > budget.limit)
|
|
7
|
+
return { kind: "rejected", reason: "invalid-effect-request" };
|
|
8
|
+
if (!manifest.capabilities.includes(request.capability))
|
|
9
|
+
return { kind: "rejected", reason: "unadmitted-capability" };
|
|
10
|
+
const spent = budget.spent + request.units;
|
|
11
|
+
if (spent > budget.limit)
|
|
12
|
+
return { kind: "rejected", reason: "budget-exhausted" };
|
|
13
|
+
return { kind: "authorized", spent };
|
|
14
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { AdmissionResult, ExecutionManifest } from "./workflow-admission.ts";
|
|
2
|
+
export declare function pinnedIdentity(manifest: ExecutionManifest): string;
|
|
3
|
+
export declare function resumePinned(pinned: ExecutionManifest, available: ExecutionManifest): AdmissionResult;
|
|
4
|
+
export declare function readExecutionManifest(value: unknown): ExecutionManifest;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
const canonical = {
|
|
2
|
+
name: (manifest) => JSON.stringify(manifest.name),
|
|
3
|
+
workflowId: (manifest) => JSON.stringify(manifest.workflowId),
|
|
4
|
+
steps: (manifest) => JSON.stringify([...manifest.steps].sort()),
|
|
5
|
+
capabilities: (manifest) => JSON.stringify([...manifest.capabilities].sort()),
|
|
6
|
+
artifacts: (manifest) => JSON.stringify(Object.keys(manifest.artifacts)
|
|
7
|
+
.sort()
|
|
8
|
+
.map((name) => [name, manifest.artifacts[name]])),
|
|
9
|
+
resources: (manifest) => JSON.stringify(Object.keys(manifest.resources)
|
|
10
|
+
.sort()
|
|
11
|
+
.map((name) => [name, manifest.resources[name]])),
|
|
12
|
+
toolchain: (manifest) => JSON.stringify(["sdk", "world", "builder", "node", "dependencies"].map((key) => manifest.toolchain[key])),
|
|
13
|
+
};
|
|
14
|
+
const fields = [
|
|
15
|
+
"name",
|
|
16
|
+
"workflowId",
|
|
17
|
+
"steps",
|
|
18
|
+
"capabilities",
|
|
19
|
+
"artifacts",
|
|
20
|
+
"resources",
|
|
21
|
+
"toolchain",
|
|
22
|
+
];
|
|
23
|
+
export function pinnedIdentity(manifest) {
|
|
24
|
+
return JSON.stringify(fields.map((field) => canonical[field](manifest)));
|
|
25
|
+
}
|
|
26
|
+
export function resumePinned(pinned, available) {
|
|
27
|
+
const changed = fields.find((field) => canonical[field](pinned) !== canonical[field](available));
|
|
28
|
+
if (changed !== undefined)
|
|
29
|
+
return {
|
|
30
|
+
kind: "rejected",
|
|
31
|
+
reason: "pinned-manifest-mismatch",
|
|
32
|
+
detail: changed,
|
|
33
|
+
};
|
|
34
|
+
return { kind: "admitted", manifest: pinned };
|
|
35
|
+
}
|
|
36
|
+
export function readExecutionManifest(value) {
|
|
37
|
+
const fields = record(value);
|
|
38
|
+
const toolchain = record(fields["toolchain"]);
|
|
39
|
+
return {
|
|
40
|
+
name: text(fields["name"]),
|
|
41
|
+
workflowId: text(fields["workflowId"]),
|
|
42
|
+
steps: texts(fields["steps"]),
|
|
43
|
+
capabilities: texts(fields["capabilities"]),
|
|
44
|
+
artifacts: textRecord(fields["artifacts"]),
|
|
45
|
+
resources: textRecord(fields["resources"]),
|
|
46
|
+
toolchain: {
|
|
47
|
+
sdk: text(toolchain["sdk"]),
|
|
48
|
+
world: text(toolchain["world"]),
|
|
49
|
+
builder: text(toolchain["builder"]),
|
|
50
|
+
node: text(toolchain["node"]),
|
|
51
|
+
dependencies: text(toolchain["dependencies"]),
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function record(value) {
|
|
56
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
57
|
+
return {};
|
|
58
|
+
return Object.fromEntries(Object.entries(value));
|
|
59
|
+
}
|
|
60
|
+
function text(value) {
|
|
61
|
+
return typeof value === "string" ? value : "";
|
|
62
|
+
}
|
|
63
|
+
function texts(value) {
|
|
64
|
+
return Array.isArray(value) ? value.map(text) : [];
|
|
65
|
+
}
|
|
66
|
+
function textRecord(value) {
|
|
67
|
+
return Object.fromEntries(Object.entries(record(value)).map(([key, item]) => [key, text(item)]));
|
|
68
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type TaggedRun } from "./world-runs.ts";
|
|
2
|
+
export type WorkflowFunction = (input: unknown, continuation?: Continuation) => Promise<unknown>;
|
|
3
|
+
export interface Continuation {
|
|
4
|
+
readonly gateId: string;
|
|
5
|
+
readonly decision: string;
|
|
6
|
+
readonly answer: string | null;
|
|
7
|
+
}
|
|
8
|
+
export interface RunIntent extends Partial<Continuation> {
|
|
9
|
+
readonly kind: string;
|
|
10
|
+
readonly runId: string;
|
|
11
|
+
readonly operationId: string;
|
|
12
|
+
}
|
|
13
|
+
export type RunOutcome = {
|
|
14
|
+
readonly kind: "accepted";
|
|
15
|
+
readonly receipt: string;
|
|
16
|
+
} | {
|
|
17
|
+
readonly kind: "stopped";
|
|
18
|
+
readonly receipt: string;
|
|
19
|
+
} | {
|
|
20
|
+
readonly kind: "absent";
|
|
21
|
+
} | {
|
|
22
|
+
readonly kind: "unknown";
|
|
23
|
+
readonly evidence: string;
|
|
24
|
+
};
|
|
25
|
+
type OperationRun = Pick<TaggedRun, "receipt" | "operationId" | "status">;
|
|
26
|
+
export interface StartParts {
|
|
27
|
+
readonly runs: () => Promise<readonly OperationRun[]>;
|
|
28
|
+
readonly input: (runId: string) => Promise<string | undefined>;
|
|
29
|
+
readonly document: (digest: string) => Promise<string | undefined>;
|
|
30
|
+
readonly workflow: (runId: string) => Promise<WorkflowFunction | undefined>;
|
|
31
|
+
readonly cancel: (receipt: string) => Promise<string>;
|
|
32
|
+
}
|
|
33
|
+
export interface StartDelivery {
|
|
34
|
+
readonly reconcile: (intent: RunIntent) => Promise<RunOutcome>;
|
|
35
|
+
readonly deliver: (intent: RunIntent) => Promise<{
|
|
36
|
+
readonly receipt: string;
|
|
37
|
+
}>;
|
|
38
|
+
readonly stop: (intent: RunIntent) => Promise<RunOutcome>;
|
|
39
|
+
}
|
|
40
|
+
export declare function startDelivery(parts: StartParts): StartDelivery;
|
|
41
|
+
export {};
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { start } from "workflow/api";
|
|
2
|
+
import { operationTag, runTag } from "./world-runs.js";
|
|
3
|
+
const ends = ["cancelled", "completed", "failed"];
|
|
4
|
+
async function segments(parts, intent) {
|
|
5
|
+
return (await parts.runs()).filter((run) => run.operationId === intent.operationId);
|
|
6
|
+
}
|
|
7
|
+
async function reconciled(parts, intent) {
|
|
8
|
+
const found = await segments(parts, intent);
|
|
9
|
+
const [first, ...others] = found;
|
|
10
|
+
if (first === undefined)
|
|
11
|
+
return { kind: "absent" };
|
|
12
|
+
if (others.length === 0)
|
|
13
|
+
return { kind: "accepted", receipt: first.receipt };
|
|
14
|
+
return {
|
|
15
|
+
kind: "unknown",
|
|
16
|
+
evidence: found.map((run) => `world-run:${run.receipt}`).join(" "),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
async function continuation(parts, intent) {
|
|
20
|
+
const { kind, gateId, decision, answer } = intent;
|
|
21
|
+
if (kind === "start-run")
|
|
22
|
+
return undefined;
|
|
23
|
+
if (kind !== "continue-run" || gateId === undefined || decision === undefined)
|
|
24
|
+
throw new Error(`unsupported-intent: ${kind}`);
|
|
25
|
+
if (answer === undefined || answer === null)
|
|
26
|
+
return { gateId, decision, answer: null };
|
|
27
|
+
const text = await parts.document(answer);
|
|
28
|
+
if (text === undefined)
|
|
29
|
+
throw new Error(`answer-not-available: ${gateId}`);
|
|
30
|
+
return { gateId, decision, answer: text };
|
|
31
|
+
}
|
|
32
|
+
async function delivered(parts, intent) {
|
|
33
|
+
const continued = await continuation(parts, intent);
|
|
34
|
+
const workflow = await parts.workflow(intent.runId);
|
|
35
|
+
const input = await parts.input(intent.runId);
|
|
36
|
+
if (workflow === undefined || input === undefined)
|
|
37
|
+
throw new Error(`start-not-available: ${intent.runId}`);
|
|
38
|
+
const argument = JSON.parse(input);
|
|
39
|
+
const started = await start(workflow, [argument, continued], {
|
|
40
|
+
attributes: {
|
|
41
|
+
[runTag]: intent.runId,
|
|
42
|
+
[operationTag]: intent.operationId,
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
return { receipt: started.runId };
|
|
46
|
+
}
|
|
47
|
+
async function stopped(parts, intent) {
|
|
48
|
+
const found = await segments(parts, intent);
|
|
49
|
+
const [first] = found;
|
|
50
|
+
if (first === undefined)
|
|
51
|
+
return { kind: "absent" };
|
|
52
|
+
const alive = [];
|
|
53
|
+
for (const run of found.filter((run) => !ends.includes(run.status))) {
|
|
54
|
+
const status = await parts.cancel(run.receipt);
|
|
55
|
+
if (!ends.includes(status))
|
|
56
|
+
alive.push(`world-run:${run.receipt} ${status}`);
|
|
57
|
+
}
|
|
58
|
+
if (alive.length > 0)
|
|
59
|
+
return { kind: "unknown", evidence: alive.join(" ") };
|
|
60
|
+
return { kind: "stopped", receipt: first.receipt };
|
|
61
|
+
}
|
|
62
|
+
export function startDelivery(parts) {
|
|
63
|
+
return {
|
|
64
|
+
reconcile: (intent) => reconciled(parts, intent),
|
|
65
|
+
deliver: (intent) => delivered(parts, intent),
|
|
66
|
+
stop: (intent) => stopped(parts, intent),
|
|
67
|
+
};
|
|
68
|
+
}
|