Skip to content

Ask Waza

Ask about Waza commands, writing evals, or troubleshooting an error. Paste YAML below for a schema check.

AI answers can be wrong. Do not share secrets or sensitive information. History may be retained.

CLI reference | Privacy & limits

    Check pasted YAML (optional)

    Local runner container reference

    Source-build foundation for v0.40.0, not a published image. This reference uses the existing public runner contract and terminal envelope. The default reference target remains a scratch image for inline.mock-text only. The explicit native-reference target adds a digest-pinned Debian/glibc runtime and supports the exact-unit native Copilot text profile. It is tested with the actual bundled CLI and an isolated synthetic provider; no live provider, paid request or external network is used by that test. This is native execution evidence, not inference-quality or provider assurance. Issue #762 remains open until the public image and pinned published-image acceptance run are verified. There is no published v0.40.0 runner image or registry digest to copy today. A manual-only GHCR publisher is defined in source, but has not been dispatched; package creation permission and public visibility remain unverified. A separate manual verifier is also prepared; it must anonymously pull the exact digest and pass mock and bundled-native production-caller controls before that image is accepted. Neither workflow has been dispatched. No Lab dashboard change is required: this adds no new evidence or status surface.

    Use a reviewed source checkout with hydrated Git LFS objects, Docker Engine with BuildKit and Linux containers, and a POSIX shell. The source-built targets have been exercised on matching native Linux architectures; the CI gate specifically requires native Linux AMD64. Local ARM64 evidence is not AMD64 evidence. Windows-native containers, cross-platform emulation and alternate container engines are not established by this reference.

    Builds need network access for the digest-pinned Node/Go/runtime base images, Debian packages, locked npm dependencies and checksummed Go modules. The native-reference build uses Debian Bookworm glibc and installs Bash, CA certificates and Git for the bundled CLI’s runtime features. It embeds the real dashboard and native CLI payloads, not compile stubs. The mock profile does not need runtime extraction. Tests deny runtime networking and use only a local synthetic HTTP provider; they do not supply credentials or contact a paid provider. A real native provider may require network access and caller-managed authentication when you run it. If your network requires a public npm mirror, pass --build-arg NPM_CONFIG_REGISTRY=https://your-mirror.example/npm/ to the build. For the test command below, set NPM_CONFIG_REGISTRY to that same URL. Do not pass credentials in build arguments; no private registry authentication mechanism is provided.

    From the repository root:

    Terminal window
    work=$(mktemp -d)
    cp examples/runner/unit.json "$work/request.json"
    docker build --file examples/runner/container/Dockerfile \
    --iidfile "$work/image.id" .
    image=$(docker image inspect --format '{{.Id}}' "$(cat "$work/image.id")")
    docker image inspect "$image"
    # Build the native-capable reference separately; the default remains scratch.
    docker build --file examples/runner/container/Dockerfile \
    --target native-reference --iidfile "$work/native-image.id" .
    native_image=$(docker image inspect --format '{{.Id}}' "$(cat "$work/native-image.id")")
    docker image inspect "$native_image"

    The inspected image ID is sha256: followed by 64 hex digits. It is an immutable local image identifier, not evidence of publication or a pullable registry reference. Its meaning depends on Docker’s image store: Docker 29’s containerd store can report an OCI index digest rather than a configuration digest. Neither --iidfile nor .Id is a published-image acceptance result. The build does not push, tag a release or publish anything. Keep the work directory until you have inspected its outputs.

    The native-reference image is configured as non-root UID/GID 65532:65532 with HOME=/home/waza, COPILOT_HOME=/home/waza/.copilot and TMPDIR=/tmp. The bundled runtime extracts executable files under COPILOT_HOME, so that directory and temporary storage must be writable and executable. With a read-only root filesystem, provide them explicitly:

    Terminal window
    docker run --rm --pull=never --network=none --read-only \
    --cap-drop=ALL --security-opt=no-new-privileges --pids-limit=64 \
    --memory=2g --cpus=1 \
    --tmpfs /tmp:rw,exec,nosuid,nodev,size=1g,mode=1777 \
    --tmpfs /home/waza/.copilot:rw,exec,nosuid,nodev,size=1g,uid=65532,gid=65532,mode=700 \
    "$native_image" runner capabilities

    One GiB was exercised for the current bundled CLI; it is not a measured minimum. Use a persistent writable executable mount at COPILOT_HOME if retaining the downloaded bundle is desired. These settings provide runtime storage, not a container sandbox or hermetic build.

    Terminal window
    docker run --rm --pull=never --network=none --read-only \
    --cap-drop=ALL --security-opt=no-new-privileges --pids-limit=64 \
    --memory=256m --cpus=1 \
    --tmpfs /tmp:rw,noexec,nosuid,size=32m,mode=1777 \
    -i "$image" runner run \
    < "$work/request.json" > "$work/terminal.json" 2> "$work/stderr.log"
    code=$?
    printf 'Container exit: %s\n' "$code"
    cat "$work/terminal.json"

    The clean request selects exactly {"shard":"shard-a","task":"selected","trial":2,"attempt":2}. Its eval permits three trials and attempts, but these are selectors, not loops. The captured adjacent task glob is never expanded. The only task is the inline captured task; no neighboring source files are supplied to the container.

    Expect exit 0, empty stderr, and exactly one JSON envelope with kind: "waza.runner-terminal", schema_version: "1.0", outcome: "success", exit_code: 0, engine_calls: 1, validation: "valid" and failure_boundary: "none". Both selection and observation.selection equal the tuple above; observation has execution_mode: "mock", engine_calls: 1, run_number: 2, attempts: 2, status: "passed" and one passed validation. identity is input-derived lineage, not an isolation or delivery attestation. The producer validates the terminal schema before its single emission.

    The host shell writes terminal.json and stderr.log; the container writes only ephemeral temporary workspace data. There is no mounted output directory, archive, upload, ingestion service or scheduler. Docker’s own launch errors can produce stderr and no envelope (typically exit 125); do not interpret those as Waza verdicts. Redirection is neither exclusive creation nor atomic/durable publication: use a fresh work directory, never overwrite valuable outputs, and retain partial bytes on failure for diagnosis. A successful write is not proof that another process received the result.

    With Node.js 24 available on the host, run:

    Terminal window
    node --test examples/runner/container/test.mjs

    This builds the image, resolves its local ID, starts actual Linux containers and uses the production CLI, admission, mock engine and terminal producer. It checks capability discovery, zero-call offline validation, exact 2/2 and alternative 3/3 selection, one failed text check (exit 1), wrong shard/task, out-of-range trial/attempt, external prompt-file and malformed JSON rejection (exit 6), and unavailable native capability even with paid consent (exit 5). Rejected requests have no observation or invented execution identity. Fresh host input/output files round-trip the real envelope; no host files or credentials are mounted. The test prints the actual local image ID and cleans only its own temporary directory. It leaves the built image in Docker’s local store.

    Offline SDK subprocess and bundled-runtime controls

    Section titled “Offline SDK subprocess and bundled-runtime controls”
    Terminal window
    node --test examples/runner/container/native-test.mjs

    The same Dockerfile has explicit test-only targets. synthetic-test adds a deterministic stdio peer to the scratch image and selects it using the supported COPILOT_CLI_PATH override. The real built waza runner run consumes derivatives of examples/runner/copilot-unit.json, including its explicit paid-consent field. Every invocation nevertheless has --network=none, fresh tmpfs configuration directories and no credentials/provider settings. Only an empty, invocation-owned RPC output directory is mounted; no input/configuration or credentials are mounted. The peer does not perform inference. Its text, authentication and usage responses are synthetic. The host reads only its test RPC log after the container stops.

    The controls compare emitted identities with offline admission, exact 2/2 selection, one create/send, text verdicts, complete RPC inventories, startup rejection, protocol mismatch, execution errors, timeout and unsupported-capability rejection. They also require explicit context-discovery/file-hook/store/git/memory opt-outs and session.options.update before sending. An update rejection must produce infrastructure failure without a prompt. Declared eval metrics remain uncomputed identity metadata; success does not assert aggregate thresholds. The default scratch reference is separately required to report a native startup failure with zero engine calls; synthetic success does not make that image native-ready.

    native-smoke uses a digest-pinned Alpine base and the existing bundled-runtime test. It checks actual native ping/status/session create/get-messages/detach/delete with a local rejecting provider and zero provider requests, without sending a prompt. This establishes only that bounded lifecycle on the executed Linux architecture. It does not prove inference, credentials, billing, provider quality or general native workflow support.

    The scratch image supplies no dynamic loader or runtime dependencies. The bundle can extract successfully yet fail fork/exec with “no such file or directory” even when its executable exists. Alpine supplies the musl loader and ldd, which the SDK uses to select the musl bundle. Native extraction additionally needs a writable, executable cache/temp area: 256 MiB proved insufficient for CLI 1.0.101 assets; the smoke control uses 1 GiB, not a measured minimum. The mock walkthrough’s 32 MiB noexec tmpfs is intentionally not reused.

    Terminal window
    node --test examples/runner/container/native-bundle-test.mjs

    This builds the native-reference target and a separate test-only native-bundle-test target. It verifies the native reference’s mock path, then executes /waza runner run from the Debian-based target with the actual bundled Copilot CLI. A loopback OpenAI-compatible provider runs inside the same --network=none container and returns deterministic synthetic text and usage. The controls assert one exact selected unit and one provider request, deny ambient instruction/configuration discovery and hooks on the runner path, and prove those canaries activate in a separate positive SDK control. They also exercise timeout, a stopped native child, SIGTERM cancellation, terminal exits, native-process reaping and cleanup. The bind mount contains only two synthetic-evidence files; they are written by the non-root container and checked for cross-UID host readability. No checkout, credentials or host environment is mounted into the test container.

    The script requires the Docker daemon architecture to match the image. Docker CI additionally requires Linux AMD64 and rejects cross-architecture execution; the architecture printed by a local run describes only that local run. These controls demonstrate current-bundle startup and a synthetic native text turn, not paid inference, real-provider behavior, billing assurance or model quality. The native targets and their local image IDs are not published; they do not complete #762’s immutable public-manifest acceptance gate.

    After a separately authorized publisher run, confirm the package is actually public in GHCR; the first push may create a private package. Then run the manual-only Verify Published Runner Reference workflow with the source revision and sha256:... digest from the publisher summary. Its isolated provenance job has contents: read, attestations: read and actions: read; the production container-test job has only contents: read. Neither has package permission or logs in to GHCR. It uses a fresh, empty Docker configuration for an anonymous pull, so a private package fails the gate rather than silently using credentials.

    The workflow must be dispatched from the current main tip, and the image source revision must still be reachable from current main. On a native Linux AMD64 runner, it checks that the immutable registry reference resolves to the expected source/revision labels and only the claimed runtime platform, and verifies the signed provenance for that digest and publisher workflow. It also checks the exact publisher run and attempt recorded in the verified provenance and requires successful publication/finalization steps. A signed digest left by a failed, cancelled or incomplete publisher is rejected. It then runs the production CLI’s mock exact-unit profile and the actual bundled Copilot CLI against an in-container synthetic provider, with network isolation and all six native lifecycle/discovery controls. The probe binaries and fixture come from the validated source checkout and are mounted read-only; /waza remains the binary from the pulled digest. Only a successful verifier run proves anonymous access and caller behavior for that published digest. A failed publisher finalization or verifier leaves the candidate unaccepted; no rollback is implied.

    • Cannot connect to Docker: start the daemon/Desktop and select Linux containers.
    • Build fails fetching dependencies: check network, registry access and LFS hydration; no offline build is claimed.
    • Exit 6: compare the exact shard/task and one-based bounds; retain the inline mock/text profile rather than dropping unsupported semantics.
    • Exit 5: negotiate currently advertised capabilities; native consent cannot activate an absent capability.
    • Exit 1: inspect the actual false verdict, not an infrastructure retry.
    • Empty/partial terminal output: inspect stderr and Docker’s exit; process loss, output failure and SIGKILL cannot guarantee an envelope.

    The non-root user, read-only filesystem, network denial, resource bounds and dropped capabilities reduce exposure but do not establish strong isolation. The image contains the full Waza binary and embedded assets, not a sandboxed mock-only binary. Do not mount secrets or run untrusted native workloads. There is no scheduler integration, automatic retry or exactly-once delivery. See the maintainer procedure for pinning and update limitations.