cloving 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +525 -185
- package/dist/src/agent-harness-shell.d.ts +12 -0
- package/dist/src/agent-harness-shell.js +90 -0
- package/dist/src/agent-harness-versions.d.ts +8 -0
- package/dist/src/agent-harness-versions.js +49 -0
- package/dist/src/agent-harnesses.d.ts +4 -0
- package/dist/src/agent-harnesses.js +13 -0
- package/dist/src/authority/commands.d.ts +1 -0
- package/dist/src/authority/commands.js +24 -4
- package/dist/src/authority/gate-reduction.d.ts +1 -0
- package/dist/src/authority/gate-reduction.js +18 -3
- package/dist/src/authority/gates.d.ts +2 -1
- package/dist/src/authority/gates.js +5 -1
- package/dist/src/authority/operations.js +1 -1
- package/dist/src/authority/reduction.d.ts +1 -1
- package/dist/src/authority/reduction.js +6 -1
- package/dist/src/authority/status-input.d.ts +1 -1
- package/dist/src/authority/status.d.ts +1 -0
- package/dist/src/authority/status.js +27 -3
- package/dist/src/authority/transitions.d.ts +5 -5
- package/dist/src/authority/transitions.js +6 -0
- package/dist/src/broker/actor/authority-delivery.js +1 -0
- package/dist/src/broker/actor/authority-queries.d.ts +7 -1
- package/dist/src/broker/actor/authority-queries.js +17 -2
- package/dist/src/broker/actor/authority-receipts.js +11 -1
- package/dist/src/broker/actor/authority-session.js +2 -2
- package/dist/src/broker/actor/authority-settings.js +4 -0
- package/dist/src/broker/actor/delivery-intents.d.ts +2 -1
- package/dist/src/broker/actor/delivery-intents.js +4 -4
- package/dist/src/broker/actor/effect-delivery.js +4 -1
- package/dist/src/broker/actor/effect-queries.d.ts +1 -0
- package/dist/src/broker/actor/effect-queries.js +7 -0
- package/dist/src/broker/actor/pin-check.js +1 -1
- package/dist/src/broker/actor/stop-plan.js +1 -1
- package/dist/src/broker/actor/turn-state.js +1 -1
- package/dist/src/broker/authority-admission.js +22 -9
- package/dist/src/broker/authority-restore.js +1 -0
- package/dist/src/broker/decision-restore.js +4 -4
- package/dist/src/broker/socket-address.d.ts +3 -1
- package/dist/src/broker/socket-address.js +2 -2
- package/dist/src/cli/arguments.d.ts +11 -13
- package/dist/src/cli/arguments.js +37 -107
- package/dist/src/cli/command-effects.d.ts +7 -0
- package/dist/src/cli/command-effects.js +39 -0
- package/dist/src/cli/commands.js +11 -4
- package/dist/src/cli/config-arguments.d.ts +11 -0
- package/dist/src/cli/config-arguments.js +59 -0
- package/dist/src/cli/config-command.d.ts +2 -0
- package/dist/src/cli/config-command.js +105 -0
- package/dist/src/cli/config-file.d.ts +3 -0
- package/dist/src/cli/config-file.js +50 -0
- package/dist/src/cli/config-lock.d.ts +7 -0
- package/dist/src/cli/config-lock.js +61 -0
- package/dist/src/cli/config-notice.d.ts +5 -0
- package/dist/src/cli/config-notice.js +46 -0
- package/dist/src/cli/doctor-github.d.ts +9 -0
- package/dist/src/cli/doctor-github.js +138 -0
- package/dist/src/cli/doctor-harness.d.ts +13 -0
- package/dist/src/cli/doctor-harness.js +242 -0
- package/dist/src/cli/doctor-local.d.ts +18 -0
- package/dist/src/cli/doctor-local.js +77 -0
- package/dist/src/cli/doctor-runtime.d.ts +15 -0
- package/dist/src/cli/doctor-runtime.js +176 -0
- package/dist/src/cli/doctor-service.d.ts +1 -0
- package/dist/src/cli/doctor-service.js +11 -0
- package/dist/src/cli/doctor-workflows.d.ts +3 -0
- package/dist/src/cli/doctor-workflows.js +45 -0
- package/dist/src/cli/doctor.d.ts +15 -0
- package/dist/src/cli/doctor.js +190 -0
- package/dist/src/cli/github-ci-progress.d.ts +8 -0
- package/dist/src/cli/github-ci-progress.js +83 -0
- package/dist/src/cli/github-retry.d.ts +6 -0
- package/dist/src/cli/github-retry.js +47 -0
- package/dist/src/cli/harness-probes.d.ts +22 -0
- package/dist/src/cli/harness-probes.js +183 -0
- package/dist/src/cli/main.d.ts +7 -1
- package/dist/src/cli/main.js +39 -61
- package/dist/src/cli/phone-arguments.d.ts +14 -0
- package/dist/src/cli/phone-arguments.js +37 -0
- package/dist/src/cli/phone-client.d.ts +2 -0
- package/dist/src/cli/phone-client.js +32 -0
- package/dist/src/cli/phone-command.d.ts +13 -0
- package/dist/src/cli/phone-command.js +101 -0
- package/dist/src/cli/probe-command.d.ts +36 -0
- package/dist/src/cli/probe-command.js +59 -0
- package/dist/src/cli/project-settings.d.ts +4 -0
- package/dist/src/cli/project-settings.js +33 -0
- package/dist/src/cli/render.d.ts +2 -1
- package/dist/src/cli/render.js +44 -28
- package/dist/src/cli/report-github.d.ts +18 -0
- package/dist/src/cli/report-github.js +200 -0
- package/dist/src/cli/report.d.ts +17 -0
- package/dist/src/cli/report.js +192 -0
- package/dist/src/cli/repository-arguments.d.ts +5 -0
- package/dist/src/cli/repository-arguments.js +34 -0
- package/dist/src/cli/runtime-arguments.d.ts +4 -0
- package/dist/src/cli/runtime-arguments.js +15 -0
- package/dist/src/cli/runtime-directory.d.ts +6 -2
- package/dist/src/cli/runtime-directory.js +72 -14
- package/dist/src/cli/toolchain.d.ts +2 -0
- package/dist/src/cli/toolchain.js +22 -2
- package/dist/src/cli/usage-render.d.ts +5 -0
- package/dist/src/cli/usage-render.js +40 -1
- package/dist/src/cli/usage.d.ts +3 -3
- package/dist/src/cli/usage.js +70 -44
- package/dist/src/cli/watch-actions.d.ts +2 -0
- package/dist/src/cli/watch-actions.js +4 -4
- package/dist/src/cli/watch-board-view.d.ts +1 -1
- package/dist/src/cli/watch-board-view.js +8 -2
- package/dist/src/cli/watch-board.js +23 -10
- package/dist/src/cli/watch-card-forms.js +2 -2
- package/dist/src/cli/watch-client.d.ts +1 -1
- package/dist/src/cli/watch-client.js +7 -2
- package/dist/src/cli/watch-header-view.d.ts +27 -0
- package/dist/src/cli/watch-header-view.js +116 -0
- package/dist/src/cli/watch-model.js +17 -4
- package/dist/src/cli/watch-page.js +48 -12
- package/dist/src/cli/watch-phone-client.d.ts +1 -0
- package/dist/src/cli/watch-phone-client.js +84 -0
- package/dist/src/cli/watch-phone-view.d.ts +56 -0
- package/dist/src/cli/watch-phone-view.js +113 -0
- package/dist/src/cli/watch-phone.d.ts +5 -0
- package/dist/src/cli/watch-phone.js +53 -0
- package/dist/src/cli/watch-pull-request.d.ts +3 -1
- package/dist/src/cli/watch-pull-request.js +4 -0
- package/dist/src/cli/watch-render.d.ts +9 -1
- package/dist/src/cli/watch-server.js +23 -5
- package/dist/src/cli/watch-turn.d.ts +4 -1
- package/dist/src/cli/watch-turn.js +37 -1
- package/dist/src/cli/watch-usage.js +5 -1
- package/dist/src/cli/watch-view.d.ts +6 -20
- package/dist/src/cli/watch-view.js +14 -106
- package/dist/src/cli.js +106 -23
- package/dist/src/command-settings.d.ts +16 -0
- package/dist/src/command-settings.js +42 -0
- package/dist/src/configuration-change.d.ts +11 -0
- package/dist/src/configuration-change.js +62 -0
- package/dist/src/configuration-display.d.ts +21 -0
- package/dist/src/configuration-display.js +69 -0
- package/dist/src/configuration-schema.d.ts +49 -0
- package/dist/src/configuration-schema.js +159 -0
- package/dist/src/daemon/claude-turn.d.ts +19 -5
- package/dist/src/daemon/claude-turn.js +116 -53
- package/dist/src/daemon/claude-worker.d.ts +3 -3
- package/dist/src/daemon/claude-worker.js +65 -76
- package/dist/src/daemon/command-journal.d.ts +5 -0
- package/dist/src/daemon/command-journal.js +50 -0
- package/dist/src/daemon/command-process.d.ts +28 -0
- package/dist/src/daemon/command-process.js +164 -0
- package/dist/src/daemon/command-worker.d.ts +19 -0
- package/dist/src/daemon/command-worker.js +182 -0
- package/dist/src/daemon/cursor-stream.d.ts +4 -0
- package/dist/src/daemon/cursor-stream.js +154 -0
- package/dist/src/daemon/daemon-adapters.d.ts +58 -0
- package/dist/src/daemon/daemon-adapters.js +102 -0
- package/dist/src/daemon/daemon-loops.d.ts +14 -0
- package/dist/src/daemon/daemon-loops.js +39 -0
- package/dist/src/daemon/daemon.d.ts +2 -33
- package/dist/src/daemon/daemon.js +126 -132
- package/dist/src/daemon/declared-input.d.ts +3 -0
- package/dist/src/daemon/declared-input.js +9 -0
- package/dist/src/daemon/delivery-router.js +1 -1
- package/dist/src/daemon/gemini-stream.d.ts +4 -0
- package/dist/src/daemon/gemini-stream.js +129 -0
- package/dist/src/daemon/github-ci-rerun.d.ts +26 -0
- package/dist/src/daemon/github-ci-rerun.js +92 -0
- package/dist/src/daemon/github-ci.js +89 -8
- package/dist/src/daemon/github-merge-call.d.ts +2 -0
- package/dist/src/daemon/github-merge.js +7 -3
- package/dist/src/daemon/github-methods.js +10 -0
- package/dist/src/daemon/github-operation.d.ts +1 -0
- package/dist/src/daemon/github-retry.js +8 -44
- package/dist/src/daemon/issue-queue.d.ts +1 -0
- package/dist/src/daemon/issue-queue.js +3 -26
- package/dist/src/daemon/notify.js +2 -1
- package/dist/src/daemon/opencode-stream.d.ts +5 -0
- package/dist/src/daemon/opencode-stream.js +87 -0
- package/dist/src/daemon/queue-status.d.ts +4 -0
- package/dist/src/daemon/queue-status.js +38 -0
- package/dist/src/daemon/retry-worktree.d.ts +18 -0
- package/dist/src/daemon/retry-worktree.js +139 -0
- package/dist/src/daemon/retrying-turn.d.ts +2 -0
- package/dist/src/daemon/retrying-turn.js +108 -30
- package/dist/src/daemon/schedule-journal.d.ts +19 -0
- package/dist/src/daemon/schedule-journal.js +57 -0
- package/dist/src/daemon/text-output.d.ts +18 -0
- package/dist/src/daemon/text-output.js +44 -0
- package/dist/src/daemon/ticket-registration.d.ts +5 -7
- package/dist/src/daemon/ticket-registration.js +85 -40
- package/dist/src/daemon/turn-command.d.ts +10 -0
- package/dist/src/daemon/turn-command.js +33 -0
- package/dist/src/daemon/turn-report.d.ts +18 -0
- package/dist/src/daemon/turn-report.js +79 -0
- package/dist/src/daemon/work-tree.d.ts +2 -1
- package/dist/src/daemon/work-tree.js +15 -12
- package/dist/src/daemon/workflow-generations.d.ts +32 -0
- package/dist/src/daemon/workflow-generations.js +57 -0
- package/dist/src/daemon/workflow-replay.d.ts +16 -0
- package/dist/src/daemon/workflow-replay.js +58 -0
- package/dist/src/daemon/workflow-schedules.d.ts +27 -0
- package/dist/src/daemon/workflow-schedules.js +185 -0
- package/dist/src/decision-wait.d.ts +1 -0
- package/dist/src/decision-wait.js +3 -0
- package/dist/src/delivery-backoff.d.ts +1 -0
- package/dist/src/delivery-backoff.js +3 -0
- package/dist/src/doctor-report.d.ts +24 -0
- package/dist/src/doctor-report.js +70 -0
- package/dist/src/execution-pin.d.ts +5 -0
- package/dist/src/execution-pin.js +67 -4
- package/dist/src/grok-result.d.ts +12 -0
- package/dist/src/grok-result.js +61 -0
- package/dist/src/harness-defaults.d.ts +35 -0
- package/dist/src/harness-defaults.js +121 -0
- package/dist/src/host/decision-resume.d.ts +35 -0
- package/dist/src/host/decision-resume.js +86 -0
- package/dist/src/host/gate-bridge.d.ts +48 -0
- package/dist/src/host/gate-bridge.js +124 -0
- package/dist/src/host/run-wait.d.ts +26 -0
- package/dist/src/host/run-wait.js +37 -0
- package/dist/src/host/start-delivery.d.ts +1 -1
- package/dist/src/host/start-delivery.js +10 -3
- package/dist/src/host/step-bridge-host.d.ts +6 -20
- package/dist/src/host/step-bridge-host.js +44 -58
- package/dist/src/merge-request.d.ts +19 -0
- package/dist/src/merge-request.js +32 -0
- package/dist/src/phone/canonical-json.d.ts +1 -0
- package/dist/src/phone/canonical-json.js +16 -0
- package/dist/src/phone/phone-link.d.ts +7 -0
- package/dist/src/phone/phone-link.js +21 -0
- package/dist/src/phone/qr-data.d.ts +8 -0
- package/dist/src/phone/qr-data.js +133 -0
- package/dist/src/phone/qr-matrix.d.ts +6 -0
- package/dist/src/phone/qr-matrix.js +175 -0
- package/dist/src/phone/qr-penalty.d.ts +3 -0
- package/dist/src/phone/qr-penalty.js +67 -0
- package/dist/src/phone/qr-picture.d.ts +5 -0
- package/dist/src/phone/qr-picture.js +24 -0
- package/dist/src/private-config.schema.json +263 -0
- package/dist/src/project-config.schema.json +65 -0
- package/dist/src/project-settings.d.ts +19 -0
- package/dist/src/project-settings.js +131 -0
- package/dist/src/relay/answer-check.d.ts +24 -0
- package/dist/src/relay/answer-check.js +145 -0
- package/dist/src/relay/answer-inbox.d.ts +15 -0
- package/dist/src/relay/answer-inbox.js +173 -0
- package/dist/src/relay/daemon-keys.d.ts +16 -0
- package/dist/src/relay/daemon-keys.js +75 -0
- package/dist/src/relay/decision-check.d.ts +3 -0
- package/dist/src/relay/decision-check.js +77 -0
- package/dist/src/relay/decision-close.d.ts +6 -0
- package/dist/src/relay/decision-close.js +72 -0
- package/dist/src/relay/decision-envelopes.d.ts +29 -0
- package/dist/src/relay/decision-envelopes.js +93 -0
- package/dist/src/relay/decision-watch.d.ts +14 -0
- package/dist/src/relay/decision-watch.js +68 -0
- package/dist/src/relay/envelope-post.d.ts +8 -0
- package/dist/src/relay/envelope-post.js +71 -0
- package/dist/src/relay/envelope.d.ts +28 -0
- package/dist/src/relay/envelope.js +53 -0
- package/dist/src/relay/hpke.d.ts +25 -0
- package/dist/src/relay/hpke.js +108 -0
- package/dist/src/relay/pairing-checks.d.ts +42 -0
- package/dist/src/relay/pairing-checks.js +172 -0
- package/dist/src/relay/pairing-follow.d.ts +8 -0
- package/dist/src/relay/pairing-follow.js +95 -0
- package/dist/src/relay/pairing-session.d.ts +29 -0
- package/dist/src/relay/pairing-session.js +87 -0
- package/dist/src/relay/phone-delivery.d.ts +51 -0
- package/dist/src/relay/phone-delivery.js +139 -0
- package/dist/src/relay/phone-devices.d.ts +36 -0
- package/dist/src/relay/phone-devices.js +46 -0
- package/dist/src/relay/phone-inbox.d.ts +18 -0
- package/dist/src/relay/phone-inbox.js +17 -0
- package/dist/src/relay/phone-operations.d.ts +18 -0
- package/dist/src/relay/phone-operations.js +121 -0
- package/dist/src/relay/phone-outbox.d.ts +21 -0
- package/dist/src/relay/phone-outbox.js +25 -0
- package/dist/src/relay/phone-socket.d.ts +6 -0
- package/dist/src/relay/phone-socket.js +63 -0
- package/dist/src/relay/relay-control.d.ts +7 -0
- package/dist/src/relay/relay-control.js +24 -0
- package/dist/src/relay/relay-files.d.ts +2 -0
- package/dist/src/relay/relay-files.js +23 -0
- package/dist/src/relay/relay-heartbeat.d.ts +17 -0
- package/dist/src/relay/relay-heartbeat.js +81 -0
- package/dist/src/relay/relay-http.d.ts +14 -0
- package/dist/src/relay/relay-http.js +63 -0
- package/dist/src/relay/relay-registration.d.ts +15 -0
- package/dist/src/relay/relay-registration.js +63 -0
- package/dist/src/relay/relay-service.d.ts +25 -0
- package/dist/src/relay/relay-service.js +216 -0
- package/dist/src/relay/relay-store.d.ts +48 -0
- package/dist/src/relay/relay-store.js +131 -0
- package/dist/src/relay/sealed-post.d.ts +25 -0
- package/dist/src/relay/sealed-post.js +52 -0
- package/dist/src/relay.d.ts +1 -0
- package/dist/src/relay.js +8 -0
- package/dist/src/report-statistics.d.ts +50 -0
- package/dist/src/report-statistics.js +70 -0
- package/dist/src/report.d.ts +171 -0
- package/dist/src/report.js +119 -0
- package/dist/src/repository-identity.d.ts +4 -0
- package/dist/src/repository-identity.js +4 -0
- package/dist/src/review-subject.d.ts +41 -0
- package/dist/src/review-subject.js +91 -0
- package/dist/src/run-wait.d.ts +23 -0
- package/dist/src/run-wait.js +20 -0
- package/dist/src/service/active-tickets.d.ts +4 -0
- package/dist/src/service/active-tickets.js +49 -0
- package/dist/src/service/command-effects.d.ts +4 -0
- package/dist/src/service/command-effects.js +16 -0
- package/dist/src/service/decision-handler.d.ts +4 -0
- package/dist/src/service/decision-handler.js +39 -4
- package/dist/src/service/gateway.js +18 -3
- package/dist/src/service/registry.d.ts +16 -3
- package/dist/src/service/registry.js +34 -3
- package/dist/src/service/replies.d.ts +9 -1
- package/dist/src/service/replies.js +12 -0
- package/dist/src/service/run-handlers.js +14 -55
- package/dist/src/service/run-metadata.d.ts +8 -0
- package/dist/src/service/run-metadata.js +53 -0
- package/dist/src/service/run-waits.d.ts +3 -0
- package/dist/src/service/run-waits.js +41 -0
- package/dist/src/service/service.d.ts +18 -2
- package/dist/src/service/service.js +23 -7
- package/dist/src/service/submission-handler.d.ts +0 -1
- package/dist/src/service/submission-handler.js +6 -34
- package/dist/src/service/worker-port.d.ts +1 -0
- package/dist/src/service/worker-totals.js +8 -23
- package/dist/src/step-bridge.d.ts +23 -0
- package/dist/src/steps/decision-gate.d.ts +2 -1
- package/dist/src/steps/decision-gate.js +7 -0
- package/dist/src/steps/merge-by-person.d.ts +2 -0
- package/dist/src/steps/merge-by-person.js +18 -0
- package/dist/src/steps/merge-when-green.d.ts +2 -0
- package/dist/src/steps/merge-when-green.js +62 -0
- package/dist/src/steps/review-by-agent.d.ts +5 -0
- package/dist/src/steps/review-by-agent.js +124 -0
- package/dist/src/steps/review-by-person.d.ts +4 -0
- package/dist/src/steps/review-by-person.js +16 -0
- package/dist/src/steps/review-subject.d.ts +2 -0
- package/dist/src/steps/review-subject.js +11 -0
- package/dist/src/steps/run-command.d.ts +2 -0
- package/dist/src/steps/run-command.js +15 -0
- package/dist/src/steps/sleep.d.ts +3 -0
- package/dist/src/steps/sleep.js +19 -0
- package/dist/src/steps/wait-for-decision.d.ts +2 -0
- package/dist/src/steps/wait-for-decision.js +71 -0
- package/dist/src/steps/wait-for-run.d.ts +5 -0
- package/dist/src/steps/wait-for-run.js +9 -0
- package/dist/src/storage/decision-snapshots.d.ts +1 -0
- package/dist/src/storage/decision-snapshots.js +7 -1
- package/dist/src/submission.d.ts +4 -0
- package/dist/src/submission.js +6 -2
- package/dist/src/testing.d.ts +29 -0
- package/dist/src/testing.js +264 -0
- package/dist/src/ticket-status-stream.d.ts +9 -0
- package/dist/src/ticket-status-stream.js +94 -0
- package/dist/src/token-prices.d.ts +12 -4
- package/dist/src/token-prices.js +15 -2
- package/dist/src/turn-profile.d.ts +1 -0
- package/dist/src/turn-profile.js +8 -1
- package/dist/src/worker-usage.d.ts +16 -0
- package/dist/src/worker-usage.js +57 -0
- package/dist/src/workflow-admission.d.ts +5 -0
- package/dist/src/workflow-candidate.d.ts +7 -2
- package/dist/src/workflow-candidate.js +47 -5
- package/dist/src/workflow-declaration.d.ts +21 -3
- package/dist/src/workflow-declaration.js +77 -9
- package/dist/src/workflow-discovery.d.ts +2 -1
- package/dist/src/workflow-discovery.js +4 -1
- package/dist/src/workflow-refusals.js +3 -0
- package/dist/src/workflow-schedule.d.ts +22 -0
- package/dist/src/workflow-schedule.js +53 -0
- package/dist/src/workflows.d.ts +11 -1
- package/dist/src/workflows.js +8 -0
- package/dist/tools/admit-workflow.d.ts +1 -0
- package/dist/tools/admit-workflow.js +18 -5
- package/dist/tools/doctor-adoption.d.ts +1 -0
- package/dist/tools/doctor-adoption.js +11 -0
- package/dist/tools/project-configuration.d.ts +4 -0
- package/dist/tools/project-configuration.js +47 -0
- package/dist/tools/self-host-processes.d.ts +1 -0
- package/dist/tools/self-host-processes.js +33 -22
- package/dist/tools/self-host-project.d.ts +4 -0
- package/dist/tools/self-host-project.js +61 -14
- package/dist/tools/self-host-runtime.d.ts +16 -0
- package/dist/tools/self-host-runtime.js +60 -0
- package/dist/tools/self-host-workflows.d.ts +1 -0
- package/dist/tools/self-host-workflows.js +36 -1
- package/dist/tools/self-host.js +86 -61
- package/dist/tools/workflow-candidate-counts.d.ts +6 -2
- package/dist/tools/workflow-candidate-counts.js +31 -16
- package/dist/tools/workflow-candidate-fields.d.ts +5 -0
- package/dist/tools/workflow-candidate-fields.js +24 -0
- package/dist/tools/workflow-candidate-helper-counts.d.ts +10 -0
- package/dist/tools/workflow-candidate-helper-counts.js +129 -0
- package/dist/tools/workflow-candidate-program.d.ts +2 -0
- package/dist/tools/workflow-candidate-program.js +36 -8
- package/dist/tools/workflow-candidate-source.js +77 -15
- package/dist/tools/workflow-candidate-syntax.d.ts +8 -2
- package/dist/tools/workflow-candidate-syntax.js +70 -26
- package/dist/tools/workflow-command.d.ts +1 -0
- package/dist/tools/workflow-command.js +143 -0
- package/dist/tools/workflow-folder-capture.d.ts +1 -0
- package/dist/tools/workflow-folder-capture.js +47 -2
- package/dist/tools/workflow-folders.d.ts +17 -1
- package/dist/tools/workflow-folders.js +59 -6
- package/dist/tools/workflow-test-hook.d.ts +7 -0
- package/dist/tools/workflow-test-hook.js +16 -0
- package/dist/tools/workflow-test-loader.d.ts +1 -0
- package/dist/tools/workflow-test-loader.js +10 -0
- package/dist/workflows/develop-ticket.js +1 -1
- package/dist/workflows/ticket-prompts.js +5 -1
- package/package.json +46 -4
- package/templates/develop/README.md +78 -0
- package/templates/develop/develop/accept.ts +11 -0
- package/templates/develop/develop/flow-tests.ts +357 -0
- package/templates/develop/develop/local.ts +40 -0
- package/templates/develop/develop/option-tests.ts +174 -0
- package/templates/develop/develop/partial-choice.ts +29 -0
- package/templates/develop/develop/partial.ts +28 -0
- package/templates/develop/develop/pull.ts +152 -0
- package/templates/develop/develop/queue-partial.ts +39 -0
- package/templates/develop/develop/refusal-tests.ts +174 -0
- package/templates/develop/develop/report.ts +156 -0
- package/templates/develop/develop/round.ts +40 -0
- package/templates/develop/develop/scenarios.ts +87 -0
- package/templates/develop/develop/turn.ts +67 -0
- package/templates/develop/develop.declaration.json +24 -0
- package/templates/develop/develop.test.ts +287 -0
- package/templates/develop/develop.ts +30 -0
- package/templates/develop/template.json +153 -0
- package/dist/src/chats/analysis-batches.d.ts +0 -42
- package/dist/src/chats/analysis-batches.js +0 -97
- package/dist/src/chats/analysis-checkpoint.d.ts +0 -29
- package/dist/src/chats/analysis-checkpoint.js +0 -31
- package/dist/src/chats/analysis-contract.d.ts +0 -80
- package/dist/src/chats/analysis-contract.js +0 -16
- package/dist/src/chats/analysis-data.d.ts +0 -3
- package/dist/src/chats/analysis-data.js +0 -85
- package/dist/src/chats/analysis-input.d.ts +0 -18
- package/dist/src/chats/analysis-input.js +0 -97
- package/dist/src/chats/analysis-links.d.ts +0 -2
- package/dist/src/chats/analysis-links.js +0 -25
- package/dist/src/chats/analysis-merge.d.ts +0 -16
- package/dist/src/chats/analysis-merge.js +0 -134
- package/dist/src/chats/analysis-prompt.d.ts +0 -18
- package/dist/src/chats/analysis-prompt.js +0 -42
- package/dist/src/chats/analysis-proposal.d.ts +0 -4
- package/dist/src/chats/analysis-proposal.js +0 -41
- package/dist/src/chats/analysis-provenance.d.ts +0 -4
- package/dist/src/chats/analysis-provenance.js +0 -99
- package/dist/src/chats/analysis-shape.d.ts +0 -4
- package/dist/src/chats/analysis-shape.js +0 -235
- package/dist/src/chats/analysis.d.ts +0 -3
- package/dist/src/chats/analysis.js +0 -42
- package/dist/src/chats/corpus-input.d.ts +0 -5
- package/dist/src/chats/corpus-input.js +0 -288
- package/dist/src/chats/destination.d.ts +0 -4
- package/dist/src/chats/destination.js +0 -96
- package/dist/src/chats/import.d.ts +0 -15
- package/dist/src/chats/import.js +0 -243
- package/dist/src/chats/input-file.d.ts +0 -3
- package/dist/src/chats/input-file.js +0 -32
- package/dist/src/chats/normalize.d.ts +0 -29
- package/dist/src/chats/normalize.js +0 -155
- package/dist/src/chats/previous-import.d.ts +0 -5
- package/dist/src/chats/previous-import.js +0 -34
- package/dist/src/chats/reader.d.ts +0 -21
- package/dist/src/chats/reader.js +0 -118
- package/dist/src/chats/redact-import.d.ts +0 -14
- package/dist/src/chats/redact-import.js +0 -141
- package/dist/src/chats/redaction.d.ts +0 -41
- package/dist/src/chats/redaction.js +0 -161
- package/dist/src/chats/reference-mapping.d.ts +0 -16
- package/dist/src/chats/reference-mapping.js +0 -153
- package/dist/src/chats/revision-input.d.ts +0 -3
- package/dist/src/chats/revision-input.js +0 -180
- package/dist/src/chats/revision.d.ts +0 -48
- package/dist/src/chats/revision.js +0 -94
- package/dist/src/chats/selection.d.ts +0 -25
- package/dist/src/chats/selection.js +0 -109
- package/dist/src/chats/source.d.ts +0 -23
- package/dist/src/chats/source.js +0 -135
- package/dist/src/chats/structure.d.ts +0 -57
- package/dist/src/chats/structure.js +0 -216
- package/dist/src/chats/workflow-generation-projection.d.ts +0 -8
- package/dist/src/chats/workflow-generation-projection.js +0 -75
- package/dist/src/chats/workflow-generation-source.d.ts +0 -25
- package/dist/src/chats/workflow-generation-source.js +0 -124
- package/dist/src/chats/workflow-generation-text.d.ts +0 -23
- package/dist/src/chats/workflow-generation-text.js +0 -74
- package/dist/src/chats/workflow-generation.d.ts +0 -69
- package/dist/src/chats/workflow-generation.js +0 -142
- package/dist/src/daemon/analysis-launch.d.ts +0 -5
- package/dist/src/daemon/analysis-launch.js +0 -81
- package/dist/src/daemon/analysis-token.d.ts +0 -6
- package/dist/src/daemon/analysis-token.js +0 -88
- package/dist/src/daemon/analysis-worker.d.ts +0 -20
- package/dist/src/daemon/analysis-worker.js +0 -271
- package/dist/src/daemon/chats-batch-binding.d.ts +0 -23
- package/dist/src/daemon/chats-batch-binding.js +0 -99
- package/dist/src/daemon/chats-capture.d.ts +0 -18
- package/dist/src/daemon/chats-capture.js +0 -194
- package/dist/src/daemon/chats-checkpoints.d.ts +0 -41
- package/dist/src/daemon/chats-checkpoints.js +0 -186
- package/dist/src/daemon/chats-files.d.ts +0 -42
- package/dist/src/daemon/chats-files.js +0 -252
- package/dist/src/daemon/chats-follow-up.d.ts +0 -38
- package/dist/src/daemon/chats-follow-up.js +0 -180
- package/dist/src/daemon/chats-question.d.ts +0 -15
- package/dist/src/daemon/chats-question.js +0 -93
- package/dist/src/daemon/chats-worker.d.ts +0 -13
- package/dist/src/daemon/chats-worker.js +0 -201
- package/dist/workflows/analyze-chats.d.ts +0 -15
- package/dist/workflows/analyze-chats.declaration.json +0 -22
- package/dist/workflows/analyze-chats.js +0 -250
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
|
+
import { dirname, relative, sep } from "node:path";
|
|
2
3
|
import { candidateProgram, resolvedSymbol, } from "./workflow-candidate-program.js";
|
|
3
4
|
import { protectedEffectFact, passiveCandidateModule, unsupportedCandidateNode, workflowShape, } from "./workflow-candidate-syntax.js";
|
|
4
5
|
import { sourceEffectNodes } from "./workflow-source-effects.js";
|
|
5
6
|
import { candidateEffectTotals } from "./workflow-candidate-counts.js";
|
|
7
|
+
import { helperEffectTotals } from "./workflow-candidate-helper-counts.js";
|
|
6
8
|
function exportSnapshot(modules, checker) {
|
|
7
9
|
return Object.fromEntries([...modules].map(([name, declaration]) => {
|
|
8
10
|
const symbol = checker.getSymbolAtLocation(declaration);
|
|
@@ -68,8 +70,21 @@ function sourceImport(node) {
|
|
|
68
70
|
: [],
|
|
69
71
|
};
|
|
70
72
|
}
|
|
73
|
+
function mergeHelpers(modules, checker) {
|
|
74
|
+
return [
|
|
75
|
+
["merge-when-green", "mergeWhenGreen"],
|
|
76
|
+
["merge-by-person", "mergeByPerson"],
|
|
77
|
+
].flatMap(([module, name]) => {
|
|
78
|
+
const symbol = protectedHelper(modules, {
|
|
79
|
+
checker,
|
|
80
|
+
subpath: `cloving/workflows/steps/${String(module)}`,
|
|
81
|
+
name: String(name),
|
|
82
|
+
});
|
|
83
|
+
return symbol === undefined ? [] : [symbol];
|
|
84
|
+
});
|
|
85
|
+
}
|
|
71
86
|
export function analyzeWorkflowCandidate(text, installed = {}) {
|
|
72
|
-
const { program, source, modules } = candidateProgram(text, installed);
|
|
87
|
+
const { program, source, sources, modules } = candidateProgram(text, installed);
|
|
73
88
|
const checker = program.getTypeChecker();
|
|
74
89
|
const symbols = {
|
|
75
90
|
checker,
|
|
@@ -84,24 +99,71 @@ export function analyzeWorkflowCandidate(text, installed = {}) {
|
|
|
84
99
|
subpath: "cloving/workflows/steps/handoff",
|
|
85
100
|
name: "handoff",
|
|
86
101
|
}),
|
|
102
|
+
commandSymbol: protectedHelper(modules, {
|
|
103
|
+
checker,
|
|
104
|
+
subpath: "cloving/workflows/steps/run-command",
|
|
105
|
+
name: "runCommand",
|
|
106
|
+
}),
|
|
107
|
+
reviewSymbol: protectedHelper(modules, {
|
|
108
|
+
checker,
|
|
109
|
+
subpath: "cloving/workflows/steps/review-by-agent",
|
|
110
|
+
name: "reviewByAgent",
|
|
111
|
+
}),
|
|
112
|
+
mergeSymbols: mergeHelpers(modules, checker),
|
|
113
|
+
};
|
|
114
|
+
const facts = sources.map((entry) => analyzedSource({ ...symbols, source: entry }, { program, workflow: source }));
|
|
115
|
+
return {
|
|
116
|
+
analysis: combineFacts({
|
|
117
|
+
localSources: Object.keys(installed.helpers ?? {}),
|
|
118
|
+
facts,
|
|
119
|
+
expanded: helperEffectTotals({
|
|
120
|
+
symbols: { ...symbols, source },
|
|
121
|
+
sources,
|
|
122
|
+
}),
|
|
123
|
+
}),
|
|
124
|
+
installedExports: exportSnapshot(modules, checker),
|
|
87
125
|
};
|
|
126
|
+
}
|
|
127
|
+
function analyzedSource(symbols, input) {
|
|
128
|
+
const { source } = symbols;
|
|
88
129
|
const facts = sourceFacts(symbols);
|
|
89
|
-
const
|
|
90
|
-
|
|
130
|
+
const kind = source === input.workflow ? "workflow" : "helper";
|
|
131
|
+
const path = relative(dirname(input.workflow.fileName), source.fileName)
|
|
132
|
+
.split(sep)
|
|
133
|
+
.join("/");
|
|
134
|
+
const invalid = source.referencedFiles.length > 0 ||
|
|
91
135
|
source.typeReferenceDirectives.length > 0 ||
|
|
92
136
|
source.libReferenceDirectives.length > 0 ||
|
|
93
|
-
program.getSyntacticDiagnostics(source).length > 0;
|
|
137
|
+
input.program.getSyntacticDiagnostics(source).length > 0;
|
|
94
138
|
return {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
139
|
+
...facts,
|
|
140
|
+
imports: facts.imports.map((entry) => kind === "workflow" ? entry : { ...entry, source: path }),
|
|
141
|
+
unsupportedForms: [
|
|
142
|
+
...facts.unsupportedForms,
|
|
143
|
+
...(invalid || (kind === "workflow" && !workflowShape(source))
|
|
144
|
+
? ["workflow-shape"]
|
|
145
|
+
: []),
|
|
146
|
+
...(facts.directEffects.length === 0 &&
|
|
147
|
+
!passiveCandidateModule(source, kind)
|
|
148
|
+
? ["module-initialization"]
|
|
149
|
+
: []),
|
|
150
|
+
],
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function combineFacts(input) {
|
|
154
|
+
const { localSources, facts } = input;
|
|
155
|
+
return {
|
|
156
|
+
localSources,
|
|
157
|
+
imports: facts.flatMap((entry) => entry.imports),
|
|
158
|
+
effects: facts.flatMap((entry) => entry.effects),
|
|
159
|
+
directEffects: facts.flatMap((entry) => entry.directEffects),
|
|
160
|
+
unsupportedForms: [
|
|
161
|
+
...facts.flatMap((entry) => entry.unsupportedForms),
|
|
162
|
+
...input.expanded.unsupportedForms,
|
|
163
|
+
],
|
|
164
|
+
knownCallCount: input.expanded.totals?.knownCallCount ??
|
|
165
|
+
facts.reduce((total, entry) => total + entry.knownCallCount, 0),
|
|
166
|
+
knownUnitTotal: input.expanded.totals?.knownUnitTotal ??
|
|
167
|
+
facts.reduce((total, entry) => total + entry.knownUnitTotal, 0),
|
|
106
168
|
};
|
|
107
169
|
}
|
|
@@ -5,11 +5,17 @@ export interface CandidateSymbols {
|
|
|
5
5
|
readonly source: ts.SourceFile;
|
|
6
6
|
readonly protectedSymbol: ts.Symbol | undefined;
|
|
7
7
|
readonly handoffSymbol: ts.Symbol | undefined;
|
|
8
|
+
readonly commandSymbol: ts.Symbol | undefined;
|
|
9
|
+
readonly reviewSymbol: ts.Symbol | undefined;
|
|
10
|
+
readonly mergeSymbols: readonly ts.Symbol[];
|
|
8
11
|
}
|
|
9
|
-
export declare function propertyName(name: ts.PropertyName): string | undefined;
|
|
10
12
|
export declare function protectedCall(node: ts.Node, symbols: CandidateSymbols): node is ts.CallExpression;
|
|
11
13
|
export declare function handoffCall(node: ts.CallExpression, symbols: CandidateSymbols): boolean;
|
|
14
|
+
export declare function commandCall(node: ts.CallExpression, symbols: CandidateSymbols): boolean;
|
|
15
|
+
export declare function reviewCall(node: ts.CallExpression, symbols: CandidateSymbols): boolean;
|
|
16
|
+
export declare function helperCall(node: ts.CallExpression, symbols: CandidateSymbols): boolean;
|
|
17
|
+
export declare function mergeCall(node: ts.CallExpression, symbols: CandidateSymbols): boolean;
|
|
12
18
|
export declare function protectedEffectFact(node: ts.Node, symbols: CandidateSymbols): CandidateEffect | undefined;
|
|
13
19
|
export declare function unsupportedCandidateNode(node: ts.Node, symbols: CandidateSymbols): boolean;
|
|
14
20
|
export declare function workflowShape(source: ts.SourceFile): boolean;
|
|
15
|
-
export declare function passiveCandidateModule(source: ts.SourceFile): boolean;
|
|
21
|
+
export declare function passiveCandidateModule(source: ts.SourceFile, kind?: "workflow" | "helper"): boolean;
|
|
@@ -1,29 +1,41 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
2
|
import { resolvedSymbol } from "./workflow-candidate-program.js";
|
|
3
3
|
import { referenceSymbol } from "./workflow-source-effects.js";
|
|
4
|
-
|
|
5
|
-
if (ts.isIdentifier(name) || ts.isStringLiteral(name))
|
|
6
|
-
return name.text;
|
|
7
|
-
return undefined;
|
|
8
|
-
}
|
|
4
|
+
import { invalidFields, literalField, propertyInitializer, } from "./workflow-candidate-fields.js";
|
|
9
5
|
export function protectedCall(node, symbols) {
|
|
10
6
|
if (!ts.isCallExpression(node) || !ts.isIdentifier(node.expression))
|
|
11
7
|
return false;
|
|
12
8
|
const symbol = resolvedSymbol(symbols.checker, symbols.checker.getSymbolAtLocation(node.expression));
|
|
13
9
|
return (symbol !== undefined &&
|
|
14
|
-
[
|
|
10
|
+
[
|
|
11
|
+
symbols.protectedSymbol,
|
|
12
|
+
symbols.handoffSymbol,
|
|
13
|
+
symbols.commandSymbol,
|
|
14
|
+
symbols.reviewSymbol,
|
|
15
|
+
...symbols.mergeSymbols,
|
|
16
|
+
].includes(symbol));
|
|
17
|
+
}
|
|
18
|
+
function calledSymbol(node, symbols) {
|
|
19
|
+
return resolvedSymbol(symbols.checker, symbols.checker.getSymbolAtLocation(node.expression));
|
|
15
20
|
}
|
|
16
21
|
export function handoffCall(node, symbols) {
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
const symbol = symbols.handoffSymbol;
|
|
23
|
+
return symbol !== undefined && calledSymbol(node, symbols) === symbol;
|
|
24
|
+
}
|
|
25
|
+
export function commandCall(node, symbols) {
|
|
26
|
+
const symbol = symbols.commandSymbol;
|
|
27
|
+
return symbol !== undefined && calledSymbol(node, symbols) === symbol;
|
|
19
28
|
}
|
|
20
|
-
function
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
29
|
+
export function reviewCall(node, symbols) {
|
|
30
|
+
const symbol = symbols.reviewSymbol;
|
|
31
|
+
return symbol !== undefined && calledSymbol(node, symbols) === symbol;
|
|
32
|
+
}
|
|
33
|
+
export function helperCall(node, symbols) {
|
|
34
|
+
return [handoffCall, commandCall, reviewCall, mergeCall].some((call) => call(node, symbols));
|
|
35
|
+
}
|
|
36
|
+
export function mergeCall(node, symbols) {
|
|
37
|
+
const symbol = calledSymbol(node, symbols);
|
|
38
|
+
return symbol !== undefined && symbols.mergeSymbols.includes(symbol);
|
|
27
39
|
}
|
|
28
40
|
export function protectedEffectFact(node, symbols) {
|
|
29
41
|
if (!protectedCall(node, symbols))
|
|
@@ -33,17 +45,45 @@ export function protectedEffectFact(node, symbols) {
|
|
|
33
45
|
const argument = node.arguments[0];
|
|
34
46
|
if (!argument || !ts.isObjectLiteralExpression(argument))
|
|
35
47
|
return undefined;
|
|
48
|
+
if (reviewCall(node, symbols))
|
|
49
|
+
return reviewEffectFact(propertyInitializer(argument, "reviewer"));
|
|
50
|
+
if (mergeCall(node, symbols))
|
|
51
|
+
return { capability: "github", method: "merge" };
|
|
52
|
+
if (commandCall(node, symbols)) {
|
|
53
|
+
const name = literalField(argument, "name");
|
|
54
|
+
return {
|
|
55
|
+
capability: "command",
|
|
56
|
+
method: name === null ? null : `run:${name}`,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
36
59
|
return {
|
|
37
60
|
capability: literalField(argument, "capability"),
|
|
38
61
|
method: literalField(argument, "method"),
|
|
39
62
|
};
|
|
40
63
|
}
|
|
64
|
+
function reviewEffectFact(reviewer) {
|
|
65
|
+
const kind = literalField(reviewer, "kind");
|
|
66
|
+
if (kind === "greptile")
|
|
67
|
+
return { capability: "github", method: "wait-review" };
|
|
68
|
+
const profile = literalField(reviewer, "profile");
|
|
69
|
+
if (kind === "turn" &&
|
|
70
|
+
profile !== null &&
|
|
71
|
+
/^[A-Za-z0-9_-]{1,119}$/.test(profile))
|
|
72
|
+
return { capability: "claude", method: `run-turn:${profile}` };
|
|
73
|
+
return { capability: null, method: null };
|
|
74
|
+
}
|
|
41
75
|
function escapedHelper(node, symbols) {
|
|
42
76
|
if (!ts.isIdentifier(node))
|
|
43
77
|
return false;
|
|
44
78
|
const symbol = resolvedSymbol(symbols.checker, referenceSymbol(node, { parent: node.parent, checker: symbols.checker }));
|
|
45
79
|
if (symbol === undefined ||
|
|
46
|
-
![
|
|
80
|
+
![
|
|
81
|
+
symbols.protectedSymbol,
|
|
82
|
+
symbols.handoffSymbol,
|
|
83
|
+
symbols.commandSymbol,
|
|
84
|
+
symbols.reviewSymbol,
|
|
85
|
+
...symbols.mergeSymbols,
|
|
86
|
+
].includes(symbol))
|
|
47
87
|
return false;
|
|
48
88
|
if (ts.isImportSpecifier(node.parent))
|
|
49
89
|
return false;
|
|
@@ -71,10 +111,13 @@ function invalidRequest(node, symbols) {
|
|
|
71
111
|
!argument ||
|
|
72
112
|
!ts.isObjectLiteralExpression(argument))
|
|
73
113
|
return true;
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
114
|
+
const reviewer = reviewCall(node, symbols)
|
|
115
|
+
? propertyInitializer(argument, "reviewer")
|
|
116
|
+
: undefined;
|
|
117
|
+
return (invalidFields(argument) ||
|
|
118
|
+
(reviewer !== undefined &&
|
|
119
|
+
ts.isObjectLiteralExpression(reviewer) &&
|
|
120
|
+
invalidFields(reviewer)));
|
|
78
121
|
}
|
|
79
122
|
function workflowBodyCall(node) {
|
|
80
123
|
let child = node;
|
|
@@ -198,12 +241,13 @@ function passiveInitializer(node) {
|
|
|
198
241
|
const inner = unwrappedInitializer(node);
|
|
199
242
|
return inner ? passiveInitializer(inner) : passiveCompound(node);
|
|
200
243
|
}
|
|
201
|
-
function passiveStatement(node) {
|
|
244
|
+
function passiveStatement(node, kind) {
|
|
202
245
|
if (ts.isVariableStatement(node))
|
|
203
246
|
return ((node.declarationList.flags & ts.NodeFlags.Const) !== 0 &&
|
|
204
|
-
node.declarationList.declarations.every((declaration) => (
|
|
205
|
-
ts.
|
|
206
|
-
|
|
247
|
+
node.declarationList.declarations.every((declaration) => (kind === "helper" ||
|
|
248
|
+
(ts.getCombinedModifierFlags(declaration) &
|
|
249
|
+
ts.ModifierFlags.Export) ===
|
|
250
|
+
0) &&
|
|
207
251
|
ts.isIdentifier(declaration.name) &&
|
|
208
252
|
passiveInitializer(declaration.initializer)));
|
|
209
253
|
if (ts.isExpressionStatement(node))
|
|
@@ -214,6 +258,6 @@ function passiveStatement(node) {
|
|
|
214
258
|
ts.isFunctionDeclaration(node) ||
|
|
215
259
|
ts.isEmptyStatement(node));
|
|
216
260
|
}
|
|
217
|
-
export function passiveCandidateModule(source) {
|
|
218
|
-
return source.statements.every(passiveStatement);
|
|
261
|
+
export function passiveCandidateModule(source, kind = "workflow") {
|
|
262
|
+
return source.statements.every((node) => passiveStatement(node, kind));
|
|
219
263
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function workflowCommand(argumentsList: readonly string[]): Promise<number>;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { absoluteWorkflowFolder } from "../src/project-settings.js";
|
|
2
|
+
import { projectConfiguration, projectRoot } from "./project-configuration.js";
|
|
3
|
+
import { spawn } from "node:child_process";
|
|
4
|
+
import { lstat, mkdtemp, rm } from "node:fs/promises";
|
|
5
|
+
import { homedir, tmpdir } from "node:os";
|
|
6
|
+
import { join, resolve } from "node:path";
|
|
7
|
+
import { parseArgs } from "node:util";
|
|
8
|
+
import { workflowTestLoader } from "./workflow-test-loader.js";
|
|
9
|
+
import { preparedProject } from "./self-host-project.js";
|
|
10
|
+
const usage = "Usage: cloving workflows list [--json] [--repository <directory>]\n cloving workflows test [<id>] [--repository <directory>]\n";
|
|
11
|
+
function invocation(argumentsList) {
|
|
12
|
+
const { values, positionals } = parseArgs({
|
|
13
|
+
args: [...argumentsList],
|
|
14
|
+
allowPositionals: true,
|
|
15
|
+
options: {
|
|
16
|
+
json: { type: "boolean" },
|
|
17
|
+
repository: { type: "string" },
|
|
18
|
+
help: { type: "boolean", short: "h" },
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
const [command, id, ...extra] = positionals;
|
|
22
|
+
if (extra.length > 0 || (command === "list" && id !== undefined))
|
|
23
|
+
throw new Error("unexpected-argument");
|
|
24
|
+
if (command !== "list" && command !== "test")
|
|
25
|
+
throw new Error("unknown-command");
|
|
26
|
+
if (command === "test" && values.json)
|
|
27
|
+
throw new Error("unexpected-option");
|
|
28
|
+
return { ...values, command, id };
|
|
29
|
+
}
|
|
30
|
+
export async function workflowCommand(argumentsList) {
|
|
31
|
+
let selected;
|
|
32
|
+
try {
|
|
33
|
+
selected = invocation(argumentsList);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
process.stderr.write("invalid-invocation: " + usage);
|
|
37
|
+
return 2;
|
|
38
|
+
}
|
|
39
|
+
if (selected.help) {
|
|
40
|
+
process.stdout.write(usage);
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
const temporary = await mkdtemp(join(tmpdir(), "cloving-workflows-"));
|
|
44
|
+
try {
|
|
45
|
+
const repository = resolve(selected.repository ?? process.cwd());
|
|
46
|
+
const result = await preparedProject({
|
|
47
|
+
product: resolve(import.meta.dirname, ".."),
|
|
48
|
+
project: join(temporary, "project"),
|
|
49
|
+
repository,
|
|
50
|
+
home: homedir(),
|
|
51
|
+
xdgConfigHome: process.env["XDG_CONFIG_HOME"],
|
|
52
|
+
userFolder: absoluteWorkflowFolder((await projectConfiguration(await projectRoot(repository), process.env))
|
|
53
|
+
.environment["CLOVING_WORKFLOW_FOLDER"]),
|
|
54
|
+
});
|
|
55
|
+
if (selected.command === "test")
|
|
56
|
+
return await testWorkflows(result.workflows, {
|
|
57
|
+
id: selected.id,
|
|
58
|
+
repository,
|
|
59
|
+
});
|
|
60
|
+
presentWorkflows(result.workflows, { json: selected.json === true });
|
|
61
|
+
return 0;
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
process.stderr.write("workflow-inspection-failed: " +
|
|
65
|
+
(error instanceof Error ? error.message : "unavailable") +
|
|
66
|
+
"\n");
|
|
67
|
+
return 1;
|
|
68
|
+
}
|
|
69
|
+
finally {
|
|
70
|
+
await rm(temporary, { recursive: true, force: true });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function presentWorkflows(workflows, options) {
|
|
74
|
+
if (options.json) {
|
|
75
|
+
process.stdout.write(JSON.stringify(workflows) + "\n");
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
for (const workflow of workflows)
|
|
79
|
+
process.stdout.write(`${workflow.workflowId ?? "unknown"} (${workflow.scope}, ${workflow.admitted ? "admitted" : "refused: " + workflow.codes.join(", ")}) ${JSON.stringify(workflow.file)}\n`);
|
|
80
|
+
}
|
|
81
|
+
async function testWorkflows(workflows, options) {
|
|
82
|
+
const { id, repository } = options;
|
|
83
|
+
const selected = workflows.filter((workflow) => workflow.scope !== "bundled" &&
|
|
84
|
+
(id === undefined || workflow.workflowId === id));
|
|
85
|
+
if (id !== undefined &&
|
|
86
|
+
!workflows.some((workflow) => workflow.workflowId === id)) {
|
|
87
|
+
process.stderr.write("unknown-workflow: " + id + "\n");
|
|
88
|
+
return 1;
|
|
89
|
+
}
|
|
90
|
+
const files = [];
|
|
91
|
+
for (const workflow of selected) {
|
|
92
|
+
const file = workflow.file.replace(/\.ts$/, ".test.ts");
|
|
93
|
+
const exists = await lstat(file).catch((error) => {
|
|
94
|
+
if (error instanceof Error && "code" in error && error.code === "ENOENT")
|
|
95
|
+
return undefined;
|
|
96
|
+
throw error;
|
|
97
|
+
});
|
|
98
|
+
if (exists?.isFile())
|
|
99
|
+
files.push(file);
|
|
100
|
+
}
|
|
101
|
+
if (files.length === 0) {
|
|
102
|
+
process.stderr.write("workflow-test-missing: " + (id ?? "no project or user tests") + "\n");
|
|
103
|
+
return 1;
|
|
104
|
+
}
|
|
105
|
+
return await runTests(files, repository);
|
|
106
|
+
}
|
|
107
|
+
function runTests(files, repository) {
|
|
108
|
+
return new Promise((settle, reject) => {
|
|
109
|
+
const child = spawn(process.execPath, [
|
|
110
|
+
"--experimental-strip-types",
|
|
111
|
+
"--import",
|
|
112
|
+
workflowTestLoader(),
|
|
113
|
+
"--test",
|
|
114
|
+
...files,
|
|
115
|
+
], {
|
|
116
|
+
cwd: repository,
|
|
117
|
+
stdio: "inherit",
|
|
118
|
+
env: { ...process.env, NODE_TEST_CONTEXT: undefined },
|
|
119
|
+
});
|
|
120
|
+
const interrupt = () => {
|
|
121
|
+
child.kill("SIGINT");
|
|
122
|
+
};
|
|
123
|
+
const terminate = () => {
|
|
124
|
+
child.kill("SIGTERM");
|
|
125
|
+
};
|
|
126
|
+
process.on("SIGINT", interrupt);
|
|
127
|
+
process.on("SIGTERM", terminate);
|
|
128
|
+
const cleanup = () => {
|
|
129
|
+
process.off("SIGINT", interrupt);
|
|
130
|
+
process.off("SIGTERM", terminate);
|
|
131
|
+
};
|
|
132
|
+
child.once("error", (error) => {
|
|
133
|
+
cleanup();
|
|
134
|
+
reject(error);
|
|
135
|
+
});
|
|
136
|
+
child.once("close", (code) => {
|
|
137
|
+
cleanup();
|
|
138
|
+
settle(code ?? 1);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
if (process.argv[1] === import.meta.filename)
|
|
143
|
+
process.exitCode = await workflowCommand(process.argv.slice(2));
|
|
@@ -11,6 +11,7 @@ export declare function inspectWorkflowFolder(root: string, parts: readonly stri
|
|
|
11
11
|
export declare function captureWorkflowCandidate(folder: WorkflowFolder, name: string): Promise<{
|
|
12
12
|
source: string | undefined;
|
|
13
13
|
declaration: string | undefined;
|
|
14
|
+
helpers: Record<string, string>;
|
|
14
15
|
codes: WorkflowCaptureCode[];
|
|
15
16
|
}>;
|
|
16
17
|
export declare function workflowCaptureFailure(error: unknown): WorkflowCaptureCode;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { constants } from "node:fs";
|
|
2
2
|
import { lstat, open, readdir, realpath, } from "node:fs/promises";
|
|
3
3
|
import { isAbsolute, join, relative, sep } from "node:path";
|
|
4
|
+
import ts from "typescript";
|
|
5
|
+
import { workflowHelperPath } from "../src/workflow-candidate.js";
|
|
4
6
|
function contained(root, path) {
|
|
5
7
|
const suffix = relative(root, path);
|
|
6
8
|
return (!isAbsolute(suffix) && suffix !== ".." && !suffix.startsWith(`..${sep}`));
|
|
@@ -92,6 +94,19 @@ async function openSource(folder, name) {
|
|
|
92
94
|
}
|
|
93
95
|
}
|
|
94
96
|
async function inspectFile(folder, name) {
|
|
97
|
+
const parts = name.split("/");
|
|
98
|
+
const fileName = parts.pop();
|
|
99
|
+
if (!fileName || parts.some((part) => !safeComponent(part)))
|
|
100
|
+
throw new Error("unsafe-workflow-path");
|
|
101
|
+
let parent = folder;
|
|
102
|
+
for (const part of parts) {
|
|
103
|
+
const path = join(parent.path, part);
|
|
104
|
+
const stats = await lstat(path, { bigint: true });
|
|
105
|
+
if (!stats.isDirectory())
|
|
106
|
+
throw new Error("unsafe-workflow-path");
|
|
107
|
+
parent = { path, components: [...parent.components, { path, stats }] };
|
|
108
|
+
}
|
|
109
|
+
await verifyFolder(parent);
|
|
95
110
|
const path = join(folder.path, name);
|
|
96
111
|
const stats = await lstat(path, { bigint: true });
|
|
97
112
|
if (!stats.isFile())
|
|
@@ -101,11 +116,12 @@ async function inspectFile(folder, name) {
|
|
|
101
116
|
throw new Error("workflow-source-changed");
|
|
102
117
|
if (!contained(folder.path, resolved))
|
|
103
118
|
throw new Error("unsafe-workflow-path");
|
|
104
|
-
return { path, name, stats };
|
|
119
|
+
return { path, name, stats, folder: parent, fileName };
|
|
105
120
|
}
|
|
106
121
|
async function captureFile(folder, file) {
|
|
107
122
|
const { stats } = file;
|
|
108
|
-
|
|
123
|
+
await verifyFolder(folder);
|
|
124
|
+
const handle = await openSource(file.folder, file.fileName).catch(changedPathError);
|
|
109
125
|
try {
|
|
110
126
|
if (!sameSnapshot(stats, await handle.stat({ bigint: true })))
|
|
111
127
|
throw new Error("workflow-source-changed");
|
|
@@ -140,11 +156,38 @@ async function captureFiles(folder, names) {
|
|
|
140
156
|
}
|
|
141
157
|
}
|
|
142
158
|
for (const file of captured) {
|
|
159
|
+
await verifyFolder(file.folder);
|
|
143
160
|
if (!sameSnapshot(file.stats, await capturedStats(file.path)))
|
|
144
161
|
throw new Error("workflow-source-changed");
|
|
145
162
|
}
|
|
146
163
|
return { captured, codes };
|
|
147
164
|
}
|
|
165
|
+
async function captureImports(folder, snapshot) {
|
|
166
|
+
const { captured, codes } = snapshot;
|
|
167
|
+
const helpers = {};
|
|
168
|
+
for (const source of captured) {
|
|
169
|
+
if (!source.name.endsWith(".ts"))
|
|
170
|
+
continue;
|
|
171
|
+
for (const imported of ts.preProcessFile(source.bytes.toString("utf8"))
|
|
172
|
+
.importedFiles) {
|
|
173
|
+
const name = workflowHelperPath(source.name, imported.fileName);
|
|
174
|
+
if (!name || captured.some((file) => file.name === name))
|
|
175
|
+
continue;
|
|
176
|
+
const result = await captureFiles(folder, [name]);
|
|
177
|
+
codes.push(...result.codes);
|
|
178
|
+
captured.push(...result.captured);
|
|
179
|
+
const text = decodedFile({ bytes: result.captured[0]?.bytes, code: "unsupported-source" }, codes);
|
|
180
|
+
if (text !== undefined)
|
|
181
|
+
helpers[name] = text;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
for (const file of captured) {
|
|
185
|
+
await verifyFolder(file.folder);
|
|
186
|
+
if (!sameSnapshot(file.stats, await capturedStats(file.path)))
|
|
187
|
+
throw new Error("workflow-source-changed");
|
|
188
|
+
}
|
|
189
|
+
return helpers;
|
|
190
|
+
}
|
|
148
191
|
function decodedFile(input, codes) {
|
|
149
192
|
if (input.bytes === undefined)
|
|
150
193
|
return undefined;
|
|
@@ -163,6 +206,7 @@ export async function captureWorkflowCandidate(folder, name) {
|
|
|
163
206
|
name,
|
|
164
207
|
declarationName,
|
|
165
208
|
]);
|
|
209
|
+
const helpers = await captureImports(folder, { captured, codes });
|
|
166
210
|
await verifyFolder(folder);
|
|
167
211
|
const source = decodedFile({
|
|
168
212
|
bytes: captured.find((file) => file.name === name)?.bytes,
|
|
@@ -175,6 +219,7 @@ export async function captureWorkflowCandidate(folder, name) {
|
|
|
175
219
|
return {
|
|
176
220
|
source,
|
|
177
221
|
declaration,
|
|
222
|
+
helpers,
|
|
178
223
|
codes: [
|
|
179
224
|
...new Set(codes.includes("unsafe-workflow-path")
|
|
180
225
|
? codes.filter((code) => code !== "workflow-read-failed")
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { WorkflowDeclaration } from "../src/workflow-declaration.ts";
|
|
2
|
+
import { type CandidateDeclaration, type WorkflowCandidateCode } from "../src/workflow-candidate.ts";
|
|
2
3
|
import { type WorkflowConflictCode, type WorkflowReservation } from "../src/workflow-discovery.ts";
|
|
3
4
|
import type { CandidatePackageOptions } from "./workflow-candidate-program.ts";
|
|
4
5
|
import { type WorkflowCaptureCode } from "./workflow-folder-capture.ts";
|
|
@@ -6,6 +7,7 @@ export interface WorkflowFolderInput {
|
|
|
6
7
|
readonly repository: string;
|
|
7
8
|
readonly home: string;
|
|
8
9
|
readonly xdgConfigHome?: string | undefined;
|
|
10
|
+
readonly userFolder?: string | undefined;
|
|
9
11
|
readonly bundled: readonly WorkflowReservation[];
|
|
10
12
|
}
|
|
11
13
|
interface WorkflowLabel {
|
|
@@ -16,6 +18,7 @@ interface WorkflowSnapshot extends WorkflowLabel {
|
|
|
16
18
|
readonly baseName: string;
|
|
17
19
|
readonly source: string;
|
|
18
20
|
readonly declaration: string;
|
|
21
|
+
readonly helpers: Readonly<Record<string, string>>;
|
|
19
22
|
}
|
|
20
23
|
export interface WorkflowFolderCandidate extends WorkflowSnapshot {
|
|
21
24
|
readonly repository: string;
|
|
@@ -24,10 +27,23 @@ export interface WorkflowFolderCandidate extends WorkflowSnapshot {
|
|
|
24
27
|
export interface WorkflowFolderRefusal extends WorkflowLabel {
|
|
25
28
|
readonly codes: readonly (WorkflowCandidateCode | WorkflowCaptureCode | WorkflowConflictCode | "compile-failed")[];
|
|
26
29
|
}
|
|
30
|
+
export interface WorkflowListing {
|
|
31
|
+
readonly scope: "bundled" | "project" | "user";
|
|
32
|
+
readonly workflowId: string | null;
|
|
33
|
+
readonly file: string;
|
|
34
|
+
readonly admitted: boolean;
|
|
35
|
+
readonly codes: readonly string[];
|
|
36
|
+
readonly declaration?: CandidateDeclaration | WorkflowDeclaration;
|
|
37
|
+
}
|
|
27
38
|
export interface WorkflowFolderResult {
|
|
39
|
+
readonly workflows: readonly WorkflowListing[];
|
|
28
40
|
readonly repository: string;
|
|
29
41
|
readonly candidates: readonly WorkflowFolderCandidate[];
|
|
30
42
|
readonly refusals: readonly WorkflowFolderRefusal[];
|
|
31
43
|
}
|
|
44
|
+
export declare function userLocation(input: Pick<WorkflowFolderInput, "home" | "xdgConfigHome" | "userFolder">): {
|
|
45
|
+
readonly root: string;
|
|
46
|
+
readonly parts: readonly string[];
|
|
47
|
+
};
|
|
32
48
|
export declare function loadWorkflowFolders(input: WorkflowFolderInput, installed?: CandidatePackageOptions): Promise<WorkflowFolderResult>;
|
|
33
49
|
export {};
|