cloving 1.1.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +584 -144
- package/assets/watch-fonts/fira-code-OFL.md +93 -0
- package/assets/watch-fonts/fira-code-latin-400-normal.woff2 +0 -0
- package/assets/watch-fonts/fira-code-latin-500-normal.woff2 +0 -0
- package/assets/watch-fonts/heebo-OFL.md +93 -0
- package/assets/watch-fonts/heebo-latin-500-normal.woff2 +0 -0
- package/assets/watch-fonts/heebo-latin-700-normal.woff2 +0 -0
- package/assets/watch-fonts/heebo-latin-800-normal.woff2 +0 -0
- package/assets/watch-fonts/manifest.json +112 -0
- package/assets/watch-fonts/space-grotesk-OFL.md +93 -0
- package/assets/watch-fonts/space-grotesk-latin-400-normal.woff2 +0 -0
- package/assets/watch-fonts/space-grotesk-latin-500-normal.woff2 +0 -0
- package/assets/watch-fonts/space-grotesk-latin-600-normal.woff2 +0 -0
- package/assets/watch-fonts/space-grotesk-latin-700-normal.woff2 +0 -0
- package/dist/src/agent-harness-shell.d.ts +12 -0
- package/dist/src/agent-harness-shell.js +90 -0
- package/dist/src/agent-harness-versions.d.ts +8 -0
- package/dist/src/agent-harness-versions.js +49 -0
- package/dist/src/agent-harnesses.d.ts +4 -0
- package/dist/src/agent-harnesses.js +13 -0
- package/dist/src/authority/commands.d.ts +2 -0
- package/dist/src/authority/commands.js +49 -8
- package/dist/src/authority/dispatch-decision.d.ts +1 -0
- package/dist/src/authority/dispatch-decision.js +7 -4
- package/dist/src/authority/events.js +2 -2
- package/dist/src/authority/gate-reduction.d.ts +1 -0
- package/dist/src/authority/gate-reduction.js +18 -3
- package/dist/src/authority/gates.d.ts +2 -1
- package/dist/src/authority/gates.js +5 -1
- package/dist/src/authority/handoff-chain.d.ts +24 -0
- package/dist/src/authority/handoff-chain.js +46 -0
- package/dist/src/authority/operations.js +1 -1
- package/dist/src/authority/reconciliation.d.ts +1 -0
- package/dist/src/authority/reconciliation.js +18 -11
- package/dist/src/authority/reduction.d.ts +1 -1
- package/dist/src/authority/reduction.js +6 -1
- package/dist/src/authority/status-input.d.ts +1 -1
- package/dist/src/authority/status.d.ts +1 -0
- package/dist/src/authority/status.js +27 -3
- package/dist/src/authority/transitions.d.ts +5 -5
- package/dist/src/authority/transitions.js +9 -0
- package/dist/src/broker/actor/authority-delivery.js +1 -0
- package/dist/src/broker/actor/authority-queries.d.ts +11 -1
- package/dist/src/broker/actor/authority-queries.js +67 -3
- package/dist/src/broker/actor/authority-receipts.js +11 -1
- package/dist/src/broker/actor/authority-session.js +2 -2
- package/dist/src/broker/actor/authority-settings.js +4 -0
- package/dist/src/broker/actor/delivery-intents.d.ts +3 -1
- package/dist/src/broker/actor/delivery-intents.js +4 -4
- package/dist/src/broker/actor/effect-delivery.js +13 -1
- package/dist/src/broker/actor/effect-queries.d.ts +1 -0
- package/dist/src/broker/actor/effect-queries.js +7 -0
- package/dist/src/broker/actor/pin-check.js +1 -1
- package/dist/src/broker/actor/stop-plan.js +1 -1
- package/dist/src/broker/actor/turn-state.js +1 -1
- package/dist/src/broker/authority-admission.js +26 -5
- package/dist/src/broker/authority-restore.js +1 -0
- package/dist/src/broker/decision-restore.js +4 -4
- package/dist/src/broker/socket-address.d.ts +3 -1
- package/dist/src/broker/socket-address.js +2 -2
- package/dist/src/cli/arguments.d.ts +11 -13
- package/dist/src/cli/arguments.js +37 -107
- package/dist/src/cli/command-effects.d.ts +7 -0
- package/dist/src/cli/command-effects.js +39 -0
- package/dist/src/cli/commands.js +11 -4
- package/dist/src/cli/config-arguments.d.ts +11 -0
- package/dist/src/cli/config-arguments.js +59 -0
- package/dist/src/cli/config-command.d.ts +2 -0
- package/dist/src/cli/config-command.js +105 -0
- package/dist/src/cli/config-file.d.ts +3 -0
- package/dist/src/cli/config-file.js +50 -0
- package/dist/src/cli/config-lock.d.ts +7 -0
- package/dist/src/cli/config-lock.js +61 -0
- package/dist/src/cli/config-notice.d.ts +5 -0
- package/dist/src/cli/config-notice.js +46 -0
- package/dist/src/cli/doctor-github.d.ts +9 -0
- package/dist/src/cli/doctor-github.js +138 -0
- package/dist/src/cli/doctor-harness.d.ts +13 -0
- package/dist/src/cli/doctor-harness.js +242 -0
- package/dist/src/cli/doctor-local.d.ts +18 -0
- package/dist/src/cli/doctor-local.js +77 -0
- package/dist/src/cli/doctor-runtime.d.ts +15 -0
- package/dist/src/cli/doctor-runtime.js +176 -0
- package/dist/src/cli/doctor-service.d.ts +1 -0
- package/dist/src/cli/doctor-service.js +11 -0
- package/dist/src/cli/doctor-workflows.d.ts +3 -0
- package/dist/src/cli/doctor-workflows.js +45 -0
- package/dist/src/cli/doctor.d.ts +15 -0
- package/dist/src/cli/doctor.js +190 -0
- package/dist/src/cli/github-ci-progress.d.ts +8 -0
- package/dist/src/cli/github-ci-progress.js +83 -0
- package/dist/src/cli/github-retry.d.ts +6 -0
- package/dist/src/cli/github-retry.js +47 -0
- package/dist/src/cli/harness-probes.d.ts +22 -0
- package/dist/src/cli/harness-probes.js +183 -0
- package/dist/src/cli/main.d.ts +7 -1
- package/dist/src/cli/main.js +39 -61
- package/dist/src/cli/phone-arguments.d.ts +14 -0
- package/dist/src/cli/phone-arguments.js +37 -0
- package/dist/src/cli/phone-client.d.ts +2 -0
- package/dist/src/cli/phone-client.js +32 -0
- package/dist/src/cli/phone-command.d.ts +13 -0
- package/dist/src/cli/phone-command.js +101 -0
- package/dist/src/cli/probe-command.d.ts +36 -0
- package/dist/src/cli/probe-command.js +59 -0
- package/dist/src/cli/project-settings.d.ts +4 -0
- package/dist/src/cli/project-settings.js +33 -0
- package/dist/src/cli/render.d.ts +3 -1
- package/dist/src/cli/render.js +102 -39
- package/dist/src/cli/report-github.d.ts +18 -0
- package/dist/src/cli/report-github.js +200 -0
- package/dist/src/cli/report.d.ts +17 -0
- package/dist/src/cli/report.js +192 -0
- package/dist/src/cli/repository-arguments.d.ts +5 -0
- package/dist/src/cli/repository-arguments.js +34 -0
- package/dist/src/cli/runtime-arguments.d.ts +4 -0
- package/dist/src/cli/runtime-arguments.js +15 -0
- package/dist/src/cli/runtime-directory.d.ts +6 -2
- package/dist/src/cli/runtime-directory.js +72 -14
- package/dist/src/cli/toolchain.d.ts +2 -0
- package/dist/src/cli/toolchain.js +22 -2
- package/dist/src/cli/usage-render.d.ts +5 -0
- package/dist/src/cli/usage-render.js +40 -1
- package/dist/src/cli/usage.d.ts +3 -3
- package/dist/src/cli/usage.js +74 -45
- package/dist/src/cli/watch-actions.d.ts +2 -0
- package/dist/src/cli/watch-actions.js +4 -4
- package/dist/src/cli/watch-board-view.d.ts +12 -1
- package/dist/src/cli/watch-board-view.js +64 -12
- package/dist/src/cli/watch-board.d.ts +7 -1
- package/dist/src/cli/watch-board.js +61 -16
- package/dist/src/cli/watch-card-forms.js +2 -2
- package/dist/src/cli/watch-client.d.ts +1 -1
- package/dist/src/cli/watch-client.js +12 -3
- package/dist/src/cli/watch-header-view.d.ts +27 -0
- package/dist/src/cli/watch-header-view.js +116 -0
- package/dist/src/cli/watch-model.d.ts +10 -4
- package/dist/src/cli/watch-model.js +49 -59
- package/dist/src/cli/watch-page.js +67 -14
- package/dist/src/cli/watch-phases.js +3 -3
- package/dist/src/cli/watch-phone-client.d.ts +1 -0
- package/dist/src/cli/watch-phone-client.js +84 -0
- package/dist/src/cli/watch-phone-view.d.ts +56 -0
- package/dist/src/cli/watch-phone-view.js +113 -0
- package/dist/src/cli/watch-phone.d.ts +5 -0
- package/dist/src/cli/watch-phone.js +53 -0
- package/dist/src/cli/watch-pr-command.d.ts +5 -2
- package/dist/src/cli/watch-pr-command.js +41 -4
- package/dist/src/cli/watch-pr-identity.d.ts +14 -2
- package/dist/src/cli/watch-pr-identity.js +25 -0
- package/dist/src/cli/watch-pr-observer.d.ts +1 -0
- package/dist/src/cli/watch-pr-observer.js +48 -6
- package/dist/src/cli/watch-pull-request.d.ts +12 -0
- package/dist/src/cli/watch-pull-request.js +134 -0
- package/dist/src/cli/watch-reads.d.ts +7 -1
- package/dist/src/cli/watch-reads.js +42 -20
- package/dist/src/cli/watch-render.d.ts +23 -2
- package/dist/src/cli/watch-render.js +2 -1
- package/dist/src/cli/watch-server.js +56 -7
- package/dist/src/cli/watch-turn.d.ts +4 -1
- package/dist/src/cli/watch-turn.js +38 -2
- package/dist/src/cli/watch-usage.js +5 -1
- package/dist/src/cli/watch-view.d.ts +10 -17
- package/dist/src/cli/watch-view.js +33 -77
- package/dist/src/cli.js +106 -23
- package/dist/src/command-settings.d.ts +16 -0
- package/dist/src/command-settings.js +42 -0
- package/dist/src/configuration-change.d.ts +11 -0
- package/dist/src/configuration-change.js +62 -0
- package/dist/src/configuration-display.d.ts +21 -0
- package/dist/src/configuration-display.js +69 -0
- package/dist/src/configuration-schema.d.ts +49 -0
- package/dist/src/configuration-schema.js +159 -0
- package/dist/src/daemon/claude-turn.d.ts +20 -5
- package/dist/src/daemon/claude-turn.js +116 -53
- package/dist/src/daemon/claude-worker.d.ts +3 -5
- package/dist/src/daemon/claude-worker.js +64 -80
- package/dist/src/daemon/command-journal.d.ts +5 -0
- package/dist/src/daemon/command-journal.js +50 -0
- package/dist/src/daemon/command-process.d.ts +28 -0
- package/dist/src/daemon/command-process.js +164 -0
- package/dist/src/daemon/command-worker.d.ts +19 -0
- package/dist/src/daemon/command-worker.js +182 -0
- package/dist/src/daemon/cursor-stream.d.ts +4 -0
- package/dist/src/daemon/cursor-stream.js +154 -0
- package/dist/src/daemon/daemon-adapters.d.ts +58 -0
- package/dist/src/daemon/daemon-adapters.js +102 -0
- package/dist/src/daemon/daemon-loops.d.ts +14 -0
- package/dist/src/daemon/daemon-loops.js +39 -0
- package/dist/src/daemon/daemon.d.ts +3 -30
- package/dist/src/daemon/daemon.js +132 -110
- package/dist/src/daemon/declared-input.d.ts +3 -0
- package/dist/src/daemon/declared-input.js +9 -0
- package/dist/src/daemon/delivery-router.js +7 -1
- package/dist/src/daemon/gemini-stream.d.ts +4 -0
- package/dist/src/daemon/gemini-stream.js +129 -0
- package/dist/src/daemon/github-calls.d.ts +4 -0
- package/dist/src/daemon/github-calls.js +16 -7
- package/dist/src/daemon/github-ci-rerun.d.ts +26 -0
- package/dist/src/daemon/github-ci-rerun.js +92 -0
- package/dist/src/daemon/github-ci.d.ts +6 -0
- package/dist/src/daemon/github-ci.js +251 -0
- package/dist/src/daemon/github-merge-call.d.ts +16 -0
- package/dist/src/daemon/github-merge-call.js +73 -0
- package/dist/src/daemon/github-merge.d.ts +3 -5
- package/dist/src/daemon/github-merge.js +59 -98
- package/dist/src/daemon/github-methods.d.ts +28 -0
- package/dist/src/daemon/github-methods.js +90 -16
- package/dist/src/daemon/github-operation.d.ts +3 -0
- package/dist/src/daemon/github-retry.d.ts +6 -0
- package/dist/src/daemon/github-retry.js +13 -0
- package/dist/src/daemon/github-ticket-status.js +27 -1
- package/dist/src/daemon/github-worker.js +2 -1
- package/dist/src/daemon/handoff-worker.d.ts +10 -0
- package/dist/src/daemon/handoff-worker.js +232 -0
- package/dist/src/daemon/issue-queue.d.ts +2 -0
- package/dist/src/daemon/issue-queue.js +92 -63
- package/dist/src/daemon/notify-journal.d.ts +18 -0
- package/dist/src/daemon/notify-journal.js +108 -0
- package/dist/src/daemon/notify-message.js +2 -1
- package/dist/src/daemon/notify.js +177 -37
- package/dist/src/daemon/opencode-stream.d.ts +5 -0
- package/dist/src/daemon/opencode-stream.js +87 -0
- package/dist/src/daemon/queue-status.d.ts +4 -0
- package/dist/src/daemon/queue-status.js +38 -0
- package/dist/src/daemon/retry-worktree.d.ts +18 -0
- package/dist/src/daemon/retry-worktree.js +139 -0
- package/dist/src/daemon/retrying-turn.d.ts +5 -0
- package/dist/src/daemon/retrying-turn.js +145 -21
- package/dist/src/daemon/schedule-journal.d.ts +19 -0
- package/dist/src/daemon/schedule-journal.js +57 -0
- package/dist/src/daemon/text-output.d.ts +18 -0
- package/dist/src/daemon/text-output.js +44 -0
- package/dist/src/daemon/ticket-dependency-waits.d.ts +18 -0
- package/dist/src/daemon/ticket-dependency-waits.js +60 -0
- package/dist/src/daemon/ticket-registration.d.ts +10 -8
- package/dist/src/daemon/ticket-registration.js +146 -47
- package/dist/src/daemon/ticket-source.d.ts +4 -1
- package/dist/src/daemon/ticket-source.js +8 -2
- package/dist/src/daemon/turn-command.d.ts +10 -0
- package/dist/src/daemon/turn-command.js +33 -0
- package/dist/src/daemon/turn-report.d.ts +18 -0
- package/dist/src/daemon/turn-report.js +79 -0
- package/dist/src/daemon/work-tree.d.ts +2 -1
- package/dist/src/daemon/work-tree.js +15 -12
- package/dist/src/daemon/workflow-generations.d.ts +32 -0
- package/dist/src/daemon/workflow-generations.js +57 -0
- package/dist/src/daemon/workflow-replay.d.ts +16 -0
- package/dist/src/daemon/workflow-replay.js +58 -0
- package/dist/src/daemon/workflow-schedules.d.ts +27 -0
- package/dist/src/daemon/workflow-schedules.js +185 -0
- package/dist/src/decision-visibility.d.ts +2 -0
- package/dist/src/decision-visibility.js +10 -0
- package/dist/src/decision-wait.d.ts +1 -0
- package/dist/src/decision-wait.js +3 -0
- package/dist/src/delivery-backoff.d.ts +1 -0
- package/dist/src/delivery-backoff.js +3 -0
- package/dist/src/doctor-report.d.ts +24 -0
- package/dist/src/doctor-report.js +70 -0
- package/dist/src/execution-pin.d.ts +9 -0
- package/dist/src/execution-pin.js +86 -2
- package/dist/src/grok-result.d.ts +12 -0
- package/dist/src/grok-result.js +61 -0
- package/dist/src/harness-defaults.d.ts +35 -0
- package/dist/src/harness-defaults.js +121 -0
- package/dist/src/host/decision-resume.d.ts +35 -0
- package/dist/src/host/decision-resume.js +86 -0
- package/dist/src/host/gate-bridge.d.ts +48 -0
- package/dist/src/host/gate-bridge.js +124 -0
- package/dist/src/host/run-wait.d.ts +26 -0
- package/dist/src/host/run-wait.js +37 -0
- package/dist/src/host/start-delivery.d.ts +3 -2
- package/dist/src/host/start-delivery.js +11 -4
- package/dist/src/host/step-bridge-host.d.ts +6 -19
- package/dist/src/host/step-bridge-host.js +57 -55
- package/dist/src/host/world-reconciliation.d.ts +1 -0
- package/dist/src/host/world-reconciliation.js +3 -0
- package/dist/src/host/world-runs.js +5 -0
- package/dist/src/issue-identity.d.ts +6 -0
- package/dist/src/issue-identity.js +23 -0
- package/dist/src/merge-request.d.ts +19 -0
- package/dist/src/merge-request.js +32 -0
- package/dist/src/phone/canonical-json.d.ts +1 -0
- package/dist/src/phone/canonical-json.js +16 -0
- package/dist/src/phone/phone-link.d.ts +7 -0
- package/dist/src/phone/phone-link.js +21 -0
- package/dist/src/phone/qr-data.d.ts +8 -0
- package/dist/src/phone/qr-data.js +133 -0
- package/dist/src/phone/qr-matrix.d.ts +6 -0
- package/dist/src/phone/qr-matrix.js +175 -0
- package/dist/src/phone/qr-penalty.d.ts +3 -0
- package/dist/src/phone/qr-penalty.js +67 -0
- package/dist/src/phone/qr-picture.d.ts +5 -0
- package/dist/src/phone/qr-picture.js +24 -0
- package/dist/src/private-config.schema.json +263 -0
- package/dist/src/project-config.schema.json +65 -0
- package/dist/src/project-settings.d.ts +19 -0
- package/dist/src/project-settings.js +131 -0
- package/dist/src/relay/answer-check.d.ts +24 -0
- package/dist/src/relay/answer-check.js +145 -0
- package/dist/src/relay/answer-inbox.d.ts +15 -0
- package/dist/src/relay/answer-inbox.js +173 -0
- package/dist/src/relay/daemon-keys.d.ts +16 -0
- package/dist/src/relay/daemon-keys.js +75 -0
- package/dist/src/relay/decision-check.d.ts +3 -0
- package/dist/src/relay/decision-check.js +77 -0
- package/dist/src/relay/decision-close.d.ts +6 -0
- package/dist/src/relay/decision-close.js +72 -0
- package/dist/src/relay/decision-envelopes.d.ts +29 -0
- package/dist/src/relay/decision-envelopes.js +93 -0
- package/dist/src/relay/decision-watch.d.ts +14 -0
- package/dist/src/relay/decision-watch.js +68 -0
- package/dist/src/relay/envelope-post.d.ts +8 -0
- package/dist/src/relay/envelope-post.js +71 -0
- package/dist/src/relay/envelope.d.ts +28 -0
- package/dist/src/relay/envelope.js +53 -0
- package/dist/src/relay/hpke.d.ts +25 -0
- package/dist/src/relay/hpke.js +108 -0
- package/dist/src/relay/pairing-checks.d.ts +42 -0
- package/dist/src/relay/pairing-checks.js +172 -0
- package/dist/src/relay/pairing-follow.d.ts +8 -0
- package/dist/src/relay/pairing-follow.js +95 -0
- package/dist/src/relay/pairing-session.d.ts +29 -0
- package/dist/src/relay/pairing-session.js +87 -0
- package/dist/src/relay/phone-delivery.d.ts +51 -0
- package/dist/src/relay/phone-delivery.js +139 -0
- package/dist/src/relay/phone-devices.d.ts +36 -0
- package/dist/src/relay/phone-devices.js +46 -0
- package/dist/src/relay/phone-inbox.d.ts +18 -0
- package/dist/src/relay/phone-inbox.js +17 -0
- package/dist/src/relay/phone-operations.d.ts +18 -0
- package/dist/src/relay/phone-operations.js +121 -0
- package/dist/src/relay/phone-outbox.d.ts +21 -0
- package/dist/src/relay/phone-outbox.js +25 -0
- package/dist/src/relay/phone-socket.d.ts +6 -0
- package/dist/src/relay/phone-socket.js +63 -0
- package/dist/src/relay/relay-control.d.ts +7 -0
- package/dist/src/relay/relay-control.js +24 -0
- package/dist/src/relay/relay-files.d.ts +2 -0
- package/dist/src/relay/relay-files.js +23 -0
- package/dist/src/relay/relay-heartbeat.d.ts +17 -0
- package/dist/src/relay/relay-heartbeat.js +81 -0
- package/dist/src/relay/relay-http.d.ts +14 -0
- package/dist/src/relay/relay-http.js +63 -0
- package/dist/src/relay/relay-registration.d.ts +15 -0
- package/dist/src/relay/relay-registration.js +63 -0
- package/dist/src/relay/relay-service.d.ts +25 -0
- package/dist/src/relay/relay-service.js +216 -0
- package/dist/src/relay/relay-store.d.ts +48 -0
- package/dist/src/relay/relay-store.js +131 -0
- package/dist/src/relay/sealed-post.d.ts +25 -0
- package/dist/src/relay/sealed-post.js +52 -0
- package/dist/src/relay.d.ts +1 -0
- package/dist/src/relay.js +8 -0
- package/dist/src/report-statistics.d.ts +50 -0
- package/dist/src/report-statistics.js +70 -0
- package/dist/src/report.d.ts +171 -0
- package/dist/src/report.js +119 -0
- package/dist/src/repository-identity.d.ts +4 -0
- package/dist/src/repository-identity.js +4 -0
- package/dist/src/review-subject.d.ts +41 -0
- package/dist/src/review-subject.js +91 -0
- package/dist/src/run-wait.d.ts +23 -0
- package/dist/src/run-wait.js +20 -0
- package/dist/src/service/active-tickets.d.ts +4 -0
- package/dist/src/service/active-tickets.js +49 -0
- package/dist/src/service/command-effects.d.ts +4 -0
- package/dist/src/service/command-effects.js +16 -0
- package/dist/src/service/decision-handler.d.ts +4 -0
- package/dist/src/service/decision-handler.js +39 -4
- package/dist/src/service/gateway.js +18 -3
- package/dist/src/service/queue-runs.d.ts +3 -0
- package/dist/src/service/queue-runs.js +39 -0
- package/dist/src/service/registry.d.ts +22 -3
- package/dist/src/service/registry.js +51 -8
- package/dist/src/service/replies.d.ts +10 -0
- package/dist/src/service/replies.js +12 -0
- package/dist/src/service/run-handlers.js +45 -54
- package/dist/src/service/run-metadata.d.ts +8 -0
- package/dist/src/service/run-metadata.js +53 -0
- package/dist/src/service/run-waits.d.ts +3 -0
- package/dist/src/service/run-waits.js +41 -0
- package/dist/src/service/service.d.ts +21 -2
- package/dist/src/service/service.js +23 -5
- package/dist/src/service/submission-handler.js +70 -19
- package/dist/src/service/worker-port.d.ts +1 -0
- package/dist/src/service/worker-totals.js +10 -1
- package/dist/src/step-bridge.d.ts +32 -0
- package/dist/src/steps/decision-gate.d.ts +2 -1
- package/dist/src/steps/decision-gate.js +7 -0
- package/dist/src/steps/handoff.d.ts +2 -0
- package/dist/src/steps/handoff.js +13 -0
- package/dist/src/steps/merge-by-person.d.ts +2 -0
- package/dist/src/steps/merge-by-person.js +18 -0
- package/dist/src/steps/merge-when-green.d.ts +2 -0
- package/dist/src/steps/merge-when-green.js +62 -0
- package/dist/src/steps/review-by-agent.d.ts +5 -0
- package/dist/src/steps/review-by-agent.js +124 -0
- package/dist/src/steps/review-by-person.d.ts +4 -0
- package/dist/src/steps/review-by-person.js +16 -0
- package/dist/src/steps/review-subject.d.ts +2 -0
- package/dist/src/steps/review-subject.js +11 -0
- package/dist/src/steps/run-command.d.ts +2 -0
- package/dist/src/steps/run-command.js +15 -0
- package/dist/src/steps/sleep.d.ts +3 -0
- package/dist/src/steps/sleep.js +19 -0
- package/dist/src/steps/wait-for-decision.d.ts +2 -0
- package/dist/src/steps/wait-for-decision.js +71 -0
- package/dist/src/steps/wait-for-run.d.ts +5 -0
- package/dist/src/steps/wait-for-run.js +9 -0
- package/dist/src/storage/decision-snapshots.d.ts +1 -0
- package/dist/src/storage/decision-snapshots.js +7 -1
- package/dist/src/submission.d.ts +4 -0
- package/dist/src/submission.js +6 -2
- package/dist/src/testing.d.ts +29 -0
- package/dist/src/testing.js +264 -0
- package/dist/src/ticket-dependencies.d.ts +1 -0
- package/dist/src/ticket-dependencies.js +15 -0
- package/dist/src/ticket-status-stream.d.ts +9 -0
- package/dist/src/ticket-status-stream.js +94 -0
- package/dist/src/ticket-status.js +7 -4
- package/dist/src/token-prices.d.ts +14 -4
- package/dist/src/token-prices.js +56 -11
- package/dist/src/turn-profile.d.ts +1 -0
- package/dist/src/turn-profile.js +8 -1
- package/dist/src/worker-usage.d.ts +25 -0
- package/dist/src/worker-usage.js +58 -1
- package/dist/src/workflow-admission.d.ts +6 -0
- package/dist/src/workflow-candidate.d.ts +7 -2
- package/dist/src/workflow-candidate.js +48 -5
- package/dist/src/workflow-contracts.d.ts +2 -0
- package/dist/src/workflow-contracts.js +8 -3
- package/dist/src/workflow-declaration.d.ts +31 -2
- package/dist/src/workflow-declaration.js +140 -16
- package/dist/src/workflow-discovery.d.ts +19 -0
- package/dist/src/workflow-discovery.js +36 -0
- package/dist/src/workflow-refusals.d.ts +6 -0
- package/dist/src/workflow-refusals.js +42 -0
- package/dist/src/workflow-schedule.d.ts +22 -0
- package/dist/src/workflow-schedule.js +53 -0
- package/dist/src/workflows.d.ts +12 -1
- package/dist/src/workflows.js +9 -0
- package/dist/tools/admit-workflow.d.ts +14 -0
- package/dist/tools/admit-workflow.js +107 -0
- package/dist/tools/doctor-adoption.d.ts +1 -0
- package/dist/tools/doctor-adoption.js +11 -0
- package/dist/tools/project-configuration.d.ts +4 -0
- package/dist/tools/project-configuration.js +47 -0
- package/dist/tools/self-host-processes.d.ts +1 -0
- package/dist/tools/self-host-processes.js +33 -22
- package/dist/tools/self-host-project.d.ts +21 -0
- package/dist/tools/self-host-project.js +224 -0
- package/dist/tools/self-host-runtime.d.ts +16 -0
- package/dist/tools/self-host-runtime.js +60 -0
- package/dist/tools/self-host-workflows.d.ts +1 -0
- package/dist/tools/self-host-workflows.js +36 -1
- package/dist/tools/self-host.js +106 -135
- package/dist/tools/workflow-bundle-dependencies.d.ts +5 -0
- package/dist/tools/workflow-bundle-dependencies.js +93 -0
- package/dist/tools/workflow-bundles.d.ts +20 -0
- package/dist/tools/workflow-bundles.js +173 -0
- package/dist/tools/workflow-candidate-counts.d.ts +12 -0
- package/dist/tools/workflow-candidate-counts.js +266 -0
- package/dist/tools/workflow-candidate-fields.d.ts +5 -0
- package/dist/tools/workflow-candidate-fields.js +24 -0
- package/dist/tools/workflow-candidate-helper-counts.d.ts +10 -0
- package/dist/tools/workflow-candidate-helper-counts.js +129 -0
- package/dist/tools/workflow-candidate-program.d.ts +13 -0
- package/dist/tools/workflow-candidate-program.js +106 -0
- package/dist/tools/workflow-candidate-source.d.ts +6 -0
- package/dist/tools/workflow-candidate-source.js +169 -0
- package/dist/tools/workflow-candidate-syntax.d.ts +21 -0
- package/dist/tools/workflow-candidate-syntax.js +263 -0
- package/dist/tools/workflow-command.d.ts +1 -0
- package/dist/tools/workflow-command.js +143 -0
- package/dist/tools/workflow-folder-capture.d.ts +18 -0
- package/dist/tools/workflow-folder-capture.js +261 -0
- package/dist/tools/workflow-folders.d.ts +49 -0
- package/dist/tools/workflow-folders.js +203 -0
- package/dist/tools/workflow-source-effects.d.ts +10 -0
- package/dist/tools/workflow-source-effects.js +213 -0
- package/dist/tools/workflow-test-hook.d.ts +7 -0
- package/dist/tools/workflow-test-hook.js +16 -0
- package/dist/tools/workflow-test-loader.d.ts +1 -0
- package/dist/tools/workflow-test-loader.js +10 -0
- package/dist/workflows/develop-prd.js +71 -3
- package/dist/workflows/develop-ticket.js +6 -1
- package/dist/workflows/ticket-prompts.js +17 -3
- package/package.json +66 -6
- package/templates/develop/README.md +78 -0
- package/templates/develop/develop/accept.ts +11 -0
- package/templates/develop/develop/flow-tests.ts +357 -0
- package/templates/develop/develop/local.ts +40 -0
- package/templates/develop/develop/option-tests.ts +174 -0
- package/templates/develop/develop/partial-choice.ts +29 -0
- package/templates/develop/develop/partial.ts +28 -0
- package/templates/develop/develop/pull.ts +152 -0
- package/templates/develop/develop/queue-partial.ts +39 -0
- package/templates/develop/develop/refusal-tests.ts +174 -0
- package/templates/develop/develop/report.ts +156 -0
- package/templates/develop/develop/round.ts +40 -0
- package/templates/develop/develop/scenarios.ts +87 -0
- package/templates/develop/develop/turn.ts +67 -0
- package/templates/develop/develop.declaration.json +24 -0
- package/templates/develop/develop.test.ts +287 -0
- package/templates/develop/develop.ts +30 -0
- package/templates/develop/template.json +153 -0
- package/dist/src/chats/analysis-batches.d.ts +0 -24
- package/dist/src/chats/analysis-batches.js +0 -83
- package/dist/src/chats/analysis-contract.d.ts +0 -80
- package/dist/src/chats/analysis-contract.js +0 -16
- package/dist/src/chats/analysis-data.d.ts +0 -3
- package/dist/src/chats/analysis-data.js +0 -85
- package/dist/src/chats/analysis-input.d.ts +0 -12
- package/dist/src/chats/analysis-input.js +0 -83
- package/dist/src/chats/analysis-links.d.ts +0 -2
- package/dist/src/chats/analysis-links.js +0 -25
- package/dist/src/chats/analysis-prompt.d.ts +0 -10
- package/dist/src/chats/analysis-prompt.js +0 -16
- package/dist/src/chats/analysis-proposal.d.ts +0 -2
- package/dist/src/chats/analysis-proposal.js +0 -32
- package/dist/src/chats/analysis-provenance.d.ts +0 -4
- package/dist/src/chats/analysis-provenance.js +0 -99
- package/dist/src/chats/analysis-shape.d.ts +0 -3
- package/dist/src/chats/analysis-shape.js +0 -228
- package/dist/src/chats/analysis.d.ts +0 -3
- package/dist/src/chats/analysis.js +0 -42
- package/dist/src/chats/corpus-input.d.ts +0 -5
- package/dist/src/chats/corpus-input.js +0 -288
- package/dist/src/chats/destination.d.ts +0 -4
- package/dist/src/chats/destination.js +0 -96
- package/dist/src/chats/import.d.ts +0 -15
- package/dist/src/chats/import.js +0 -243
- package/dist/src/chats/input-file.d.ts +0 -3
- package/dist/src/chats/input-file.js +0 -32
- package/dist/src/chats/normalize.d.ts +0 -29
- package/dist/src/chats/normalize.js +0 -155
- package/dist/src/chats/previous-import.d.ts +0 -5
- package/dist/src/chats/previous-import.js +0 -34
- package/dist/src/chats/reader.d.ts +0 -21
- package/dist/src/chats/reader.js +0 -118
- package/dist/src/chats/redact-import.d.ts +0 -14
- package/dist/src/chats/redact-import.js +0 -141
- package/dist/src/chats/redaction.d.ts +0 -41
- package/dist/src/chats/redaction.js +0 -161
- package/dist/src/chats/revision-input.d.ts +0 -3
- package/dist/src/chats/revision-input.js +0 -180
- package/dist/src/chats/revision.d.ts +0 -48
- package/dist/src/chats/revision.js +0 -94
- package/dist/src/chats/selection.d.ts +0 -25
- package/dist/src/chats/selection.js +0 -109
- package/dist/src/chats/source.d.ts +0 -23
- package/dist/src/chats/source.js +0 -135
- package/dist/src/chats/structure.d.ts +0 -57
- package/dist/src/chats/structure.js +0 -216
- package/dist/src/daemon/analysis-launch.d.ts +0 -5
- package/dist/src/daemon/analysis-launch.js +0 -81
- package/dist/src/daemon/analysis-token.d.ts +0 -6
- package/dist/src/daemon/analysis-token.js +0 -88
- package/dist/src/daemon/analysis-worker.d.ts +0 -22
- package/dist/src/daemon/analysis-worker.js +0 -219
- package/dist/src/daemon/chats-files.d.ts +0 -15
- package/dist/src/daemon/chats-files.js +0 -113
- package/dist/src/daemon/chats-worker.d.ts +0 -12
- package/dist/src/daemon/chats-worker.js +0 -200
- package/dist/workflows/analyze-chats.d.ts +0 -10
- package/dist/workflows/analyze-chats.declaration.json +0 -9
- package/dist/workflows/analyze-chats.js +0 -73
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { qrMatrix } from "../phone/qr-matrix.js";
|
|
2
|
+
import { qrPicture } from "../phone/qr-picture.js";
|
|
3
|
+
import { phoneRequest } from "./phone-client.js";
|
|
4
|
+
import { actionAllowed, actionBody, } from "./watch-actions.js";
|
|
5
|
+
const operations = {
|
|
6
|
+
"/actions/phone/pair": "phone-pair-start",
|
|
7
|
+
"/actions/phone/cancel": "phone-pair-cancel",
|
|
8
|
+
"/actions/phone/accept": "phone-pair-accept",
|
|
9
|
+
"/actions/phone/deny": "phone-pair-deny",
|
|
10
|
+
"/actions/phone/remove": "phone-remove",
|
|
11
|
+
};
|
|
12
|
+
export function isPhoneAction(path) {
|
|
13
|
+
return Object.hasOwn(operations, path);
|
|
14
|
+
}
|
|
15
|
+
function withPicture(result) {
|
|
16
|
+
const link = result["link"];
|
|
17
|
+
return typeof link === "string"
|
|
18
|
+
? { ...result, picture: qrPicture(qrMatrix(link).modules) }
|
|
19
|
+
: result;
|
|
20
|
+
}
|
|
21
|
+
export async function phoneAction(actions, request) {
|
|
22
|
+
const operation = operations[new URL(String(request.url), "http://localhost").pathname];
|
|
23
|
+
if (operation === undefined || !actionAllowed(actions, request))
|
|
24
|
+
return null;
|
|
25
|
+
const body = await actionBody(request);
|
|
26
|
+
if (typeof body !== "object" || body === null || Array.isArray(body))
|
|
27
|
+
return null;
|
|
28
|
+
const reply = await phoneRequest(actions.runtimeDirectory, {
|
|
29
|
+
operation,
|
|
30
|
+
parameters: { ...body },
|
|
31
|
+
});
|
|
32
|
+
if (reply === undefined)
|
|
33
|
+
return JSON.stringify({
|
|
34
|
+
error: {
|
|
35
|
+
code: "phone-relay-off",
|
|
36
|
+
detail: "The phone relay is off or not started.",
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
return JSON.stringify(reply.kind === "result"
|
|
40
|
+
? withPicture(reply.result)
|
|
41
|
+
: { error: reply.error });
|
|
42
|
+
}
|
|
43
|
+
export async function phoneRead(runtimeDirectory) {
|
|
44
|
+
const reply = await phoneRequest(runtimeDirectory, {
|
|
45
|
+
operation: "phone-state",
|
|
46
|
+
parameters: {},
|
|
47
|
+
});
|
|
48
|
+
if (reply === undefined)
|
|
49
|
+
return JSON.stringify({ relay: "off" });
|
|
50
|
+
return JSON.stringify(reply.kind === "result"
|
|
51
|
+
? { relay: "on", ...reply.result }
|
|
52
|
+
: { relay: "on", error: reply.error });
|
|
53
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type PrIdentity, type
|
|
1
|
+
import { type PrIdentity, type PrReadResult } from "./watch-pr-identity.ts";
|
|
2
2
|
export interface WatchCommandOutput {
|
|
3
3
|
readonly stdout: string;
|
|
4
4
|
readonly stderr: string;
|
|
@@ -12,4 +12,7 @@ export interface WatchCommandRequest {
|
|
|
12
12
|
}
|
|
13
13
|
export type WatchCommandRunner = (request: WatchCommandRequest) => Promise<WatchCommandOutput>;
|
|
14
14
|
export declare function prArguments(identity: PrIdentity): readonly string[];
|
|
15
|
-
export declare function prCommandResult(identity: PrIdentity,
|
|
15
|
+
export declare function prCommandResult(identity: PrIdentity, reply: {
|
|
16
|
+
readonly output: WatchCommandOutput;
|
|
17
|
+
readonly now: number;
|
|
18
|
+
}): PrReadResult;
|
|
@@ -15,15 +15,52 @@ function commandFailure(output) {
|
|
|
15
15
|
/^HTTP\/[^ ]+ (\d{3})/m.exec(output.stdout)?.[1]);
|
|
16
16
|
if (status === 429 ||
|
|
17
17
|
/rate limit/i.test(output.stderr) ||
|
|
18
|
-
|
|
18
|
+
headerValues(output.stdout, "x-ratelimit-remaining").includes("0"))
|
|
19
19
|
return "rate-limit";
|
|
20
20
|
if (output.status === 4 || [401, 403, 404].includes(status))
|
|
21
21
|
return "access";
|
|
22
22
|
return "command";
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
if (
|
|
26
|
-
return
|
|
24
|
+
function headerValues(stdout, name) {
|
|
25
|
+
if (!/^HTTP\/[^ ]+ \d{3}/.test(stdout))
|
|
26
|
+
return [];
|
|
27
|
+
const headers = stdout.split(/\r?\n\r?\n/, 1)[0] ?? "";
|
|
28
|
+
return headers.split(/\r?\n/).flatMap((line) => {
|
|
29
|
+
const separator = line.indexOf(":");
|
|
30
|
+
return line.slice(0, separator).toLowerCase() === name
|
|
31
|
+
? [line.slice(separator + 1).trim()]
|
|
32
|
+
: [];
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
function millisecondsOf(value) {
|
|
36
|
+
if (!/^\d+$/.test(value))
|
|
37
|
+
return [];
|
|
38
|
+
const milliseconds = Number(value) * 1000;
|
|
39
|
+
return Number.isSafeInteger(milliseconds) ? [milliseconds] : [];
|
|
40
|
+
}
|
|
41
|
+
function retryDeadline(output, now) {
|
|
42
|
+
const delays = headerValues(output.stdout, "retry-after")
|
|
43
|
+
.flatMap(millisecondsOf)
|
|
44
|
+
.map((delay) => now + delay)
|
|
45
|
+
.filter(Number.isSafeInteger);
|
|
46
|
+
const resets = headerValues(output.stdout, "x-ratelimit-remaining").includes("0")
|
|
47
|
+
? headerValues(output.stdout, "x-ratelimit-reset").flatMap(millisecondsOf)
|
|
48
|
+
: [];
|
|
49
|
+
const deadlines = [...delays, ...resets];
|
|
50
|
+
return deadlines.length === 0 ? now + 60000 : Math.max(now, ...deadlines);
|
|
51
|
+
}
|
|
52
|
+
export function prCommandResult(identity, reply) {
|
|
53
|
+
const { output, now } = reply;
|
|
54
|
+
if (output.status !== 0 || output.errorCode !== null) {
|
|
55
|
+
const failure = commandFailure(output);
|
|
56
|
+
return {
|
|
57
|
+
status: "unavailable",
|
|
58
|
+
failure,
|
|
59
|
+
...(failure === "rate-limit"
|
|
60
|
+
? { retryAt: retryDeadline(output, now) }
|
|
61
|
+
: {}),
|
|
62
|
+
};
|
|
63
|
+
}
|
|
27
64
|
const envelope = /^HTTP\/[^ ]+ 200[^\n]*\r?\n[\s\S]*?\r?\n\r?\n([\s\S]*)$/.exec(output.stdout);
|
|
28
65
|
if (envelope?.[1] === undefined)
|
|
29
66
|
return { status: "unavailable", failure: "response" };
|
|
@@ -5,14 +5,26 @@ export interface PrIdentity {
|
|
|
5
5
|
readonly number: number;
|
|
6
6
|
}
|
|
7
7
|
export type PrFailure = "configuration" | "identity" | "command" | "access" | "rate-limit" | "response" | "timeout";
|
|
8
|
-
export type
|
|
8
|
+
export type PrReadResult = {
|
|
9
9
|
readonly status: "merged" | "unmerged";
|
|
10
10
|
} | {
|
|
11
11
|
readonly status: "unavailable";
|
|
12
12
|
readonly failure: PrFailure;
|
|
13
|
+
readonly retryAt?: number;
|
|
13
14
|
};
|
|
14
|
-
export
|
|
15
|
+
export type PrObservation = (PrReadResult | {
|
|
16
|
+
readonly status: "pending";
|
|
17
|
+
}) & {
|
|
18
|
+
readonly retryAt?: number;
|
|
19
|
+
readonly lastSuccess?: {
|
|
20
|
+
readonly status: "merged" | "unmerged";
|
|
21
|
+
readonly readAt: number;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export declare function prResponse(identity: PrIdentity, value: unknown): PrReadResult;
|
|
15
25
|
export type PrRepository = Omit<PrIdentity, "number">;
|
|
26
|
+
export declare function establishedIssue(repository: PrRepository | null, value: unknown): PrIdentity | null;
|
|
27
|
+
export declare function sameIssue(first: PrIdentity | null | undefined, second: PrIdentity | null | undefined): boolean;
|
|
16
28
|
export declare function prRepository(origin: string): PrRepository | null;
|
|
17
29
|
export declare function prIdentity(repository: PrRepository, pullRequest: {
|
|
18
30
|
readonly number: number;
|
|
@@ -31,6 +31,31 @@ export function prResponse(identity, value) {
|
|
|
31
31
|
return { status: "unavailable", failure: "response" };
|
|
32
32
|
return { status: merged ? "merged" : "unmerged" };
|
|
33
33
|
}
|
|
34
|
+
export function establishedIssue(repository, value) {
|
|
35
|
+
const fields = record(value) ?? {};
|
|
36
|
+
const number = fields["number"];
|
|
37
|
+
if (repository === null ||
|
|
38
|
+
typeof number !== "number" ||
|
|
39
|
+
!Number.isSafeInteger(number) ||
|
|
40
|
+
number <= 0)
|
|
41
|
+
return null;
|
|
42
|
+
const owner = fields["owner"];
|
|
43
|
+
const name = fields["repository"];
|
|
44
|
+
if (typeof owner !== "string" ||
|
|
45
|
+
typeof name !== "string" ||
|
|
46
|
+
owner.toLowerCase() !== repository.owner ||
|
|
47
|
+
name.toLowerCase() !== repository.repository)
|
|
48
|
+
return null;
|
|
49
|
+
return { ...repository, number };
|
|
50
|
+
}
|
|
51
|
+
export function sameIssue(first, second) {
|
|
52
|
+
return (first != null &&
|
|
53
|
+
second != null &&
|
|
54
|
+
first.host === second.host &&
|
|
55
|
+
first.owner === second.owner &&
|
|
56
|
+
first.repository === second.repository &&
|
|
57
|
+
first.number === second.number);
|
|
58
|
+
}
|
|
34
59
|
export function prRepository(origin) {
|
|
35
60
|
const address = origin
|
|
36
61
|
.replace(/^git@([^:/]+):/, "ssh://git@$1/")
|
|
@@ -2,6 +2,7 @@ import type { WatchPullRequest } from "./watch-render.ts";
|
|
|
2
2
|
import { type WatchCommandRunner } from "./watch-pr-command.ts";
|
|
3
3
|
import { type PrObservation, type PrRepository } from "./watch-pr-identity.ts";
|
|
4
4
|
export interface PrObserver {
|
|
5
|
+
readonly repository?: PrRepository | null;
|
|
5
6
|
readonly observe: (pullRequest: WatchPullRequest) => PrObservation | null;
|
|
6
7
|
readonly close: () => void;
|
|
7
8
|
}
|
|
@@ -9,13 +9,23 @@ const systemClock = {
|
|
|
9
9
|
};
|
|
10
10
|
},
|
|
11
11
|
};
|
|
12
|
+
function observationOf(entry, reply) {
|
|
13
|
+
const { result, now } = reply;
|
|
14
|
+
if (result.status !== "unavailable")
|
|
15
|
+
return { ...result, lastSuccess: { status: result.status, readAt: now } };
|
|
16
|
+
const lastSuccess = entry.result?.lastSuccess;
|
|
17
|
+
return { ...result, ...(lastSuccess === undefined ? {} : { lastSuccess }) };
|
|
18
|
+
}
|
|
12
19
|
async function readPr(state, attempt) {
|
|
13
20
|
const { entry, controller } = attempt;
|
|
14
21
|
const deadline = { expired: false };
|
|
15
22
|
const timeout = { status: "unavailable", failure: "timeout" };
|
|
16
23
|
const cancel = state.clock.after(() => {
|
|
17
24
|
deadline.expired = true;
|
|
18
|
-
entry.result =
|
|
25
|
+
entry.result = observationOf(entry, {
|
|
26
|
+
result: timeout,
|
|
27
|
+
now: state.clock.now(),
|
|
28
|
+
});
|
|
19
29
|
controller.abort();
|
|
20
30
|
}, 5000);
|
|
21
31
|
controller.signal.addEventListener("abort", cancel, { once: true });
|
|
@@ -28,7 +38,9 @@ async function readPr(state, attempt) {
|
|
|
28
38
|
directory: state.settings.directory,
|
|
29
39
|
signal: controller.signal,
|
|
30
40
|
}));
|
|
31
|
-
return deadline.expired
|
|
41
|
+
return deadline.expired
|
|
42
|
+
? timeout
|
|
43
|
+
: prCommandResult(entry.identity, { output, now: state.clock.now() });
|
|
32
44
|
}
|
|
33
45
|
catch {
|
|
34
46
|
return deadline.expired
|
|
@@ -43,14 +55,32 @@ async function readPr(state, attempt) {
|
|
|
43
55
|
function pump(state) {
|
|
44
56
|
if (state.closed || state.active !== null)
|
|
45
57
|
return;
|
|
46
|
-
|
|
58
|
+
state.wake?.();
|
|
59
|
+
state.wake = null;
|
|
60
|
+
if (state.queue.length === 0)
|
|
61
|
+
return;
|
|
62
|
+
const now = state.clock.now();
|
|
63
|
+
const position = state.queue.findIndex((entry) => (state.retryDeadlines.get(entry.identity.host) ?? 0) <= now);
|
|
64
|
+
if (position === -1) {
|
|
65
|
+
const next = Math.min(...state.queue.map((entry) => state.retryDeadlines.get(entry.identity.host) ?? now));
|
|
66
|
+
state.wake = state.clock.after(() => {
|
|
67
|
+
state.wake = null;
|
|
68
|
+
pump(state);
|
|
69
|
+
}, Math.min(next - now, 2147483647));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const [entry] = state.queue.splice(position, 1);
|
|
47
73
|
if (entry === undefined)
|
|
48
74
|
return;
|
|
49
75
|
const controller = new AbortController();
|
|
50
76
|
state.active = controller;
|
|
51
77
|
entry.started = state.clock.now();
|
|
52
78
|
const completed = (result) => {
|
|
53
|
-
|
|
79
|
+
if (state.closed)
|
|
80
|
+
return;
|
|
81
|
+
entry.result = observationOf(entry, { result, now: state.clock.now() });
|
|
82
|
+
if (result.status === "unavailable" && result.failure === "rate-limit")
|
|
83
|
+
state.retryDeadlines.set(entry.identity.host, Math.max(state.retryDeadlines.get(entry.identity.host) ?? 0, result.retryAt ?? state.clock.now() + 60000));
|
|
54
84
|
entry.pending = false;
|
|
55
85
|
state.active = null;
|
|
56
86
|
pump(state);
|
|
@@ -59,6 +89,11 @@ function pump(state) {
|
|
|
59
89
|
completed({ status: "unavailable", failure: "command" });
|
|
60
90
|
});
|
|
61
91
|
}
|
|
92
|
+
function currentObservation(state, entry) {
|
|
93
|
+
const result = entry.result ?? { status: "pending" };
|
|
94
|
+
const retryAt = state.retryDeadlines.get(entry.identity.host) ?? 0;
|
|
95
|
+
return retryAt > state.clock.now() ? { ...result, retryAt } : result;
|
|
96
|
+
}
|
|
62
97
|
function needsRead(entry, now) {
|
|
63
98
|
if (entry === undefined)
|
|
64
99
|
return true;
|
|
@@ -72,6 +107,8 @@ export function prObserver(settings) {
|
|
|
72
107
|
clock: settings.clock ?? systemClock,
|
|
73
108
|
cache: new Map(),
|
|
74
109
|
queue: [],
|
|
110
|
+
retryDeadlines: new Map(),
|
|
111
|
+
wake: null,
|
|
75
112
|
active: null,
|
|
76
113
|
closed: false,
|
|
77
114
|
};
|
|
@@ -85,7 +122,9 @@ export function prObserver(settings) {
|
|
|
85
122
|
const key = JSON.stringify(identity);
|
|
86
123
|
const known = state.cache.get(key);
|
|
87
124
|
if (state.closed || !needsRead(known, state.clock.now()))
|
|
88
|
-
return known
|
|
125
|
+
return known === undefined
|
|
126
|
+
? { status: "pending" }
|
|
127
|
+
: currentObservation(state, known);
|
|
89
128
|
const entry = {
|
|
90
129
|
identity,
|
|
91
130
|
result: known?.result ?? null,
|
|
@@ -95,13 +134,16 @@ export function prObserver(settings) {
|
|
|
95
134
|
state.cache.set(key, entry);
|
|
96
135
|
state.queue.push(entry);
|
|
97
136
|
pump(state);
|
|
98
|
-
return entry
|
|
137
|
+
return currentObservation(state, entry);
|
|
99
138
|
};
|
|
100
139
|
return {
|
|
140
|
+
repository: settings.repository,
|
|
101
141
|
observe,
|
|
102
142
|
close: () => {
|
|
103
143
|
state.closed = true;
|
|
104
144
|
state.queue.length = 0;
|
|
145
|
+
state.wake?.();
|
|
146
|
+
state.wake = null;
|
|
105
147
|
state.active?.abort();
|
|
106
148
|
},
|
|
107
149
|
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { CiRerunNotice } from "./github-ci-progress.ts";
|
|
2
|
+
import type { WatchRun } from "./watch-render.ts";
|
|
3
|
+
import { type PrRepository } from "./watch-pr-identity.ts";
|
|
4
|
+
export interface GithubRecords {
|
|
5
|
+
readonly started: unknown;
|
|
6
|
+
readonly result: unknown;
|
|
7
|
+
readonly ciReruns?: readonly CiRerunNotice[];
|
|
8
|
+
}
|
|
9
|
+
export declare function pullOf(inputs: {
|
|
10
|
+
readonly records: readonly GithubRecords[];
|
|
11
|
+
readonly repository: PrRepository | null;
|
|
12
|
+
}, runId: string): Pick<WatchRun, "pullRequest" | "reviews" | "mergeCommit" | "mergeProof" | "ciReruns">;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { operationIdentity } from "../operation-identity.js";
|
|
2
|
+
import { prIdentity, } from "./watch-pr-identity.js";
|
|
3
|
+
function record(value) {
|
|
4
|
+
return typeof value === "object" && value !== null ? { ...value } : {};
|
|
5
|
+
}
|
|
6
|
+
function text(value) {
|
|
7
|
+
return typeof value === "string" ? value : "";
|
|
8
|
+
}
|
|
9
|
+
function stamp(value) {
|
|
10
|
+
return typeof value === "string" ? value : null;
|
|
11
|
+
}
|
|
12
|
+
function parsed(line) {
|
|
13
|
+
try {
|
|
14
|
+
return JSON.parse(line);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
function list(value) {
|
|
21
|
+
return Array.isArray(value) ? value.map((item) => item) : [];
|
|
22
|
+
}
|
|
23
|
+
function count(value) {
|
|
24
|
+
return typeof value === "number" ? value : null;
|
|
25
|
+
}
|
|
26
|
+
function attributed(started, operation) {
|
|
27
|
+
const stage = list(operation[5]);
|
|
28
|
+
const checked = operationIdentity({
|
|
29
|
+
round: operation[1],
|
|
30
|
+
run: operation[2],
|
|
31
|
+
phase: operation[3],
|
|
32
|
+
operation: operation[4],
|
|
33
|
+
...(operation[5] === null
|
|
34
|
+
? {}
|
|
35
|
+
: { stage: { id: stage[0], visit: stage[1], branch: stage[2] } }),
|
|
36
|
+
...(operation[6] === null ? {} : { key: operation[6] }),
|
|
37
|
+
});
|
|
38
|
+
return (checked.kind === "valid" &&
|
|
39
|
+
checked.value === JSON.stringify(operation) &&
|
|
40
|
+
operation[3] === "pull-request" &&
|
|
41
|
+
operation[4] === `github-${text(started["method"])}` &&
|
|
42
|
+
(started["runId"] === undefined || started["runId"] === operation[2]));
|
|
43
|
+
}
|
|
44
|
+
function githubOf(records) {
|
|
45
|
+
const started = record(records.started);
|
|
46
|
+
const operation = list(parsed(text(started["operationId"])));
|
|
47
|
+
const result = record(records.result);
|
|
48
|
+
const completed = result["outcome"] === "completed";
|
|
49
|
+
return {
|
|
50
|
+
runId: text(operation[2]),
|
|
51
|
+
round: Number(operation[1]),
|
|
52
|
+
method: text(started["method"]),
|
|
53
|
+
completed,
|
|
54
|
+
attributed: attributed(started, operation) && !Object.hasOwn(result, "reason"),
|
|
55
|
+
report: completed ? record(parsed(text(result["result"]))) : {},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function pullRequestOf(results) {
|
|
59
|
+
const opened = results
|
|
60
|
+
.filter((item) => item.method === "open-pr")
|
|
61
|
+
.map((item) => item.report)
|
|
62
|
+
.findLast((report) => text(report["url"]).startsWith("https://"));
|
|
63
|
+
if (opened === undefined)
|
|
64
|
+
return null;
|
|
65
|
+
return { number: Number(opened["number"]), url: text(opened["url"]) };
|
|
66
|
+
}
|
|
67
|
+
function reviewsOf(results) {
|
|
68
|
+
return results
|
|
69
|
+
.filter((item) => item.method === "wait-review")
|
|
70
|
+
.flatMap(({ round, report }) => {
|
|
71
|
+
const score = count(report["score"]);
|
|
72
|
+
if (score === null)
|
|
73
|
+
return [];
|
|
74
|
+
return [{ round, commit: text(report["commit"]), score }];
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
function mergeCommitOf(results) {
|
|
78
|
+
const merged = results
|
|
79
|
+
.filter((item) => item.method === "merge")
|
|
80
|
+
.map((item) => stamp(item.report["merged"]));
|
|
81
|
+
return merged.find((commit) => commit !== null) ?? null;
|
|
82
|
+
}
|
|
83
|
+
function mergeProofOf(results, context) {
|
|
84
|
+
if (context.repository === null || context.pullRequest === null)
|
|
85
|
+
return null;
|
|
86
|
+
const repository = context.repository;
|
|
87
|
+
const identity = prIdentity(repository, context.pullRequest);
|
|
88
|
+
if (identity === null)
|
|
89
|
+
return null;
|
|
90
|
+
const opened = results.filter((item) => item.method === "open-pr" && item.completed && item.attributed);
|
|
91
|
+
if (opened.length === 0 ||
|
|
92
|
+
opened.some(({ report }) => report["number"] !== identity.number ||
|
|
93
|
+
typeof report["url"] !== "string" ||
|
|
94
|
+
prIdentity(repository, {
|
|
95
|
+
number: identity.number,
|
|
96
|
+
url: report["url"],
|
|
97
|
+
}) === null))
|
|
98
|
+
return null;
|
|
99
|
+
const merged = results.filter((item) => item.method === "merge" &&
|
|
100
|
+
item.completed &&
|
|
101
|
+
item.attributed &&
|
|
102
|
+
(typeof item.report["reason"] !== "string" ||
|
|
103
|
+
Object.hasOwn(item.report, "merged")));
|
|
104
|
+
if (merged.length === 0 ||
|
|
105
|
+
merged.some(({ report }) => report["number"] !== identity.number ||
|
|
106
|
+
typeof report["merged"] !== "string" ||
|
|
107
|
+
report["merged"].trim() === "" ||
|
|
108
|
+
Object.hasOwn(report, "reason")))
|
|
109
|
+
return null;
|
|
110
|
+
return new Set(merged.map(({ report }) => report["merged"])).size === 1
|
|
111
|
+
? identity
|
|
112
|
+
: null;
|
|
113
|
+
}
|
|
114
|
+
export function pullOf(inputs, runId) {
|
|
115
|
+
const results = inputs.records
|
|
116
|
+
.map(githubOf)
|
|
117
|
+
.filter((item) => item.runId === runId)
|
|
118
|
+
.toSorted((first, second) => first.round - second.round);
|
|
119
|
+
const pullRequest = pullRequestOf(results);
|
|
120
|
+
const mergeProof = mergeProofOf(results, {
|
|
121
|
+
repository: inputs.repository,
|
|
122
|
+
pullRequest,
|
|
123
|
+
});
|
|
124
|
+
const ciReruns = inputs.records
|
|
125
|
+
.filter((item) => record(item.started)["runId"] === runId)
|
|
126
|
+
.flatMap((item) => item.ciReruns ?? []);
|
|
127
|
+
return {
|
|
128
|
+
pullRequest,
|
|
129
|
+
reviews: reviewsOf(results),
|
|
130
|
+
mergeCommit: mergeCommitOf(results),
|
|
131
|
+
...(ciReruns.length === 0 ? {} : { ciReruns }),
|
|
132
|
+
...(mergeProof === null ? {} : { mergeProof }),
|
|
133
|
+
};
|
|
134
|
+
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { type PrRepository } from "./watch-pr-identity.ts";
|
|
2
|
+
import { type WorkflowStages } from "../workflow-declaration.ts";
|
|
1
3
|
import { type Fields } from "../protocol.ts";
|
|
4
|
+
import { type WorkflowRefusal } from "../workflow-refusals.ts";
|
|
2
5
|
interface ReadStatus extends Fields {
|
|
3
6
|
readonly runId: string;
|
|
4
7
|
readonly latestSequence: number;
|
|
@@ -13,8 +16,11 @@ interface ReadRun {
|
|
|
13
16
|
readonly events: readonly ReadEvent[];
|
|
14
17
|
}
|
|
15
18
|
export interface WatchRead {
|
|
19
|
+
readonly queue?: Fields;
|
|
16
20
|
readonly service: string;
|
|
17
21
|
readonly workflows: readonly string[];
|
|
22
|
+
readonly workflowRefusals: readonly WorkflowRefusal[];
|
|
23
|
+
readonly workflowStages?: WorkflowStages;
|
|
18
24
|
readonly summaries: readonly ReadStatus[];
|
|
19
25
|
readonly runs: readonly ReadRun[];
|
|
20
26
|
readonly completionCandidates: readonly ReadRun[];
|
|
@@ -24,5 +30,5 @@ export interface WatchReader {
|
|
|
24
30
|
readonly read: (now: string) => Promise<WatchRead>;
|
|
25
31
|
readonly run: (runId: string) => Promise<WatchRead>;
|
|
26
32
|
}
|
|
27
|
-
export declare function watchReader(runtimeDirectory: string): WatchReader;
|
|
33
|
+
export declare function watchReader(runtimeDirectory: string, repository?: PrRepository | null): WatchReader;
|
|
28
34
|
export {};
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import { establishedIssue } from "./watch-pr-identity.js";
|
|
2
|
+
import { isWorkflowStages, } from "../workflow-declaration.js";
|
|
1
3
|
import { record } from "../protocol.js";
|
|
2
4
|
import { send } from "./client.js";
|
|
3
5
|
import { activeRun, recentRun } from "./watch-board.js";
|
|
6
|
+
import { workflowRefusals, } from "../workflow-refusals.js";
|
|
4
7
|
const unavailable = {
|
|
5
8
|
service: "down",
|
|
6
9
|
workflows: [],
|
|
10
|
+
workflowRefusals: [],
|
|
7
11
|
summaries: [],
|
|
8
12
|
runs: [],
|
|
9
13
|
completionCandidates: [],
|
|
@@ -79,15 +83,15 @@ async function creationOf(reader, runId) {
|
|
|
79
83
|
}
|
|
80
84
|
return null;
|
|
81
85
|
}
|
|
82
|
-
function matchingCompletion(status,
|
|
83
|
-
const
|
|
86
|
+
function matchingCompletion(status, context) {
|
|
87
|
+
const issue = establishedIssue(context.repository, status["issueIdentity"]);
|
|
84
88
|
return (status.state === "completed" &&
|
|
85
89
|
status["workflowId"] === "develop-issue" &&
|
|
86
90
|
record(status["outcome"])?.["kind"] === "handoff_requested" &&
|
|
87
91
|
record(status["outcome"])?.["ticketStatus"] !== "partial" &&
|
|
88
92
|
record(status["outcome"])?.["issueUpdate"] !== "failed" &&
|
|
89
|
-
|
|
90
|
-
|
|
93
|
+
issue !== null &&
|
|
94
|
+
context.issues.has(JSON.stringify(issue)));
|
|
91
95
|
}
|
|
92
96
|
async function completionOf(reader, search) {
|
|
93
97
|
const { runId, latestSequence } = search.summary;
|
|
@@ -106,12 +110,16 @@ async function completionOf(reader, search) {
|
|
|
106
110
|
state: status.state,
|
|
107
111
|
workflowId: status["workflowId"],
|
|
108
112
|
ticketId: status["ticketId"],
|
|
113
|
+
issueIdentity: status["issueIdentity"],
|
|
109
114
|
outcome: status["outcome"],
|
|
110
115
|
},
|
|
111
116
|
};
|
|
112
117
|
reader.completions.set(runId, known);
|
|
113
118
|
}
|
|
114
|
-
if (!matchingCompletion(known.status,
|
|
119
|
+
if (!matchingCompletion(known.status, {
|
|
120
|
+
issues: search.issues,
|
|
121
|
+
repository: reader.repository,
|
|
122
|
+
}))
|
|
115
123
|
return null;
|
|
116
124
|
const creation = known.creation === undefined
|
|
117
125
|
? await creationOf(reader, runId)
|
|
@@ -119,11 +127,20 @@ async function completionOf(reader, search) {
|
|
|
119
127
|
reader.completions.set(runId, { ...known, creation });
|
|
120
128
|
return { status: known.status, events: creation === null ? [] : [creation] };
|
|
121
129
|
}
|
|
130
|
+
function refreshedLinks(run, status) {
|
|
131
|
+
const links = Object.fromEntries(["parentRunId", "chainId", "childRunIds"]
|
|
132
|
+
.filter((name) => Object.hasOwn(status, name))
|
|
133
|
+
.map((name) => [name, status[name]]));
|
|
134
|
+
return {
|
|
135
|
+
...run,
|
|
136
|
+
status: { ...run.status, ...links },
|
|
137
|
+
};
|
|
138
|
+
}
|
|
122
139
|
async function detailed(reader, summary) {
|
|
123
140
|
const { runId, latestSequence: sequence } = summary;
|
|
124
141
|
const known = reader.details.get(runId);
|
|
125
142
|
if (known !== undefined && known.sequence === sequence)
|
|
126
|
-
return known.value;
|
|
143
|
+
return refreshedLinks(known.value, summary);
|
|
127
144
|
const shown = await asked(reader, {
|
|
128
145
|
operation: "status",
|
|
129
146
|
parameters: { runId },
|
|
@@ -160,10 +177,10 @@ async function decisionsOf(reader) {
|
|
|
160
177
|
});
|
|
161
178
|
return list(questions["decisions"]);
|
|
162
179
|
}
|
|
163
|
-
function
|
|
180
|
+
function stoppedIssues(runs, context) {
|
|
164
181
|
const stopped = runs
|
|
165
182
|
.map((run) => run.status)
|
|
166
|
-
.filter((status) => recentRun(status.latestAt, now) &&
|
|
183
|
+
.filter((status) => recentRun(status.latestAt, context.now) &&
|
|
167
184
|
status["workflowId"] === "develop-issue" &&
|
|
168
185
|
(["failed", "cancelled"].includes(status.state) ||
|
|
169
186
|
(status.state === "completed" &&
|
|
@@ -171,16 +188,15 @@ function stoppedTicketIds(runs, now) {
|
|
|
171
188
|
.toSorted((first, second) => Date.parse(second.latestAt ?? "") - Date.parse(first.latestAt ?? ""))
|
|
172
189
|
.slice(0, 20);
|
|
173
190
|
return new Set(stopped.flatMap((status) => {
|
|
174
|
-
const
|
|
175
|
-
return status.state === "completed" &&
|
|
176
|
-
|
|
177
|
-
record(status["outcome"])?.["issueUpdate"] !== "failed" &&
|
|
178
|
-
typeof ticketId === "string" &&
|
|
179
|
-
ticketId !== ""
|
|
180
|
-
? [ticketId]
|
|
191
|
+
const issue = establishedIssue(context.repository, status["issueIdentity"]);
|
|
192
|
+
return status.state === "completed" && issue !== null
|
|
193
|
+
? [JSON.stringify(issue)]
|
|
181
194
|
: [];
|
|
182
195
|
}));
|
|
183
196
|
}
|
|
197
|
+
function stageMetadata(value) {
|
|
198
|
+
return Object.fromEntries(Object.entries(record(value) ?? {}).flatMap(([workflowId, stages]) => isWorkflowStages(stages) ? [[workflowId, stages]] : []));
|
|
199
|
+
}
|
|
184
200
|
async function service(reader, now) {
|
|
185
201
|
const status = await asked(reader, {
|
|
186
202
|
operation: "status",
|
|
@@ -194,20 +210,25 @@ async function service(reader, now) {
|
|
|
194
210
|
const current = summaries.filter((summary) => activeRun(summary.state) || recentRun(summary.latestAt, now));
|
|
195
211
|
for (const summary of current)
|
|
196
212
|
runs.push(await detailed(reader, summary));
|
|
197
|
-
const
|
|
198
|
-
const older =
|
|
213
|
+
const issues = stoppedIssues(runs, { now, repository: reader.repository });
|
|
214
|
+
const older = issues.size === 0
|
|
199
215
|
? []
|
|
200
216
|
: summaries.filter((summary) => !recentRun(summary.latestAt, now) &&
|
|
201
217
|
summary["workflowId"] === "develop-issue" &&
|
|
202
218
|
summary.state === "completed");
|
|
203
219
|
for (const summary of older) {
|
|
204
|
-
const candidate = await completionOf(reader, { summary,
|
|
220
|
+
const candidate = await completionOf(reader, { summary, issues });
|
|
205
221
|
if (candidate !== null)
|
|
206
222
|
completionCandidates.push(candidate);
|
|
207
223
|
}
|
|
208
224
|
return {
|
|
209
225
|
service: "up",
|
|
226
|
+
...(record(status["queue"]) === undefined
|
|
227
|
+
? {}
|
|
228
|
+
: { queue: record(status["queue"]) ?? {} }),
|
|
210
229
|
workflows: list(status["workflows"]).filter((value) => typeof value === "string"),
|
|
230
|
+
workflowStages: stageMetadata(status["workflowStages"]),
|
|
231
|
+
workflowRefusals: workflowRefusals(status["workflowRefusals"]),
|
|
211
232
|
summaries,
|
|
212
233
|
runs,
|
|
213
234
|
completionCandidates,
|
|
@@ -226,7 +247,7 @@ async function singleRun(reader, runId) {
|
|
|
226
247
|
const status = statusOf(reply.result["run"]);
|
|
227
248
|
const known = reader.details.get(runId);
|
|
228
249
|
const value = known !== undefined && known.sequence === status.latestSequence
|
|
229
|
-
? known.value
|
|
250
|
+
? refreshedLinks(known.value, status)
|
|
230
251
|
: await remember(reader, status);
|
|
231
252
|
return {
|
|
232
253
|
...unavailable,
|
|
@@ -235,9 +256,10 @@ async function singleRun(reader, runId) {
|
|
|
235
256
|
decisions: await decisionsOf(reader),
|
|
236
257
|
};
|
|
237
258
|
}
|
|
238
|
-
export function watchReader(runtimeDirectory) {
|
|
259
|
+
export function watchReader(runtimeDirectory, repository = null) {
|
|
239
260
|
const reader = {
|
|
240
261
|
runtimeDirectory,
|
|
262
|
+
repository,
|
|
241
263
|
details: new Map(),
|
|
242
264
|
completions: new Map(),
|
|
243
265
|
};
|