@wardby/cli 0.5.3 → 0.6.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 +33 -0
- package/README.md +25 -14
- package/dist/claude-coding-worker/context.d.ts +22 -0
- package/dist/claude-coding-worker/context.js +92 -0
- package/dist/claude-coding-worker/driver.d.ts +7 -1
- package/dist/claude-coding-worker/driver.js +38 -5
- package/dist/claude-coding-worker/sdk.js +13 -4
- package/dist/cli-help.d.ts +1 -1
- package/dist/cli-help.js +5 -2
- package/dist/cli-native-mode.d.ts +9 -0
- package/dist/cli-native-mode.js +20 -0
- package/dist/cli.d.ts +3 -1
- package/dist/cli.js +141 -5
- package/dist/coding/claude-context.d.ts +45 -0
- package/dist/coding/claude-context.js +434 -0
- package/dist/coding/profile.d.ts +12 -0
- package/dist/coding/profile.js +6 -0
- package/dist/coding/protocol.d.ts +104 -0
- package/dist/coding/protocol.js +87 -3
- package/dist/coding-worker/artifact.d.ts +8 -0
- package/dist/coding-worker/artifact.js +2 -2
- package/dist/coding-worker/driver.js +2 -0
- package/dist/coding-worker/sdk.d.ts +6 -0
- package/dist/coding-worker/sdk.js +1 -0
- package/dist/coding-worker/skills.d.ts +23 -0
- package/dist/coding-worker/skills.js +117 -0
- package/dist/coding-worker/types.d.ts +2 -0
- package/dist/config/github-allowed-accounts.d.ts +15 -0
- package/dist/config/github-allowed-accounts.js +36 -0
- package/dist/config/low-power.d.ts +12 -0
- package/dist/config/low-power.js +18 -0
- package/dist/config/mobile.d.ts +12 -0
- package/dist/config/mobile.js +18 -0
- package/dist/config/providers.d.ts +53 -0
- package/dist/config/providers.js +92 -6
- package/dist/core/db.d.ts +16 -6
- package/dist/core/db.js +12 -10
- package/dist/core/dispatch.d.ts +11 -0
- package/dist/core/dispatch.js +36 -1
- package/dist/core/engine-native.js +9 -5
- package/dist/core/host-events.d.ts +49 -3
- package/dist/core/host-events.js +289 -15
- package/dist/core/issue-bridge.js +42 -2
- package/dist/core/issue-events.js +12 -1
- package/dist/core/issue-status.js +14 -3
- package/dist/core/merge-order-check.d.ts +129 -0
- package/dist/core/merge-order-check.js +336 -0
- package/dist/core/notification-dispatcher.d.ts +70 -0
- package/dist/core/notification-dispatcher.js +368 -0
- package/dist/core/notification-templates.d.ts +25 -0
- package/dist/core/notification-templates.js +105 -0
- package/dist/core/notifications.d.ts +10 -0
- package/dist/core/notifications.js +38 -0
- package/dist/core/pg-auth.d.ts +22 -0
- package/dist/core/pg-auth.js +152 -0
- package/dist/core/power-composition.d.ts +16 -0
- package/dist/core/power-composition.js +37 -0
- package/dist/core/power-idle.d.ts +14 -0
- package/dist/core/power-idle.js +30 -0
- package/dist/core/power.d.ts +71 -0
- package/dist/core/power.js +202 -0
- package/dist/core/reconciler.d.ts +4 -2
- package/dist/core/reconciler.js +29 -5
- package/dist/core/related-pull-requests.d.ts +48 -4
- package/dist/core/related-pull-requests.js +113 -11
- package/dist/core/repo-access.d.ts +15 -0
- package/dist/core/repo-access.js +66 -0
- package/dist/core/review-fix.d.ts +37 -0
- package/dist/core/review-fix.js +207 -6
- package/dist/core/review-host-tools.d.ts +20 -0
- package/dist/core/review-host-tools.js +58 -2
- package/dist/core/runner.d.ts +336 -3
- package/dist/core/runner.js +894 -317
- package/dist/core/secret-broker-config.d.ts +103 -0
- package/dist/core/secret-broker-config.js +112 -0
- package/dist/core/secrets.d.ts +39 -4
- package/dist/core/secrets.js +148 -40
- package/dist/core/workflow-event-recorder.d.ts +14 -0
- package/dist/core/workflow-event-recorder.js +120 -0
- package/dist/core/workflow-events.d.ts +82 -0
- package/dist/core/workflow-events.js +44 -0
- package/dist/core/workflow-run-events.d.ts +16 -0
- package/dist/core/workflow-run-events.js +40 -0
- package/dist/generated/prisma/browser.d.ts +58 -0
- package/dist/generated/prisma/client.d.ts +58 -0
- package/dist/generated/prisma/commonInputTypes.d.ts +150 -0
- package/dist/generated/prisma/enums.d.ts +27 -0
- package/dist/generated/prisma/enums.js +23 -0
- package/dist/generated/prisma/internal/class.d.ts +88 -0
- package/dist/generated/prisma/internal/class.js +4 -4
- package/dist/generated/prisma/internal/prismaNamespace.d.ts +772 -1
- package/dist/generated/prisma/internal/prismaNamespace.js +135 -4
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.d.ts +139 -0
- package/dist/generated/prisma/internal/prismaNamespaceBrowser.js +135 -4
- package/dist/generated/prisma/models/Agent.d.ts +360 -1
- package/dist/generated/prisma/models/CodingAgentProfile.d.ts +73 -1
- package/dist/generated/prisma/models/CodingRun.d.ts +205 -1
- package/dist/generated/prisma/models/DeferredReview.d.ts +78 -1
- package/dist/generated/prisma/models/NativeGatewayCall.d.ts +1675 -0
- package/dist/generated/prisma/models/NativeGatewayCall.js +1 -0
- package/dist/generated/prisma/models/NativeGatewaySession.d.ts +1517 -0
- package/dist/generated/prisma/models/NativeGatewaySession.js +1 -0
- package/dist/generated/prisma/models/NativeWarmWorker.d.ts +1296 -0
- package/dist/generated/prisma/models/NativeWarmWorker.js +1 -0
- package/dist/generated/prisma/models/NotificationChannel.d.ts +1543 -0
- package/dist/generated/prisma/models/NotificationChannel.js +1 -0
- package/dist/generated/prisma/models/NotificationDelivery.d.ts +1502 -0
- package/dist/generated/prisma/models/NotificationDelivery.js +1 -0
- package/dist/generated/prisma/models/NotificationThread.d.ts +1090 -0
- package/dist/generated/prisma/models/NotificationThread.js +1 -0
- package/dist/generated/prisma/models/Run.d.ts +826 -1
- package/dist/generated/prisma/models/RunHostCheck.d.ts +36 -1
- package/dist/generated/prisma/models/Secret.d.ts +37 -1
- package/dist/generated/prisma/models/SecretBrokerChange.d.ts +1101 -0
- package/dist/generated/prisma/models/SecretBrokerChange.js +1 -0
- package/dist/generated/prisma/models/WorkflowEvent.d.ts +1422 -0
- package/dist/generated/prisma/models/WorkflowEvent.js +1 -0
- package/dist/generated/prisma/models.d.ts +8 -0
- package/dist/help/build.js +4 -2
- package/dist/help/catalog.d.ts +1 -1
- package/dist/help/catalog.js +31 -6
- package/dist/help-index.json +1363 -176
- package/dist/import/create.js +17 -0
- package/dist/import/neutral-schema.d.ts +6 -2
- package/dist/import/neutral-schema.js +2 -0
- package/dist/mcp/auth/access.d.ts +1 -0
- package/dist/mcp/auth/repo-authorization.js +14 -0
- package/dist/mcp/auth/resource-server.d.ts +2 -1
- package/dist/mcp/auth/resource-server.js +7 -2
- package/dist/mcp/auth/self-hosted/browser.d.ts +1 -1
- package/dist/mcp/auth/self-hosted/browser.js +19 -6
- package/dist/mcp/context.d.ts +6 -0
- package/dist/mcp/host-events/github-ingress.d.ts +23 -1
- package/dist/mcp/host-events/github-ingress.js +68 -0
- package/dist/mcp/index.d.ts +13 -0
- package/dist/mcp/index.js +59 -10
- package/dist/mcp/tools/agents.js +82 -11
- package/dist/mcp/tools/notification-channels.d.ts +2 -0
- package/dist/mcp/tools/notification-channels.js +293 -0
- package/dist/mcp/tools/power.d.ts +2 -0
- package/dist/mcp/tools/power.js +77 -0
- package/dist/mcp/tools/runs.d.ts +0 -6
- package/dist/mcp/tools/runs.js +7 -2
- package/dist/mcp/tools/secret-broker-compat.d.ts +12 -0
- package/dist/mcp/tools/secret-broker-compat.js +23 -0
- package/dist/mcp/tools/secret-elicitation-form.d.ts +22 -2
- package/dist/mcp/tools/secret-elicitation-form.js +200 -10
- package/dist/mcp/tools/secret-elicitation-server.js +8 -1
- package/dist/mcp/tools/secret-elicitation.d.ts +38 -3
- package/dist/mcp/tools/secret-elicitation.js +110 -12
- package/dist/mcp/tools/secrets.js +184 -7
- package/dist/mcp/tools/tools.d.ts +1 -1
- package/dist/mcp/tools/tools.js +22 -2
- package/dist/native-worker/composition.d.ts +23 -0
- package/dist/native-worker/composition.js +77 -0
- package/dist/native-worker/docker-isolation.d.ts +65 -0
- package/dist/native-worker/docker-isolation.js +183 -0
- package/dist/native-worker/docker-launcher.d.ts +74 -0
- package/dist/native-worker/docker-launcher.js +237 -0
- package/dist/native-worker/gateway-server.d.ts +39 -0
- package/dist/native-worker/gateway-server.js +315 -0
- package/dist/native-worker/gateway.d.ts +44 -0
- package/dist/native-worker/gateway.js +197 -0
- package/dist/native-worker/http-server.d.ts +22 -0
- package/dist/native-worker/http-server.js +109 -0
- package/dist/native-worker/http-transport.d.ts +17 -0
- package/dist/native-worker/http-transport.js +88 -0
- package/dist/native-worker/kubernetes-isolation.d.ts +90 -0
- package/dist/native-worker/kubernetes-isolation.js +218 -0
- package/dist/native-worker/kubernetes-launcher.d.ts +102 -0
- package/dist/native-worker/kubernetes-launcher.js +335 -0
- package/dist/native-worker/launch.d.ts +45 -0
- package/dist/native-worker/launch.js +44 -0
- package/dist/native-worker/ledger.d.ts +109 -0
- package/dist/native-worker/ledger.js +192 -0
- package/dist/native-worker/loopback.d.ts +12 -0
- package/dist/native-worker/loopback.js +49 -0
- package/dist/native-worker/main.d.ts +7 -0
- package/dist/native-worker/main.js +74 -0
- package/dist/native-worker/protocol.d.ts +744 -0
- package/dist/native-worker/protocol.js +200 -0
- package/dist/native-worker/sandbox-executor.d.ts +68 -0
- package/dist/native-worker/sandbox-executor.js +210 -0
- package/dist/native-worker/stdio.d.ts +29 -0
- package/dist/native-worker/stdio.js +188 -0
- package/dist/native-worker/warm-delivery.d.ts +16 -0
- package/dist/native-worker/warm-delivery.js +33 -0
- package/dist/native-worker/warm-pool-ledger.d.ts +39 -0
- package/dist/native-worker/warm-pool-ledger.js +73 -0
- package/dist/native-worker/warm-pool.d.ts +107 -0
- package/dist/native-worker/warm-pool.js +283 -0
- package/dist/native-worker/worker.d.ts +17 -0
- package/dist/native-worker/worker.js +115 -0
- package/dist/providers/auth/authorization-server.d.ts +3 -0
- package/dist/providers/auth/index.js +2 -0
- package/dist/providers/auth/self-hosted.d.ts +13 -1
- package/dist/providers/auth/self-hosted.js +54 -4
- package/dist/providers/chat/fake.d.ts +46 -0
- package/dist/providers/chat/fake.js +39 -0
- package/dist/providers/chat/index.d.ts +4 -0
- package/dist/providers/chat/index.js +8 -0
- package/dist/providers/chat/slack.d.ts +37 -0
- package/dist/providers/chat/slack.js +105 -0
- package/dist/providers/chat/types.d.ts +42 -0
- package/dist/providers/chat/types.js +19 -0
- package/dist/providers/engine/types.d.ts +19 -0
- package/dist/providers/engine/types.js +22 -0
- package/dist/providers/executor/composition.d.ts +24 -1
- package/dist/providers/executor/composition.js +39 -6
- package/dist/providers/executor/container.d.ts +24 -1
- package/dist/providers/executor/container.js +101 -11
- package/dist/providers/executor/dbos.d.ts +42 -0
- package/dist/providers/executor/dbos.js +118 -12
- package/dist/providers/executor/deferred.d.ts +56 -0
- package/dist/providers/executor/deferred.js +119 -0
- package/dist/providers/executor/routing.d.ts +37 -10
- package/dist/providers/executor/routing.js +73 -32
- package/dist/providers/executor/types.d.ts +12 -0
- package/dist/providers/jobs/docker.js +3 -3
- package/dist/providers/jobs/fake-kubernetes-api.d.ts +21 -2
- package/dist/providers/jobs/fake-kubernetes-api.js +42 -1
- package/dist/providers/jobs/kubernetes-api.d.ts +17 -1
- package/dist/providers/jobs/kubernetes-api.js +7 -0
- package/dist/providers/jobs/kubernetes-client.d.ts +10 -1
- package/dist/providers/jobs/kubernetes-client.js +52 -3
- package/dist/providers/jobs/kubernetes-dry-run-fixture.d.ts +6 -1
- package/dist/providers/jobs/kubernetes-dry-run-fixture.js +6 -3
- package/dist/providers/jobs/kubernetes-isolation.d.ts +3 -1
- package/dist/providers/jobs/kubernetes-isolation.js +6 -0
- package/dist/providers/jobs/kubernetes-platform.d.ts +4 -1
- package/dist/providers/jobs/kubernetes-platform.js +38 -1
- package/dist/providers/jobs/kubernetes-preflight.d.ts +2 -1
- package/dist/providers/jobs/kubernetes-preflight.js +4 -2
- package/dist/providers/jobs/kubernetes.d.ts +36 -1
- package/dist/providers/jobs/kubernetes.js +74 -4
- package/dist/providers/jobs/metadata-probes.d.ts +11 -0
- package/dist/providers/jobs/metadata-probes.js +13 -0
- package/dist/providers/jobs/types.d.ts +9 -0
- package/dist/providers/review-host/github.d.ts +11 -1
- package/dist/providers/review-host/github.js +50 -0
- package/dist/providers/review-host/types.d.ts +23 -0
- package/dist/providers/vcs/github.d.ts +32 -6
- package/dist/providers/vcs/github.js +74 -16
- package/dist/quickstart/coding-seed.d.ts +10 -3
- package/dist/quickstart/coding-seed.js +74 -3
- package/dist/quickstart/images.d.ts +2 -0
- package/dist/quickstart/images.js +7 -1
- package/dist/quickstart/reviewer-prompt.d.ts +1 -1
- package/dist/quickstart/reviewer-prompt.js +1 -1
- package/dist/quickstart-images.json +1 -1
- package/dist/sandbox/brokered-fetch.d.ts +23 -0
- package/dist/sandbox/brokered-fetch.js +37 -0
- package/dist/sandbox/host-functions.d.ts +34 -0
- package/dist/sandbox/host-functions.js +144 -80
- package/dist/sandbox/prelude.js +7 -1
- package/dist/sandbox/run-in-sandbox.d.ts +19 -0
- package/dist/sandbox/run-in-sandbox.js +28 -10
- package/dist/sandbox/safe-fetch.d.ts +2 -0
- package/dist/sandbox/safe-fetch.js +3 -1
- package/dist/sandbox/secret-broker-sigv4.d.ts +2 -0
- package/dist/sandbox/secret-broker-sigv4.js +49 -0
- package/dist/sandbox/secret-broker.d.ts +34 -0
- package/dist/sandbox/secret-broker.js +162 -0
- package/dist/sandbox/user-tool.d.ts +14 -0
- package/dist/sandbox/user-tool.js +32 -0
- package/dist/serve.js +18 -0
- package/dist/viewer/api-schema.d.ts +210 -14
- package/dist/viewer/api-schema.js +22 -0
- package/dist/viewer/build-schemas.js +4 -1
- package/dist/viewer/event-bus.d.ts +6 -0
- package/dist/viewer/event-bus.js +16 -7
- package/dist/viewer/graph.d.ts +5 -2
- package/dist/viewer/graph.js +7 -2
- package/dist/viewer/http.d.ts +0 -1
- package/dist/viewer/http.js +2 -2
- package/dist/viewer/infra.js +25 -2
- package/dist/viewer/limits.d.ts +4 -0
- package/dist/viewer/limits.js +4 -0
- package/dist/viewer/openapi.d.ts +15 -0
- package/dist/viewer/openapi.js +172 -0
- package/docs/README.md +7 -0
- package/docs/agent-recipes.md +57 -8
- package/docs/architecture-runtime.md +16 -1
- package/docs/code-review-agents.md +139 -5
- package/docs/coding-agent-setup.md +113 -5
- package/docs/coding-packages.md +4 -2
- package/docs/coding-services.md +3 -1
- package/docs/coding-worker-byo-images.md +198 -6
- package/docs/coding-worker-isolation.md +68 -14
- package/docs/getting-started-gke.md +225 -9
- package/docs/getting-started-identity-provider.md +21 -10
- package/docs/getting-started.md +5 -4
- package/docs/jira-agents.md +5 -1
- package/docs/native-sandbox.md +635 -0
- package/docs/release-verification.md +9 -0
- package/docs/security-deployment.md +113 -12
- package/docs/slack-notifications.md +252 -0
- package/docs/tool-secrets.md +252 -0
- package/docs/viewer-api.md +46 -5
- package/docs/viewer-api.openapi.yml +1404 -0
- package/help/admin-viewer.md +6 -2
- package/help/agent-recipes.md +27 -0
- package/help/architecture-agent.md +1 -1
- package/help/brokered-secrets.md +79 -0
- package/help/build-claude-code-image.md +131 -0
- package/help/build-worker-image.md +3 -6
- package/help/code-review-agents.md +68 -6
- package/help/deploy-gke.md +8 -1
- package/help/deployment-targets.md +25 -14
- package/help/errors/coding-provider-not-configured.md +2 -2
- package/help/errors/database-auth-invalid.md +28 -0
- package/help/errors/github-account-not-allowed.md +25 -0
- package/help/errors/low-power-disabled.md +29 -0
- package/help/errors/low-power-scale-forbidden.md +35 -0
- package/help/errors/low-power-wake-timeout.md +30 -0
- package/help/errors/mobile-disabled.md +31 -0
- package/help/errors/native-sandbox-capacity.md +22 -0
- package/help/errors/native-sandbox-deadline-exceeded.md +19 -0
- package/help/errors/native-sandbox-docker-failed.md +20 -0
- package/help/errors/native-sandbox-gateway-unavailable.md +21 -0
- package/help/errors/native-sandbox-image-not-pinned.md +19 -0
- package/help/errors/native-sandbox-isolation-mismatch.md +20 -0
- package/help/errors/native-sandbox-network-unenforced.md +22 -0
- package/help/errors/native-sandbox-requires-catalog.md +31 -0
- package/help/errors/native-sandbox-unavailable.md +19 -0
- package/help/errors/native-sandbox-warm-delivery-failed.md +21 -0
- package/help/errors/native-sandbox-worker-exited.md +20 -0
- package/help/errors/native-sandbox-worker-lost.md +20 -0
- package/help/errors/native-sandbox-worker-unready.md +22 -0
- package/help/errors/secret-broker-body-invalid.md +26 -0
- package/help/errors/secret-broker-changed.md +20 -0
- package/help/errors/secret-broker-config-invalid.md +30 -0
- package/help/errors/secret-broker-conflict.md +27 -0
- package/help/errors/secret-broker-destination-denied.md +28 -0
- package/help/errors/secret-broker-value-invalid.md +28 -0
- package/help/errors/secret-brokered.md +24 -0
- package/help/errors/secret-not-brokered.md +25 -0
- package/help/errors/slack-auth-failed.md +48 -0
- package/help/errors/slack-channel-unreachable.md +39 -0
- package/help/errors/slack-not-configured.md +33 -0
- package/help/getting-started.md +4 -5
- package/help/github.md +18 -1
- package/help/identity-and-access.md +5 -1
- package/help/local-repositories.md +2 -3
- package/help/low-power-mode.md +125 -0
- package/help/merge-order-check.md +117 -0
- package/help/mobile-app.md +54 -0
- package/help/native-sandbox.md +136 -0
- package/help/observability.md +8 -0
- package/help/related-pull-requests.md +70 -9
- package/help/repo-instructions-and-skills.md +91 -0
- package/help/review-fix-rounds.md +10 -0
- package/help/slack-notifications.md +62 -0
- package/help/troubleshooting/coding-workers.md +21 -0
- package/package.json +11 -4
- package/prisma/migrations/20261009000003_native_execution_mode/migration.sql +12 -0
- package/prisma/migrations/20261009000004_native_gateway_ledger/migration.sql +65 -0
- package/prisma/migrations/20261009000005_native_gateway_call_child_agent/migration.sql +5 -0
- package/prisma/migrations/20261009000006_run_deferred_start_stop/migration.sql +14 -0
- package/prisma/migrations/20261009000007_native_gateway_network_ready/migration.sql +5 -0
- package/prisma/migrations/20261010000001_workflow_notifications/migration.sql +99 -0
- package/prisma/migrations/20261011000001_native_gateway_session_status_index/migration.sql +2 -0
- package/prisma/migrations/20261012000001_native_warm_worker/migration.sql +32 -0
- package/prisma/migrations/20261013000001_coding_run_merge_order/migration.sql +2 -0
- package/prisma/migrations/20261013000001_secret_broker/migration.sql +17 -0
- package/prisma/migrations/20261013000002_deferred_review_request/migration.sql +4 -0
- package/prisma/migrations/20261014000000_repo_skills/migration.sql +15 -0
- package/prisma/migrations/20261015000001_coding_run_merge_order_index/migration.sql +2 -0
- package/prisma/migrations/20261015000002_no_change_rereview/migration.sql +2 -0
- package/prisma/schema.prisma +362 -91
|
@@ -104,8 +104,8 @@ JOB_LAUNCHER=docker
|
|
|
104
104
|
folder as missing. The machine needs git 2.24 or newer.
|
|
105
105
|
- **Worker images.** Use worker images from the same release as the control
|
|
106
106
|
plane. An older worker image rejects `local:` repositories (the run fails with
|
|
107
|
-
`worker_input_failed`), including a bring-your-own
|
|
108
|
-
which must be rebuilt on a current driver image.
|
|
107
|
+
`worker_input_failed`), including a Codex agent's bring-your-own
|
|
108
|
+
`workerImageRef` image, which must be rebuilt on a current driver image.
|
|
109
109
|
|
|
110
110
|
### What a coding run does
|
|
111
111
|
|
|
@@ -146,9 +146,9 @@ The server selects the image from `CODING_WORKER_IMAGE_NODE_PYTHON_3_12`
|
|
|
146
146
|
at its committed root; see
|
|
147
147
|
[Python projects](getting-started.md#python-projects).
|
|
148
148
|
|
|
149
|
-
For any other language,
|
|
150
|
-
|
|
151
|
-
Claude Code
|
|
149
|
+
For any other language, use `codingProfile.workerImageRef` (admin only). It is
|
|
150
|
+
a custom image for the container that runs the agent's commands, for Codex and
|
|
151
|
+
for Claude Code; see [Bring-your-own worker images](coding-worker-byo-images.md).
|
|
152
152
|
|
|
153
153
|
### Review agents
|
|
154
154
|
|
|
@@ -219,6 +219,8 @@ GITHUB_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVA
|
|
|
219
219
|
`npm run claude:images:local` builds the Claude agent image and both tool-runner
|
|
220
220
|
images (`wardby-claude-tool-runner:phase5`, and
|
|
221
221
|
`wardby-claude-tool-runner:phase5-node-python` for the `node-python` toolchain).
|
|
222
|
+
It also builds `wardby-claude-tool-runner-custom:phase5`, a test-only custom
|
|
223
|
+
tool runner that `npm run test:claude-docker` needs.
|
|
222
224
|
This local, immutable-`sha256:` ID form of the `CODING_CLAUDE_*` images is only
|
|
223
225
|
accepted by the Docker launcher.
|
|
224
226
|
`JOB_LAUNCHER=kubernetes` needs both images pushed to a registry and set as
|
|
@@ -262,6 +264,112 @@ See [release verification](release-verification.md) for the complete gate.
|
|
|
262
264
|
If the repository has `docs/knowledge/index.md`, every coding run's prompt
|
|
263
265
|
includes it. See [Architecture knowledge bundles](knowledge.md).
|
|
264
266
|
|
|
267
|
+
## Repository instructions
|
|
268
|
+
|
|
269
|
+
Every coding run loads the repository's own instructions; there is no
|
|
270
|
+
`codingProfile` setting to turn this off. Codex reads the repository's
|
|
271
|
+
`AGENTS.md` itself, directly from the checkout. Claude Code is handed
|
|
272
|
+
`CLAUDE.md`, `.claude/CLAUDE.md`, and whatever either file pulls in with
|
|
273
|
+
`@path` imports, up to 5 import levels deep; a repository that only has
|
|
274
|
+
`AGENTS.md` gets a one-line `CLAUDE.md` that imports it, so a repository
|
|
275
|
+
written for another coding agent still has its instructions in Claude Code.
|
|
276
|
+
Subdirectory `CLAUDE.md` files (anything other than the repository root and
|
|
277
|
+
`.claude/CLAUDE.md`) are not loaded unless an imported file pulls them in.
|
|
278
|
+
|
|
279
|
+
Claude Code's instructions and skills are read from the checkout and bounded:
|
|
280
|
+
at most 64 KiB per file, 200 files, and 256 KiB combined; symlinks and
|
|
281
|
+
non-UTF-8 files are refused. A file that doesn't pass, or that would push
|
|
282
|
+
the run's input past its 512 KiB size limit once encoded (skills and the
|
|
283
|
+
deepest imports are dropped first), is left out and logged as
|
|
284
|
+
`coding.claude_context_skipped` (the first 50 individually, then one
|
|
285
|
+
aggregate line with an overflow count); when the repository's context can't
|
|
286
|
+
be read at all, the run continues without it and logs
|
|
287
|
+
`coding.claude_context_unavailable`. A run never fails because its
|
|
288
|
+
repository context couldn't be loaded.
|
|
289
|
+
|
|
290
|
+
Claude Code never receives the repository's `.claude/settings.json`, hooks,
|
|
291
|
+
`.mcp.json`, agents, or commands — only Markdown instruction files and
|
|
292
|
+
`.claude/skills/<name>/SKILL.md` files pass the allowlist, whatever an
|
|
293
|
+
instruction file imports. Repository instructions and skills are untrusted
|
|
294
|
+
guidance: they can shape a run's work but never relax the worker's sandbox
|
|
295
|
+
rules.
|
|
296
|
+
|
|
297
|
+
## Claude Code loading mode
|
|
298
|
+
|
|
299
|
+
`codingProfile.claudeBareMode` controls how Claude Code uses the repository
|
|
300
|
+
instructions above. It defaults to `true` and only affects Claude Code
|
|
301
|
+
agents.
|
|
302
|
+
|
|
303
|
+
- **`true` (default, bare mode).** Claude Code keeps its hardened bare mode.
|
|
304
|
+
Wardby adds the repository's instruction files to the system prompt in
|
|
305
|
+
full, and lists each skill by name, description, and path; the model reads
|
|
306
|
+
a skill's full `SKILL.md` itself with `run_command`.
|
|
307
|
+
- **`false`.** Bare mode is off. Claude Code loads `CLAUDE.md` and skills
|
|
308
|
+
itself, through its native Skill tool, instead of reading them from the
|
|
309
|
+
system prompt. Repository settings, hooks, MCP configuration, agents, and
|
|
310
|
+
commands are still never loaded in either mode; native loading also locks
|
|
311
|
+
Claude Code's own hooks to wardby's managed set.
|
|
312
|
+
|
|
313
|
+
If the worker can't write the native-mode context to disk for a run, that
|
|
314
|
+
run falls back to bare mode instead of failing, and the worker logs a
|
|
315
|
+
`claude_context_unavailable` warning.
|
|
316
|
+
|
|
317
|
+
The agent owner or an admin can change it:
|
|
318
|
+
|
|
319
|
+
```json
|
|
320
|
+
{ "id": "<agent-id>", "codingProfile": { "claudeBareMode": false } }
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
## Repository skills
|
|
324
|
+
|
|
325
|
+
`codingProfile.repoSkills` loads the repository's own agent skills into a
|
|
326
|
+
run. It defaults to `true`.
|
|
327
|
+
|
|
328
|
+
| Builder | Reads skills from | `repoSkills: true` (default) | `repoSkills: false` |
|
|
329
|
+
| ----------- | ----------------------------------- | --------------------------------------------------- | ---------------------------------- |
|
|
330
|
+
| Codex | `.agents/skills/`, `.codex/skills/` | Repository skills load | Every repository skill is disabled |
|
|
331
|
+
| Claude Code | `.claude/skills/<name>/SKILL.md` | Repository skills load (bare or native mode, above) | No skill context is collected |
|
|
332
|
+
|
|
333
|
+
Codex's own four built-in skills (`imagegen`, `openai-docs`, `skill-creator`,
|
|
334
|
+
`skill-installer`) are always disabled, whatever `repoSkills` is set to —
|
|
335
|
+
wardby's coding runs never offer them. With `repoSkills: false`, the Codex
|
|
336
|
+
worker scans both roots for the skill names to disable; that scan stops after
|
|
337
|
+
2000 directory entries, to bound the work an adversarial skills tree could
|
|
338
|
+
cause, logs `codex_skill_scan_truncated`, and disables whatever names it found
|
|
339
|
+
so far rather than failing the run.
|
|
340
|
+
|
|
341
|
+
Claude Code skills ship to the worker as their `SKILL.md` only. A skill's
|
|
342
|
+
other files (scripts, references, data) stay in the repository checkout and
|
|
343
|
+
are read or run through the command runner at
|
|
344
|
+
`/workspace/.claude/skills/<name>/`.
|
|
345
|
+
|
|
346
|
+
Turn repository skills off for an agent:
|
|
347
|
+
|
|
348
|
+
```json
|
|
349
|
+
{ "id": "<agent-id>", "codingProfile": { "repoSkills": false } }
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
**Upgrading.** `repoSkills` and `claudeBareMode` both default to `true`, so
|
|
353
|
+
upgrading changes behavior for existing agents: Claude Code agents start
|
|
354
|
+
loading `CLAUDE.md` and `.claude/skills/` (previously neither was loaded),
|
|
355
|
+
and Codex agents stop getting Codex's own built-in skills (previously always
|
|
356
|
+
offered). Set `repoSkills: false` on an agent to keep its repository's
|
|
357
|
+
skills out of its runs; there is no setting that keeps repository
|
|
358
|
+
instructions themselves out, for either builder.
|
|
359
|
+
|
|
360
|
+
Use the worker images (`CODING_WORKER_IMAGE` and `CODING_CLAUDE_WORKER_IMAGE`)
|
|
361
|
+
from the same release as the control plane. On an older Claude Code worker
|
|
362
|
+
image, runs fail with `worker_input_failed` once the repository has a
|
|
363
|
+
`CLAUDE.md`, `AGENTS.md`, or skill to load, or the agent sets `repoSkills` or
|
|
364
|
+
`claudeBareMode` to `false`; on an older Codex worker image, runs of agents with
|
|
365
|
+
`repoSkills: false` fail the same way. A `workerImageRef` image must also be
|
|
366
|
+
rebuilt for this release: on this release's driver image for a Codex agent, or
|
|
367
|
+
on this release's tool runner image for a Claude Code agent. On a Claude Code
|
|
368
|
+
agent, `workerImageRef` replaces only the tool runner (the container that runs
|
|
369
|
+
the agent's commands); Claude Code itself always runs on
|
|
370
|
+
`CODING_CLAUDE_WORKER_IMAGE`. See
|
|
371
|
+
[Bring-Your-Own Coding-Worker Images](coding-worker-byo-images.md).
|
|
372
|
+
|
|
265
373
|
## Budgets
|
|
266
374
|
|
|
267
375
|
A coding run's budget is reserved when it is dispatched: the agent's own
|
package/docs/coding-packages.md
CHANGED
|
@@ -42,8 +42,10 @@ request never names the internal proxy.
|
|
|
42
42
|
image to build or maintain; the agent installs what it needs at run time.
|
|
43
43
|
2. **A custom `workerImageRef` with dependencies baked in.** Still supported:
|
|
44
44
|
point the agent's profile at your own image, built on wardby's driver base
|
|
45
|
-
image
|
|
46
|
-
|
|
45
|
+
image for a Codex agent, or `FROM` the same release's tool runner image for
|
|
46
|
+
a Claude Code agent (see
|
|
47
|
+
[Bring-your-own worker images](coding-worker-byo-images.md)), with
|
|
48
|
+
everything preinstalled. Setting `workerImageRef` needs `agents:admin`
|
|
47
49
|
and the admin role, and the image must be pinned by digest.
|
|
48
50
|
3. **Both together.** Use a custom image for a toolchain or system libraries
|
|
49
51
|
the registry can't provide (a compiler, a non-Node/Python runtime, apt
|
package/docs/coding-services.md
CHANGED
|
@@ -194,7 +194,9 @@ to an agent that allows at least one service.
|
|
|
194
194
|
|
|
195
195
|
A [bring-your-own worker image](coding-worker-byo-images.md) must be built on
|
|
196
196
|
driver v11 or later to run with services; an agent whose `workerImageRef`
|
|
197
|
-
predates driver v11 rejects the run input once services are on it.
|
|
197
|
+
predates driver v11 rejects the run input once services are on it. For a
|
|
198
|
+
Claude Code agent, build the custom image `FROM` the tool runner image of the
|
|
199
|
+
same wardby release.
|
|
198
200
|
|
|
199
201
|
## Letting a coding agent change the declaration
|
|
200
202
|
|
|
@@ -7,6 +7,9 @@ wardby's published **driver base image** and point your agent's
|
|
|
7
7
|
`workerImageRef` at it, instead of waiting for wardby to hand-author a new
|
|
8
8
|
`Dockerfile.<toolchain>`.
|
|
9
9
|
|
|
10
|
+
The driver image is for Codex agents. A Claude Code agent's image starts from a
|
|
11
|
+
different base; see [Codex and Claude Code](#codex-and-claude-code).
|
|
12
|
+
|
|
10
13
|
## The driver image
|
|
11
14
|
|
|
12
15
|
`ghcr.io/wardby/wardby/wardby-coding-worker-driver` contains wardby's
|
|
@@ -112,13 +115,188 @@ point one at an arbitrary image without the step-up scope. The scope alone
|
|
|
112
115
|
isn't enough: the caller must also hold the admin role (see
|
|
113
116
|
[roles and privileged operations](security-deployment.md#roles-and-privileged-operations)).
|
|
114
117
|
|
|
115
|
-
## Codex
|
|
118
|
+
## Codex and Claude Code
|
|
119
|
+
|
|
120
|
+
A Codex agent runs in one container, and its commands run there too. A Claude
|
|
121
|
+
Code agent uses two containers: one runs Claude Code and holds its API key; the
|
|
122
|
+
other runs the agent's commands and has your repository. `workerImageRef` always
|
|
123
|
+
replaces the container that runs commands.
|
|
124
|
+
|
|
125
|
+
| | Codex agent | Claude Code agent |
|
|
126
|
+
| ------------------------------ | ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
127
|
+
| What `workerImageRef` replaces | the agent's only container | the container that runs commands |
|
|
128
|
+
| Build your image `FROM` | [the coding-worker driver image](#the-driver-image) (`driver-vN`) | the `wardby-claude-tool-runner` image from the same wardby release (or `wardby-claude-tool-runner-node-python`) |
|
|
129
|
+
| Rebuild when | the driver image changes | you upgrade wardby |
|
|
130
|
+
| Claude Code itself runs on | — | wardby's standard image, never yours |
|
|
131
|
+
|
|
132
|
+
The driver image sections above are for Codex. The subsections below are for
|
|
133
|
+
Claude Code. In them, "tool runner" means the container that runs a Claude Code
|
|
134
|
+
agent's commands.
|
|
135
|
+
|
|
136
|
+
### Build a custom image for a Claude Code agent
|
|
137
|
+
|
|
138
|
+
1. **Find your release's tool runner image.** It is the value of
|
|
139
|
+
`CODING_CLAUDE_TOOL_RUNNER_IMAGE` on your server. To start from Node and
|
|
140
|
+
Python, use `CODING_CLAUDE_TOOL_RUNNER_IMAGE_NODE_PYTHON_3_12` instead. A
|
|
141
|
+
release value looks like
|
|
142
|
+
`ghcr.io/wardby/wardby/wardby-claude-tool-runner@sha256:<digest>`. If the
|
|
143
|
+
value is a local image ID (`sha256:...` only), give it a name first, because
|
|
144
|
+
Docker cannot build `FROM` a bare ID:
|
|
145
|
+
`docker tag sha256:<id> wardby-tool-runner-base:local`.
|
|
146
|
+
2. **Make a build folder.** Use a small folder of your own, outside your
|
|
147
|
+
repository. Put in it the Dockerfile and only the files the Dockerfile
|
|
148
|
+
copies.
|
|
149
|
+
3. **Write the Dockerfile.** Start from the image in step 1, install your tools
|
|
150
|
+
as `root`, then switch back to the tool runner's user:
|
|
151
|
+
|
|
152
|
+
```dockerfile
|
|
153
|
+
FROM <image from step 1>
|
|
154
|
+
USER root
|
|
155
|
+
RUN apt-get update \
|
|
156
|
+
&& apt-get install -y --no-install-recommends <your packages> \
|
|
157
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
158
|
+
USER 10001:10001
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Keep these rules:
|
|
162
|
+
- The last `USER` line is `USER 10001:10001`.
|
|
163
|
+
- Do not set `ENTRYPOINT` or `CMD`. The tool runner starts with the base
|
|
164
|
+
image's own entrypoint.
|
|
165
|
+
- Install everything at build time. A run cannot install system packages.
|
|
166
|
+
- Put tools in `/usr/local/bin` or `/usr/bin`. Do not put anything under
|
|
167
|
+
`/tmp` or `/home/wardby`: a run hides both.
|
|
168
|
+
- Put environment settings your commands need in a file under
|
|
169
|
+
`/etc/profile.d/` (see "How the tool runner runs commands" below). `ENV`
|
|
170
|
+
lines in the Dockerfile do not reach the agent's commands.
|
|
171
|
+
|
|
172
|
+
4. **Build it:** `docker build --tag <name> <build folder>`. Release images are
|
|
173
|
+
`linux/amd64`. On an ARM machine, add `--platform linux/amd64` here and to
|
|
174
|
+
`docker run` in step 5.
|
|
175
|
+
5. **Run the tests the way a run would.** Clone the repository to a throwaway
|
|
176
|
+
folder (on Linux, make it writable: `chmod -R a+rwX <clone>`). Then run the
|
|
177
|
+
project's test command with a run's restrictions and its fixed environment,
|
|
178
|
+
so `ENV` lines in the image do not apply:
|
|
179
|
+
|
|
180
|
+
```sh
|
|
181
|
+
docker run --rm --read-only --tmpfs /tmp:rw,noexec,nosuid,size=64m --tmpfs /home/wardby:rw,noexec,nosuid,size=64m,uid=10001,gid=10001,mode=0700 --network none --user 10001:10001 --cap-drop ALL --security-opt no-new-privileges -v <clone>:/workspace -w /workspace --entrypoint env <name> -i HOME=/home/wardby LANG=C.UTF-8 PATH=/opt/wardby/bin:/usr/local/bin:/usr/bin:/bin sh -lc '<test command>'
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
On an ARM machine, add `--platform linux/amd64` after `docker run`. Fix the
|
|
185
|
+
Dockerfile until the tests pass, then delete the clone.
|
|
186
|
+
|
|
187
|
+
6. **Get an immutable reference.** A tag is refused.
|
|
188
|
+
- **Docker launcher** (wardby runs coding jobs with Docker on a single
|
|
189
|
+
machine): use the local image ID,
|
|
190
|
+
`docker image inspect --format '{{.Id}}' <name>`. Build on that machine.
|
|
191
|
+
Wardby never pulls these images.
|
|
192
|
+
- **Kubernetes:** push the image to a registry your cluster can pull from,
|
|
193
|
+
and use `<registry>/<name>@sha256:<digest>`.
|
|
194
|
+
7. **Point the agent at it.** Call `update_agent` with the agent's id. This
|
|
195
|
+
needs the `agents:admin` scope and the admin role:
|
|
196
|
+
|
|
197
|
+
```json
|
|
198
|
+
{
|
|
199
|
+
"id": "<agent id>",
|
|
200
|
+
"codingProfile": { "workerImageRef": "<reference from step 6>" }
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
8. **Try it.** Trigger a small task that uses your tools, such as "Run the
|
|
205
|
+
project's tests and report the results. Change nothing."
|
|
206
|
+
|
|
207
|
+
To undo it, set `codingProfile.workerImageRef` to `null`. The agent then uses
|
|
208
|
+
the standard tool runner for its `toolchain`.
|
|
209
|
+
|
|
210
|
+
### Languages other than Node and Python
|
|
211
|
+
|
|
212
|
+
A run can download packages only from wardby's package registry, which serves
|
|
213
|
+
npm and PyPI. Packages for any other language must be in the image. If a
|
|
214
|
+
package compiles native code, compile it in an earlier build stage and copy
|
|
215
|
+
only the results into the final image. The final image then needs no compiler.
|
|
216
|
+
|
|
217
|
+
The tool runner is based on Debian 12 (bookworm). Build stages that compile
|
|
218
|
+
code must use a bookworm-based image too, so the results work with the tool
|
|
219
|
+
runner's system libraries.
|
|
116
220
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
221
|
+
This example adds Ruby and a project's gems. It is a starting point to adapt,
|
|
222
|
+
not a tested recipe. Copy the project's `Gemfile` and `Gemfile.lock` into the
|
|
223
|
+
build folder first.
|
|
224
|
+
|
|
225
|
+
```dockerfile
|
|
226
|
+
# Stage 1: install Ruby and the project's gems, compiling any native code.
|
|
227
|
+
FROM ruby:3.3-slim-bookworm AS builder
|
|
228
|
+
RUN apt-get update \
|
|
229
|
+
&& apt-get install -y --no-install-recommends build-essential \
|
|
230
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
231
|
+
ENV BUNDLE_PATH=/usr/local/bundle \
|
|
232
|
+
BUNDLE_DEPLOYMENT=true
|
|
233
|
+
WORKDIR /build
|
|
234
|
+
COPY Gemfile Gemfile.lock ./
|
|
235
|
+
RUN bundle install
|
|
236
|
+
|
|
237
|
+
# Stage 2: the tool runner from your wardby release, plus Ruby and the gems.
|
|
238
|
+
FROM <tool runner image from step 1>
|
|
239
|
+
USER root
|
|
240
|
+
# Shared libraries Ruby needs at run time, plus any library your native gems
|
|
241
|
+
# link to (for example libpq5 for pg).
|
|
242
|
+
RUN apt-get update \
|
|
243
|
+
&& apt-get install -y --no-install-recommends libffi8 libgmp10 libssl3 libyaml-0-2 zlib1g \
|
|
244
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
245
|
+
# Ruby lives in /usr/local, and the gems in /usr/local/bundle.
|
|
246
|
+
COPY --from=builder /usr/local /usr/local
|
|
247
|
+
# Settings for the agent's commands (Dockerfile ENV lines do not reach them).
|
|
248
|
+
RUN ldconfig \
|
|
249
|
+
&& printf '%s\n' \
|
|
250
|
+
'export GEM_HOME=/usr/local/bundle' \
|
|
251
|
+
'export BUNDLE_PATH=/usr/local/bundle' \
|
|
252
|
+
'export BUNDLE_APP_CONFIG=/usr/local/bundle' \
|
|
253
|
+
'export BUNDLE_DEPLOYMENT=true' \
|
|
254
|
+
> /etc/profile.d/ruby.sh \
|
|
255
|
+
&& sh -lc 'ruby --version && bundle --version'
|
|
256
|
+
USER 10001:10001
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Pin the `ruby` image by digest for repeatable builds. Rebuild the image when
|
|
260
|
+
the project's `Gemfile.lock` changes.
|
|
261
|
+
|
|
262
|
+
### If a run fails
|
|
263
|
+
|
|
264
|
+
| What you see | What it usually means |
|
|
265
|
+
| --------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
266
|
+
| `worker_tool_runner_unreachable` | The image was not built `FROM` the tool runner of the same wardby release, or the Dockerfile changed its `USER` or `ENTRYPOINT`. |
|
|
267
|
+
| A command is "not found" | The tool is not in the image, or a setting it needs is in an `ENV` line instead of `/etc/profile.d/`. |
|
|
268
|
+
| "Permission denied" when running a file | On Docker, something writes a program to `/tmp` or `/home/wardby` and runs it. Point that tool's temporary or cache folder under `/workspace/.cache/`. |
|
|
269
|
+
|
|
270
|
+
### How the tool runner runs commands
|
|
271
|
+
|
|
272
|
+
These details explain the rules above.
|
|
273
|
+
|
|
274
|
+
- **User and privileges.** Commands always run as user `10001`, with no Linux
|
|
275
|
+
capabilities and `no-new-privileges`. `root` and setuid programs do not work
|
|
276
|
+
at run time.
|
|
277
|
+
- **Filesystem.** The root filesystem is read-only. `/tmp` and `/home/wardby`
|
|
278
|
+
are small, empty scratch space; anything the image put there is hidden. On
|
|
279
|
+
Docker, files there cannot be run. `/workspace` holds the repository; put
|
|
280
|
+
caches, build output and temporary files under `/workspace/.cache/`.
|
|
281
|
+
- **Shell and environment.** Each command runs as `sh -lc "<command>"` with a
|
|
282
|
+
fixed environment: `HOME=/home/wardby`, `LANG=C.UTF-8`, `TMPDIR` under
|
|
283
|
+
`/workspace/.cache/`, wardby's package registry settings, and
|
|
284
|
+
`PATH=/opt/wardby/bin:/usr/local/bin:/usr/bin:/bin`. The login shell reads
|
|
285
|
+
`/etc/profile` and the files in `/etc/profile.d/`, so that is where your own
|
|
286
|
+
settings go. `/etc/profile` resets `PATH` to Debian's default, so add any
|
|
287
|
+
other folder to `PATH` in your `/etc/profile.d/` file.
|
|
288
|
+
- **Network.** The tool runner reaches only wardby's package registry (npm and
|
|
289
|
+
PyPI).
|
|
290
|
+
- **Images on the Docker launcher are never pulled.** When wardby runs coding
|
|
291
|
+
jobs with Docker on a single machine, the image must already be on that
|
|
292
|
+
machine. Kubernetes needs a registry digest
|
|
293
|
+
(`repo@sha256:<64 hex>`).
|
|
294
|
+
- **Server settings.** Claude Code itself always runs on
|
|
295
|
+
`CODING_CLAUDE_WORKER_IMAGE`. The server still needs both
|
|
296
|
+
`CODING_CLAUDE_WORKER_IMAGE` and `CODING_CLAUDE_TOOL_RUNNER_IMAGE` set, even
|
|
297
|
+
for agents with their own `workerImageRef`.
|
|
298
|
+
- **Toolchain.** While `workerImageRef` is set, `toolchain` and
|
|
299
|
+
`toolchainVersion` do not choose the image, for either builder.
|
|
122
300
|
|
|
123
301
|
## Running services with a BYO image
|
|
124
302
|
|
|
@@ -130,6 +308,20 @@ a worker built on an older driver base doesn't recognize the input's
|
|
|
130
308
|
without them. Rebuild your image on a current `driver-vN` digest (see "The
|
|
131
309
|
driver image" above) before allowing any service on an agent that uses it.
|
|
132
310
|
|
|
311
|
+
## Repository skills need a current driver
|
|
312
|
+
|
|
313
|
+
On a Codex agent, a `workerImageRef` image never receives Claude Code's
|
|
314
|
+
repository context (`claudeContext`) or `claudeBareMode`. The one new input key
|
|
315
|
+
it can see is `repoSkills`, which wardby writes only when an agent sets
|
|
316
|
+
`repoSkills: false`. A worker built on
|
|
317
|
+
an older driver base validates its input with a strict schema, so it rejects
|
|
318
|
+
runs of agents with `repoSkills: false` (the run fails with
|
|
319
|
+
`worker_input_failed`), and it keeps offering Codex's built-in skills
|
|
320
|
+
(`imagegen`, `openai-docs`, `skill-creator`, `skill-installer`), which a
|
|
321
|
+
current driver always disables. Rebuild any `workerImageRef` image on a
|
|
322
|
+
current `driver-vN` digest (see "The driver image" above) before relying on
|
|
323
|
+
either behavior.
|
|
324
|
+
|
|
133
325
|
## What this doesn't cover
|
|
134
326
|
|
|
135
327
|
wardby does not re-validate the contents of your built image beyond the
|
|
@@ -1,16 +1,24 @@
|
|
|
1
1
|
# Coding Worker Isolation
|
|
2
2
|
|
|
3
|
-
Wardby
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Wardby runs Codex and Claude Code coding workers through Docker or Kubernetes
|
|
4
|
+
launchers. Both fail closed when the effective runtime does not match the
|
|
5
|
+
reviewed policy. Claude Code separates its model-facing worker from its
|
|
6
|
+
workspace-facing tool runner: Docker uses companion containers, while
|
|
7
|
+
Kubernetes uses a native sidecar in the run pod.
|
|
6
8
|
|
|
7
9
|
## Security Boundary
|
|
8
10
|
|
|
9
|
-
Coding-agent repositories and instructions are untrusted. The
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
Coding-agent repositories and instructions are untrusted. The Wardby control
|
|
12
|
+
plane, immutable worker images, dedicated coding proxy, and the platform
|
|
13
|
+
enforcing container and network policies are trusted.
|
|
14
|
+
|
|
15
|
+
### Docker launcher
|
|
16
|
+
|
|
17
|
+
The Docker daemon and host kernel are trusted. Docker containers are defense
|
|
18
|
+
in depth rather than a VM boundary. Production should run the Docker host on a
|
|
19
|
+
dedicated worker node or VM with no production credentials beyond those
|
|
20
|
+
required by the proxy. The Kubernetes launcher section below describes the
|
|
21
|
+
corresponding pod and network rules.
|
|
14
22
|
|
|
15
23
|
The Codex worker has one network attachment: a unique per-run internal bridge using
|
|
16
24
|
Docker's isolated gateway mode. It has no default external route, published
|
|
@@ -588,6 +596,7 @@ Kubernetes-specific settings (`src/config/providers.ts`,
|
|
|
588
596
|
| `KUBERNETES_CONTEXT` | (unset → in-cluster/default kubeconfig context) | Which kubeconfig context `ClientNodeKubernetesApi` connects with. |
|
|
589
597
|
| `KUBERNETES_RUNTIME_CLASS` | (unset) | e.g. `gvisor` on GKE. Unset means pods run without a sandboxing runtime class — logged once per launch as `kubernetes_runtime_class_unset` and development-only. |
|
|
590
598
|
| `KUBERNETES_RESOURCE_QUOTA` | (unset) | Name of the namespace ResourceQuota run pods count against, e.g. `wardby-coding` in the GKE overlay. When set, a run whose pod would not fit the quota's free room waits in the coding queue instead of failing at pod create. Needs `get` on that one `resourcequotas` object. Unset means no check. |
|
|
599
|
+
| `KUBERNETES_PLATFORM` | `generic` | `generic`, `gke-autopilot` or `eks`. Selects the cluster's admission rules that run pods are conformed to. `gke-autopilot` and `eks` both require `KUBERNETES_RUNTIME_CLASS=gvisor`; see the platform profile section below. |
|
|
591
600
|
| `KUBERNETES_RUN_PRIORITY_CLASS` | (unset) | PriorityClass for run pods and the preflight canary, e.g. `wardby-coding-run` in the GKE overlay. Must be an existing class and a DNS-1123 subdomain; `system-` classes are refused. Unset means no class (priority 0). |
|
|
592
601
|
|
|
593
602
|
The `CODING_CPUS` / `CODING_MEMORY_MB` / `CODING_PIDS` / `CODING_DISK_MB` /
|
|
@@ -798,6 +807,16 @@ landed on — cannot appear in it. That case reached a live Autopilot launch wit
|
|
|
798
807
|
every dry-run-derived check passing, and is now pinned by tests. Treat a
|
|
799
808
|
captured fixture as a lower bound on what a platform mutates.
|
|
800
809
|
|
|
810
|
+
The `eks` profile is for Amazon EKS clusters with a dedicated gVisor node group.
|
|
811
|
+
EKS has no managed sandbox runtime, so the cluster must provide a RuntimeClass
|
|
812
|
+
named `gvisor` with handler `runsc` whose `scheduling` block selects nodes
|
|
813
|
+
labelled `wardby.dev/sandbox=gvisor` and tolerates the taint
|
|
814
|
+
`sandbox=gvisor:NoSchedule` on those nodes. Kubernetes' RuntimeClass admission
|
|
815
|
+
merges that block into each pod; Wardby sets neither the node selector nor the
|
|
816
|
+
toleration itself, and the `eks` profile forgives exactly that nodeSelector and
|
|
817
|
+
that toleration and nothing else. Pod resources follow the generic rules, plus
|
|
818
|
+
an explicit ephemeral-storage request and limit.
|
|
819
|
+
|
|
801
820
|
### The enforcement gate
|
|
802
821
|
|
|
803
822
|
The Kubernetes API can create a NetworkPolicy object without that policy
|
|
@@ -911,9 +930,9 @@ default 90,000ms):
|
|
|
911
930
|
1. `platform` — pure configuration, checked before any cluster API call:
|
|
912
931
|
`assertPlatformConfig` (`src/providers/jobs/kubernetes-platform.ts`) refuses
|
|
913
932
|
a deployment that cannot work under `KUBERNETES_PLATFORM`. Under
|
|
914
|
-
`gke-autopilot`
|
|
915
|
-
|
|
916
|
-
|
|
933
|
+
`gke-autopilot` and `eks`, `KUBERNETES_RUNTIME_CLASS` must be `gvisor` (an
|
|
934
|
+
unset or different runtime class is refused, not warned about). Under
|
|
935
|
+
`gke-autopilot` the effective `CODING_MAX_DISK_MB` must also leave room
|
|
917
936
|
for the worker container's 1 GiB reservation inside Autopilot's 10 GiB pod
|
|
918
937
|
ephemeral-storage ceiling. The same assertion runs again at process
|
|
919
938
|
start-up in `buildConfiguredExecutor`
|
|
@@ -942,20 +961,55 @@ default 90,000ms):
|
|
|
942
961
|
5. `canary` — creates a real run pod + NetworkPolicy from the same builders
|
|
943
962
|
as a live run, running a script that waits for policy enforcement (as
|
|
944
963
|
above) then attempts DNS resolution, a connect to the proxy's deny port,
|
|
945
|
-
the internet (`1.1.1.1:443`), the metadata
|
|
946
|
-
|
|
964
|
+
the internet (`1.1.1.1:443`), the cloud metadata endpoints (`169.254.169.254:80`,
|
|
965
|
+
the EKS Pod Identity agent `169.254.170.23:80` and its IPv6 address
|
|
966
|
+
`[fd00:ec2::23]:80`, and EC2's IPv6 metadata address `[fd00:ec2::254]:80`), and the proxy itself —
|
|
967
|
+
requiring every one of the first four kinds to fail and the proxy connect to
|
|
947
968
|
succeed. Any other outcome, or a canary pod that itself fails to
|
|
948
969
|
schedule/run, is `kubernetes_isolation_unsupported:canary`.
|
|
949
970
|
|
|
950
971
|
This whole preflight is **memoized per launcher instance and its failure is
|
|
951
972
|
sticky**: `KubernetesJobLauncher.runPreflight()` caches the first call's
|
|
952
|
-
promise (`this.preflightResult ??= ...`, `kubernetes.ts:
|
|
973
|
+
promise (`this.preflightResult ??= ...`, `kubernetes.ts:790`), including
|
|
953
974
|
a rejection — so once a launcher process has seen preflight fail, every
|
|
954
975
|
subsequent `launch()` in that process fails immediately with the same error
|
|
955
976
|
without re-probing the cluster. A fresh preflight requires a new process
|
|
956
977
|
(or, from the CLI, a fresh `wardby coding preflight` invocation, which is
|
|
957
978
|
not memoized).
|
|
958
979
|
|
|
980
|
+
**A long-running server process starts this same memoized preflight at
|
|
981
|
+
start-up, not on the first coding run.** `wardby serve`, `wardby mcp` (both
|
|
982
|
+
transports), and `wardby scheduler` each call `KubernetesJobLauncher.warmUp()`
|
|
983
|
+
right after the executor is built, fire-and-forget: it runs the identical
|
|
984
|
+
preflight `launch()` would otherwise run lazily, so the first coding run
|
|
985
|
+
after a restart doesn't pay the preflight's own cost (a canary pod, routinely
|
|
986
|
+
tens of seconds on a resource-constrained cluster such as `kind`).
|
|
987
|
+
`wardby scheduler` needs this just as much as the other two — it dispatches
|
|
988
|
+
scheduled coding runs through its own Kubernetes executor without ever
|
|
989
|
+
starting an MCP server, so without this it would still pay the lazy cost on
|
|
990
|
+
its first scheduled run. The result is logged once at start-up — an info
|
|
991
|
+
line on success, a warning naming the failure code (e.g.
|
|
992
|
+
`kubernetes_isolation_unsupported:<check>`) otherwise.
|
|
993
|
+
|
|
994
|
+
**A start-up warm-up's failure is logged and retried on the next run, not
|
|
995
|
+
left stuck until restart.** This is the one way a preflight failure is
|
|
996
|
+
_not_ memoized: a transient cluster problem at process start (the API
|
|
997
|
+
server briefly unreachable, a slow CNI not yet programmed, and the like)
|
|
998
|
+
must not fail every coding run for the rest of that process's life, so a
|
|
999
|
+
failed warm-up clears its own failed attempt once it has logged it, and the
|
|
1000
|
+
_next_ `launch()` runs the preflight fresh — succeeding if the cluster has
|
|
1001
|
+
since recovered. A `launch()` that was already waiting on that same
|
|
1002
|
+
in-flight warm-up attempt still fails with that attempt's error (it shares
|
|
1003
|
+
the same preflight call), exactly as it always has; it's only the attempt
|
|
1004
|
+
_after_ that one which retries. A preflight failure `launch()` triggers
|
|
1005
|
+
itself — because no warm-up ran, or because a warm-up's cleared failure was
|
|
1006
|
+
never retried before the next `launch()` found the cluster still broken —
|
|
1007
|
+
keeps the original behavior exactly: it stays memoized, failing every
|
|
1008
|
+
subsequent `launch()` in that process until it is restarted. This never
|
|
1009
|
+
runs for a one-shot CLI command (`wardby run`, `wardby coding preflight`,
|
|
1010
|
+
migrations, imports) — only for a process that stays up to serve or
|
|
1011
|
+
dispatch runs.
|
|
1012
|
+
|
|
959
1013
|
**A hung pod create during preflight can leave a preflight pod and its
|
|
960
1014
|
NetworkPolicy behind.** If `createPod` never settles (rather than failing),
|
|
961
1015
|
the preflight's own timeout still fires and the caller sees `:timeout`, but
|