Skip to content

Sandbox Survival Guide

Mikhail Deynekin edited this page Oct 14, 2026 · 1 revision

Sandbox Survival Guide

The kit is built for ephemeral agent sandboxes, and ephemeral sandboxes break things in characteristic ways: stale servers on collided ports, non-persistent temp dirs, absent terminals, empty package lists, runtimes below the subject's floor, and filesystem layers that disagree with themselves. This page is the operational guide to setup/PITFALLS.md (31 traps ordered by time wasted), the recovery-file system, snapshot discipline — plus one trap this wiki run discovered in the wild that the kit documents only in embryonic form.

Contents


The PITFALLS taxonomy

setup/PITFALLS.md groups 31 traps into four classes. The ordering is deliberate: class A traps produce silently wrong results, which is worse than a crash, so they come first and must be read before writing any probe.

Class Scope Traps The headline
A Wrong answers that look fine A1–A4 port collision → tests hit a stale server; a file named http.py shadows the stdlib; /tmp does not persist; the README lies
B Sandbox environment B1–B11 apt-get update first; curl may be absent; no pkill/lsof; heredoc path mangling; f-string backslashes (3.11); no controlling terminal; do not cat huge files; bundle clones need -b; composer needs unzip; distro runtime below subject floor; long probes losing filesystem visibility
C GitHub Wiki specifics C1–C8 filename↔URL↔wiki-link agreement; master branch; placeholder wikis; [[…]] in prose is live; the slug algorithm; mermaid &/quoting; nested fences; substring matching fires on quotes and negations
D Process D1–D8 rebuild derived data after renames; distrust your own checker once; write research files before you need them; keep a provenance table; budget the writing phase; narrow your avoid-patterns; never hardcode page names in templates; scope bulk regex rewrites

Each entry follows the same anatomy: the incident (what actually happened and what it cost), the symptom (often a misleading error), and the fix (usually "use the kit tool that exists because of this"). The document is append-only in spirit: classes gained B9–B11, C8 and D8 from the second field run, and this wiki run adds one more below.

B4 in the wild: path rewriting at the tooling layer

PITFALLS B4 warns that "absolute paths inside bash heredocs can get mangled". During this wiki run, the trap appeared in a sharper, fully deterministic form worth recording because it looks exactly like the transient B11 filesystem quirk and is not:

The incident. A backup script written through the agent's file-writing tool contained the literal path /home/user/work. Executed in the sandbox, its find /home/user/work … returned "No such file or directory" — while the same find, typed as a shell command in the same session, listed the directory fine. Retries, backoffs and wait-loops all "failed"; the condition looked transient.

The diagnosis. Base64-encoding tool output (which bypasses display rewriting) revealed the mechanism: the harness rewrote the literal string /home/user into "$ARENA_WORKSPACE" inside command strings before execution, but not inside file contents. Commands typed at the shell therefore always resolved to the real workspace; a script file kept the literal /home/user, which inside the execution container is an unrelated overlay directory. Worse, mkdir -p /home/user/backup/work in the script succeeded — creating junk in the overlay — so the failure looked like partial visibility rather than a wrong path. A separate display-layer rewrite maps real workspace paths back to /home/user in captured output, which hides the whole arrangement unless you encode around it.

The fixes, in order of preference (this is B4's ladder, confirmed):

  1. Inside script files, resolve the workspace at runtime: WS="${ARENA_WORKSPACE:-/home/user}" — never hardcode a sandbox-specific absolute path in a file.
  2. cd first and use relative paths in commands.
  3. Pass paths via environment variables.
  4. For diagnosis when outputs look impossible: encode them (base64) and decode outside the rewriting layer.

The lesson for wiki runs: when a sandbox quirk "matches" a documented pitfall but behaves deterministically instead of transiently, suspect the tooling layer itself — and record the finding in REWORK-STATE.md immediately, because it will otherwise cost the next agent the same 45 minutes.

The recovery-file system

Five files make a run resumable by a fresh agent (or by you after a context compaction). Update them at phase boundaries, not at the end:

File Role Key sections
STATE.md orientation current phase; layout map; confirmed facts (from the scan brief); checklist; done-so-far; the next single action; notes a fresh agent must not lose
PROGRESS.json machine state per-page status/words; style contract; do_not_claim; latest QA numbers; delivery fields
REWORK-STATE.md the recovery artefact resume recipe (5 steps); exact environment-rebuild commands; key-paths table; sandbox quirks learned (append as you hit them); checklist; next action; append-only log with evidence pointers
research/facts.json verified facts every value with a source; enough to resume writing without re-reading the subject
research/sources.md provenance §A citations · §B named tests · §C external · §D claims not made

The payoff, from the reference run: a hard session interruption in the middle of Phase 4 cost zero work because REWORK-STATE.md and research/ were current — resuming took one ls and one head.

Snapshot and backup discipline

Two complementary mechanisms:

# in-workspace git snapshots (branch 'snapshot'), at every phase boundary
bash setup/snapshot.sh workspace "phase 1 done"

# before ANY destructive bulk edit
cp -a workspace/wiki workspace/.backup-wiki-$(date -u +%s)

Rules this wiki run applied (and recommends):

  1. Snapshot at phase boundaries — a bad bulk edit then costs minutes, not hours.
  2. Mirror the whole workspace to a second location (work/ → backup/work/) with a verify-after-copy script: compare file counts, retry on transient failure, and print what was synced.
  3. Distrust your own backup verifier once (D2 applies to infrastructure too): this run's mirror script failed permanently until inspection showed its verification step counting its own .last-sync marker file — a self-inflicted mismatch. The copies had been succeeding all along.
  4. Never put deliverables in directories that snapshot systems exclude (dist/, build/, out/, node_modules/, caches) — they vanish between sessions (PITFALLS A3).
  5. Remember .git/config is among the excluded paths in agent-snapshot systems: a prepared clone can lose its origin on reload. publish.sh re-adds it on the fallback path for exactly this reason.

Environment triage at session start

The bootstrap capability report is your triage sheet. What to check before trusting any result:

Check Command Why
package lists bash setup/bootstrap.sh (starts with apt-get update) installs fail with "Unable to locate package" until you update (B1)
interpreter vs subject floor python3 setup/check_runtime.py repo/SUBJECT exit 2 = every probe would measure a corpse (B10)
unzip/zip presence capability report composer install without unzip prints a usage dump that reads like a wrong-flag error (B9)
port sanity lib/serve.py (never hand-roll php -S &) collided ports serve stale state (A1)
process tools assume pkill/pgrep/lsof/ss absent use the Python socket-bind probe from B3; serve.py tracks its own children
terminal assume none no interactive prompts anywhere in your scripts; git push will fail — plan for bundles (B6)
egress bootstrap's three URL checks know whether clone/publish paths can work at all

When a tool fails: the diagnostic ladder

  1. Read the error literally, then doubt it once. Misleading errors are documented per-trap (http.py shadowing names http.client; composer's usage dump; the B8 empty-tree clone that makes later checks pass vacuously).
  2. Verify one case by hand before believing a mass failure, and verify the checker can fail before believing a mass success (D2 — the 381/12/235 phantom-error incidents).
  3. Re-run in a fresh call/process. Some sandbox filesystem views are call-scoped; a failure that does not reproduce in a fresh process is an environment artefact, not a code defect — but record it in REWORK-STATE.md either way.
  4. Check the layer between you and the filesystem (the B4-in-the-wild story): harness path rewriting, display rewriting, mount timing. Encode outputs to see raw bytes when results look impossible.
  5. Snapshot, then experiment. Never debug destructively inside the only copy of a workspace.

See also

Clone this wiki locally