cloving 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +329 -215
- package/dist/src/agent-harness-shell.d.ts +2 -1
- package/dist/src/agent-harness-shell.js +8 -5
- package/dist/src/authority/command-wait-checks.d.ts +8 -0
- package/dist/src/authority/command-wait-checks.js +88 -0
- package/dist/src/authority/command-wait-results.d.ts +15 -0
- package/dist/src/authority/command-wait-results.js +73 -0
- package/dist/src/authority/command-wait-view.d.ts +21 -0
- package/dist/src/authority/command-wait-view.js +34 -0
- package/dist/src/authority/command-waits.d.ts +39 -0
- package/dist/src/authority/command-waits.js +97 -0
- package/dist/src/authority/commands.js +22 -1
- package/dist/src/authority/dispatch-decision.d.ts +8 -0
- package/dist/src/authority/dispatch-decision.js +26 -1
- package/dist/src/authority/effect-requests.js +6 -3
- package/dist/src/authority/effect-results.js +4 -2
- package/dist/src/authority/history-state.d.ts +2 -0
- package/dist/src/authority/history-state.js +13 -1
- package/dist/src/authority/instants.d.ts +1 -0
- package/dist/src/authority/instants.js +21 -0
- package/dist/src/authority/reduction-state.d.ts +2 -0
- package/dist/src/authority/reduction-state.js +5 -0
- package/dist/src/authority/reduction.js +24 -0
- package/dist/src/authority/status-input.d.ts +2 -0
- package/dist/src/authority/status.d.ts +2 -0
- package/dist/src/authority/status.js +1 -0
- package/dist/src/authority/stop-sequence.d.ts +1 -0
- package/dist/src/authority/stop-sequence.js +2 -1
- package/dist/src/authority/transitions.d.ts +6 -4
- package/dist/src/authority/transitions.js +7 -0
- package/dist/src/broker/actor/authority-health.d.ts +9 -0
- package/dist/src/broker/actor/authority-health.js +24 -0
- package/dist/src/broker/actor/authority-queries.d.ts +2 -1
- package/dist/src/broker/actor/authority-queries.js +14 -5
- package/dist/src/broker/actor/authority-receipts.js +1 -1
- package/dist/src/broker/actor/authority-runtime.d.ts +4 -2
- package/dist/src/broker/actor/authority-runtime.js +29 -20
- package/dist/src/broker/actor/authority-session.d.ts +6 -19
- package/dist/src/broker/actor/authority-session.js +66 -88
- package/dist/src/broker/actor/authority-settings.d.ts +2 -1
- package/dist/src/broker/actor/authority-settings.js +6 -3
- package/dist/src/broker/actor/authority-upgrades.d.ts +23 -2
- package/dist/src/broker/actor/authority-upgrades.js +8 -2
- package/dist/src/broker/actor/authority-watchdog.d.ts +6 -2
- package/dist/src/broker/actor/authority-watchdog.js +31 -9
- package/dist/src/broker/actor/authority.js +3 -1
- package/dist/src/broker/actor/delivery-intents.js +2 -0
- package/dist/src/broker/actor/effect-delivery.d.ts +1 -1
- package/dist/src/broker/actor/effect-delivery.js +15 -2
- package/dist/src/broker/actor/effect-plan.js +11 -2
- package/dist/src/broker/actor/effect-queries.d.ts +4 -0
- package/dist/src/broker/actor/effect-queries.js +9 -1
- package/dist/src/broker/actor/effect-turn.js +2 -0
- package/dist/src/broker/actor/projection-memory.d.ts +43 -0
- package/dist/src/broker/actor/projection-memory.js +207 -0
- package/dist/src/broker/actor/runtime-parts.d.ts +5 -0
- package/dist/src/broker/actor/runtime-parts.js +8 -3
- package/dist/src/broker/actor/stop-plan.js +9 -3
- package/dist/src/broker/actor/stop-turn.d.ts +2 -0
- package/dist/src/broker/actor/stop-turn.js +24 -11
- package/dist/src/broker/actor/turn-draft.d.ts +1 -0
- package/dist/src/broker/actor/turn-draft.js +4 -0
- package/dist/src/broker/actor/turn-state.js +5 -1
- package/dist/src/broker/authority-admission.js +60 -0
- package/dist/src/broker/authority-restore.d.ts +2 -0
- package/dist/src/broker/authority-restore.js +35 -1
- package/dist/src/broker/command-wait-restore.d.ts +31 -0
- package/dist/src/broker/command-wait-restore.js +86 -0
- package/dist/src/broker/decision-restore.d.ts +1 -1
- package/dist/src/broker/decision-restore.js +1 -0
- package/dist/src/broker/effect-upgrade.d.ts +3 -0
- package/dist/src/broker/effect-upgrade.js +11 -2
- package/dist/src/cli/arguments.d.ts +13 -0
- package/dist/src/cli/arguments.js +43 -3
- package/dist/src/cli/chat-stores.d.ts +2 -0
- package/dist/src/cli/chat-stores.js +113 -0
- package/dist/src/cli/client.d.ts +7 -2
- package/dist/src/cli/client.js +13 -7
- package/dist/src/cli/command-requests.d.ts +46 -0
- package/dist/src/cli/command-requests.js +84 -0
- package/dist/src/cli/command-waits.d.ts +9 -0
- package/dist/src/cli/command-waits.js +51 -0
- package/dist/src/cli/commands.js +70 -88
- package/dist/src/cli/config-file.d.ts +2 -2
- package/dist/src/cli/config-file.js +4 -2
- package/dist/src/cli/config-notice.js +5 -2
- package/dist/src/cli/doctor-retention.d.ts +2 -0
- package/dist/src/cli/doctor-retention.js +93 -0
- package/dist/src/cli/doctor-workflows.d.ts +5 -2
- package/dist/src/cli/doctor-workflows.js +12 -7
- package/dist/src/cli/doctor.js +11 -9
- package/dist/src/cli/harness-probes.d.ts +2 -0
- package/dist/src/cli/harness-probes.js +1 -1
- package/dist/src/cli/harness-processes.d.ts +6 -0
- package/dist/src/cli/harness-processes.js +36 -0
- package/dist/src/cli/init-command.d.ts +9 -0
- package/dist/src/cli/init-command.js +52 -0
- package/dist/src/cli/init-prompt-command.d.ts +10 -0
- package/dist/src/cli/init-prompt-command.js +145 -0
- package/dist/src/cli/init-prompt.d.ts +35 -0
- package/dist/src/cli/init-prompt.js +74 -0
- package/dist/src/cli/init-selection.d.ts +13 -0
- package/dist/src/cli/init-selection.js +75 -0
- package/dist/src/cli/main.d.ts +2 -0
- package/dist/src/cli/main.js +37 -7
- package/dist/src/cli/mcp-server.d.ts +1 -0
- package/dist/src/cli/mcp-server.js +156 -0
- package/dist/src/cli/mcp-tools.d.ts +15 -0
- package/dist/src/cli/mcp-tools.js +242 -0
- package/dist/src/cli/queue-arguments.d.ts +15 -0
- package/dist/src/cli/queue-arguments.js +31 -0
- package/dist/src/cli/queue-render.d.ts +3 -0
- package/dist/src/cli/queue-render.js +26 -0
- package/dist/src/cli/reload-render.d.ts +2 -0
- package/dist/src/cli/reload-render.js +12 -0
- package/dist/src/cli/render.d.ts +1 -1
- package/dist/src/cli/render.js +54 -38
- package/dist/src/cli/report-ci-jobs.d.ts +23 -0
- package/dist/src/cli/report-ci-jobs.js +103 -0
- package/dist/src/cli/report-ci-usage.d.ts +9 -0
- package/dist/src/cli/report-ci-usage.js +185 -0
- package/dist/src/cli/report-ci.d.ts +13 -0
- package/dist/src/cli/report-ci.js +74 -0
- package/dist/src/cli/report-closures.d.ts +6 -0
- package/dist/src/cli/report-closures.js +97 -0
- package/dist/src/cli/report-flow.d.ts +7 -0
- package/dist/src/cli/report-flow.js +122 -0
- package/dist/src/cli/report-github-reader.d.ts +29 -0
- package/dist/src/cli/report-github-reader.js +157 -0
- package/dist/src/cli/report-github.d.ts +15 -8
- package/dist/src/cli/report-github.js +131 -150
- package/dist/src/cli/report-operator.d.ts +3 -0
- package/dist/src/cli/report-operator.js +40 -0
- package/dist/src/cli/report-ready.d.ts +3 -0
- package/dist/src/cli/report-ready.js +96 -0
- package/dist/src/cli/report-text.d.ts +9 -0
- package/dist/src/cli/report-text.js +33 -0
- package/dist/src/cli/report.d.ts +1 -0
- package/dist/src/cli/report.js +104 -27
- package/dist/src/cli/runtime-arguments.d.ts +18 -3
- package/dist/src/cli/runtime-arguments.js +29 -20
- package/dist/src/cli/schedule-arguments.d.ts +14 -0
- package/dist/src/cli/schedule-arguments.js +26 -0
- package/dist/src/cli/schedule-render.d.ts +22 -0
- package/dist/src/cli/schedule-render.js +73 -0
- package/dist/src/cli/terminal-text.d.ts +3 -0
- package/dist/src/cli/terminal-text.js +28 -0
- package/dist/src/cli/toolchain.d.ts +1 -0
- package/dist/src/cli/toolchain.js +1 -0
- package/dist/src/cli/usage-render.d.ts +1 -0
- package/dist/src/cli/usage-render.js +28 -1
- package/dist/src/cli/usage.d.ts +2 -2
- package/dist/src/cli/usage.js +89 -11
- package/dist/src/cli/watch-actions.js +2 -2
- package/dist/src/cli/watch-api-document.d.ts +430 -0
- package/dist/src/cli/watch-api-document.js +291 -0
- package/dist/src/cli/watch-api-run.d.ts +56 -0
- package/dist/src/cli/watch-api-run.js +112 -0
- package/dist/src/cli/watch-api.d.ts +17 -0
- package/dist/src/cli/watch-api.js +230 -0
- package/dist/src/cli/watch-board-view.js +19 -2
- package/dist/src/cli/watch-board.d.ts +4 -2
- package/dist/src/cli/watch-board.js +53 -43
- package/dist/src/cli/watch-card-forms.d.ts +1 -1
- package/dist/src/cli/watch-card-forms.js +11 -10
- package/dist/src/cli/watch-client.d.ts +1 -1
- package/dist/src/cli/watch-client.js +2 -11
- package/dist/src/cli/watch-header-view.d.ts +1 -5
- package/dist/src/cli/watch-header-view.js +17 -21
- package/dist/src/cli/watch-model.d.ts +5 -1
- package/dist/src/cli/watch-model.js +20 -11
- package/dist/src/cli/watch-page.js +15 -15
- package/dist/src/cli/watch-phases.d.ts +12 -3
- package/dist/src/cli/watch-phases.js +68 -11
- package/dist/src/cli/watch-pr-board.js +1 -1
- package/dist/src/cli/watch-pr-command.d.ts +1 -0
- package/dist/src/cli/watch-pull-request.js +18 -8
- package/dist/src/cli/watch-reads.d.ts +3 -0
- package/dist/src/cli/watch-reads.js +22 -20
- package/dist/src/cli/watch-render.d.ts +15 -0
- package/dist/src/cli/watch-run-input.d.ts +0 -1
- package/dist/src/cli/watch-run-input.js +0 -13
- package/dist/src/cli/watch-server.js +24 -10
- package/dist/src/cli/watch-view.d.ts +0 -3
- package/dist/src/cli/watch-view.js +13 -13
- package/dist/src/cli.js +73 -12
- package/dist/src/command-wait.d.ts +4 -0
- package/dist/src/command-wait.js +45 -0
- package/dist/src/configuration-change.d.ts +7 -0
- package/dist/src/configuration-change.js +14 -0
- package/dist/src/configuration-display.js +2 -0
- package/dist/src/configuration-schema.d.ts +14 -0
- package/dist/src/configuration-schema.js +6 -2
- package/dist/src/daemon/attachment-file.d.ts +6 -0
- package/dist/src/daemon/attachment-file.js +86 -0
- package/dist/src/daemon/attachments.d.ts +14 -0
- package/dist/src/daemon/attachments.js +17 -0
- package/dist/src/daemon/claude-recovery.d.ts +50 -0
- package/dist/src/daemon/claude-recovery.js +208 -0
- package/dist/src/daemon/claude-stream.d.ts +27 -0
- package/dist/src/daemon/claude-stream.js +63 -0
- package/dist/src/daemon/claude-turn.d.ts +11 -25
- package/dist/src/daemon/claude-turn.js +64 -81
- package/dist/src/daemon/claude-worker.d.ts +5 -4
- package/dist/src/daemon/claude-worker.js +127 -126
- package/dist/src/daemon/daemon-adapters.d.ts +9 -0
- package/dist/src/daemon/daemon-adapters.js +33 -5
- package/dist/src/daemon/daemon-loops.d.ts +5 -1
- package/dist/src/daemon/daemon-loops.js +18 -10
- package/dist/src/daemon/daemon.js +80 -61
- package/dist/src/daemon/github-attach.d.ts +2 -0
- package/dist/src/daemon/github-attach.js +222 -0
- package/dist/src/daemon/github-calls.js +1 -1
- package/dist/src/daemon/github-ci-filters.d.ts +6 -0
- package/dist/src/daemon/github-ci-filters.js +138 -0
- package/dist/src/daemon/github-ci-workflows.d.ts +10 -0
- package/dist/src/daemon/github-ci-workflows.js +148 -0
- package/dist/src/daemon/github-ci.js +22 -4
- package/dist/src/daemon/github-issue-methods.d.ts +2 -0
- package/dist/src/daemon/github-issue-methods.js +37 -2
- package/dist/src/daemon/github-merge-call.d.ts +2 -1
- package/dist/src/daemon/github-merge-call.js +10 -3
- package/dist/src/daemon/github-merge.js +52 -24
- package/dist/src/daemon/github-methods.js +18 -4
- package/dist/src/daemon/github-operation.d.ts +4 -0
- package/dist/src/daemon/github-operation.js +6 -0
- package/dist/src/daemon/github-worker.d.ts +4 -0
- package/dist/src/daemon/github-worker.js +6 -0
- package/dist/src/daemon/issue-queue.d.ts +4 -1
- package/dist/src/daemon/issue-queue.js +76 -78
- package/dist/src/daemon/merge-turns.d.ts +10 -0
- package/dist/src/daemon/merge-turns.js +37 -0
- package/dist/src/daemon/notify-events.d.ts +6 -0
- package/dist/src/daemon/notify-events.js +84 -0
- package/dist/src/daemon/notify-journal.js +1 -1
- package/dist/src/daemon/notify-message.d.ts +4 -1
- package/dist/src/daemon/notify-message.js +36 -0
- package/dist/src/daemon/notify.d.ts +1 -1
- package/dist/src/daemon/notify.js +5 -77
- package/dist/src/daemon/operation-journal.d.ts +1 -0
- package/dist/src/daemon/queue-control.d.ts +13 -0
- package/dist/src/daemon/queue-control.js +86 -0
- package/dist/src/daemon/queue-journal.d.ts +20 -0
- package/dist/src/daemon/queue-journal.js +89 -0
- package/dist/src/daemon/queue-status.d.ts +9 -3
- package/dist/src/daemon/queue-status.js +17 -4
- package/dist/src/daemon/record-archive.d.ts +19 -0
- package/dist/src/daemon/record-archive.js +82 -0
- package/dist/src/daemon/record-sweep.d.ts +24 -0
- package/dist/src/daemon/record-sweep.js +147 -0
- package/dist/src/daemon/resume-index-lock.d.ts +13 -0
- package/dist/src/daemon/resume-index-lock.js +160 -0
- package/dist/src/daemon/resume-worktree.d.ts +7 -0
- package/dist/src/daemon/resume-worktree.js +29 -0
- package/dist/src/daemon/retrying-turn.d.ts +2 -12
- package/dist/src/daemon/retrying-turn.js +98 -172
- package/dist/src/daemon/schedule-control.d.ts +26 -0
- package/dist/src/daemon/schedule-control.js +110 -0
- package/dist/src/daemon/schedule-journal.d.ts +2 -15
- package/dist/src/daemon/schedule-journal.js +67 -4
- package/dist/src/daemon/settings-reload.d.ts +26 -0
- package/dist/src/daemon/settings-reload.js +82 -0
- package/dist/src/daemon/ticket-registration.d.ts +2 -7
- package/dist/src/daemon/ticket-registration.js +15 -81
- package/dist/src/daemon/turn-attempt-journal.d.ts +38 -0
- package/dist/src/daemon/turn-attempt-journal.js +136 -0
- package/dist/src/daemon/turn-attempts.d.ts +47 -0
- package/dist/src/daemon/turn-attempts.js +166 -0
- package/dist/src/daemon/turn-details.d.ts +4 -0
- package/dist/src/daemon/turn-details.js +33 -0
- package/dist/src/daemon/turn-report.d.ts +8 -1
- package/dist/src/daemon/turn-report.js +39 -0
- package/dist/src/daemon/work-tree.d.ts +9 -0
- package/dist/src/daemon/work-tree.js +20 -0
- package/dist/src/daemon/worker-profile.d.ts +9 -0
- package/dist/src/daemon/worker-profile.js +44 -0
- package/dist/src/daemon/workflow-generations.d.ts +7 -4
- package/dist/src/daemon/workflow-generations.js +22 -14
- package/dist/src/daemon/workflow-reload.d.ts +41 -0
- package/dist/src/daemon/workflow-reload.js +244 -0
- package/dist/src/daemon/workflow-replay.d.ts +2 -1
- package/dist/src/daemon/workflow-replay.js +7 -3
- package/dist/src/daemon/workflow-schedules.d.ts +3 -0
- package/dist/src/daemon/workflow-schedules.js +98 -45
- package/dist/src/daemon/worktree-processes.d.ts +9 -0
- package/dist/src/daemon/worktree-processes.js +151 -0
- package/dist/src/doctor-report.d.ts +4 -6
- package/dist/src/doctor-report.js +8 -13
- package/dist/src/harness-start.d.ts +15 -0
- package/dist/src/harness-start.js +37 -0
- package/dist/src/host/command-wait.d.ts +38 -0
- package/dist/src/host/command-wait.js +115 -0
- package/dist/src/host/start-delivery.d.ts +5 -7
- package/dist/src/host/start-delivery.js +3 -15
- package/dist/src/host/step-bridge-host.d.ts +2 -0
- package/dist/src/host/step-bridge-host.js +21 -0
- package/dist/src/operation-identity.d.ts +1 -0
- package/dist/src/operation-identity.js +4 -0
- package/dist/src/private-config.schema.json +71 -0
- package/dist/src/project-config.schema.json +40 -0
- package/dist/src/project-settings.d.ts +16 -2
- package/dist/src/project-settings.js +35 -1
- package/dist/src/queue-spend.d.ts +4 -0
- package/dist/src/queue-spend.js +21 -0
- package/dist/src/queue-state.d.ts +26 -0
- package/dist/src/queue-state.js +34 -0
- package/dist/src/record-retention.d.ts +46 -0
- package/dist/src/record-retention.js +81 -0
- package/dist/src/relay/relay-service.d.ts +3 -0
- package/dist/src/relay/relay-service.js +5 -3
- package/dist/src/report-ci.d.ts +164 -0
- package/dist/src/report-ci.js +32 -0
- package/dist/src/report-effects.d.ts +15 -0
- package/dist/src/report-effects.js +212 -0
- package/dist/src/report-flow-types.d.ts +38 -0
- package/dist/src/report-flow-types.js +7 -0
- package/dist/src/report-flow.d.ts +43 -0
- package/dist/src/report-flow.js +193 -0
- package/dist/src/report-operator.d.ts +67 -0
- package/dist/src/report-operator.js +25 -0
- package/dist/src/report-quality.d.ts +221 -0
- package/dist/src/report-quality.js +94 -0
- package/dist/src/report-ready.d.ts +23 -0
- package/dist/src/report-ready.js +117 -0
- package/dist/src/report-statistics.d.ts +2 -1
- package/dist/src/report-statistics.js +40 -4
- package/dist/src/report.d.ts +588 -47
- package/dist/src/report.js +156 -41
- package/dist/src/schedule-progress.d.ts +33 -0
- package/dist/src/schedule-progress.js +45 -0
- package/dist/src/service/active-tickets.js +11 -6
- package/dist/src/service/command-waits.d.ts +34 -0
- package/dist/src/service/command-waits.js +86 -0
- package/dist/src/service/dispatcher.d.ts +4 -0
- package/dist/src/service/dispatcher.js +33 -0
- package/dist/src/service/expiry.js +2 -0
- package/dist/src/service/gateway.js +3 -1
- package/dist/src/service/queue-handlers.d.ts +4 -0
- package/dist/src/service/queue-handlers.js +32 -0
- package/dist/src/service/queue-spend.d.ts +6 -0
- package/dist/src/service/queue-spend.js +68 -0
- package/dist/src/service/registry.d.ts +28 -2
- package/dist/src/service/registry.js +48 -0
- package/dist/src/service/replies.d.ts +22 -8
- package/dist/src/service/replies.js +16 -2
- package/dist/src/service/run-handlers.js +37 -12
- package/dist/src/service/run-metadata.d.ts +15 -1
- package/dist/src/service/run-metadata.js +93 -8
- package/dist/src/service/service.d.ts +11 -3
- package/dist/src/service/service.js +22 -37
- package/dist/src/service/submission-handler.js +18 -4
- package/dist/src/service/worker-port.js +9 -1
- package/dist/src/service/worker-totals.d.ts +6 -0
- package/dist/src/service/worker-totals.js +8 -1
- package/dist/src/service/workflow-reload.d.ts +35 -0
- package/dist/src/service/workflow-reload.js +52 -0
- package/dist/src/step-bridge.d.ts +20 -0
- package/dist/src/steps/command-wait.d.ts +12 -0
- package/dist/src/steps/command-wait.js +26 -0
- package/dist/src/steps/open-decision-wait.d.ts +2 -0
- package/dist/src/steps/{decision-gate.js → open-decision-wait.js} +0 -7
- package/dist/src/steps/review-by-person.js +4 -1
- package/dist/src/steps/wait-for-command.d.ts +3 -0
- package/dist/src/steps/wait-for-command.js +17 -0
- package/dist/src/steps/wait-for-decision.js +1 -1
- package/dist/src/storage/command-wait-rows.d.ts +30 -0
- package/dist/src/storage/command-wait-rows.js +96 -0
- package/dist/src/storage/decision-snapshots.d.ts +8 -2
- package/dist/src/storage/decision-snapshots.js +16 -8
- package/dist/src/storage/domain-changes.d.ts +3 -1
- package/dist/src/storage/domain-changes.js +4 -0
- package/dist/src/storage/domain-schema.d.ts +16 -1
- package/dist/src/storage/domain-schema.js +35 -4
- package/dist/src/storage/effect-schema.d.ts +2 -0
- package/dist/src/storage/effect-schema.js +9 -0
- package/dist/src/storage/projection-changes.d.ts +12 -0
- package/dist/src/storage/projection-changes.js +194 -0
- package/dist/src/storage/projection-lookups.d.ts +7 -0
- package/dist/src/storage/projection-lookups.js +30 -0
- package/dist/src/testing-requests.d.ts +15 -0
- package/dist/src/testing-requests.js +93 -0
- package/dist/src/testing.d.ts +4 -10
- package/dist/src/testing.js +33 -86
- package/dist/src/worker-usage.d.ts +1 -0
- package/dist/src/worker-usage.js +3 -0
- package/dist/src/workflow-candidate.d.ts +1 -0
- package/dist/src/workflow-candidate.js +12 -1
- package/dist/src/workflow-contracts.d.ts +1 -0
- package/dist/src/workflow-contracts.js +9 -2
- package/dist/src/workflow-declaration.d.ts +1 -0
- package/dist/src/workflow-declaration.js +3 -0
- package/dist/src/workflow-discovery.d.ts +2 -13
- package/dist/src/workflow-discovery.js +1 -13
- package/dist/src/workflow-refusals.js +0 -1
- package/dist/src/workflows.d.ts +1 -1
- package/dist/src/workflows.js +1 -1
- package/dist/tools/compile-workflows.js +3 -0
- package/dist/tools/project-configuration.d.ts +7 -2
- package/dist/tools/project-configuration.js +30 -1
- package/dist/tools/red-green-command.d.ts +1 -0
- package/dist/tools/red-green-command.js +174 -0
- package/dist/tools/red-green-process.d.ts +10 -0
- package/dist/tools/red-green-process.js +59 -0
- package/dist/tools/self-host-processes.d.ts +2 -0
- package/dist/tools/self-host-processes.js +69 -26
- package/dist/tools/self-host-project.d.ts +2 -0
- package/dist/tools/self-host-project.js +30 -77
- package/dist/tools/self-host-runtime.js +1 -1
- package/dist/tools/self-host.js +76 -34
- package/dist/tools/template-command.d.ts +1 -0
- package/dist/tools/template-command.js +160 -0
- package/dist/tools/template-copy.d.ts +11 -0
- package/dist/tools/template-copy.js +130 -0
- package/dist/tools/template-files.d.ts +17 -0
- package/dist/tools/template-files.js +74 -0
- package/dist/tools/workflow-bundles.js +1 -0
- package/dist/tools/workflow-candidate-counts.js +2 -2
- package/dist/tools/workflow-candidate-program.d.ts +4 -2
- package/dist/tools/workflow-candidate-program.js +30 -11
- package/dist/tools/workflow-candidate-shape.d.ts +3 -0
- package/dist/tools/workflow-candidate-shape.js +90 -0
- package/dist/tools/workflow-candidate-source.d.ts +1 -0
- package/dist/tools/workflow-candidate-source.js +26 -4
- package/dist/tools/workflow-candidate-syntax.d.ts +2 -2
- package/dist/tools/workflow-candidate-syntax.js +24 -94
- package/dist/tools/workflow-command.js +1 -2
- package/dist/tools/workflow-folders.d.ts +2 -3
- package/dist/tools/workflow-folders.js +1 -1
- package/package.json +17 -9
- package/templates/develop/README.md +93 -4
- package/templates/develop/develop/flow-tests.ts +38 -1
- package/templates/develop/develop/interruption-tests.ts +157 -0
- package/templates/develop/develop/local.ts +1 -0
- package/templates/develop/develop/option-tests.ts +138 -9
- package/templates/develop/develop/pull.ts +5 -1
- package/templates/develop/develop/red-green.ts +55 -0
- package/templates/develop/develop/refusal-tests.ts +77 -0
- package/templates/develop/develop/report.ts +31 -11
- package/templates/develop/develop/round.ts +1 -0
- package/templates/develop/develop/scenarios.ts +27 -0
- package/templates/develop/develop/turn.ts +28 -7
- package/templates/develop/develop.declaration.json +1 -1
- package/templates/develop/develop.test.ts +4 -0
- package/templates/develop/template.json +29 -2
- package/templates/idea-to-issue/README.md +27 -0
- package/templates/idea-to-issue/idea-to-issue/effects.ts +52 -0
- package/templates/idea-to-issue/idea-to-issue/leave.ts +10 -0
- package/templates/idea-to-issue/idea-to-issue/next.ts +29 -0
- package/templates/idea-to-issue/idea-to-issue/post-person.ts +18 -0
- package/templates/idea-to-issue/idea-to-issue/post.ts +50 -0
- package/templates/idea-to-issue/idea-to-issue/queue.ts +27 -0
- package/templates/idea-to-issue/idea-to-issue/review.ts +42 -0
- package/templates/idea-to-issue/idea-to-issue/scenarios.ts +50 -0
- package/templates/idea-to-issue/idea-to-issue/turn.ts +40 -0
- package/templates/idea-to-issue/idea-to-issue.declaration.json +16 -0
- package/templates/idea-to-issue/idea-to-issue.test.ts +79 -0
- package/templates/idea-to-issue/idea-to-issue.ts +49 -0
- package/templates/idea-to-issue/template.json +81 -0
- package/templates/review-day/README.md +97 -0
- package/templates/review-day/review-day/critique.ts +58 -0
- package/templates/review-day/review-day/decision.ts +29 -0
- package/templates/review-day/review-day/facts.ts +69 -0
- package/templates/review-day/review-day/label.ts +29 -0
- package/templates/review-day/review-day/next.ts +28 -0
- package/templates/review-day/review-day/post.ts +27 -0
- package/templates/review-day/review-day/report.ts +98 -0
- package/templates/review-day/review-day/rules.ts +12 -0
- package/templates/review-day/review-day/scenarios.ts +76 -0
- package/templates/review-day/review-day/turn.ts +73 -0
- package/templates/review-day/review-day.declaration.json +16 -0
- package/templates/review-day/review-day.test.ts +362 -0
- package/templates/review-day/review-day.ts +37 -0
- package/templates/review-day/template.json +56 -0
- package/dist/src/cli/watch-start-view.d.ts +0 -18
- package/dist/src/cli/watch-start-view.js +0 -77
- package/dist/src/steps/decision-gate.d.ts +0 -3
- package/dist/workflows/develop-prd.d.ts +0 -7
- package/dist/workflows/develop-prd.js +0 -165
- package/dist/workflows/develop-ticket.d.ts +0 -9
- package/dist/workflows/develop-ticket.js +0 -207
- package/dist/workflows/issue-labels.d.ts +0 -16
- package/dist/workflows/issue-labels.js +0 -70
- package/dist/workflows/ticket-prompts.d.ts +0 -35
- package/dist/workflows/ticket-prompts.js +0 -147
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { adapters, recoverCommands, } from "./daemon-adapters.js";
|
|
1
|
+
import { adapters, recoverCommands, recoverClaude, } from "./daemon-adapters.js";
|
|
2
2
|
import { mkdir, realpath } from "node:fs/promises";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import { registerStepBridge, sdkStepCall, stepBridge, } from "../host/step-bridge-host.js";
|
|
@@ -12,8 +12,14 @@ import { commandEffects } from "./command-journal.js";
|
|
|
12
12
|
import { worldDirectory } from "./host-environment.js";
|
|
13
13
|
import { pinnedWorkflowHandler } from "./workflow-replay.js";
|
|
14
14
|
import { scheduledDeclarations } from "./workflow-schedules.js";
|
|
15
|
+
import { scheduleConnection } from "./schedule-control.js";
|
|
16
|
+
import { queueConnection } from "./queue-control.js";
|
|
15
17
|
import { daemonLoops } from "./daemon-loops.js";
|
|
16
|
-
import {
|
|
18
|
+
import { authorityRuns, recordRetention } from "./record-sweep.js";
|
|
19
|
+
import { turnDetailsPlace } from "./turn-details.js";
|
|
20
|
+
import { defaultRetention } from "../record-retention.js";
|
|
21
|
+
import { clovingVersion } from "../cli/toolchain.js";
|
|
22
|
+
import { daemonRegistrations, queueWorkflowId, workflowReload, } from "./workflow-reload.js";
|
|
17
23
|
export const turnLeaseMilliseconds = 4 * 3_600_000;
|
|
18
24
|
export const loopMilliseconds = 250;
|
|
19
25
|
export const bridgeTiming = {
|
|
@@ -65,45 +71,6 @@ async function hosted(settings, hosting) {
|
|
|
65
71
|
},
|
|
66
72
|
};
|
|
67
73
|
}
|
|
68
|
-
async function daemonRegistrations(settings) {
|
|
69
|
-
const conflict = settings.workflowRefusals?.find((refusal) => refusal.codes.includes("queue-workflow-conflict"));
|
|
70
|
-
if (conflict !== undefined)
|
|
71
|
-
return {
|
|
72
|
-
table: [],
|
|
73
|
-
admitted: {
|
|
74
|
-
kind: "rejected",
|
|
75
|
-
detail: `queue-workflow-conflict: ${conflict.scope} ${conflict.label}`,
|
|
76
|
-
},
|
|
77
|
-
};
|
|
78
|
-
const table = ticketRegistrationTable({
|
|
79
|
-
repository: settings.repository,
|
|
80
|
-
command: settings.ticketCommand,
|
|
81
|
-
nextCommand: settings.nextCommand,
|
|
82
|
-
githubCommand: settings.githubCommand,
|
|
83
|
-
}, settings.declarations);
|
|
84
|
-
const admitted = await ticketRegistrations(settings.manifests, {
|
|
85
|
-
table,
|
|
86
|
-
commands: settings.commands ?? {},
|
|
87
|
-
...(settings.bundleDigest === undefined
|
|
88
|
-
? {}
|
|
89
|
-
: { bundleDigest: settings.bundleDigest }),
|
|
90
|
-
});
|
|
91
|
-
return {
|
|
92
|
-
table,
|
|
93
|
-
admitted: admitted.kind === "rejected"
|
|
94
|
-
? admitted
|
|
95
|
-
: {
|
|
96
|
-
...admitted,
|
|
97
|
-
registrations: admitted.registrations.map((registration) => ({
|
|
98
|
-
...registration,
|
|
99
|
-
...(settings.queueMilliseconds !== undefined &&
|
|
100
|
-
registration.workflowId === queueWorkflowId(settings)
|
|
101
|
-
? { admission: settings.queueLanes ?? 1, queue: true }
|
|
102
|
-
: {}),
|
|
103
|
-
})),
|
|
104
|
-
},
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
74
|
export async function startDaemon(givenSettings) {
|
|
108
75
|
const repository = await realpath(givenSettings.repository);
|
|
109
76
|
const scheduled = scheduledDeclarations(givenSettings, {
|
|
@@ -118,16 +85,56 @@ export async function startDaemon(givenSettings) {
|
|
|
118
85
|
repository,
|
|
119
86
|
});
|
|
120
87
|
}
|
|
88
|
+
function controlConnections() {
|
|
89
|
+
return { schedules: scheduleConnection(), queues: queueConnection() };
|
|
90
|
+
}
|
|
91
|
+
function retentionReads(settings, ports) {
|
|
92
|
+
return turnDetailsPlace({
|
|
93
|
+
directory: settings.directory,
|
|
94
|
+
retention: settings.retention ?? defaultRetention,
|
|
95
|
+
runs: async (runIds) => authorityRuns(await ports)(runIds),
|
|
96
|
+
now: settings.retentionClock ?? Date.now,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
function rejectedOpening(detail) {
|
|
100
|
+
return {
|
|
101
|
+
kind: "refused",
|
|
102
|
+
reason: detail.startsWith("queue-workflow-conflict")
|
|
103
|
+
? "queue-workflow-conflict"
|
|
104
|
+
: "workflow-rejected",
|
|
105
|
+
detail,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function workflowOptions(settings, parts) {
|
|
109
|
+
const { reloadCommand, loadBundle } = settings;
|
|
110
|
+
const { generations, turnSettings } = parts;
|
|
111
|
+
return {
|
|
112
|
+
workflowBundles: {
|
|
113
|
+
directory: join(settings.directory, "workflow-bundles"),
|
|
114
|
+
repository: settings.repository,
|
|
115
|
+
},
|
|
116
|
+
workflowRefusals: settings.workflowRefusals ?? [],
|
|
117
|
+
retainedWorkflow: generations.available,
|
|
118
|
+
...(settings.bundleDigest === undefined
|
|
119
|
+
? {}
|
|
120
|
+
: { bundleDigest: settings.bundleDigest }),
|
|
121
|
+
...(reloadCommand === undefined || loadBundle === undefined
|
|
122
|
+
? {}
|
|
123
|
+
: {
|
|
124
|
+
reload: workflowReload({
|
|
125
|
+
...settings,
|
|
126
|
+
reloadCommand,
|
|
127
|
+
loadBundle,
|
|
128
|
+
generations,
|
|
129
|
+
turnSettings,
|
|
130
|
+
}),
|
|
131
|
+
}),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
121
134
|
async function openDaemon(settings) {
|
|
122
135
|
const { table, admitted } = await daemonRegistrations(settings);
|
|
123
136
|
if (admitted.kind === "rejected")
|
|
124
|
-
return
|
|
125
|
-
kind: "refused",
|
|
126
|
-
reason: admitted.detail.startsWith("queue-workflow-conflict")
|
|
127
|
-
? "queue-workflow-conflict"
|
|
128
|
-
: "workflow-rejected",
|
|
129
|
-
detail: admitted.detail,
|
|
130
|
-
};
|
|
137
|
+
return rejectedOpening(admitted.detail);
|
|
131
138
|
const given = Promise.withResolvers();
|
|
132
139
|
const generations = workflowGenerations({
|
|
133
140
|
...settings,
|
|
@@ -138,18 +145,21 @@ async function openDaemon(settings) {
|
|
|
138
145
|
const { worker, github, runs, handoff, commands } = resources;
|
|
139
146
|
await mkdir(join(settings.directory, "state"), { recursive: true });
|
|
140
147
|
await mkdir(settings.runtimeDirectory, { recursive: true, mode: 0o700 });
|
|
148
|
+
const controls = controlConnections();
|
|
141
149
|
const opening = await startService({
|
|
150
|
+
version: clovingVersion,
|
|
151
|
+
schedule: controls.schedules.request,
|
|
152
|
+
queue: controls.queues.port,
|
|
153
|
+
...(settings.queueDailySpendLimitUsd === undefined
|
|
154
|
+
? {}
|
|
155
|
+
: { queueDailySpendLimitUsd: settings.queueDailySpendLimitUsd }),
|
|
142
156
|
workerHarness: worker.harness,
|
|
157
|
+
turnDetails: retentionReads(settings, given.promise),
|
|
143
158
|
commandEffects: commandEffects(join(settings.directory, "commands")),
|
|
144
159
|
stateDirectory: join(settings.directory, "state"),
|
|
145
160
|
runtimeDirectory: settings.runtimeDirectory,
|
|
146
|
-
|
|
147
|
-
directory: join(settings.directory, "workflow-bundles"),
|
|
148
|
-
repository: settings.repository,
|
|
149
|
-
},
|
|
150
|
-
workflowRefusals: settings.workflowRefusals ?? [],
|
|
161
|
+
...workflowOptions(settings, { ...resources, generations }),
|
|
151
162
|
workflows: admitted.registrations,
|
|
152
|
-
retainedWorkflow: generations.available,
|
|
153
163
|
delivery: deliveryRouter({
|
|
154
164
|
runs,
|
|
155
165
|
effects: { claude: worker, github, handoff, command: commands },
|
|
@@ -164,16 +174,18 @@ async function openDaemon(settings) {
|
|
|
164
174
|
await closeWorkers(resources);
|
|
165
175
|
return opening;
|
|
166
176
|
}
|
|
167
|
-
const running = { ...resources, service: opening.service };
|
|
177
|
+
const running = { ...resources, ...controls, service: opening.service };
|
|
168
178
|
await recoverWorkers(running, given.promise);
|
|
169
179
|
return {
|
|
170
180
|
kind: "started",
|
|
171
|
-
daemon: await runningDaemon(settings, running),
|
|
181
|
+
daemon: await runningDaemon(settings, { ...running, ports: given.promise }),
|
|
172
182
|
};
|
|
173
183
|
}
|
|
174
184
|
async function recoverWorkers(resources, ports) {
|
|
175
185
|
try {
|
|
176
|
-
|
|
186
|
+
const host = await ports;
|
|
187
|
+
await recoverCommands(resources.commands, host);
|
|
188
|
+
await recoverClaude(resources.worker, host);
|
|
177
189
|
}
|
|
178
190
|
catch (error) {
|
|
179
191
|
await Promise.allSettled([
|
|
@@ -192,12 +204,22 @@ async function closeWorkers(resources) {
|
|
|
192
204
|
}
|
|
193
205
|
async function runningDaemon(settings, resources) {
|
|
194
206
|
const { service, github } = resources;
|
|
207
|
+
const retention = await recordRetention({
|
|
208
|
+
directory: settings.directory,
|
|
209
|
+
retention: settings.retention ?? defaultRetention,
|
|
210
|
+
runs: authorityRuns(await resources.ports),
|
|
211
|
+
now: settings.retentionClock ?? Date.now,
|
|
212
|
+
log: (line) => process.stderr.write(line),
|
|
213
|
+
});
|
|
195
214
|
await github.scan();
|
|
196
215
|
const loops = await daemonLoops({
|
|
197
216
|
...settings,
|
|
217
|
+
scheduleConnection: resources.schedules,
|
|
218
|
+
queueConnection: resources.queues,
|
|
198
219
|
submit: service.worker.submit,
|
|
199
220
|
queueWorkflowId: queueWorkflowId(settings),
|
|
200
221
|
}).catch(async (error) => {
|
|
222
|
+
await retention.stop();
|
|
201
223
|
await closeWorkers(resources);
|
|
202
224
|
await service.close();
|
|
203
225
|
throw error;
|
|
@@ -205,13 +227,10 @@ async function runningDaemon(settings, resources) {
|
|
|
205
227
|
return {
|
|
206
228
|
socket: service.socket,
|
|
207
229
|
close: async () => {
|
|
230
|
+
await retention.stop();
|
|
208
231
|
await loops.stop();
|
|
209
232
|
await closeWorkers(resources);
|
|
210
233
|
await service.close();
|
|
211
234
|
},
|
|
212
235
|
};
|
|
213
236
|
}
|
|
214
|
-
function queueWorkflowId(settings) {
|
|
215
|
-
return (settings.declarations?.find((declaration) => declaration.queue === true)
|
|
216
|
-
?.workflowId ?? issueWorkflow);
|
|
217
|
-
}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { rm, writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { copiedAttachment, openedAttachment } from "./attachment-file.js";
|
|
4
|
+
import { attachmentFolder } from "./attachments.js";
|
|
5
|
+
import { repositoryName } from "./github-issue-methods.js";
|
|
6
|
+
import { issuePrivacy, operatorPrivateTexts } from "./github-issue-privacy.js";
|
|
7
|
+
import { field, repositoryPath, text, } from "./github-operation.js";
|
|
8
|
+
import { githubRead } from "./github-retry.js";
|
|
9
|
+
import { inTurn } from "./merge-turns.js";
|
|
10
|
+
function isList(value) {
|
|
11
|
+
return Array.isArray(value);
|
|
12
|
+
}
|
|
13
|
+
function validName(name) {
|
|
14
|
+
return /^[\w-][\w.-]*\.(?:mp4|webm|png)$/.test(name) && !name.includes("..");
|
|
15
|
+
}
|
|
16
|
+
function validRelease(release) {
|
|
17
|
+
return /^[a-z][a-z0-9-]{0,63}$/.test(release) && !/^v\d/.test(release);
|
|
18
|
+
}
|
|
19
|
+
function placeOf(operation) {
|
|
20
|
+
const place = operation.payload["place"] ?? "comment";
|
|
21
|
+
if (place !== "comment" && place !== "description")
|
|
22
|
+
throw new Error("invalid-payload");
|
|
23
|
+
return place;
|
|
24
|
+
}
|
|
25
|
+
function attachmentOf(operation) {
|
|
26
|
+
const number = operation.payload["number"];
|
|
27
|
+
const name = text(operation, "name");
|
|
28
|
+
const release = text(operation, "release");
|
|
29
|
+
const comment = text(operation, "comment");
|
|
30
|
+
if (typeof number !== "number" || !Number.isSafeInteger(number) || number < 1)
|
|
31
|
+
throw new Error("invalid-payload");
|
|
32
|
+
if (!validName(name) || !validRelease(release) || comment.length > 4000)
|
|
33
|
+
throw new Error("invalid-payload");
|
|
34
|
+
return { number, name, release, comment, place: placeOf(operation) };
|
|
35
|
+
}
|
|
36
|
+
function attachedFile(operation, name) {
|
|
37
|
+
return openedAttachment({
|
|
38
|
+
folder: attachmentFolder({
|
|
39
|
+
worktrees: operation.settings.worktrees,
|
|
40
|
+
target: operation.target,
|
|
41
|
+
}),
|
|
42
|
+
name,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
async function pages(operation, path) {
|
|
46
|
+
const reply = JSON.parse(await githubRead(operation, ["api", "--paginate", "--slurp", path]));
|
|
47
|
+
if (!isList(reply))
|
|
48
|
+
throw new Error("github-call-failed");
|
|
49
|
+
return reply.flatMap((page) => {
|
|
50
|
+
if (!isList(page))
|
|
51
|
+
throw new Error("github-call-failed");
|
|
52
|
+
return page;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
async function releaseOf(operation, tag) {
|
|
56
|
+
const releases = await pages(operation, `${repositoryPath}/releases?per_page=100`);
|
|
57
|
+
return releases.find((item) => field(item, "tag_name") === tag);
|
|
58
|
+
}
|
|
59
|
+
async function ensuredRelease(operation, release) {
|
|
60
|
+
if ((await releaseOf(operation, release)) !== undefined)
|
|
61
|
+
return;
|
|
62
|
+
try {
|
|
63
|
+
await operation.calls.gh([
|
|
64
|
+
"release",
|
|
65
|
+
"create",
|
|
66
|
+
release,
|
|
67
|
+
"--prerelease",
|
|
68
|
+
"--latest=false",
|
|
69
|
+
"--title",
|
|
70
|
+
"Pull request demos",
|
|
71
|
+
"--notes",
|
|
72
|
+
"Demo videos of pull requests. Cloving uploads them.",
|
|
73
|
+
]);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if ((await releaseOf(operation, release)) === undefined)
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async function uploaded(operation, attachment) {
|
|
81
|
+
const { release } = attachment;
|
|
82
|
+
await ensuredRelease(operation, release);
|
|
83
|
+
const asset = `pr-${String(attachment.number)}-${attachment.name}`;
|
|
84
|
+
const copy = join(operation.folder, asset);
|
|
85
|
+
try {
|
|
86
|
+
await copiedAttachment(attachment.file, copy);
|
|
87
|
+
await operation.calls.gh(["release", "upload", release, copy, "--clobber"]);
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
await rm(copy, { force: true });
|
|
91
|
+
}
|
|
92
|
+
const assets = field(await releaseOf(operation, release), "assets");
|
|
93
|
+
const found = isList(assets)
|
|
94
|
+
? assets.find((item) => field(item, "name") === asset)
|
|
95
|
+
: undefined;
|
|
96
|
+
const url = field(found, "browser_download_url");
|
|
97
|
+
if (typeof url !== "string" || !url.startsWith("https://"))
|
|
98
|
+
throw new Error("github-call-failed");
|
|
99
|
+
return url;
|
|
100
|
+
}
|
|
101
|
+
async function ownLogin(operation) {
|
|
102
|
+
const user = JSON.parse(await githubRead(operation, ["api", "user"]));
|
|
103
|
+
const login = field(user, "login");
|
|
104
|
+
if (typeof login !== "string" || login === "")
|
|
105
|
+
throw new Error("github-call-failed");
|
|
106
|
+
return login;
|
|
107
|
+
}
|
|
108
|
+
async function commented(operation, attachment) {
|
|
109
|
+
const { number, name, url } = attachment;
|
|
110
|
+
const marker = `<!-- cloving-attachment:${String(number)}:${name} -->`;
|
|
111
|
+
const body = `${attachment.comment}\n\n[${name}](${url})\n\n${marker}`;
|
|
112
|
+
const comments = await pages(operation, `${repositoryPath}/issues/${String(number)}/comments?per_page=100`);
|
|
113
|
+
const login = await ownLogin(operation);
|
|
114
|
+
const known = comments.find((item) => {
|
|
115
|
+
const existing = field(item, "body");
|
|
116
|
+
return (typeof existing === "string" &&
|
|
117
|
+
existing.includes(marker) &&
|
|
118
|
+
field(field(item, "user"), "login") === login);
|
|
119
|
+
});
|
|
120
|
+
const id = field(known, "id");
|
|
121
|
+
if (typeof id === "number") {
|
|
122
|
+
await operation.calls.gh([
|
|
123
|
+
"api",
|
|
124
|
+
"-X",
|
|
125
|
+
"PATCH",
|
|
126
|
+
`${repositoryPath}/issues/comments/${String(id)}`,
|
|
127
|
+
"-f",
|
|
128
|
+
`body=${body}`,
|
|
129
|
+
]);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
await operation.calls.gh([
|
|
133
|
+
"api",
|
|
134
|
+
`${repositoryPath}/issues/${String(number)}/comments`,
|
|
135
|
+
"-f",
|
|
136
|
+
`body=${body}`,
|
|
137
|
+
]);
|
|
138
|
+
}
|
|
139
|
+
function withSection(body, marks) {
|
|
140
|
+
const from = body.indexOf(marks.start);
|
|
141
|
+
const to = from < 0 ? -1 : body.indexOf(marks.end, from);
|
|
142
|
+
if (to >= 0)
|
|
143
|
+
return (body.slice(0, from) + marks.section + body.slice(to + marks.end.length));
|
|
144
|
+
const kept = body.trimEnd();
|
|
145
|
+
return kept === "" ? marks.section : `${kept}\n\n${marks.section}`;
|
|
146
|
+
}
|
|
147
|
+
async function pullBody(operation, number) {
|
|
148
|
+
const pull = JSON.parse(await githubRead(operation, [
|
|
149
|
+
"api",
|
|
150
|
+
`${repositoryPath}/pulls/${String(number)}`,
|
|
151
|
+
]));
|
|
152
|
+
const body = field(pull, "body");
|
|
153
|
+
return typeof body === "string" ? body : "";
|
|
154
|
+
}
|
|
155
|
+
function attachedUrl(body, marks) {
|
|
156
|
+
const from = body.indexOf(marks.start);
|
|
157
|
+
const to = from < 0 ? -1 : body.indexOf(marks.end, from);
|
|
158
|
+
const url = to < 0 ? "" : (body.slice(from, to).trimEnd().split("\n").at(-1) ?? "");
|
|
159
|
+
if (!/^https:\/\/github\.com\/user-attachments\/assets\/[\w-]+$/.test(url))
|
|
160
|
+
throw new Error("github-call-failed");
|
|
161
|
+
return url;
|
|
162
|
+
}
|
|
163
|
+
async function described(operation, attachment) {
|
|
164
|
+
const { number, name } = attachment;
|
|
165
|
+
const start = `<!-- cloving-attachment:${String(number)}:${name} -->`;
|
|
166
|
+
const end = `<!-- /cloving-attachment:${String(number)}:${name} -->`;
|
|
167
|
+
const section = `${start}\n${attachment.comment}\n\n\n${end}`;
|
|
168
|
+
const copy = join(operation.folder, name);
|
|
169
|
+
const text = join(operation.folder, "body.md");
|
|
170
|
+
const turn = {
|
|
171
|
+
key: `${operation.settings.repository}#pull-${String(number)}`,
|
|
172
|
+
signal: operation.signal,
|
|
173
|
+
};
|
|
174
|
+
try {
|
|
175
|
+
await copiedAttachment(attachment.file, copy);
|
|
176
|
+
await inTurn(turn, async () => {
|
|
177
|
+
const current = await pullBody(operation, number);
|
|
178
|
+
await writeFile(text, withSection(current, { start, end, section }), "utf8");
|
|
179
|
+
await operation.calls.gh([
|
|
180
|
+
"pr",
|
|
181
|
+
"edit",
|
|
182
|
+
String(number),
|
|
183
|
+
"--body-file",
|
|
184
|
+
text,
|
|
185
|
+
"--attach",
|
|
186
|
+
copy,
|
|
187
|
+
]);
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
finally {
|
|
191
|
+
await rm(copy, { force: true });
|
|
192
|
+
await rm(text, { force: true });
|
|
193
|
+
}
|
|
194
|
+
return attachedUrl(await pullBody(operation, number), {
|
|
195
|
+
start,
|
|
196
|
+
end,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
async function delivered(operation, attachment) {
|
|
200
|
+
if (attachment.place === "description")
|
|
201
|
+
return await described(operation, attachment);
|
|
202
|
+
const url = await uploaded(operation, attachment);
|
|
203
|
+
await commented(operation, { ...attachment, url });
|
|
204
|
+
return url;
|
|
205
|
+
}
|
|
206
|
+
export async function attachAsset(operation) {
|
|
207
|
+
const attachment = attachmentOf(operation);
|
|
208
|
+
operatorPrivateTexts(operation.settings);
|
|
209
|
+
const repository = repositoryName(await operation.calls.gh(["repo", "view", "--json", "nameWithOwner"]));
|
|
210
|
+
issuePrivacy(attachment.comment, {
|
|
211
|
+
settings: operation.settings,
|
|
212
|
+
repository,
|
|
213
|
+
});
|
|
214
|
+
const file = await attachedFile(operation, attachment.name);
|
|
215
|
+
try {
|
|
216
|
+
const url = await delivered(operation, { ...attachment, file });
|
|
217
|
+
return { number: attachment.number, url };
|
|
218
|
+
}
|
|
219
|
+
finally {
|
|
220
|
+
await file.close();
|
|
221
|
+
}
|
|
222
|
+
}
|
|
@@ -24,7 +24,7 @@ function failureDetail(error, place) {
|
|
|
24
24
|
const text = typeof stderr === "string" ? stderr : "";
|
|
25
25
|
return {
|
|
26
26
|
detail: githubText(text, place).slice(-2_000),
|
|
27
|
-
status: Number(/\
|
|
27
|
+
status: Number(/\bHTTP (\d{3})\b/.exec(text)?.[1]),
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
export function githubText(text, settings) {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function triggerKind(trigger: unknown): "push" | "event";
|
|
2
|
+
export declare function pullRequestTrigger(source: string): unknown;
|
|
3
|
+
export declare function workflowApplies(trigger: unknown, context: {
|
|
4
|
+
readonly branch: string;
|
|
5
|
+
readonly paths: readonly string[];
|
|
6
|
+
}): boolean;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { parse } from "yaml";
|
|
2
|
+
function isRecord(value) {
|
|
3
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4
|
+
}
|
|
5
|
+
export function triggerKind(trigger) {
|
|
6
|
+
if (!isRecord(trigger))
|
|
7
|
+
return "push";
|
|
8
|
+
const types = patterns(trigger["types"]);
|
|
9
|
+
return types === undefined || types.includes("synchronize")
|
|
10
|
+
? "push"
|
|
11
|
+
: "event";
|
|
12
|
+
}
|
|
13
|
+
export function pullRequestTrigger(source) {
|
|
14
|
+
try {
|
|
15
|
+
const document = parse(source, { merge: true });
|
|
16
|
+
if (!isRecord(document) || !("on" in document))
|
|
17
|
+
return true;
|
|
18
|
+
const events = document["on"];
|
|
19
|
+
if (typeof events === "string")
|
|
20
|
+
return events === "pull_request";
|
|
21
|
+
if (Array.isArray(events))
|
|
22
|
+
return events.includes("pull_request");
|
|
23
|
+
if (isRecord(events))
|
|
24
|
+
return "pull_request" in events ? events["pull_request"] : false;
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function patternToken(token) {
|
|
32
|
+
if (token === "**/")
|
|
33
|
+
return { kind: "directory" };
|
|
34
|
+
if (token === "*" || token === "**")
|
|
35
|
+
return {
|
|
36
|
+
kind: "character",
|
|
37
|
+
matcher: token === "*" ? /[^/]/ : /[\s\S]/,
|
|
38
|
+
optional: true,
|
|
39
|
+
repeat: true,
|
|
40
|
+
};
|
|
41
|
+
const literal = token.startsWith("\\") ? token.slice(1) : token;
|
|
42
|
+
const source = token.startsWith("[")
|
|
43
|
+
? token
|
|
44
|
+
: literal.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
45
|
+
return {
|
|
46
|
+
kind: "character",
|
|
47
|
+
matcher: new RegExp(`^${source}$`),
|
|
48
|
+
optional: false,
|
|
49
|
+
repeat: false,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function patternTokens(source) {
|
|
53
|
+
const tokens = [];
|
|
54
|
+
for (const raw of source.match(/\*\*\/|\*\*|\*|\[[a-zA-Z0-9-]+\]|\\[\s\S]|[\s\S]/g) ?? []) {
|
|
55
|
+
if (raw !== "?" && raw !== "+") {
|
|
56
|
+
tokens.push(patternToken(raw));
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
const previous = tokens.pop();
|
|
60
|
+
if (previous?.kind !== "character" || previous.optional || previous.repeat)
|
|
61
|
+
throw new Error("invalid-workflow-filter");
|
|
62
|
+
tokens.push({ ...previous, optional: raw === "?", repeat: raw === "+" });
|
|
63
|
+
}
|
|
64
|
+
return tokens;
|
|
65
|
+
}
|
|
66
|
+
function advanceDirectory({ value, previous, }) {
|
|
67
|
+
let reachable = false;
|
|
68
|
+
return Array.from({ length: value.length + 1 }, (_, index) => {
|
|
69
|
+
const matches = previous[index] === true || (reachable && value[index - 1] === "/");
|
|
70
|
+
reachable ||= previous[index] === true;
|
|
71
|
+
return matches;
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function advancePattern(token, input) {
|
|
75
|
+
const { value, previous } = input;
|
|
76
|
+
const next = [];
|
|
77
|
+
for (let index = 0; index <= value.length; index += 1) {
|
|
78
|
+
const consumes = index > 0 && token.matcher.test(value[index - 1] ?? "");
|
|
79
|
+
next[index] =
|
|
80
|
+
(token.optional && previous[index] === true) ||
|
|
81
|
+
(consumes &&
|
|
82
|
+
(previous[index - 1] === true ||
|
|
83
|
+
(token.repeat && next[index - 1] === true)));
|
|
84
|
+
}
|
|
85
|
+
return next;
|
|
86
|
+
}
|
|
87
|
+
function matchesPattern(value, source) {
|
|
88
|
+
let previous = [true];
|
|
89
|
+
for (const token of patternTokens(source))
|
|
90
|
+
previous =
|
|
91
|
+
token.kind === "directory"
|
|
92
|
+
? advanceDirectory({ value, previous })
|
|
93
|
+
: advancePattern(token, { value, previous });
|
|
94
|
+
return previous[value.length] === true;
|
|
95
|
+
}
|
|
96
|
+
function selected(value, patterns) {
|
|
97
|
+
let included = false;
|
|
98
|
+
for (const pattern of patterns) {
|
|
99
|
+
const negative = pattern.startsWith("!");
|
|
100
|
+
const source = negative ? pattern.slice(1) : pattern;
|
|
101
|
+
try {
|
|
102
|
+
if (matchesPattern(value, source))
|
|
103
|
+
included = !negative;
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return included;
|
|
110
|
+
}
|
|
111
|
+
function patterns(value) {
|
|
112
|
+
if (!Array.isArray(value) || value.length === 0)
|
|
113
|
+
return undefined;
|
|
114
|
+
return value.every((item) => typeof item === "string")
|
|
115
|
+
? value
|
|
116
|
+
: undefined;
|
|
117
|
+
}
|
|
118
|
+
function allows(values, filters) {
|
|
119
|
+
const include = patterns(filters.include);
|
|
120
|
+
const ignore = patterns(filters.ignore);
|
|
121
|
+
if (include !== undefined &&
|
|
122
|
+
!values.some((value) => selected(value, include) !== false))
|
|
123
|
+
return false;
|
|
124
|
+
return (ignore === undefined ||
|
|
125
|
+
values.some((value) => selected(value, ignore) !== true));
|
|
126
|
+
}
|
|
127
|
+
export function workflowApplies(trigger, context) {
|
|
128
|
+
if (!isRecord(trigger))
|
|
129
|
+
return trigger !== false;
|
|
130
|
+
return (allows([context.branch], {
|
|
131
|
+
include: trigger["branches"],
|
|
132
|
+
ignore: trigger["branches-ignore"],
|
|
133
|
+
}) &&
|
|
134
|
+
allows(context.paths, {
|
|
135
|
+
include: trigger["paths"],
|
|
136
|
+
ignore: trigger["paths-ignore"],
|
|
137
|
+
}));
|
|
138
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type Operation } from "./github-operation.ts";
|
|
2
|
+
export interface ExpectedWorkflow {
|
|
3
|
+
readonly path: string;
|
|
4
|
+
readonly kind: "push" | "event";
|
|
5
|
+
}
|
|
6
|
+
export declare function pullRequestWorkflows(operation: Operation, commit: string): Promise<readonly ExpectedWorkflow[]>;
|
|
7
|
+
export declare function pendingWorkflows(operation: Operation, input: {
|
|
8
|
+
readonly commit: string;
|
|
9
|
+
readonly workflows: readonly ExpectedWorkflow[];
|
|
10
|
+
}): Promise<readonly string[]>;
|