docs(agents): how the containers and agents are actually set up #31

Merged
fabi merged 1 commits from docs/containers-setup into main 2026-09-15 19:15:12 +00:00
Owner

For the other machine, which asked for the container and agent setup. Everything in docs/agents/CONTAINERS-AND-AGENTS.md was read off the running host rather than remembered.

What it covers

  • The rule — every heavy command runs in a capped container. CARGO_BUILD_JOBS caps codegen units, not rustc's threads, not the linker, not the test harness; a bare host build is unbounded and has frozen this box repeatedly. --memory-swap == --memory means a build that would swap is killed instead.
  • Three kinds of container — the CI/build image, and the two agent images, with their exact caps: decoder 5 CPU / 6 GB / 2 GB shm, port 3 CPU / 4 GB. The budget is split deliberately rather than each container claiming half of a box it shares.
  • Every volume, what it holds, and why /dev/shm is an exec-capable tmpfs rather than --shm-size (Xenia maps its JIT code cache out of a shm file; Docker's default is noexec).
  • The credential layout — and why the narrow scope on ~/.sylph-git-credentials is load-bearing: every issue endpoint refuses it, which is what stops an agent reaching the API as the human. The human's full-grant token is mounted into nothing.
  • How an iteration works, and that notifications are polled — nothing is pushed.
  • The Pi's half, including that the runner serialises: three jobs per push, one at a time, so a pending check is not necessarily a slow one.

🔴 Two agent defects it records

A brief change does not reach a resumed session. The entrypoint resumes the newest transcript with only a <120 s restart-loop guard, so a container restarted after a workflow change comes back following the old brief. Adopting a change means archiving the transcripts.

Nothing brought an agent back to its own red PR — it pushed over a red CI six times. Fixed in #24, which is itself subject to the defect above.

Also: docker/ci/

The CI image existed on exactly one host and its Dockerfile was in a scratch directory under /tmp, which was swept. Same shape as everything else this consolidation has found.

docker/ci/Dockerfile          rust 1.98.1 + the apt list copied from ci.yml
docker/ci/Dockerfile.ffmpeg   + ffmpeg, which sylpheed-export shells out to
docker/ci/run                 6 CPU / 7 GB / no swap, named cargo volumes
docker/ci/run cargo clippy --workspace --all-targets --keep-going -- -D warnings

⚠️ Two traps written into the Dockerfile itself: the Rust version is pinned here and floats on the runner (issue #15 — when they disagree, the runner wins), and cargo clippy stops at the first failing compilation unit, so without --keep-going the list looks short and is not — 14 shown against 80 real, on the corpus branch.

**For the other machine**, which asked for the container and agent setup. Everything in `docs/agents/CONTAINERS-AND-AGENTS.md` was read off the running host rather than remembered. ### What it covers * **The rule** — every heavy command runs in a capped container. `CARGO_BUILD_JOBS` caps codegen units, not rustc's threads, not the linker, not the test harness; a bare host build is unbounded and has frozen this box repeatedly. `--memory-swap == --memory` means a build that *would* swap is killed instead. * **Three kinds of container** — the CI/build image, and the two agent images, with their exact caps: decoder **5 CPU / 6 GB / 2 GB shm**, port **3 CPU / 4 GB**. The budget is split deliberately rather than each container claiming half of a box it shares. * **Every volume**, what it holds, and why `/dev/shm` is an exec-capable tmpfs rather than `--shm-size` (Xenia maps its JIT code cache out of a shm file; Docker's default is `noexec`). * **The credential layout** — and why the narrow scope on `~/.sylph-git-credentials` is load-bearing: every issue endpoint refuses it, which is what stops an agent reaching the API as the human. The human's full-grant token is mounted into nothing. * **How an iteration works**, and that **notifications are polled — nothing is pushed.** * **The Pi's half**, including that the runner serialises: three jobs per push, one at a time, so a pending check is not necessarily a slow one. ### 🔴 Two agent defects it records **A brief change does not reach a resumed session.** The entrypoint resumes the newest transcript with only a `<120 s` restart-loop guard, so a container restarted after a workflow change comes back following the *old* brief. Adopting a change means archiving the transcripts. **Nothing brought an agent back to its own red PR** — it pushed over a red CI six times. Fixed in #24, which is itself subject to the defect above. ### Also: `docker/ci/` The CI image existed on exactly one host and its Dockerfile was in a scratch directory under `/tmp`, which was swept. Same shape as everything else this consolidation has found. ``` docker/ci/Dockerfile rust 1.98.1 + the apt list copied from ci.yml docker/ci/Dockerfile.ffmpeg + ffmpeg, which sylpheed-export shells out to docker/ci/run 6 CPU / 7 GB / no swap, named cargo volumes ``` ```bash docker/ci/run cargo clippy --workspace --all-targets --keep-going -- -D warnings ``` ⚠️ Two traps written into the Dockerfile itself: the Rust version is **pinned here and floats on the runner** (issue #15 — when they disagree, the runner wins), and `cargo clippy` **stops at the first failing compilation unit**, so without `--keep-going` the list looks short and is not — 14 shown against 80 real, on the corpus branch.
fabi added 1 commit 2026-09-13 18:44:24 +00:00
docs(agents): how the containers and agents are actually set up
All checks were successful
CI / Native — linux (pull_request) Successful in 42m12s
CI / WASM — Web (pull_request) Successful in 26m29s
CI / Formatting (pull_request) Successful in 35s
70d3a54acb
Written for the other machine, which asked. Everything in it was read off the
running host rather than remembered.

Also adds docker/ci/ -- the CI image recipe and a capped runner -- because the
image existed on exactly one host and its Dockerfile was in a scratch directory
under /tmp, which was swept. That is the same shape as every other thing this
consolidation has turned up: something correct that exists in one place.

  docker/ci/Dockerfile          rust 1.98.1 + the apt list copied from ci.yml
  docker/ci/Dockerfile.ffmpeg   + ffmpeg, which sylpheed-export shells out to
  docker/ci/run                 6 CPUs / 7 GB / NO SWAP, named cargo volumes

The rule the runner exists to enforce: every heavy command goes in the capped
container. CARGO_BUILD_JOBS caps codegen units, not rustc's threads, not the
linker, not the test harness -- a bare host build is unbounded and has frozen
this box repeatedly.

The document also records the two agent defects the other machine will meet:
a brief change does not reach a RESUMED session, and nothing brought an agent
back to its own red PR (fixed in #24, which is itself subject to the first).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
fabi added 1 commit 2026-09-13 18:44:25 +00:00
docs(agents): how the containers and agents are actually set up
All checks were successful
CI / Native — linux (pull_request) Successful in 42m12s
CI / WASM — Web (pull_request) Successful in 26m29s
CI / Formatting (pull_request) Successful in 35s
70d3a54acb
Written for the other machine, which asked. Everything in it was read off the
running host rather than remembered.

Also adds docker/ci/ -- the CI image recipe and a capped runner -- because the
image existed on exactly one host and its Dockerfile was in a scratch directory
under /tmp, which was swept. That is the same shape as every other thing this
consolidation has turned up: something correct that exists in one place.

  docker/ci/Dockerfile          rust 1.98.1 + the apt list copied from ci.yml
  docker/ci/Dockerfile.ffmpeg   + ffmpeg, which sylpheed-export shells out to
  docker/ci/run                 6 CPUs / 7 GB / NO SWAP, named cargo volumes

The rule the runner exists to enforce: every heavy command goes in the capped
container. CARGO_BUILD_JOBS caps codegen units, not rustc's threads, not the
linker, not the test harness -- a bare host build is unbounded and has frozen
this box repeatedly.

The document also records the two agent defects the other machine will meet:
a brief change does not reach a RESUMED session, and nothing brought an agent
back to its own red PR (fixed in #24, which is itself subject to the first).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
fabi merged commit 94cb8ef836 into main 2026-09-15 19:15:12 +00:00
Sign in to join this conversation.