@wardby/cli 0.6.0 → 0.8.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/.env.example +5 -5
- package/README.md +6 -1
- package/deploy/local/docker-compose.quickstart-coding.yml +19 -0
- package/dist/claude-coding-worker/driver.d.ts +33 -3
- package/dist/claude-coding-worker/driver.js +151 -21
- package/dist/claude-coding-worker/main.js +38 -6
- package/dist/claude-coding-worker/sdk.js +29 -2
- package/dist/claude-coding-worker/tool-socket.d.ts +27 -0
- package/dist/claude-coding-worker/tool-socket.js +111 -0
- package/dist/claude-coding-worker/transcript.d.ts +18 -0
- package/dist/claude-coding-worker/transcript.js +77 -0
- package/dist/claude-plugin/command.d.ts +61 -0
- package/dist/claude-plugin/command.js +376 -0
- package/dist/cli-help.d.ts +1 -1
- package/dist/cli-help.js +3 -1
- package/dist/cli.js +71 -13
- package/dist/coding/code-host.d.ts +16 -0
- package/dist/coding/code-host.js +60 -0
- package/dist/coding/continuation-wording.d.ts +35 -0
- package/dist/coding/continuation-wording.js +73 -0
- package/dist/coding/linked-issue-note.d.ts +23 -0
- package/dist/coding/linked-issue-note.js +47 -0
- package/dist/coding/mcp-token.d.ts +12 -0
- package/dist/coding/mcp-token.js +26 -0
- package/dist/coding/merge-wording.d.ts +28 -0
- package/dist/coding/merge-wording.js +78 -0
- package/dist/coding/pr-description-note.d.ts +9 -0
- package/dist/coding/pr-description-note.js +32 -0
- package/dist/coding/profile.d.ts +46 -126
- package/dist/coding/profile.js +45 -4
- package/dist/coding/protected-path-wording.d.ts +8 -0
- package/dist/coding/protected-path-wording.js +1 -1
- package/dist/coding/protocol.d.ts +264 -346
- package/dist/coding/protocol.js +237 -12
- package/dist/coding/redact.d.ts +3 -0
- package/dist/coding/redact.js +17 -0
- package/dist/coding/registry/allowlist.d.ts +12 -0
- package/dist/coding/registry/allowlist.js +14 -1
- package/dist/coding/registry/audit-mode.d.ts +153 -0
- package/dist/coding/registry/audit-mode.js +304 -0
- package/dist/coding/registry/lockfile-shared.d.ts +36 -0
- package/dist/coding/registry/lockfile-shared.js +128 -0
- package/dist/coding/registry/lockfiles.js +1 -1
- package/dist/coding/registry/npm-lockfile-formats.d.ts +11 -0
- package/dist/coding/registry/npm-lockfile-formats.js +41 -0
- package/dist/coding/registry/npm-lockfile.d.ts +8 -4
- package/dist/coding/registry/npm-lockfile.js +4 -6
- package/dist/coding/registry/npm.js +78 -8
- package/dist/coding/registry/pnpm-lockfile.d.ts +17 -0
- package/dist/coding/registry/pnpm-lockfile.js +189 -0
- package/dist/coding/registry/pypi-plan.d.ts +50 -0
- package/dist/coding/registry/pypi-plan.js +406 -0
- package/dist/coding/registry/pypi-requirements.d.ts +58 -0
- package/dist/coding/registry/pypi-requirements.js +155 -0
- package/dist/coding/registry/pypi.d.ts +3 -27
- package/dist/coding/registry/pypi.js +40 -154
- package/dist/coding/registry/refusal-hints.d.ts +20 -0
- package/dist/coding/registry/refusal-hints.js +61 -0
- package/dist/coding/registry/refusal-wording.d.ts +11 -0
- package/dist/coding/registry/refusal-wording.js +56 -0
- package/dist/coding/registry/report.d.ts +70 -8
- package/dist/coding/registry/report.js +112 -5
- package/dist/coding/registry/types.d.ts +58 -8
- package/dist/coding/registry/yarn-lockfile.d.ts +30 -0
- package/dist/coding/registry/yarn-lockfile.js +367 -0
- package/dist/coding/services/catalog.d.ts +37 -351
- package/dist/coding/transcript/claude-code.d.ts +13 -0
- package/dist/coding/transcript/claude-code.js +273 -0
- package/dist/coding/transcript/download-protocol.d.ts +30 -0
- package/dist/coding/transcript/download-protocol.js +18 -0
- package/dist/coding/transcript/format.d.ts +20 -0
- package/dist/coding/transcript/format.js +32 -0
- package/dist/coding/transcript/recorder.d.ts +52 -0
- package/dist/coding/transcript/recorder.js +225 -0
- package/dist/coding/transcript/resume/checkout.d.ts +31 -0
- package/dist/coding/transcript/resume/checkout.js +203 -0
- package/dist/coding/transcript/resume/command.d.ts +17 -0
- package/dist/coding/transcript/resume/command.js +176 -0
- package/dist/coding/transcript/resume/download.d.ts +20 -0
- package/dist/coding/transcript/resume/download.js +153 -0
- package/dist/coding/transcript/resume/launch.d.ts +38 -0
- package/dist/coding/transcript/resume/launch.js +128 -0
- package/dist/coding/transcript/resume/session-file.d.ts +13 -0
- package/dist/coding/transcript/resume/session-file.js +79 -0
- package/dist/coding/transcript/resume/stand-in.d.ts +11 -0
- package/dist/coding/transcript/resume/stand-in.js +49 -0
- package/dist/coding-worker/artifact.d.ts +8 -3
- package/dist/coding-worker/artifact.js +3 -1
- package/dist/coding-worker/debug-trace.d.ts +9 -6
- package/dist/coding-worker/debug-trace.js +16 -19
- package/dist/coding-worker/dependency-cache.d.mts +229 -0
- package/dist/coding-worker/dependency-cache.mjs +2123 -0
- package/dist/coding-worker/driver.d.ts +4 -3
- package/dist/coding-worker/driver.js +124 -39
- package/dist/coding-worker/errors.d.ts +1 -0
- package/dist/coding-worker/errors.js +32 -0
- package/dist/coding-worker/main.js +5 -1
- package/dist/coding-worker/mcp-config.d.ts +27 -0
- package/dist/coding-worker/mcp-config.js +32 -0
- package/dist/coding-worker/sdk.d.ts +36 -0
- package/dist/coding-worker/sdk.js +28 -1
- package/dist/coding-worker/task-note.d.ts +11 -0
- package/dist/coding-worker/task-note.js +13 -0
- package/dist/coding-worker/types.d.ts +15 -0
- package/dist/config/dependency-cache.d.ts +23 -0
- package/dist/config/dependency-cache.js +32 -0
- package/dist/config/mcp-call-limit.d.ts +8 -0
- package/dist/config/mcp-call-limit.js +18 -0
- package/dist/config/mcp-servers.d.ts +8 -0
- package/dist/config/mcp-servers.js +12 -0
- package/dist/config/providers.d.ts +12 -3
- package/dist/config/providers.js +55 -5
- package/dist/config/test-simulators.d.ts +92 -0
- package/dist/config/test-simulators.js +333 -0
- package/dist/config/tool-timeout.d.ts +1 -0
- package/dist/config/tool-timeout.js +18 -0
- package/dist/core/async-context.d.ts +2 -0
- package/dist/core/async-context.js +12 -0
- package/dist/core/budget-events.d.ts +108 -0
- package/dist/core/budget-events.js +346 -0
- package/dist/core/budget-groups.d.ts +50 -1
- package/dist/core/budget-groups.js +236 -27
- package/dist/core/budget-stopped-head.d.ts +46 -0
- package/dist/core/budget-stopped-head.js +81 -0
- package/dist/core/budget-topup.d.ts +51 -0
- package/dist/core/budget-topup.js +156 -0
- package/dist/core/budget-wording.d.ts +16 -2
- package/dist/core/budget-wording.js +40 -2
- package/dist/core/coding-mcp.d.ts +36 -0
- package/dist/core/coding-mcp.js +253 -0
- package/dist/core/coding-queue.d.ts +2 -1
- package/dist/core/coding-queue.js +7 -0
- package/dist/core/coding-repository.d.ts +46 -0
- package/dist/core/coding-repository.js +92 -0
- package/dist/core/cron.d.ts +19 -1
- package/dist/core/cron.js +17 -0
- package/dist/core/datastores.js +1 -1
- package/dist/core/deferred-coding.d.ts +14 -0
- package/dist/core/deferred-coding.js +62 -0
- package/dist/core/delegation-child.d.ts +25 -0
- package/dist/core/delegation-child.js +37 -0
- package/dist/core/delegation-slots.d.ts +27 -0
- package/dist/core/delegation-slots.js +44 -0
- package/dist/core/dispatch.d.ts +48 -2
- package/dist/core/dispatch.js +166 -66
- package/dist/core/engine-native.js +1 -1
- package/dist/core/error-code.d.ts +38 -0
- package/dist/core/error-code.js +169 -0
- package/dist/core/grants.d.ts +46 -8
- package/dist/core/grants.js +99 -8
- package/dist/core/host-events.d.ts +18 -2
- package/dist/core/host-events.js +291 -27
- package/dist/core/host-status.d.ts +85 -3
- package/dist/core/host-status.js +300 -22
- package/dist/core/issue-bridge.d.ts +50 -6
- package/dist/core/issue-bridge.js +124 -33
- package/dist/core/issue-events.d.ts +1 -1
- package/dist/core/issue-events.js +4 -10
- package/dist/core/issue-status.d.ts +1 -1
- package/dist/core/issue-status.js +58 -29
- package/dist/core/logger.d.ts +5 -0
- package/dist/core/logger.js +14 -1
- package/dist/core/lost-run-children.d.ts +6 -0
- package/dist/core/lost-run-children.js +32 -0
- package/dist/core/mark-ready.d.ts +34 -0
- package/dist/core/mark-ready.js +152 -0
- package/dist/core/markdown-code.d.ts +8 -0
- package/dist/core/markdown-code.js +107 -0
- package/dist/core/mcp-client/client.d.ts +47 -0
- package/dist/core/mcp-client/client.js +141 -0
- package/dist/core/mcp-client/jsonrpc.d.ts +15 -0
- package/dist/core/mcp-client/jsonrpc.js +54 -0
- package/dist/core/mcp-client/results.d.ts +13 -0
- package/dist/core/mcp-client/results.js +42 -0
- package/dist/core/mcp-servers.d.ts +90 -0
- package/dist/core/mcp-servers.js +230 -0
- package/dist/core/mcp-tools.d.ts +108 -0
- package/dist/core/mcp-tools.js +287 -0
- package/dist/core/memory-tools.js +7 -0
- package/dist/core/merge-order-check.d.ts +2 -1
- package/dist/core/merge-order-check.js +44 -18
- package/dist/core/notification-dispatcher.js +2 -1
- package/dist/core/notification-templates.d.ts +1 -7
- package/dist/core/notification-templates.js +36 -2
- package/dist/core/pull-request-state-sync.js +2 -2
- package/dist/core/reconciler.d.ts +4 -3
- package/dist/core/reconciler.js +8 -1
- package/dist/core/related-pull-requests.d.ts +11 -3
- package/dist/core/related-pull-requests.js +49 -20
- package/dist/core/reply-parts.d.ts +21 -0
- package/dist/core/reply-parts.js +73 -0
- package/dist/core/review-fix.d.ts +1 -1
- package/dist/core/review-fix.js +4 -3
- package/dist/core/review-host-checks.d.ts +1 -1
- package/dist/core/review-host-tools.d.ts +3 -0
- package/dist/core/review-host-tools.js +102 -14
- package/dist/core/review-reads.d.ts +55 -0
- package/dist/core/review-reads.js +233 -0
- package/dist/core/run-status.d.ts +12 -0
- package/dist/core/run-status.js +12 -0
- package/dist/core/runner.d.ts +145 -49
- package/dist/core/runner.js +719 -216
- package/dist/core/schedule-start.d.ts +12 -0
- package/dist/core/schedule-start.js +14 -0
- package/dist/core/secret-broker-config.d.ts +12 -74
- package/dist/core/secret-broker-config.js +1 -1
- package/dist/core/secret-guard.d.ts +49 -0
- package/dist/core/secret-guard.js +119 -0
- package/dist/core/secret-guarded-stores.d.ts +12 -0
- package/dist/core/secret-guarded-stores.js +41 -0
- package/dist/core/secret-spans.d.ts +50 -0
- package/dist/core/secret-spans.js +94 -0
- package/dist/core/secrets.d.ts +11 -1
- package/dist/core/secrets.js +27 -1
- package/dist/core/serializable-retry.d.ts +18 -0
- package/dist/core/serializable-retry.js +43 -0
- package/dist/core/stop-run.d.ts +46 -0
- package/dist/core/stop-run.js +61 -0
- package/dist/core/tool-admin.d.ts +5 -1
- package/dist/core/tool-admin.js +7 -2
- package/dist/core/tool-names.d.ts +13 -0
- package/dist/core/tool-names.js +20 -0
- package/dist/core/webhooks.d.ts +4 -0
- package/dist/core/webhooks.js +68 -49
- package/dist/core/workflow-events.d.ts +14 -2
- package/dist/core/workflow-events.js +4 -0
- package/dist/core/workflow-run-events.d.ts +5 -3
- package/dist/core/workflow-run-events.js +45 -9
- package/dist/core/zod-json-schema.d.ts +4 -0
- package/dist/core/zod-json-schema.js +39 -0
- package/dist/core/zod3-window.d.ts +35 -0
- package/dist/core/zod3-window.js +124 -0
- package/dist/generated/prisma/browser.d.ts +65 -3
- package/dist/generated/prisma/client.d.ts +65 -3
- package/dist/generated/prisma/commonInputTypes.d.ts +266 -106
- package/dist/generated/prisma/enums.d.ts +10 -0
- package/dist/generated/prisma/enums.js +8 -0
- package/dist/generated/prisma/internal/class.d.ts +110 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +957 -9
- package/dist/generated/prisma/internal/prismaNamespace.js +166 -2
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +174 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +166 -2
- package/dist/generated/prisma/models/Agent.d.ts +377 -8
- package/dist/generated/prisma/models/AgentMcpServer.d.ts +1412 -0
- package/dist/generated/prisma/models/AgentMcpServer.js +1 -0
- package/dist/generated/prisma/models/AgentRepository.d.ts +81 -1
- package/dist/generated/prisma/models/AuthUser.d.ts +1 -1
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +228 -7
- package/dist/generated/prisma/models/CodingProxyRequest.d.ts +207 -3
- package/dist/generated/prisma/models/CodingProxySession.d.ts +232 -2
- package/dist/generated/prisma/models/CodingRun.d.ts +1712 -1
- package/dist/generated/prisma/models/DependencySnapshot.d.ts +1668 -0
- package/dist/generated/prisma/models/DependencySnapshot.js +1 -0
- package/dist/generated/prisma/models/HostProvider.d.ts +2176 -0
- package/dist/generated/prisma/models/HostProvider.js +1 -0
- package/dist/generated/prisma/models/HostProviderCredential.d.ts +1285 -0
- package/dist/generated/prisma/models/HostProviderCredential.js +1 -0
- package/dist/generated/prisma/models/HostProviderOperation.d.ts +1470 -0
- package/dist/generated/prisma/models/HostProviderOperation.js +1 -0
- package/dist/generated/prisma/models/HostProviderTrustedAccount.d.ts +1145 -0
- package/dist/generated/prisma/models/HostProviderTrustedAccount.js +1 -0
- package/dist/generated/prisma/models/IssuePullRequest.d.ts +6 -2
- package/dist/generated/prisma/models/LocalReview.d.ts +40 -1
- package/dist/generated/prisma/models/McpServer.d.ts +1500 -0
- package/dist/generated/prisma/models/McpServer.js +1 -0
- package/dist/generated/prisma/models/NativeGatewayCall.d.ts +77 -1
- package/dist/generated/prisma/models/NativeGatewaySession.d.ts +35 -1
- package/dist/generated/prisma/models/Principal.d.ts +167 -0
- package/dist/generated/prisma/models/RegistryAllowance.d.ts +41 -1
- package/dist/generated/prisma/models/RegistryApprovedVersion.d.ts +75 -1
- package/dist/generated/prisma/models/RegistryAuditRecord.d.ts +1364 -0
- package/dist/generated/prisma/models/RegistryAuditRecord.js +1 -0
- package/dist/generated/prisma/models/ResourceGrant.d.ts +1 -1
- package/dist/generated/prisma/models/Run.d.ts +738 -2
- package/dist/generated/prisma/models/RunBudgetEvent.d.ts +1211 -0
- package/dist/generated/prisma/models/RunBudgetEvent.js +1 -0
- package/dist/generated/prisma/models/RunTranscript.d.ts +1339 -0
- package/dist/generated/prisma/models/RunTranscript.js +1 -0
- package/dist/generated/prisma/models/Secret.d.ts +387 -0
- package/dist/generated/prisma/models/Tool.d.ts +223 -1
- package/dist/generated/prisma/models.d.ts +10 -0
- package/dist/help/search.js +12 -3
- package/dist/help-index.json +2033 -110
- package/dist/import/create.js +48 -4
- package/dist/import/neutral-schema.d.ts +51 -281
- package/dist/import/neutral-schema.js +7 -4
- package/dist/knowledge/check.d.ts +1 -1
- package/dist/knowledge/cli.d.ts +11 -1
- package/dist/knowledge/cli.js +37 -4
- package/dist/knowledge/concept.d.ts +3 -19
- package/dist/knowledge/location.d.ts +31 -0
- package/dist/knowledge/location.js +78 -0
- package/dist/mcp/auth/access.d.ts +10 -2
- package/dist/mcp/auth/access.js +15 -1
- package/dist/mcp/auth/grants-cli.d.ts +6 -4
- package/dist/mcp/auth/grants-cli.js +42 -3
- package/dist/mcp/auth/ownership.d.ts +7 -7
- package/dist/mcp/auth/resource-server.d.ts +3 -1
- package/dist/mcp/auth/resource-server.js +17 -2
- package/dist/mcp/auth/self-hosted/credentials.d.ts +3 -3
- package/dist/mcp/auth/self-hosted/session.d.ts +2 -2
- package/dist/mcp/context.d.ts +3 -0
- package/dist/mcp/host-events/github-ingress.d.ts +2 -0
- package/dist/mcp/host-events/github-ingress.js +2 -1
- package/dist/mcp/index.d.ts +6 -0
- package/dist/mcp/index.js +69 -10
- package/dist/mcp/server.d.ts +13 -0
- package/dist/mcp/server.js +33 -14
- package/dist/mcp/tools/agents.d.ts +4 -0
- package/dist/mcp/tools/agents.js +295 -28
- package/dist/mcp/tools/datastore.js +17 -8
- package/dist/mcp/tools/grants.js +73 -29
- package/dist/mcp/tools/host-providers.d.ts +2 -0
- package/dist/mcp/tools/host-providers.js +215 -0
- package/dist/mcp/tools/mcp-servers.d.ts +26 -0
- package/dist/mcp/tools/mcp-servers.js +481 -0
- package/dist/mcp/tools/memory.js +11 -1
- package/dist/mcp/tools/notification-channels.js +2 -2
- package/dist/mcp/tools/packages.d.ts +2 -0
- package/dist/mcp/tools/packages.js +195 -0
- package/dist/mcp/tools/repositories.js +65 -12
- package/dist/mcp/tools/run-access.d.ts +16 -0
- package/dist/mcp/tools/run-access.js +25 -0
- package/dist/mcp/tools/run-transcript-download.d.ts +30 -0
- package/dist/mcp/tools/run-transcript-download.js +129 -0
- package/dist/mcp/tools/run-transcript.d.ts +19 -0
- package/dist/mcp/tools/run-transcript.js +70 -0
- package/dist/mcp/tools/runs.js +209 -27
- package/dist/mcp/tools/scheduling.js +3 -1
- package/dist/mcp/tools/secret-elicitation-form.js +5 -0
- package/dist/mcp/tools/secret-elicitation-server.d.ts +6 -0
- package/dist/mcp/tools/secret-elicitation-server.js +10 -61
- package/dist/mcp/tools/secret-elicitation.d.ts +2 -0
- package/dist/mcp/tools/secret-elicitation.js +25 -2
- package/dist/mcp/tools/secrets.js +40 -6
- package/dist/mcp/tools/stop-run.d.ts +2 -0
- package/dist/mcp/tools/stop-run.js +82 -0
- package/dist/mcp/tools/subagents.js +2 -2
- package/dist/mcp/tools/tools.d.ts +7 -5
- package/dist/mcp/tools/tools.js +64 -16
- package/dist/mcp/tools/trigger.js +28 -6
- package/dist/mcp/transport/http-limits.d.ts +2 -0
- package/dist/mcp/transport/http-limits.js +6 -2
- package/dist/mcp/transport/stdio-link-host.d.ts +20 -0
- package/dist/mcp/transport/stdio-link-host.js +67 -0
- package/dist/mcp/transport/streamable-http.d.ts +13 -0
- package/dist/mcp/transport/streamable-http.js +41 -1
- package/dist/mcp/webhooks/ingress.js +10 -0
- package/dist/native-worker/docker-launcher.d.ts +38 -2
- package/dist/native-worker/docker-launcher.js +65 -5
- package/dist/native-worker/gateway-server.d.ts +55 -3
- package/dist/native-worker/gateway-server.js +152 -34
- package/dist/native-worker/gateway.d.ts +29 -1
- package/dist/native-worker/gateway.js +74 -4
- package/dist/native-worker/http-server.d.ts +7 -1
- package/dist/native-worker/http-server.js +62 -7
- package/dist/native-worker/http-transport.js +1 -1
- package/dist/native-worker/kubernetes-launcher.d.ts +7 -3
- package/dist/native-worker/kubernetes-launcher.js +43 -3
- package/dist/native-worker/launch.d.ts +18 -1
- package/dist/native-worker/launch.js +6 -1
- package/dist/native-worker/ledger.d.ts +24 -4
- package/dist/native-worker/ledger.js +62 -8
- package/dist/native-worker/loopback.js +3 -8
- package/dist/native-worker/main.d.ts +2 -1
- package/dist/native-worker/main.js +14 -3
- package/dist/native-worker/protocol.d.ts +130 -577
- package/dist/native-worker/protocol.js +51 -2
- package/dist/native-worker/sandbox-executor.d.ts +17 -2
- package/dist/native-worker/sandbox-executor.js +78 -4
- package/dist/native-worker/stderr-redaction.d.ts +77 -0
- package/dist/native-worker/stderr-redaction.js +237 -0
- package/dist/native-worker/stdio.d.ts +1 -1
- package/dist/native-worker/stdio.js +6 -5
- package/dist/native-worker/warm-pool.d.ts +2 -2
- package/dist/native-worker/warm-pool.js +4 -4
- package/dist/native-worker/worker.js +28 -2
- package/dist/observability/metrics.js +6 -1
- package/dist/providers/auth/self-hosted.d.ts +1 -1
- package/dist/providers/coding-proxy/capability-hash.d.ts +2 -0
- package/dist/providers/coding-proxy/capability-hash.js +5 -0
- package/dist/providers/coding-proxy/dependency-cache/eviction.d.ts +29 -0
- package/dist/providers/coding-proxy/dependency-cache/eviction.js +87 -0
- package/dist/providers/coding-proxy/dependency-cache/key.d.ts +33 -0
- package/dist/providers/coding-proxy/dependency-cache/key.js +86 -0
- package/dist/providers/coding-proxy/dependency-cache/model-request-seal.d.ts +18 -0
- package/dist/providers/coding-proxy/dependency-cache/model-request-seal.js +40 -0
- package/dist/providers/coding-proxy/dependency-cache/prisma-store.d.ts +25 -0
- package/dist/providers/coding-proxy/dependency-cache/prisma-store.js +131 -0
- package/dist/providers/coding-proxy/dependency-cache/service.d.ts +70 -0
- package/dist/providers/coding-proxy/dependency-cache/service.js +409 -0
- package/dist/providers/coding-proxy/dependency-cache/store.d.ts +85 -0
- package/dist/providers/coding-proxy/dependency-cache/store.js +95 -0
- package/dist/providers/coding-proxy/hold.d.ts +32 -0
- package/dist/providers/coding-proxy/hold.js +86 -0
- package/dist/providers/coding-proxy/interrupted.d.ts +70 -0
- package/dist/providers/coding-proxy/interrupted.js +104 -0
- package/dist/providers/coding-proxy/mcp-route.d.ts +34 -0
- package/dist/providers/coding-proxy/mcp-route.js +166 -0
- package/dist/providers/coding-proxy/memory-ledger.d.ts +17 -2
- package/dist/providers/coding-proxy/memory-ledger.js +99 -8
- package/dist/providers/coding-proxy/metering.d.ts +16 -0
- package/dist/providers/coding-proxy/metering.js +27 -4
- package/dist/providers/coding-proxy/prisma-ledger.d.ts +16 -2
- package/dist/providers/coding-proxy/prisma-ledger.js +209 -69
- package/dist/providers/coding-proxy/proxy.d.ts +21 -2
- package/dist/providers/coding-proxy/proxy.js +300 -48
- package/dist/providers/coding-proxy/registry/audit.d.ts +53 -10
- package/dist/providers/coding-proxy/registry/audit.js +94 -17
- package/dist/providers/coding-proxy/registry/lockfile-parse-worker.d.ts +36 -0
- package/dist/providers/coding-proxy/registry/lockfile-parse-worker.js +67 -0
- package/dist/providers/coding-proxy/registry/lockfile-parse.d.ts +16 -0
- package/dist/providers/coding-proxy/registry/lockfile-parse.js +110 -0
- package/dist/providers/coding-proxy/registry/plan.d.ts +9 -0
- package/dist/providers/coding-proxy/registry/plan.js +201 -48
- package/dist/providers/coding-proxy/registry/prisma-store.d.ts +11 -5
- package/dist/providers/coding-proxy/registry/prisma-store.js +120 -17
- package/dist/providers/coding-proxy/registry/service.d.ts +97 -16
- package/dist/providers/coding-proxy/registry/service.js +579 -112
- package/dist/providers/coding-proxy/registry/store.d.ts +84 -9
- package/dist/providers/coding-proxy/registry/store.js +54 -1
- package/dist/providers/coding-proxy/runtime.d.ts +10 -0
- package/dist/providers/coding-proxy/runtime.js +109 -16
- package/dist/providers/coding-proxy/server.d.ts +9 -1
- package/dist/providers/coding-proxy/server.js +55 -1
- package/dist/providers/coding-proxy/types.d.ts +78 -1
- package/dist/providers/datastore/types.d.ts +5 -0
- package/dist/providers/engine/types.d.ts +17 -2
- package/dist/providers/engine/types.js +17 -0
- package/dist/providers/executor/composition.d.ts +10 -3
- package/dist/providers/executor/composition.js +52 -7
- package/dist/providers/executor/container.d.ts +394 -9
- package/dist/providers/executor/container.js +1210 -96
- package/dist/providers/executor/dbos-status.d.ts +31 -0
- package/dist/providers/executor/dbos-status.js +64 -0
- package/dist/providers/executor/dbos.d.ts +50 -1
- package/dist/providers/executor/dbos.js +207 -20
- package/dist/providers/executor/deferred.d.ts +12 -24
- package/dist/providers/executor/deferred.js +10 -29
- package/dist/providers/executor/in-process.d.ts +9 -1
- package/dist/providers/executor/in-process.js +14 -4
- package/dist/providers/executor/linked-issue-reader.d.ts +16 -0
- package/dist/providers/executor/linked-issue-reader.js +30 -0
- package/dist/providers/executor/routing.d.ts +2 -0
- package/dist/providers/executor/routing.js +4 -0
- package/dist/providers/executor/types.d.ts +13 -0
- package/dist/providers/host-tools/invoke.d.ts +37 -0
- package/dist/providers/host-tools/invoke.js +117 -0
- package/dist/providers/host-tools/operations.d.ts +65 -0
- package/dist/providers/host-tools/operations.js +149 -0
- package/dist/providers/host-tools/registry.d.ts +79 -0
- package/dist/providers/host-tools/registry.js +362 -0
- package/dist/providers/host-tools/request-guard.d.ts +17 -0
- package/dist/providers/host-tools/request-guard.js +99 -0
- package/dist/providers/host-tools/self-test.d.ts +64 -0
- package/dist/providers/host-tools/self-test.js +142 -0
- package/dist/providers/index.d.ts +2 -1
- package/dist/providers/issue-tracker/types.d.ts +17 -0
- package/dist/providers/issue-tracker/types.js +39 -1
- package/dist/providers/jobs/claude-tool-setup.d.ts +4 -0
- package/dist/providers/jobs/claude-tool-setup.js +5 -2
- package/dist/providers/jobs/docker-isolation.d.ts +10 -2
- package/dist/providers/jobs/docker-isolation.js +47 -8
- package/dist/providers/jobs/docker.d.ts +9 -0
- package/dist/providers/jobs/docker.js +60 -11
- package/dist/providers/jobs/fake-kubernetes-api.d.ts +2 -0
- package/dist/providers/jobs/fake-kubernetes-api.js +3 -0
- package/dist/providers/jobs/kubernetes-api.d.ts +8 -0
- package/dist/providers/jobs/kubernetes-api.js +10 -0
- package/dist/providers/jobs/kubernetes-client.js +10 -1
- package/dist/providers/jobs/kubernetes-isolation.d.ts +5 -1
- package/dist/providers/jobs/kubernetes-isolation.js +32 -3
- package/dist/providers/jobs/kubernetes.d.ts +11 -1
- package/dist/providers/jobs/kubernetes.js +111 -17
- package/dist/providers/jobs/types.d.ts +39 -0
- package/dist/providers/jobs/types.js +13 -1
- package/dist/providers/llm/anthropic.js +5 -1
- package/dist/providers/llm/bedrock.d.ts +0 -12
- package/dist/providers/llm/bedrock.js +4 -0
- package/dist/providers/llm/claude-messages.d.ts +3 -1
- package/dist/providers/llm/claude-messages.js +4 -1
- package/dist/providers/llm/claude-provider.d.ts +2 -2
- package/dist/providers/llm/claude-provider.js +2 -2
- package/dist/providers/llm/openai.d.ts +2 -2
- package/dist/providers/llm/openai.js +6 -2
- package/dist/providers/llm/routing.d.ts +2 -2
- package/dist/providers/llm/routing.js +2 -2
- package/dist/providers/llm/types.d.ts +12 -2
- package/dist/providers/review-host/github-events.d.ts +9 -1
- package/dist/providers/review-host/github-events.js +34 -12
- package/dist/providers/review-host/github.d.ts +29 -2
- package/dist/providers/review-host/github.js +224 -29
- package/dist/providers/review-host/local.d.ts +8 -4
- package/dist/providers/review-host/local.js +49 -31
- package/dist/providers/review-host/patch-pages.d.ts +41 -0
- package/dist/providers/review-host/patch-pages.js +176 -0
- package/dist/providers/review-host/review-format.d.ts +19 -1
- package/dist/providers/review-host/review-format.js +38 -7
- package/dist/providers/review-host/types.d.ts +140 -6
- package/dist/providers/review-host/types.js +9 -1
- package/dist/providers/storage/gcs.d.ts +63 -0
- package/dist/providers/storage/gcs.js +69 -0
- package/dist/providers/storage/index.d.ts +15 -0
- package/dist/providers/storage/index.js +14 -0
- package/dist/providers/storage/local.d.ts +24 -0
- package/dist/providers/storage/local.js +92 -0
- package/dist/providers/storage/meter.d.ts +14 -0
- package/dist/providers/storage/meter.js +34 -0
- package/dist/providers/storage/s3.d.ts +41 -0
- package/dist/providers/storage/s3.js +107 -0
- package/dist/providers/storage/types.d.ts +37 -3
- package/dist/providers/storage/types.js +21 -4
- package/dist/providers/vcs/git.d.ts +39 -4
- package/dist/providers/vcs/git.js +339 -26
- package/dist/providers/vcs/github-remote.d.ts +26 -3
- package/dist/providers/vcs/github-remote.js +124 -14
- package/dist/providers/vcs/github.d.ts +183 -44
- package/dist/providers/vcs/github.js +455 -56
- package/dist/providers/vcs/index.d.ts +1 -1
- package/dist/providers/vcs/index.js +9 -2
- package/dist/providers/vcs/pr-description.d.ts +127 -0
- package/dist/providers/vcs/pr-description.js +270 -0
- package/dist/providers/vcs/remote.d.ts +37 -1
- package/dist/providers/vcs/remote.js +7 -1
- package/dist/providers/vcs/routing.d.ts +16 -8
- package/dist/providers/vcs/routing.js +27 -6
- package/dist/providers/vcs/types.d.ts +150 -5
- package/dist/quickstart/coding-seed.d.ts +14 -3
- package/dist/quickstart/coding-seed.js +213 -4
- package/dist/quickstart/index.d.ts +5 -0
- package/dist/quickstart/index.js +21 -0
- package/dist/quickstart/reviewer-prompt.d.ts +1 -1
- package/dist/quickstart/reviewer-prompt.js +6 -6
- package/dist/quickstart-images.json +1 -1
- package/dist/sandbox/eval-core.d.ts +12 -2
- package/dist/sandbox/eval-core.js +20 -4
- package/dist/sandbox/generated/zod.bundle.js +62 -1
- package/dist/sandbox/generated/zod3.bundle.js +5 -0
- package/dist/sandbox/host-functions.d.ts +5 -0
- package/dist/sandbox/host-functions.js +13 -13
- package/dist/sandbox/limits.d.ts +4 -1
- package/dist/sandbox/limits.js +4 -1
- package/dist/sandbox/run-in-sandbox.d.ts +6 -0
- package/dist/sandbox/run-in-sandbox.js +14 -2
- package/dist/sandbox/safe-fetch.d.ts +2 -0
- package/dist/sandbox/safe-fetch.js +1 -1
- package/dist/sandbox/secret-broker.d.ts +1 -0
- package/dist/sandbox/secret-broker.js +4 -5
- package/dist/sandbox/tool-capabilities.d.ts +10 -30
- package/dist/sandbox/tool-timeout.d.ts +32 -0
- package/dist/sandbox/tool-timeout.js +52 -0
- package/dist/sandbox/user-tool.d.ts +8 -1
- package/dist/sandbox/user-tool.js +9 -3
- package/dist/sandbox/zod-params.d.ts +37 -5
- package/dist/sandbox/zod-params.js +181 -26
- package/dist/serve.js +8 -1
- package/dist/viewer/api-schema.d.ts +349 -2627
- package/dist/viewer/api-schema.js +7 -0
- package/dist/viewer/build-schemas.js +6 -2
- package/dist/viewer/graph.js +2 -1
- package/dist/viewer/openapi.js +2 -4
- package/dist/wardby-bin.js +15 -0
- package/docs/README.md +11 -1
- package/docs/agent-recipes.md +95 -24
- package/docs/architecture-runtime.md +1 -1
- package/docs/claude-code-plugin.md +164 -0
- package/docs/code-review-agents.md +557 -41
- package/docs/coding-agent-setup.md +566 -8
- package/docs/coding-packages.md +1033 -90
- package/docs/coding-services.md +27 -12
- package/docs/coding-worker-byo-images.md +24 -2
- package/docs/coding-worker-isolation.md +183 -37
- package/docs/debugging-agent-runs.md +242 -0
- package/docs/getting-started-gke.md +129 -141
- package/docs/getting-started-identity-provider.md +53 -38
- package/docs/getting-started.md +17 -0
- package/docs/host-providers.md +294 -0
- package/docs/jira-agents.md +17 -8
- package/docs/knowledge/blob-not-found-semantics.md +41 -0
- package/docs/knowledge/bounded-file-descriptor.md +52 -0
- package/docs/knowledge/delegation-admission-slots.md +52 -0
- package/docs/knowledge/http-dispatcher-bootstrap.md +61 -0
- package/docs/knowledge/import-rename-target.md +52 -0
- package/docs/knowledge/index.md +57 -0
- package/docs/knowledge/log.md +9 -0
- package/docs/knowledge/mcp-cancelled-task-precedence.md +41 -0
- package/docs/knowledge/mcp-http-prompt-discovery.md +41 -0
- package/docs/knowledge/mcp-schema-module-boundary.md +41 -0
- package/docs/knowledge/nullable-tool-uniqueness.md +52 -0
- package/docs/knowledge/overview-cli.md +74 -0
- package/docs/knowledge/overview-coding-proxy.md +72 -0
- package/docs/knowledge/overview-coding.md +72 -0
- package/docs/knowledge/overview-config.md +60 -0
- package/docs/knowledge/overview-core.md +72 -0
- package/docs/knowledge/overview-deploy.md +83 -0
- package/docs/knowledge/overview-mcp.md +61 -0
- package/docs/knowledge/overview-prisma.md +72 -0
- package/docs/knowledge/overview-providers.md +89 -0
- package/docs/knowledge/overview-sandbox.md +83 -0
- package/docs/knowledge/overview-surfaces.md +83 -0
- package/docs/knowledge/private-datastore-shared-boundary.md +54 -0
- package/docs/knowledge/proxy-settlement-projections.md +41 -0
- package/docs/knowledge/run-pricing-first-writer.md +43 -0
- package/docs/knowledge/schedule-claim-transaction.md +41 -0
- package/docs/knowledge/secret-entry-replica-contract.md +52 -0
- package/docs/knowledge/terminal-run-first-writer.md +41 -0
- package/docs/knowledge/transactional-agent-authorization.md +52 -0
- package/docs/knowledge/viewer-notify-write-isolation.md +30 -0
- package/docs/knowledge/warm-input-publication.md +30 -0
- package/docs/knowledge/workspace-staging-failure.md +54 -0
- package/docs/knowledge.md +54 -14
- package/docs/mcp-servers.md +254 -0
- package/docs/native-sandbox.md +143 -31
- package/docs/observability.md +4 -0
- package/docs/security-deployment.md +139 -29
- package/docs/slack-notifications.md +35 -19
- package/docs/tool-secrets.md +45 -10
- package/docs/viewer-api.md +6 -0
- package/docs/viewer-api.openapi.yml +1 -1
- package/help/admin-viewer.md +28 -2
- package/help/agent-recipes.md +33 -2
- package/help/architecture-agent.md +11 -6
- package/help/brokered-secrets.md +3 -0
- package/help/build-claude-code-image.md +1 -1
- package/help/build-worker-image.md +3 -1
- package/help/builder-agent.md +19 -6
- package/help/claude-code-run-pane.md +40 -0
- package/help/code-review-agents.md +177 -6
- package/help/coding-packages.md +156 -6
- package/help/cost-attribution.md +9 -5
- package/help/creating-agents.md +14 -1
- package/help/dependency-cache.md +143 -0
- package/help/deploy-gke.md +15 -8
- package/help/errors/budget-exhausted.md +187 -0
- package/help/errors/budget-group-exhausted.md +5 -1
- package/help/errors/coding-mcp-pins-unavailable.md +35 -0
- package/help/errors/coding-stream-quota-exceeded.md +33 -0
- package/help/errors/coding-workspace-disk-exceeds-limit.md +39 -0
- package/help/errors/continuation-closed.md +9 -12
- package/help/errors/database-auth-invalid.md +1 -1
- package/help/errors/delegation-conflict.md +24 -0
- package/help/errors/file-list-truncated.md +45 -0
- package/help/errors/full-read-required.md +49 -0
- package/help/errors/github-account-not-allowed.md +4 -0
- package/help/errors/graph-incomplete.md +43 -0
- package/help/errors/graph-limit.md +43 -0
- package/help/errors/host-provider-error.md +40 -0
- package/help/errors/host-tool-failed.md +36 -0
- package/help/errors/mcp-call-limit.md +22 -0
- package/help/errors/mcp-call-timeout.md +22 -0
- package/help/errors/mcp-server-auth-failed.md +22 -0
- package/help/errors/mcp-server-credentials-unavailable.md +45 -0
- package/help/errors/mcp-server-error.md +28 -0
- package/help/errors/mcp-server-unreachable.md +22 -0
- package/help/errors/mcp-servers-off.md +21 -0
- package/help/errors/mcp-tool-not-allowed.md +26 -0
- package/help/errors/mcp-tool-removed.md +22 -0
- package/help/errors/mcp-unavailable.md +25 -0
- package/help/errors/merge-conflict.md +49 -0
- package/help/errors/native-sandbox-capacity.md +1 -1
- package/help/errors/native-sandbox-deadline-exceeded.md +1 -1
- package/help/errors/native-sandbox-docker-failed.md +1 -1
- package/help/errors/native-sandbox-gateway-error.md +20 -0
- package/help/errors/native-sandbox-gateway-unavailable.md +1 -1
- package/help/errors/native-sandbox-image-not-pinned.md +1 -1
- package/help/errors/native-sandbox-isolation-mismatch.md +1 -1
- package/help/errors/native-sandbox-launch-abandoned.md +21 -0
- package/help/errors/native-sandbox-network-unenforced.md +1 -1
- package/help/errors/native-sandbox-requires-catalog.md +1 -1
- package/help/errors/native-sandbox-unavailable.md +1 -1
- package/help/errors/native-sandbox-warm-delivery-failed.md +1 -1
- package/help/errors/native-sandbox-worker-exited.md +4 -3
- package/help/errors/native-sandbox-worker-lost.md +1 -1
- package/help/errors/native-sandbox-worker-unready.md +1 -1
- package/help/errors/package-not-allowed-pending.md +52 -0
- package/help/errors/package-not-allowed.md +51 -0
- package/help/errors/package-refusals.md +43 -0
- package/help/errors/patch-cursor-malformed.md +31 -0
- package/help/errors/repository-not-listed.md +36 -0
- package/help/errors/repository-required.md +36 -0
- package/help/errors/run-lost.md +39 -0
- package/help/errors/run-transcript-download.md +44 -0
- package/help/errors/secret-in-value.md +69 -0
- package/help/errors/target-merge.md +40 -0
- package/help/errors/tool-timeout.md +38 -0
- package/help/fix-merge-conflicts.md +73 -0
- package/help/github-app-setup.md +132 -0
- package/help/github.md +22 -0
- package/help/host-providers.md +40 -0
- package/help/identity-and-access.md +6 -1
- package/help/jira.md +23 -6
- package/help/knowledge.md +16 -7
- package/help/local-repositories.md +1 -1
- package/help/low-power-mode.md +7 -1
- package/help/mcp-servers.md +73 -0
- package/help/mcp.md +7 -2
- package/help/merge-order-check.md +5 -0
- package/help/native-capabilities.md +55 -1
- package/help/native-sandbox.md +16 -2
- package/help/operating-agents.md +21 -0
- package/help/package-audit-mode.md +91 -0
- package/help/related-pull-requests.md +17 -10
- package/help/repo-instructions-and-skills.md +3 -1
- package/help/resume-runs-locally.md +134 -0
- package/help/review-fix-rounds.md +33 -1
- package/help/sharing-agents.md +59 -0
- package/help/slack-notifications.md +19 -5
- package/help/status-comments.md +31 -0
- package/help/stop-run.md +58 -0
- package/help/troubleshooting/budgets.md +28 -0
- package/help/troubleshooting/coding-workers.md +86 -7
- package/help/troubleshooting/debugging-agent-runs.md +29 -0
- package/package.json +18 -10
- package/prisma/migrations/20261016000000_registry_approved_accepted_advisories/migration.sql +3 -0
- package/prisma/migrations/20261016000001_mark_ready_when_passing/migration.sql +3 -0
- package/prisma/migrations/20261017000000_debug_trace_max_mb/migration.sql +4 -0
- package/prisma/migrations/20261018000000_dependency_cache/migration.sql +53 -0
- package/prisma/migrations/20261019000000_claude_max_output_tokens/migration.sql +5 -0
- package/prisma/migrations/20261021000000_pr_description_hash/migration.sql +4 -0
- package/prisma/migrations/20261022000000_dependency_snapshot_validation_metadata/migration.sql +4 -0
- package/prisma/migrations/20261023000000_package_audit_mode/migration.sql +27 -0
- package/prisma/migrations/20261024000000_budget_events/migration.sql +26 -0
- package/prisma/migrations/20261025000000_cache_aware_holds/migration.sql +9 -0
- package/prisma/migrations/20261026000000_budget_overrun/migration.sql +4 -0
- package/prisma/migrations/20261027000000_coding_run_request/migration.sql +1 -0
- package/prisma/migrations/20261028000000_native_gateway_review_reads/migration.sql +6 -0
- package/prisma/migrations/20261029000000_lead_survives_deploy/migration.sql +6 -0
- package/prisma/migrations/20261030000000_local_review_covered_sha/migration.sql +2 -0
- package/prisma/migrations/20261031000000_coding_run_budget_limit/migration.sql +9 -0
- package/prisma/migrations/20261101000000_run_transcripts/migration.sql +22 -0
- package/prisma/migrations/20261102000000_host_providers/migration.sql +56 -0
- package/prisma/migrations/20261104000000_coding_agent_repository_list/migration.sql +5 -0
- package/prisma/migrations/20261106000000_tool_timeout/migration.sql +4 -0
- package/prisma/migrations/20261107000000_mcp_servers/migration.sql +33 -0
- package/prisma/migrations/20261108000000_coding_mcp/migration.sql +5 -0
- package/prisma/migrations/20261109000000_task_run_index/migration.sql +3 -0
- package/prisma/schema.prisma +468 -109
- package/scripts/git-askpass.sh +1 -1
- package/dist/sandbox/generated/zod-to-json-schema.bundle.js +0 -5
package/dist/core/host-events.js
CHANGED
|
@@ -6,16 +6,21 @@
|
|
|
6
6
|
* docs/private/2026-09-25-code-review-host-design.md §6.3.
|
|
7
7
|
*/
|
|
8
8
|
import { Prisma } from "#prisma";
|
|
9
|
-
import {
|
|
9
|
+
import { codeProviderOf, pullRequestWebUrl } from "../coding/code-host.js";
|
|
10
|
+
import { linkedPullRequestAttribution, openingRunAttribution, resolveWorkItem, RESPONSE_PATH_SNAPSHOT_BUDGET, } from "./attribution.js";
|
|
11
|
+
import { headStoppedAtBudget, pushingRunInFlight } from "./budget-stopped-head.js";
|
|
10
12
|
import { checkContinuation, dispatchRun } from "./dispatch.js";
|
|
11
13
|
import { mentionStatusRow, postMentionStatus } from "./host-status.js";
|
|
12
|
-
import { handlePullRequestClosed } from "./issue-bridge.js";
|
|
14
|
+
import { githubIssueKey, handlePullRequestClosed } from "./issue-bridge.js";
|
|
13
15
|
import { logger } from "./logger.js";
|
|
16
|
+
import { withoutMarkdownCode } from "./markdown-code.js";
|
|
17
|
+
import { maybeMarkReady } from "./mark-ready.js";
|
|
14
18
|
import { syncMergeOrderChecksForPullRequest } from "./merge-order-check.js";
|
|
15
|
-
import { MAX_SIBLING_HINTS, openSiblings, runTreeRoot, SIBLING_GUIDANCE, } from "./related-pull-requests.js";
|
|
19
|
+
import { MAX_SIBLING_HINTS, openPullRequestHints, openSiblings, openSiblingsForIssue, runTreeRoot, SIBLING_GUIDANCE, } from "./related-pull-requests.js";
|
|
16
20
|
import { requiredLevel } from "./repo-access.js";
|
|
17
21
|
import { composeTaskOverride } from "./untrusted-content.js";
|
|
18
22
|
import { DEFAULT_KNOWLEDGE_BUNDLE_PATH, parseConcept, RESERVED_BUNDLE_FILES, } from "../knowledge/concept.js";
|
|
23
|
+
import { KNOWLEDGE_CONFIG_MAX_BYTES, KNOWLEDGE_CONFIG_PATH, resolveKnowledgeLocation } from "../knowledge/location.js";
|
|
19
24
|
import { driftScope } from "../knowledge/relevance.js";
|
|
20
25
|
import { spanHash } from "../knowledge/span-hash.js";
|
|
21
26
|
const log = logger.child({ module: "host-events" });
|
|
@@ -31,11 +36,14 @@ export const DEFERRED_REVIEW_BATCH = 50;
|
|
|
31
36
|
function escapeRegExp(value) {
|
|
32
37
|
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
33
38
|
}
|
|
39
|
+
/** A `@app review` outside code: quoting the command in code documents it. */
|
|
34
40
|
export function isReviewCommand(body, mentionHandle) {
|
|
35
|
-
return new RegExp(`(^|[^\\w-])@${escapeRegExp(mentionHandle)}\\s+review(?![\\w-])`, "i").test(body);
|
|
41
|
+
return new RegExp(`(^|[^\\w-])@${escapeRegExp(mentionHandle)}\\s+review(?![\\w-])`, "i").test(withoutMarkdownCode(body));
|
|
36
42
|
}
|
|
37
43
|
const MAX_BUNDLE_FILES = 200;
|
|
38
44
|
const BUNDLE_FILE_LINES = 2000;
|
|
45
|
+
/** `.wardby/knowledge.yaml` is one short key; a longer read is refused as too large. */
|
|
46
|
+
const KNOWLEDGE_CONFIG_MAX_LINES = 200;
|
|
39
47
|
const MAX_LISTED_CHANGES = 200;
|
|
40
48
|
/** The whole bundle load (listing plus reads) must finish inside GitHub's ~10 s webhook window. */
|
|
41
49
|
const BUNDLE_LOAD_DEADLINE_MS = 4000;
|
|
@@ -49,7 +57,7 @@ const BUNDLE_INCOMPLETE_TEXT = "The knowledge bundle could not be fully read; tr
|
|
|
49
57
|
* commits, so they and the affected concept paths travel as untrusted context.
|
|
50
58
|
* Commit messages and author names are never included.
|
|
51
59
|
*/
|
|
52
|
-
export function mergeTaskText(event, scope, bundleComplete = true, citations = new Map()) {
|
|
60
|
+
export function mergeTaskText(event, scope, bundleComplete = true, citations = new Map(), bundlePath = DEFAULT_KNOWLEDGE_BUNDLE_PATH) {
|
|
53
61
|
const statusOf = (concept) => citations.get(concept) ?? { state: "unverified" };
|
|
54
62
|
const changed = event.changedPathsComplete
|
|
55
63
|
? `Changed files:\n${[
|
|
@@ -61,7 +69,7 @@ export function mergeTaskText(event, scope, bundleComplete = true, citations = n
|
|
|
61
69
|
: "The changed-file list is incomplete (GitHub includes at most 2048 commits per push and the list is capped at 1000 paths); treat every knowledge concept as possibly affected.";
|
|
62
70
|
const listed = scope
|
|
63
71
|
? `Knowledge concepts whose citations, affects globs, or files changed (${scope.reason}):\n` +
|
|
64
|
-
scope.concepts.map((p) => `- ${
|
|
72
|
+
scope.concepts.map((p) => `- ${bundlePath}/${p} — ${describeStatus(statusOf(p))}`).join("\n")
|
|
65
73
|
: null;
|
|
66
74
|
let context;
|
|
67
75
|
if (!bundleComplete)
|
|
@@ -76,7 +84,7 @@ export function mergeTaskText(event, scope, bundleComplete = true, citations = n
|
|
|
76
84
|
if (scope && scope.concepts.length > 0) {
|
|
77
85
|
const states = scope.concepts.map((p) => statusOf(p).state);
|
|
78
86
|
const count = (state) => states.filter((x) => x === state).length;
|
|
79
|
-
const onlyKnowledge = event.changedPathsComplete && event.changedPaths.every((p) => p.startsWith(`${
|
|
87
|
+
const onlyKnowledge = event.changedPathsComplete && event.changedPaths.every((p) => p.startsWith(`${bundlePath}/`));
|
|
80
88
|
summary =
|
|
81
89
|
`Citation check at ${event.after.slice(0, 12)}: ${count("verified")} of ${states.length} affected concepts verified, ` +
|
|
82
90
|
`${count("stale")} stale, ${count("unverified")} not verified. Only knowledge files changed: ${onlyKnowledge ? "yes" : "no"}.`;
|
|
@@ -106,13 +114,36 @@ function startBudget(ms) {
|
|
|
106
114
|
});
|
|
107
115
|
return { promise, expired: () => expired, clear: () => clearTimeout(timer) };
|
|
108
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* `.wardby/knowledge.yaml` at the pushed commit, or null when it does not
|
|
119
|
+
* exist. Reads within the shared budget; a deadline or a host error throws,
|
|
120
|
+
* which resolveKnowledgeLocation turns into the default bundle with a warning.
|
|
121
|
+
*/
|
|
122
|
+
async function readKnowledgeConfig(host, event, budget) {
|
|
123
|
+
const read = await Promise.race([
|
|
124
|
+
host.readFile(event.repository, KNOWLEDGE_CONFIG_PATH, event.after, {
|
|
125
|
+
startLine: 1,
|
|
126
|
+
maxLines: KNOWLEDGE_CONFIG_MAX_LINES,
|
|
127
|
+
}),
|
|
128
|
+
budget.promise,
|
|
129
|
+
]);
|
|
130
|
+
if (read === "deadline")
|
|
131
|
+
throw new Error("the read hit its deadline");
|
|
132
|
+
if (read.kind === "not_found")
|
|
133
|
+
return null;
|
|
134
|
+
if (read.kind !== "file")
|
|
135
|
+
throw new Error("it is not a file");
|
|
136
|
+
if (read.truncated || Buffer.byteLength(read.text, "utf8") > KNOWLEDGE_CONFIG_MAX_BYTES)
|
|
137
|
+
throw new Error(`it is larger than ${KNOWLEDGE_CONFIG_MAX_BYTES} bytes`);
|
|
138
|
+
return read.text;
|
|
139
|
+
}
|
|
109
140
|
/**
|
|
110
141
|
* The knowledge bundle at the pushed commit, read with bounded concurrency
|
|
111
142
|
* under one overall deadline. A failure never fails the route; it yields an
|
|
112
143
|
* incomplete result so the watcher treats every concept as possibly affected.
|
|
113
144
|
*/
|
|
114
|
-
async function loadBundle(host, event, budget) {
|
|
115
|
-
const prefix = `${
|
|
145
|
+
async function loadBundle(host, event, budget, bundlePath) {
|
|
146
|
+
const prefix = `${bundlePath}/`;
|
|
116
147
|
const concepts = [];
|
|
117
148
|
const where = { repository: event.repository, after: event.after };
|
|
118
149
|
let filesRead = 0;
|
|
@@ -260,7 +291,7 @@ export function continuationHint(prNumber, runId) {
|
|
|
260
291
|
`continued instead of opening a new one.]`);
|
|
261
292
|
}
|
|
262
293
|
const HINT_RUN_ID = /^[A-Za-z0-9][A-Za-z0-9_-]{0,127}$/;
|
|
263
|
-
const HINT_REPOSITORY = /^[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/;
|
|
294
|
+
const HINT_REPOSITORY = /^(?:[a-z][a-z0-9-]{1,30}:)?[A-Za-z0-9._-]+\/[A-Za-z0-9._-]+$/;
|
|
264
295
|
/** One hint per open sibling (stored rows only; links built, ids re-validated), then the shared guidance. */
|
|
265
296
|
export function siblingContinuationHints(siblings) {
|
|
266
297
|
const lines = siblings
|
|
@@ -269,8 +300,11 @@ export function siblingContinuationHints(siblings) {
|
|
|
269
300
|
Number.isSafeInteger(s.number) &&
|
|
270
301
|
s.number > 0)
|
|
271
302
|
.slice(0, MAX_SIBLING_HINTS)
|
|
272
|
-
.map((s) =>
|
|
273
|
-
|
|
303
|
+
.map((s) => {
|
|
304
|
+
const url = pullRequestWebUrl(codeProviderOf(s.repository), s.repository, s.number);
|
|
305
|
+
return (`- ${s.repository}#${s.number}${url ? ` (${url})` : ""}: to change it, ` +
|
|
306
|
+
`delegate to that repository's coding agent and ${continuePriorRunPhrase(s.openedByRunId)}.`);
|
|
307
|
+
});
|
|
274
308
|
if (lines.length === 0)
|
|
275
309
|
return undefined;
|
|
276
310
|
return [
|
|
@@ -306,6 +340,12 @@ export function mentionTaskText(event, siblings = []) {
|
|
|
306
340
|
if (hints)
|
|
307
341
|
sections.push(hints);
|
|
308
342
|
}
|
|
343
|
+
else if (!event.isPullRequest) {
|
|
344
|
+
// An issue mention: the issue's open wardby pull requests, worded as a Jira issue's are.
|
|
345
|
+
const hints = openPullRequestHints(siblings);
|
|
346
|
+
if (hints)
|
|
347
|
+
sections.push(hints);
|
|
348
|
+
}
|
|
309
349
|
const title = event.subject?.title.replace(/\s+/g, " ").trim().slice(0, MAX_TITLE);
|
|
310
350
|
const description = event.subject?.body.trim() ? event.subject.body.slice(0, MAX_TASK_BODY) : "";
|
|
311
351
|
sections.push([
|
|
@@ -342,11 +382,49 @@ async function priorRunContinues(deps, event) {
|
|
|
342
382
|
const check = await checkContinuation(deps.db, event.priorRunId, event.repository);
|
|
343
383
|
return check.ok && check.root.pullRequestNumber === event.number;
|
|
344
384
|
}
|
|
385
|
+
/** The reply to a mention whose author can see the repository but cannot push to it. */
|
|
386
|
+
export const NO_WRITE_ACCESS_BODY = "😕 I can't act on this: a mention starts work only for people with write access to this repository. " +
|
|
387
|
+
"Ask someone with write access to mention me instead.";
|
|
388
|
+
/** Associations that mean the account holds a role on the repository, not just a view of a public one. */
|
|
389
|
+
const ROLE_ASSOCIATIONS = new Set(["OWNER", "MEMBER", "COLLABORATOR"]);
|
|
390
|
+
/**
|
|
391
|
+
* Whether a refused author should be told why. Triage is granted explicitly, so
|
|
392
|
+
* it always counts. GitHub reports `read` for every account on a public
|
|
393
|
+
* repository, so there `read` counts only with a role association; on a private
|
|
394
|
+
* repository `read` means the account was given access (a private organization
|
|
395
|
+
* member is labelled CONTRIBUTOR or NONE). Unknown facts stay silent.
|
|
396
|
+
*/
|
|
397
|
+
function explainsRefusal(level, event) {
|
|
398
|
+
if (level === "triage")
|
|
399
|
+
return true;
|
|
400
|
+
if (level !== "read")
|
|
401
|
+
return false;
|
|
402
|
+
return event.repositoryPrivate === true || ROLE_ASSOCIATIONS.has(event.authorAssociation ?? "");
|
|
403
|
+
}
|
|
345
404
|
export function unknownPriorRunBody(priorRunId) {
|
|
346
405
|
return (`❌ I can't continue this pull request. Its description names wardby run \`${priorRunId}\`, but this wardby ` +
|
|
347
406
|
"deployment has no record of that run opening this pull request (another wardby deployment may have opened it). " +
|
|
348
407
|
"Ask the deployment that opened it, or make the change on this branch by hand.");
|
|
349
408
|
}
|
|
409
|
+
/**
|
|
410
|
+
* Never names the App's handle: this comment is posted by the App, and a
|
|
411
|
+
* body that mentioned it could be matched as a mention of itself.
|
|
412
|
+
*/
|
|
413
|
+
export function mentionDeclinedBody(reason) {
|
|
414
|
+
switch (reason) {
|
|
415
|
+
case "no_responder":
|
|
416
|
+
return (`ℹ️ I didn't start a run: no agent on this repository is set up to answer mentions. ` +
|
|
417
|
+
'An agent owner can link one with the `mention` trigger (`link_repository`, `triggers: ["mention"]`).');
|
|
418
|
+
case "no_reviewer":
|
|
419
|
+
return (`ℹ️ I didn't start a review: no reviewer agent is linked to this repository. ` +
|
|
420
|
+
"An agent owner can link one with the `pull_request` trigger and a `checkName` (`link_repository`).");
|
|
421
|
+
case "agent_not_authorized":
|
|
422
|
+
return ("ℹ️ I didn't start a run: the agent linked here can no longer use this repository. " +
|
|
423
|
+
"Its owner's GitHub account needs access to it again; they can re-authorize it or re-link the agent.");
|
|
424
|
+
case "pull_request_not_reviewable":
|
|
425
|
+
return "ℹ️ I didn't start a review: this pull request is closed or comes from a fork, and wardby reviews only open pull requests from branches of this repository.";
|
|
426
|
+
}
|
|
427
|
+
}
|
|
350
428
|
/** A review run's task: the head to review, plus any extra context its trigger adds. */
|
|
351
429
|
export function reviewTaskText(repository, prNumber, headSha, context) {
|
|
352
430
|
const task = `Review pull request #${prNumber} in ${repository} (head ${headSha}).`;
|
|
@@ -457,6 +535,59 @@ context) {
|
|
|
457
535
|
}
|
|
458
536
|
return runIds;
|
|
459
537
|
}
|
|
538
|
+
async function budgetDraftDecision(deps, host, repository, prNumber, headSha,
|
|
539
|
+
/** The pull request's origin, when the caller already reads it once per event. */
|
|
540
|
+
readOrigin) {
|
|
541
|
+
const review = { kind: "review" };
|
|
542
|
+
const read = readOrigin ?? (host.pullRequestOrigin ? () => host.pullRequestOrigin(repository, prNumber) : undefined);
|
|
543
|
+
if (!read)
|
|
544
|
+
return review;
|
|
545
|
+
try {
|
|
546
|
+
const origin = await read();
|
|
547
|
+
if (origin.draft !== true || !origin.markerRunId)
|
|
548
|
+
return review;
|
|
549
|
+
const runId = await pushingRunInFlight(deps.db, { markerRunId: origin.markerRunId, repository });
|
|
550
|
+
if (runId)
|
|
551
|
+
return { kind: "wait", runId: await pushingRunHold(deps.db, runId) };
|
|
552
|
+
const stopped = await headStoppedAtBudget(deps.db, {
|
|
553
|
+
markerRunId: origin.markerRunId,
|
|
554
|
+
repository,
|
|
555
|
+
prNumber,
|
|
556
|
+
headSha,
|
|
557
|
+
});
|
|
558
|
+
return stopped ? { kind: "skip" } : review;
|
|
559
|
+
}
|
|
560
|
+
catch (err) {
|
|
561
|
+
log.warn({ err, repository, prNumber }, "could not read the pull request's coding run; reviewing as usual");
|
|
562
|
+
return review;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Instead of reviewing a budget-stopped draft (budgetDraftDecision `skip`): completes a neutral
|
|
567
|
+
* check per reviewer. No review run, so no RunHostCheck and no fix round. A reviewer that already
|
|
568
|
+
* reviewed this commit (an explicit request) keeps that review's check: a neutral one over it
|
|
569
|
+
* would stand, unreviewed again, once the draft is marked ready (that automatic review skips a
|
|
570
|
+
* reviewed commit).
|
|
571
|
+
*/
|
|
572
|
+
async function postSkippedReviewChecks(deps, host, repository, prNumber, headSha, targets) {
|
|
573
|
+
log.info({ repository, prNumber, headSha, agentIds: targets.map((t) => t.agentId) }, "review skipped: the draft's last push stopped at its budget");
|
|
574
|
+
for (const target of targets) {
|
|
575
|
+
try {
|
|
576
|
+
if (await alreadyReviewed(deps, repository, prNumber, headSha, target.agentId))
|
|
577
|
+
continue;
|
|
578
|
+
const { checkId } = await host.startCheck(repository, { headSha, name: target.checkName });
|
|
579
|
+
await host.completeCheck(repository, {
|
|
580
|
+
checkId,
|
|
581
|
+
conclusion: "neutral",
|
|
582
|
+
title: "Skipped: stopped at its budget",
|
|
583
|
+
summary: "The last push came from a run that stopped at its budget before finishing. This draft is reviewed when the work continues or when it is marked ready for review.",
|
|
584
|
+
});
|
|
585
|
+
}
|
|
586
|
+
catch (err) {
|
|
587
|
+
log.warn({ err, repository, prNumber, agentId: target.agentId }, "could not post the skipped review check");
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
}
|
|
460
591
|
/**
|
|
461
592
|
* CI finished on a pull request's head: re-runs, once per head, each review
|
|
462
593
|
* that published only a COMMENT while CI there was still running or had not
|
|
@@ -492,6 +623,16 @@ async function rereviewAfterCi(deps, host, event, prNumber, reviewerLinks) {
|
|
|
492
623
|
// Only reviewers still authorized are claimed, so a denied one keeps its chance for later.
|
|
493
624
|
const allowed = await authorizedLinks(deps, event, reviewerLinks.filter((l) => waiting.some((r) => r.run.agentId === l.agentId)));
|
|
494
625
|
const allowedIds = new Set(allowed.map((l) => l.agentId));
|
|
626
|
+
// Decided before the claim, so a re-review not started here is not used up.
|
|
627
|
+
const decision = await budgetDraftDecision(deps, host, event.repository, prNumber, event.headSha);
|
|
628
|
+
if (decision.kind === "wait") {
|
|
629
|
+
log.info({ repository: event.repository, prNumber, headSha: event.headSha, runId: decision.runId }, "CI finished: re-review held while the pull request's coding run is still running");
|
|
630
|
+
return [];
|
|
631
|
+
}
|
|
632
|
+
if (decision.kind === "skip") {
|
|
633
|
+
await postSkippedReviewChecks(deps, host, event.repository, prNumber, event.headSha, reviewTargets(allowed));
|
|
634
|
+
return [];
|
|
635
|
+
}
|
|
495
636
|
// Claimed per row, so concurrent completions re-run each review only once.
|
|
496
637
|
const agentIds = new Set();
|
|
497
638
|
for (const row of waiting.filter((r) => allowedIds.has(r.run.agentId))) {
|
|
@@ -624,6 +765,22 @@ async function deferUntilCi(deps, host, key, links) {
|
|
|
624
765
|
}
|
|
625
766
|
return { startNow: [], runIds };
|
|
626
767
|
}
|
|
768
|
+
/**
|
|
769
|
+
* Deferred rows whose pull request's coding run is still in flight (budgetDraftDecision `wait`):
|
|
770
|
+
* they now wait for that run, as for a delegating run (reason "request", leadRunId = the run),
|
|
771
|
+
* and are released when it finishes (startDeferredForRequest from its terminal hook, or the
|
|
772
|
+
* sweep). The run may have finished meanwhile, its release finding no row: released here then.
|
|
773
|
+
*/
|
|
774
|
+
async function waitForPushingRun(deps, key, rows, runId) {
|
|
775
|
+
const where = { repository: key.repository, prNumber: key.prNumber, headSha: key.headSha };
|
|
776
|
+
await deps.db.deferredReview.updateMany({
|
|
777
|
+
where: { id: { in: rows.map((r) => r.id) } },
|
|
778
|
+
data: { reason: "request", leadRunId: runId },
|
|
779
|
+
});
|
|
780
|
+
log.info({ ...where, runId }, "deferred review held while the pull request's coding run is still running");
|
|
781
|
+
const run = await deps.db.run.findUnique({ where: { id: runId }, select: { status: true } });
|
|
782
|
+
return !run || !RUN_NOT_FINISHED.has(run.status) ? releaseRequestRows(deps, runId, "request") : [];
|
|
783
|
+
}
|
|
627
784
|
/**
|
|
628
785
|
* Starts deferred reviews for one PR head. The head must still be that sha,
|
|
629
786
|
* open, and not a fork; otherwise every row is dropped (a newer push records
|
|
@@ -641,6 +798,9 @@ async function startDeferred(deps, host, key, rows, reviewerLinks, mode, reason)
|
|
|
641
798
|
log.info({ ...where, state: head.state }, "deferred review dropped: the pull request moved on or closed");
|
|
642
799
|
return [];
|
|
643
800
|
}
|
|
801
|
+
const decision = await budgetDraftDecision(deps, host, key.repository, key.prNumber, key.headSha);
|
|
802
|
+
if (decision.kind === "wait")
|
|
803
|
+
return waitForPushingRun(deps, key, rows, decision.runId);
|
|
644
804
|
const allowed = await authorizedLinks(deps, key, reviewerLinks.filter((l) => rows.some((r) => r.agentId === l.agentId)));
|
|
645
805
|
const allowedIds = new Set(allowed.map((l) => l.agentId));
|
|
646
806
|
const targets = [];
|
|
@@ -659,6 +819,10 @@ async function startDeferred(deps, host, key, rows, reviewerLinks, mode, reason)
|
|
|
659
819
|
return [];
|
|
660
820
|
log.info({ ...where, agentIds: targets.map((t) => t.agentId), reason }, "starting the deferred review");
|
|
661
821
|
try {
|
|
822
|
+
if (decision.kind === "skip") {
|
|
823
|
+
await postSkippedReviewChecks(deps, host, key.repository, key.prNumber, key.headSha, targets);
|
|
824
|
+
return [];
|
|
825
|
+
}
|
|
662
826
|
return await startReviews(deps, host, key.repository, key.prNumber, key.headSha, targets, true);
|
|
663
827
|
}
|
|
664
828
|
catch (err) {
|
|
@@ -809,13 +973,36 @@ export async function requestLeadRunId(db, prMarkerRunId, repository) {
|
|
|
809
973
|
}
|
|
810
974
|
/** Run statuses that mean the delegating run has not finished. */
|
|
811
975
|
const RUN_NOT_FINISHED = new Set(["pending", "running"]);
|
|
976
|
+
/**
|
|
977
|
+
* The run a draft's review waits for while its coding run `pushingRunId` may still be pushing:
|
|
978
|
+
* that run's top-level lead while the lead is pending or running, else the coding run itself.
|
|
979
|
+
* A follow-up's lead is not the one requestLeadRunId finds (that walks up from the pull
|
|
980
|
+
* request's opening run), yet the review should still wait for the whole request (#259); and
|
|
981
|
+
* the lead's finalizer releases it outside every workflow step, where the coding run's own
|
|
982
|
+
* terminal hook, inside the lead's delegation step, could not start a review run.
|
|
983
|
+
*/
|
|
984
|
+
async function pushingRunHold(db, pushingRunId) {
|
|
985
|
+
// UNION, not UNION ALL: a parentRunId cycle (never written, but not a constraint) can't recurse forever.
|
|
986
|
+
const rows = await db.$queryRaw `
|
|
987
|
+
WITH RECURSIVE up AS (
|
|
988
|
+
SELECT r."id", r."parentRunId", r."status"::text AS "status" FROM "Run" r WHERE r."id" = ${pushingRunId}
|
|
989
|
+
UNION
|
|
990
|
+
SELECT p."id", p."parentRunId", p."status"::text FROM "Run" p JOIN up u ON p."id" = u."parentRunId"
|
|
991
|
+
)
|
|
992
|
+
SELECT u."id", u."status" FROM up u WHERE u."parentRunId" IS NULL LIMIT 1`;
|
|
993
|
+
const root = rows[0];
|
|
994
|
+
return root && root.id !== pushingRunId && RUN_NOT_FINISHED.has(root.status) ? root.id : pushingRunId;
|
|
995
|
+
}
|
|
812
996
|
/**
|
|
813
997
|
* pr_updated for a pull request a delegated coding run opened, while the
|
|
814
998
|
* request's lead run is still running: records one DeferredReview row per
|
|
815
999
|
* reviewer (reason "request", with or without waitForCi) and starts nothing;
|
|
816
1000
|
* the lead's finalizer (startDeferredForRequest) or the sweep starts them.
|
|
817
1001
|
* Returns null, to review as without it, for any other pull request, or when
|
|
818
|
-
* the lead cannot be resolved or the deferral cannot be recorded.
|
|
1002
|
+
* the lead cannot be resolved or the deferral cannot be recorded. A draft whose
|
|
1003
|
+
* own coding run (root or continuation) is still in flight waits for that run
|
|
1004
|
+
* the same way: it may have pushed this head before recording whether it
|
|
1005
|
+
* stopped at its budget (budgetDraftDecision); its terminal hook releases them.
|
|
819
1006
|
*/
|
|
820
1007
|
async function deferUntilRequest(deps, host, key, links,
|
|
821
1008
|
/** The pull request's origin, read at most once per event (shared with the merge order check). */
|
|
@@ -828,6 +1015,15 @@ readOrigin) {
|
|
|
828
1015
|
if (!origin.markerRunId)
|
|
829
1016
|
return null;
|
|
830
1017
|
leadRunId = await requestLeadRunId(deps.db, origin.markerRunId, key.repository);
|
|
1018
|
+
// A draft's own coding run still in flight may have pushed this head before recording its
|
|
1019
|
+
// result (a stop at its budget among them): wait for it the same way (budgetDraftDecision).
|
|
1020
|
+
if (!leadRunId && origin.draft === true) {
|
|
1021
|
+
const pushing = await pushingRunInFlight(deps.db, {
|
|
1022
|
+
markerRunId: origin.markerRunId,
|
|
1023
|
+
repository: key.repository,
|
|
1024
|
+
});
|
|
1025
|
+
leadRunId = pushing && (await pushingRunHold(deps.db, pushing));
|
|
1026
|
+
}
|
|
831
1027
|
}
|
|
832
1028
|
catch (err) {
|
|
833
1029
|
log.warn({ err, repository: key.repository, prNumber: key.prNumber }, "could not read the pull request's delegating run; reviewing as usual");
|
|
@@ -1022,11 +1218,14 @@ export async function routeHostEvent(event, deps) {
|
|
|
1022
1218
|
const budget = startBudget(BUNDLE_LOAD_DEADLINE_MS);
|
|
1023
1219
|
let taskOverride;
|
|
1024
1220
|
try {
|
|
1025
|
-
const {
|
|
1221
|
+
const { bundlePath, warning } = await resolveKnowledgeLocation(() => readKnowledgeConfig(host, event, budget));
|
|
1222
|
+
if (warning)
|
|
1223
|
+
log.warn({ repository: event.repository, after: event.after }, warning);
|
|
1224
|
+
const { concepts, complete } = await loadBundle(host, event, budget, bundlePath);
|
|
1026
1225
|
const scope = driftScope({
|
|
1027
1226
|
changedPaths: event.changedPaths,
|
|
1028
1227
|
changedPathsComplete: event.changedPathsComplete,
|
|
1029
|
-
bundlePath
|
|
1228
|
+
bundlePath,
|
|
1030
1229
|
concepts,
|
|
1031
1230
|
});
|
|
1032
1231
|
// Only the concepts the merge affects are checked, and only against a bundle that was fully read.
|
|
@@ -1034,7 +1233,7 @@ export async function routeHostEvent(event, deps) {
|
|
|
1034
1233
|
const citations = complete
|
|
1035
1234
|
? await verifyCitations(host, event, concepts.filter((c) => affected.has(c.path)), budget)
|
|
1036
1235
|
: new Map();
|
|
1037
|
-
taskOverride = mergeTaskText(event, scope, complete, citations);
|
|
1236
|
+
taskOverride = mergeTaskText(event, scope, complete, citations, bundlePath);
|
|
1038
1237
|
}
|
|
1039
1238
|
finally {
|
|
1040
1239
|
budget.clear();
|
|
@@ -1101,7 +1300,15 @@ export async function routeHostEvent(event, deps) {
|
|
|
1101
1300
|
const reviewers = reviewTargets(allowed.filter((l) => !l.waitForCi || startNow.has(l)));
|
|
1102
1301
|
const runIds = [...deferral.runIds];
|
|
1103
1302
|
if (reviewers.length > 0) {
|
|
1104
|
-
|
|
1303
|
+
// A coding run still in flight was already waited for (deferUntilRequest); should
|
|
1304
|
+
// recording that have failed, the head is reviewed as usual.
|
|
1305
|
+
const decision = await budgetDraftDecision(deps, host, event.repository, event.prNumber, event.headSha, readOrigin);
|
|
1306
|
+
if (decision.kind === "skip") {
|
|
1307
|
+
await postSkippedReviewChecks(deps, host, event.repository, event.prNumber, event.headSha, reviewers);
|
|
1308
|
+
}
|
|
1309
|
+
else {
|
|
1310
|
+
runIds.push(...(await startReviews(deps, host, event.repository, event.prNumber, event.headSha, reviewers, true)));
|
|
1311
|
+
}
|
|
1105
1312
|
}
|
|
1106
1313
|
return { runIds, followUps };
|
|
1107
1314
|
}
|
|
@@ -1109,11 +1316,16 @@ export async function routeHostEvent(event, deps) {
|
|
|
1109
1316
|
if (reviewerLinks.length === 0)
|
|
1110
1317
|
return none;
|
|
1111
1318
|
const runIds = [];
|
|
1319
|
+
// CI going green may be the last thing a pull request waited for (#287); evaluated
|
|
1320
|
+
// after the response (a host read per PR could otherwise exceed the webhook timeout).
|
|
1321
|
+
const followUps = event.prNumbers.map((prNumber) => async () => {
|
|
1322
|
+
await maybeMarkReady({ db: deps.db, hosts: deps.hosts, log }, event.repository, prNumber, event.provider);
|
|
1323
|
+
});
|
|
1112
1324
|
for (const prNumber of event.prNumbers) {
|
|
1113
1325
|
runIds.push(...(await rereviewAfterCi(deps, host, event, prNumber, reviewerLinks)));
|
|
1114
1326
|
runIds.push(...(await startDeferredAfterCi(deps, host, event, prNumber, reviewerLinks)));
|
|
1115
1327
|
}
|
|
1116
|
-
return { runIds, followUps
|
|
1328
|
+
return { runIds, followUps };
|
|
1117
1329
|
}
|
|
1118
1330
|
case "check_rerun": {
|
|
1119
1331
|
const owners = reviewerLinks.filter((l) => l.checkName === event.checkName);
|
|
@@ -1136,12 +1348,15 @@ export async function routeHostEvent(event, deps) {
|
|
|
1136
1348
|
const reviewCommand = event.isPullRequest && isReviewCommand(event.body, deps.mentionHandle);
|
|
1137
1349
|
const responderLink = links.find((l) => l.access === "write" && l.triggers.includes("mention"));
|
|
1138
1350
|
const candidates = reviewCommand ? reviewerLinks : responderLink ? [responderLink] : [];
|
|
1139
|
-
|
|
1351
|
+
// Explanations off and nothing to start: say nothing, and skip the author lookup.
|
|
1352
|
+
if (candidates.length === 0 && deps.mentionExplanations === false)
|
|
1140
1353
|
return none;
|
|
1141
1354
|
// H5-3: a mention drives a write-capable agent holding its owner's
|
|
1142
1355
|
// tools and secrets, so its author needs real push access to the
|
|
1143
1356
|
// repository (author_association, checked upstream, is only a
|
|
1144
|
-
// pre-filter). Checked by the author's immutable id.
|
|
1357
|
+
// pre-filter). Checked by the author's immutable id. Checked before
|
|
1358
|
+
// anything is said back: someone without write access gets no reply at
|
|
1359
|
+
// all, so a mention can never be used to probe what is linked here.
|
|
1145
1360
|
const author = await deps.repoAccess.authorizeHostUser({
|
|
1146
1361
|
provider: event.provider,
|
|
1147
1362
|
repository: event.repository,
|
|
@@ -1150,15 +1365,54 @@ export async function routeHostEvent(event, deps) {
|
|
|
1150
1365
|
});
|
|
1151
1366
|
if (!author.ok) {
|
|
1152
1367
|
log.info({ repository: event.repository, number: event.number, reason: author.reason, level: author.level }, "mention ignored: its author lacks write access");
|
|
1153
|
-
|
|
1368
|
+
// Someone who can read the repository gets told why; a stranger on a public repository (GitHub reports `read` for everyone) learns nothing.
|
|
1369
|
+
if (author.reason !== "insufficient_permission" || !explainsRefusal(author.level, event)) {
|
|
1370
|
+
return none;
|
|
1371
|
+
}
|
|
1372
|
+
const refuse = async () => {
|
|
1373
|
+
await host.acknowledge(event.repository, event.comment, "refused").catch((err) => {
|
|
1374
|
+
log.warn({ err, repository: event.repository, number: event.number }, "could not add the reaction");
|
|
1375
|
+
});
|
|
1376
|
+
await host
|
|
1377
|
+
.comment(event.repository, {
|
|
1378
|
+
number: event.number,
|
|
1379
|
+
body: NO_WRITE_ACCESS_BODY,
|
|
1380
|
+
...(event.replyToReviewCommentId ? { replyToReviewCommentId: event.replyToReviewCommentId } : {}),
|
|
1381
|
+
})
|
|
1382
|
+
.catch((err) => {
|
|
1383
|
+
log.warn({ err, repository: event.repository, number: event.number }, "could not post the refusal");
|
|
1384
|
+
});
|
|
1385
|
+
};
|
|
1386
|
+
return { runIds: [], followUps: [refuse] };
|
|
1154
1387
|
}
|
|
1388
|
+
// The author may use wardby here, so tell them why nothing started
|
|
1389
|
+
// instead of leaving the mention unanswered.
|
|
1390
|
+
const decline = (reason) => {
|
|
1391
|
+
log.info({ repository: event.repository, number: event.number, reason }, "mention declined");
|
|
1392
|
+
if (deps.mentionExplanations === false)
|
|
1393
|
+
return none;
|
|
1394
|
+
const reply = async () => {
|
|
1395
|
+
await host
|
|
1396
|
+
.comment(event.repository, {
|
|
1397
|
+
number: event.number,
|
|
1398
|
+
body: mentionDeclinedBody(reason),
|
|
1399
|
+
...(event.replyToReviewCommentId ? { replyToReviewCommentId: event.replyToReviewCommentId } : {}),
|
|
1400
|
+
})
|
|
1401
|
+
.catch((err) => {
|
|
1402
|
+
log.warn({ err, repository: event.repository, number: event.number }, "could not post the explanation");
|
|
1403
|
+
});
|
|
1404
|
+
};
|
|
1405
|
+
return { runIds: [], followUps: [reply] };
|
|
1406
|
+
};
|
|
1407
|
+
if (candidates.length === 0)
|
|
1408
|
+
return decline(reviewCommand ? "no_reviewer" : "no_responder");
|
|
1155
1409
|
const allowed = await authorizedLinks(deps, event, candidates);
|
|
1156
1410
|
if (allowed.length === 0)
|
|
1157
|
-
return
|
|
1411
|
+
return decline("agent_not_authorized");
|
|
1158
1412
|
if (reviewCommand) {
|
|
1159
1413
|
const head = await host.pullRequestHead(event.repository, event.number);
|
|
1160
1414
|
if (head.isFork || head.state !== "open")
|
|
1161
|
-
return
|
|
1415
|
+
return decline("pull_request_not_reviewable");
|
|
1162
1416
|
return {
|
|
1163
1417
|
runIds: await startReviews(deps, host, event.repository, event.number, head.headSha, reviewTargets(allowed)),
|
|
1164
1418
|
followUps: [react],
|
|
@@ -1183,9 +1437,15 @@ export async function routeHostEvent(event, deps) {
|
|
|
1183
1437
|
return { runIds: [], followUps: [react, reply] };
|
|
1184
1438
|
}
|
|
1185
1439
|
// Seeded from the PR's validated marker run: the request it belongs to. Stored state only.
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1440
|
+
// An issue mention is seeded from the issue's recorded pull requests instead.
|
|
1441
|
+
const siblings = event.isPullRequest
|
|
1442
|
+
? event.priorRunId
|
|
1443
|
+
? await openSiblings(deps.db, event.priorRunId, { repository: event.repository, number: event.number })
|
|
1444
|
+
: []
|
|
1445
|
+
: await openSiblingsForIssue(deps.db, {
|
|
1446
|
+
provider: "github",
|
|
1447
|
+
key: githubIssueKey(event.repository, event.number),
|
|
1448
|
+
});
|
|
1189
1449
|
const dispatched = await dispatchRun({
|
|
1190
1450
|
db: deps.db,
|
|
1191
1451
|
executor: deps.executor,
|
|
@@ -1195,7 +1455,11 @@ export async function routeHostEvent(event, deps) {
|
|
|
1195
1455
|
taskOverride: mentionTaskText(event, siblings),
|
|
1196
1456
|
attribution: event.isPullRequest
|
|
1197
1457
|
? await linkedPullRequestAttribution(deps.db, deps.issueTrackers, { codeProvider: host.provider, repository: event.repository, number: event.number }, RESPONSE_PATH_SNAPSHOT_BUDGET)
|
|
1198
|
-
:
|
|
1458
|
+
: // A mention on an issue is that issue's own run tree, like a Jira issue event's.
|
|
1459
|
+
{
|
|
1460
|
+
source: "issue_event",
|
|
1461
|
+
item: await resolveWorkItem(deps.db, deps.issueTrackers, "github", githubIssueKey(event.repository, event.number), RESPONSE_PATH_SNAPSHOT_BUDGET),
|
|
1462
|
+
},
|
|
1199
1463
|
// Where to report, written with the run: even if this instance dies
|
|
1200
1464
|
// before the follow-up below, the run's outcome still gets a comment.
|
|
1201
1465
|
afterPersist: async (tx, run) => {
|
|
@@ -9,10 +9,22 @@
|
|
|
9
9
|
* comment. Best effort throughout: nothing here throws.
|
|
10
10
|
*/
|
|
11
11
|
import type { Prisma, PrismaClient, Run, RunStatus } from "#prisma";
|
|
12
|
+
import { type RegistryRefusalSummary } from "../coding/registry/report.js";
|
|
13
|
+
import { type PackageAuditMode, type PackageAuditSummary } from "../coding/registry/audit-mode.js";
|
|
12
14
|
import type { CodeReviewHost, ReviewHostProvider, ReviewHostRegistry } from "../providers/review-host/types.js";
|
|
15
|
+
/** The most a GitHub follow-up comment holds, header and cut note included (GitHub's limit is 65,536). */
|
|
16
|
+
export declare const GITHUB_REPLY_MAX_CHARS = 60000;
|
|
17
|
+
/** The most follow-up comments a full reply is posted as; the rest is cut, and stays on the run. */
|
|
18
|
+
export declare const REPLY_MAX_PARTS = 4;
|
|
19
|
+
/**
|
|
20
|
+
* The most a Jira follow-up comment holds, header and cut note included. Jira Cloud's limit is 32,767
|
|
21
|
+
* characters, but it may apply to the serialized ADF body markdownToAdf produces rather than to this
|
|
22
|
+
* Markdown (unverified), and ADF's JSON is longer than the text; so keep a wide margin.
|
|
23
|
+
*/
|
|
24
|
+
export declare const JIRA_REPLY_MAX_CHARS = 15000;
|
|
13
25
|
/** The run statuses a run never leaves. */
|
|
14
26
|
export declare const TERMINAL_RUN_STATUSES: readonly RunStatus[];
|
|
15
|
-
export type HostStatusDb = Pick<PrismaClient, "runHostStatus" | "run">;
|
|
27
|
+
export type HostStatusDb = Pick<PrismaClient, "runHostStatus" | "run" | "runBudgetEvent" | "registryFetch" | "registryAuditRecord" | "issuePullRequest" | "codingRun">;
|
|
16
28
|
export type FinishedRun = Pick<Run, "id" | "status" | "finalText">;
|
|
17
29
|
/** The parts of a CodingRun result this comment uses. */
|
|
18
30
|
export interface PullRequestOutcome {
|
|
@@ -48,27 +60,96 @@ export declare function mentionStatusRow(provider: ReviewHostProvider, event: {
|
|
|
48
60
|
replyToReviewCommentId?: string;
|
|
49
61
|
}, runId: string): Prisma.RunHostStatusUncheckedCreateInput;
|
|
50
62
|
export declare function pullRequestOutcome(result: unknown): PullRequestOutcome | null;
|
|
63
|
+
/**
|
|
64
|
+
* The reply to post in full as follow-up comments, or null when the ordinary quote applies: only for a
|
|
65
|
+
* run that succeeded with no pull request and no failed sub-run, whose trimmed reply is longer than the
|
|
66
|
+
* status comment's quote holds.
|
|
67
|
+
*/
|
|
68
|
+
export declare function fullReplyOf(run: FinishedRun, pullRequests: PullRequestOutcome[], failedChildren: FailedChild[]): string | null;
|
|
69
|
+
/**
|
|
70
|
+
* Numbered comment bodies for a full reply: "**Reply, part i of n**" then the part, the last ending with
|
|
71
|
+
* the cut note when the reply did not fit in `maxParts`. Each body, header and note included, is at most
|
|
72
|
+
* `maxChars`. @-mentions are defused (splitReply).
|
|
73
|
+
*/
|
|
74
|
+
export declare function fullReplyComments(reply: string, opts: {
|
|
75
|
+
maxChars: number;
|
|
76
|
+
maxParts: number;
|
|
77
|
+
}): string[];
|
|
78
|
+
type RefusalOutcome = {
|
|
79
|
+
pullRequests: readonly PullRequestOutcome[];
|
|
80
|
+
failedChildren: readonly FailedChild[];
|
|
81
|
+
packageRefusals?: readonly RegistryRefusalSummary[];
|
|
82
|
+
noChanges?: boolean;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* The refusals that can block the run: all of them when a coding sub-run failed, otherwise all but
|
|
86
|
+
* listing-only ones, which the installer may only have looked at (see LISTING_REFUSAL_FILENAME).
|
|
87
|
+
*/
|
|
88
|
+
export declare function blockingRefusals(outcome: Omit<RefusalOutcome, "noChanges">): RegistryRefusalSummary[];
|
|
89
|
+
/**
|
|
90
|
+
* Whether package refusals blocked the run: it succeeded, but nothing reached a pull request, a coding
|
|
91
|
+
* sub-run made no changes or failed, and packages were refused (blockingRefusals). The GitHub and Jira
|
|
92
|
+
* status comments and the Slack `run_blocked` event all use it, so they always agree.
|
|
93
|
+
*/
|
|
94
|
+
export declare function isBlockedByRefusals(run: Pick<FinishedRun, "status">, outcome: RefusalOutcome): boolean;
|
|
51
95
|
export declare function outcomeBody(run: FinishedRun, repository: string, pullRequests: PullRequestOutcome[], failedChildren?: FailedChild[], opts?: {
|
|
96
|
+
packageRefusals?: RegistryRefusalSummary[];
|
|
97
|
+
noChanges?: boolean;
|
|
52
98
|
budgetSentence?: string;
|
|
99
|
+
/** The run came from an issue (GitHub or Jira): a budget-stopped draft can be continued from the issue too. */
|
|
100
|
+
fromIssue?: boolean;
|
|
53
101
|
noPullRequestText?: string;
|
|
54
102
|
/** The agent's reply IS the answer (no separate reply comment): shown as written, not quoted. */
|
|
55
103
|
replyAsAnswer?: boolean;
|
|
104
|
+
/**
|
|
105
|
+
* The caller posts the full reply as follow-up comments when fullReplyOf is not null (see
|
|
106
|
+
* completeHostStatus): the ✅ no-pull-request body then points to them instead of quoting the reply.
|
|
107
|
+
*/
|
|
108
|
+
fullReplyFollows?: boolean;
|
|
109
|
+
/** The status comment is in a review thread, so the follow-ups land in the conversation instead. */
|
|
110
|
+
statusInThread?: boolean;
|
|
111
|
+
/** Package audit mode on any coding sub-run: a short block above the run line, whatever the outcome. */
|
|
112
|
+
packageAudit?: {
|
|
113
|
+
mode: PackageAuditMode;
|
|
114
|
+
summary: PackageAuditSummary;
|
|
115
|
+
};
|
|
56
116
|
}): string;
|
|
117
|
+
/** Package audit mode on a run's coding sub-runs: the strongest mode, and what it recorded across them. */
|
|
118
|
+
export type PackageAuditOutcome = {
|
|
119
|
+
mode: PackageAuditMode;
|
|
120
|
+
summary: PackageAuditSummary;
|
|
121
|
+
};
|
|
122
|
+
/** A run's package audit alone, for a run whose other outcome is not read (one that did not succeed). */
|
|
123
|
+
export declare function collectPackageAudit(db: Pick<PrismaClient, "run" | "registryAuditRecord">, runId: string): Promise<PackageAuditOutcome | undefined>;
|
|
57
124
|
/** What collectRunOutcome reads: a run's children and, when out of budget, its budget facts. */
|
|
58
|
-
export type RunOutcomeDb = Pick<PrismaClient, "run">;
|
|
125
|
+
export type RunOutcomeDb = Pick<PrismaClient, "run" | "runBudgetEvent" | "registryFetch" | "registryAuditRecord">;
|
|
59
126
|
/** The parts of a finished run's outcome a status comment reports; shared by GitHub and Jira status comments. */
|
|
60
127
|
export declare function collectRunOutcome(db: RunOutcomeDb, run: FinishedRun): Promise<{
|
|
61
128
|
pullRequests: PullRequestOutcome[];
|
|
62
129
|
failedChildren: FailedChild[];
|
|
130
|
+
packageRefusals: RegistryRefusalSummary[];
|
|
131
|
+
noChanges: boolean;
|
|
63
132
|
budgetSentence?: string;
|
|
133
|
+
packageAudit?: PackageAuditOutcome;
|
|
64
134
|
}>;
|
|
135
|
+
/**
|
|
136
|
+
* Whether a mention run's stored task is a mention on GitHub issue `number`
|
|
137
|
+
* of `repository`, not on a pull request. Read from the task's header block
|
|
138
|
+
* (mentionTaskText's "[GitHub issue #n…]" then "Repository: …"), which only
|
|
139
|
+
* wardby writes: the first section that opens with "[GitHub " is that header
|
|
140
|
+
* (any continuation hints before it are wardby's too), and everything a
|
|
141
|
+
* person wrote comes after it, so a comment cannot pass for an issue header.
|
|
142
|
+
* A review fix round's header names a PR.
|
|
143
|
+
*/
|
|
144
|
+
export declare function isIssueMentionTask(taskOverride: string | null, repository: string, number: number): boolean;
|
|
65
145
|
/**
|
|
66
146
|
* Writes a finished run's outcome to its status comment and marks it
|
|
67
147
|
* complete: edits the comment when it exists; when it does not yet, posts the
|
|
68
148
|
* outcome as a new comment only if `postIfMissing` (the reconciler, well after
|
|
69
149
|
* the run ended), and otherwise leaves the row for postMentionStatus, which
|
|
70
150
|
* is about to post it. A failed host call leaves the row open for the
|
|
71
|
-
* reconciler to retry.
|
|
151
|
+
* reconciler to retry. The row is then claimed (completed) in one step, and
|
|
152
|
+
* only the claiming call posts a full reply's follow-up comments.
|
|
72
153
|
*/
|
|
73
154
|
export declare function completeHostStatus(db: HostStatusDb, run: FinishedRun, hosts: ReviewHostRegistry | undefined, opts?: {
|
|
74
155
|
postIfMissing?: boolean;
|
|
@@ -81,3 +162,4 @@ export declare function completeHostStatus(db: HostStatusDb, run: FinishedRun, h
|
|
|
81
162
|
* already complete. Never throws.
|
|
82
163
|
*/
|
|
83
164
|
export declare function postMentionStatus(db: HostStatusDb, host: CodeReviewHost, runId: string, hosts: ReviewHostRegistry | undefined, heading?: string): Promise<void>;
|
|
165
|
+
export {};
|