# Wakeword Training Image This directory packages the one-shot, GPU-only image used by both the offline operator runner and downloadable local trainer. It is not part of `compose.yaml`, exposes no port, and contains no gateway credentials or listener dependencies. The image uses LiveKit WakeWord `0.2.1`, source revision `1ec7f680df30ff4ca0ebae6b5983441e94b10980`, and source-distribution SHA-256 `cf2d9cf4867812c06788f64c15e49abd909d9d6291f0a13f1c3f9cb649fa6127`. The gateway's `.env` deliberately contains only `WAKEWORD_CATALOG_*` settings. Do not add runner GPU, image, work-root, timeout, or retention values to it: the host-only runner receives those as explicit invocation inputs and refuses to run without `--enable`. This directory is neither a Compose service nor normal CI input. Before an operator builds it, run: ```bash scripts/build-wakeword-training-image \ registry.example/jr-wakeword-training:0.2.1 ``` The command builds from the reviewed, complete `requirements.wheelhouse.lock` with SHA-256 hashes; it never rewrites that lock. Refresh the lock only in a separate reviewed dependency-update change, then commit it before building a release image. It becomes part of each run's provenance. The pinned base image is in `base-image.lock.json`; the image build may install the reviewed dependencies, but a training container runs with `--network none`. Do not run this setup during normal gateway CI. The runtime is designed for `--network none`, a read-only `/inputs` bind mount, a writable `/run` bind mount, a read-only container root, and no Linux capabilities. A commercial run validates `sources.lock.json`, rejects default ACAV, unknown-license RIR mirrors, and unapproved Piper/VoxCPM outputs, copies only hash-locked files into `/run`, then invokes the released CLI's `augment`, `train`, `export`, and `eval` stages. It never calls `livekit-wakeword setup` or `generate` in the commercial lane. For compatibility with the released CLI only, source-lock-approved general-negative feature bundles are copied to its fixed ACAV/validation filenames beneath the isolated staging directory. The recorded source lock and materialization manifest retain their real source IDs and hashes; no ACAV data is admitted or downloaded. `quarantined_smoke` is a separately named wrapper and stays permanently non-promotable. It may exercise the upstream `run` command only after its operator has separately prepared test data; network isolation still prevents an implicit setup/download in the run container. `local_experiment` is the downloadable-trainer lane. A separate, explicit setup container may populate the user's versioned LiveKit cache with normal network access. The training container then runs the released `generate`, `augment`, `train`, `export`, and `eval` stages with `--network none`. It produces a local result, never `publish-candidate.json`. See [`docs/wakeword-trainer.md`](../../docs/wakeword-trainer.md). The source-lock format is documented by `source-lock.schema.json`; runtime validation additionally verifies every source/terms hash, publisher, version, revision, attribution, commercial disposition, approver, and partition. Raw inputs and features remain in `/run` evidence only and are never serving artifacts.