# Execution plane — agentic work lives on the buildboxes

audience: AI coding agents first.

status: ACTIVE
task IDs: —
source request: 2026-08-14. Owner: get agent compute off the laptop; "it unlocks everything, high priority to finish it." Target endorsed by owner: buildboxes become the HOME of agentic work — full dev environments, real clones, own worktrees, own tmux sessions; work arrives by `git fetch`, leaves by `git push`. The laptop becomes a terminal + observability surface plus the few genuinely local things (deploys to local services, systray, `$HOME` installs). Owner ruling on the local-access question: NOT A GAP — ssh, `deck-sudo`, and `cld-unsafe` cover it; do not design further for it now.

## Why this outranks optimizing the mirror

The target architecture DELETES the transfer problem by removing the reason it exists. Everything
under S1–S3 below is scaffolding that becomes dead code once S4 lands. That is acceptable — the
scaffolding is needed meanwhile — but NEVER defend the mirror/transport work later as architecture.

## Measured state (2026-08-14, verified)

- Seat/agent dispatch rsyncs the working tree + `.git`: 227,135 files / 68.7 GB. Three dispatches
  died at exactly 900 s (debian1 x2, debian2 x1), each returning **exit 0 with an error body** — a
  silent-ish failure worth fixing on its own.
- Root cause was NOT the excludes: `.git` alone was 68 GB, of which 61.4 GB was 444 orphaned
  `tmp_pack_*` files (debris of git ops killed by full disk/OOM). Removing those untouched 90+ min:
  `.git` 69 GB → 6 GB, free 51 → 111.7 GB, mirror payload 68.7 → 8.2 GB.
- `git gc --prune=now` reclaimed nothing and broke a branch ref by racing conducting lands.
  Follow-up investigation: NO work was lost (the pruned tip was a duplicate — same message, same
  parent — of a commit already in main); ref restored from `73a8cc50c` with the reason in its
  reflog. Standing rule in memory: never `--prune=now` here; sweep time-gated `tmp_pack_*` instead.
- `harness-seat:2` does not exist on ANY buildbox — the harness-seat path has never run.
- Load/RAM freed tonight: 26 idle language servers reaped (load 52.9 → 12.2, +10 GB RAM), so
  parallel lanes are affordable again.

## Slices — each ends in an observable behaviour change

**S1 — no-workspace dispatch mode.** Pure-inference calls (research, consultations, reviews) ship
NOTHING. Highest value per unit of work in this plan: three of tonight's failures were exactly this
shape and would have succeeded instantly. OBSERVE: a `cdx exec` research prompt from the repo
returns in seconds with no mirror.

**S2 — git-push transport** (dispatched, `wt/dispatch-git-transport`). Remote holds a bare mirror;
push the commit (delta-only); remote checks out that sha into a clean workspace; uncommitted WIP
travels as a temp commit/patch. Reuse `remote-build.mjs` git-mirror plumbing — never a third
implementation. Fold in the `__pycache__` exclude. Also fix the exit-0-with-error-body reporting.
OBSERVE: a real dispatch receipt — payload bytes + wall time + containment record — before/after.

**S3 — seat image on the boxes** (dispatched, `wt/seat-image-provisioning`). Prerequisite for
container-isolated sessions. FALLBACK IF IT STALLS (registry access, base pulls, debian3 disk):
sessions can run on a box WITHOUT the container — plain tmux + clone — less isolated, unblocks the
goal. Never force debian3 past its disk floor. OBSERVE: `podman image exists harness-seat:2` true
on debian1/2, and a seat container starting.

**S4 — box-resident sessions (the actual target).** Worker/orchestrator sessions run on the boxes:
real clone, own worktrees, own tmux; `git fetch` in, `git push` out; the laptop's deploy watcher
picks up `origin/main` and deploys locally with no laptop session involved. Move
worker/orchestrator sessions FIRST (nobody attaches to those); the interactive session moves last
or never. Prerequisite that is NOT yet done: `~/.claude` parity on the boxes (hooks, skills,
memory, settings) — see the two-writers hazard in memory. OBSERVE: a lane executes start to finish
with zero agent processes on the laptop.

**S5 — factory pi off-laptop** (dispatched, `wt/factory-pi-remote`). The factory spawns `pi`
locally via `PI_PATH`; route that seam through the dispatch machinery. Config-gated, default local
until proven, fail-closed (never a silent local fallback), factory suite green (186/186 baseline).
NOT ESTIMATED IN DAYS — first checkpoint is "does pi run at all on a box" (binary + auth presence);
duration is unknown until that answers. The earlier "~1–2 days" is withdrawn as unmeasured.

## Decisions recorded

- **Codex adapter for the factory: rejected — on OBSERVABILITY grounds only.** The metered-account
  argument is void (codex delegation already sends volume there) and must not be cited; if someone
  reopens this, the answer is that a codex adapter loses the factory's trace/gate/event surface.
- **Dispatch modes are three, not one** (no-workspace / git-fetched / mirrored-dirty). One heavy
  path for every workload is why a question needing zero files shipped 68 GB.
- **Local-only actions are not a gap** (owner ruling): ssh + `deck-sudo` + `cld-unsafe`, plus the
  deploy watcher already consuming `origin/main`. Do not build a mechanism for this.
- Estimates in this plan are checkpoints, not durations. Duration claims for infra work here have
  been wrong by 4x today; state the next checkpoint instead.

## Parallelism

Disjoint files, safe to run concurrently: S1 + S2 (both `remote_dispatch.py`/`remote-build.mjs` —
NOT disjoint, must serialize: S1 first, it is smaller), S3 (buildbox provisioning, no repo files),
S5 (`modules/harness/factory`). S4 waits on S3 + `~/.claude` parity.

## Current receipt

2026-08-14: plan registered. S2, S3, S5 dispatched. S1 dispatched immediately after this landing —
it is the smallest change fixing the largest share of observed failures.
