Generate a Wardyn sandbox policy + CLI invocation (or full pipeline job) for running a governed sandboxed task in CI — GitHub Actions, Azure DevOps, or any headless/unattended launch. Use when the user wants to run Wardyn in CI/a pipeline, generate a wardyn policy or run config, launch a sandbox non-interactively, or asks about wardyn run --wait / --image / task_mode / ci-run.sh. Triggers on "wardyn in CI", "CI sandbox policy", "pipeline sandbox", "headless wardyn run", "unattended governed run", "generate a wardyn policy".
Install
npx skillscat add cjohnstoniv/wardyn/wardyn-ci Install via the SkillsCat registry.
Wardyn CI — generate the config and invocation
Goal: produce (a) a RunPolicySpec JSON, (b) the launch invocation — ascripts/ci-run.sh env block (throwaway stack, or an existing control plane viaWARDYN_URL) or a direct wardyn run command — and (c) if asked, the pipeline
YAML.
Reuse the shipped machinery; never hand-roll what exists.
Ground truth (read these, don't restate from memory)
- Policy schema + field semantics:
RunPolicySpecis ininternal/types/policy.go,GrantSpecis ininternal/types/types.go— the validator isvalidatePolicySpec
ininternal/api/policy.go. - Baseline policies:
examples/policies/(ci.json= the unattended baseline;claude-llm.json= model-access grants; that dir's README explains each). - The one-shot wrapper + env table + exit codes:
scripts/ci-run.shanddocs/CI.md. - Pipeline examples to copy from:
docs/ci/github-actions.yml,docs/ci/azure-pipelines.yml.
Recipe
Classify the task.
- Plain command in a user image (tests, builds, tools) → BYOA exec mode:
--image <ref> --task-mode exec --task '<command>'. No LLM credentials. - Agent task (e.g. claude-code fixing/refactoring) → harness mode: needs an
existing control plane and a CI principal's model credential (step 3).
- Plain command in a user image (tests, builds, tools) → BYOA exec mode:
Author the policy from
examples/policies/ci.json, changing as little
as possible. Non-negotiable for unattended runs:"first_use_approval": "always_deny"(neverwait_for_review— it holds
connections for a human who isn't there).allowed_domains: exactly the hosts the task needs — package registries,
the SCM host if--repois used, the model provider for harness mode.
Empty = sealed (right for exec-mode tasks that need no network).- No
eligible_grantsentry with"requires_approval": true(it will never
mint). Grants must berequires_approval: false, with a secret the CI
principal already holds on the control plane. Never proposeWARDYN_CI_SECRETS:ci-run.shrefuses it. - Keep
auto_stop_after_secbounded (baseline: 3600).
Model access (harness mode only). A model credential is a person's
own: a dedicated CI principal stores it once throughPUT /model-providers/{id}/credential(or the console) on the deployment
CI launches on. The pipeline setsWARDYN_URL,WARDYN_CI_TOKEN(that
principal's ownwdn_token) andWARDYN_CI_MODEL_PROVIDER=<id>;ci-run.shchecks the credential is usable and launches on that provider
(docs/CI.md§ "CI's identity"). Nothing in the policy or the env block
carries the key.ci-run.sh's throwaway stack has no person on it, so it
runsexecmode only. Subscription modes are refused in CI — do not
propose them.Validate before shipping the config: with a control plane up, POST the
exact create-run body to/api/v1/runs/preflight(dry-run, mints nothing)
and act onsetup_items;ci-run.shdoes this automatically. At minimum,wardyn policy set -f <file> --name tmpagainst a dev stack exercises
the real validator.Least-privilege for complex tasks — derive, don't guess: run once
permissively in a trusted env, thenwardyn record synthesize <run-id>
(preview) /wardyn record save <run-id> --name <n>(persist) and export
that spec as the CI policy file, flippingfirst_use_approvaltoalways_deny.Emit the invocation.
- Pipeline job: a
ci-run.shenv block (copy the shape fromdocs/ci/github-actions.yml/azure-pipelines.yml) — exec mode on a
throwaway stack, orWARDYN_URL+WARDYN_CI_TOKEN(+WARDYN_CI_MODEL_PROVIDERfor harness mode) on an existing one. - Direct CLI on an existing control plane:
wardyn run --agent <a> [--image <ref>] [--task-mode exec] [--repo org/name] [--model-provider <id>] --task '<t>' --policy-file <f> --wait --timeout 30mwithWARDYN_URL+WARDYN_TOKENset — the CI
principal's ownwdn_token, not the sharedWARDYN_ADMIN_TOKEN. - State the exit-code contract (0 / task's code / 2 / 124 — table in
docs/CI.md) so the pipeline gate is explicit.
- Pipeline job: a
Sanity checks before handing over
- Policy JSON round-trips:
jq . <file>and no fields outsideRunPolicySpec. - Every host the task touches is in
allowed_domains(clone host included). - No approval-gated grant, no
wait_for_review, boundedauto_stop_after_sec. - Harness mode: runs on an existing control plane with
WARDYN_CI_MODEL_PROVIDERset, never on the throwaway stack.