A guided walk through the system as it exists — following one worker run from spawn to sealed trace, with the real transcripts at each proven stop.
Everything marked with a transcript ran today against live agents. The tour order is the lifecycle order: it is also, not coincidentally, the order the data flows. Companion pages: the plan as approved (what we committed to) and the rolling status page.
Three things exist at runtime. The worker is an unmodified harness (Claude Code today; Codex and Gemini on the observe-only lane) running a task inside a disposable container. The watcher is a path watch process injected into that same container, deriving the worker's session into Toolpath steps as they stabilize and streaming every emission out over the exec pipe. The orchestrator is drover on the host: it consumes the stream, checkpoints the sandbox on every step, and holds the fork, revert, resume, and select verbs. The trace is the contract between all three — the same document format whether it is growing live, being forked, or being read back next month.
Scope.start() creates the container from arena's image, forwards harness auth the way arena's runner does (Claude's OAuth token travels as an environment variable from the host keychain, so no credential ever lands in a file drover touches), injects the Linux path binary, and initializes /drover-snap: a bare shadow git repository whose work tree is /work, plus a directory for session-store tars. Scope.attach() does the same to a container arena already started, which is how the gates wrap live arena runs.
The design rule set here governs everything downstream: the worker must not be able to tell it is being observed or snapshotted. The shadow repo has its own GIT_DIR, so the agent's own git log, index, and git status never change when a checkpoint lands — an agent that saw phantom commits appear mid-run would reasonably start debugging its own repository. The container tests verify this invariant directly.
The watcher polls the session store and re-derives the full path on every poll with the same derive_path the import lane uses — live output cannot drift from post-hoc output because there is no second derivation to drift. Steps are withheld while they can still change (tool results attach to the trailing assistant turn; event steps re-parent as the session grows) and appended once stable, so the .path.jsonl is a valid document at every line boundary. Every emission — file lines verbatim, plus provisional tail steps — goes out on stdout, and drover's LiveTrace mirrors the file lines into a host-side copy.
Two contracts came out of the real runs rather than the plan. First, the transport is the exec pipe, not a shared filesystem: the watcher runs inside the sandbox, which behaves identically on remote VMs and ends every cross-VM coherence question. Second, sealing is completion-triggered: the orchestrator spawned the worker, so the orchestrator knows when it finished; inactivity is not a proxy for completion, because one long generation outlasts any reasonable idle window. The idle timeout survives only as a fallback against orphaned watchers.
$ GATE_LIVE_MOUNT=1 ARENA_PATH_BIN=…/toolpath/target/debug/path \ uv run python tests/manual_live_arena.py [gate] session visible in container: 5add62b9-8952-4aea-a4a1-9243954c6cd4 [arena] run …7de017c2: verifier=PASS toolpath=ok steps=35 cost=$0.096 [gate] sealed: steps=35 head=3614750a-ab64-4da1-83fc-3b551bd0fa6b OK: live-watched (in-container) == harvested import (35 steps)
The invariant this gate enforces is the foundation of everything else: a trace observed live is the same document a forensic import would produce later, byte for byte. It also holds in three cheaper forms — a Rust integration test replaying a captured fixture, a CLI smoke test, and the Python client's pytest.
On every live Step event, the orchestrator calls scope.checkpoint(step_id): a shadow commit of /work plus a tar of the session store, recorded in a sidecar keyed by the Toolpath step id and merged into the sealed document as step.meta.extra.snapshot. The step id is the join key across the whole system — the trace names the moment, the checkpoint names the state, and fork takes both.
One rule the fork gate encodes: checkpoints taken during the seal flush are discarded. At seal, withheld steps flush at once; snapshotting them would stamp final-state filesystems with mid-run step ids — a quiet lie that would surface later as a fork restoring the wrong world. Only live-streamed steps earn checkpoints. The git-shadow backend is the portable default everywhere, including Prime Intellect (whose gVisor blocks OverlayFS); the OverlayFS backend remains ahead for full-rootfs tasks and the paper-parity latency table.
Reverting is the small case: shadow-checkout the commit, clean what came after, untar the session store — the workdir digest afterwards equals the checkpoint's exactly, and the agent's own git never notices. Forking is the interesting case, and it happens at two layers at once. At the format layer, path fork truncates the document at the chosen step and rebases it: the new path keeps exactly the fork point's ancestry, heads at the fork step, and records lineage as base.uri = "toolpath:parent/step" — a representation the RFC had reserved before this project existed. At the sandbox layer, a sibling container is seeded from the shadow commit via git archive, and the native session JSONL is truncated after the fork step's line.
That native truncation is the same-harness fast lane: Claude Code names its JSONL entries by uuid, Toolpath preserves those uuids as step ids, so cutting the file after the fork step's uuid reconstructs the byte-exact prefix without any projection. Cross-harness forks — continue a Claude run in Codex — take the path fork + projector route instead.
The forked child resumes with plain claude --resume against its truncated session. Because the kept prefix is byte-identical to what the parent already sent, the provider's prompt cache recognizes it — the model's context is warm without reprocessing a single early step. This is the property the whole design funnels toward, and it is now a measured fact rather than a design hope:
$ uv run python tests/manual_fork_resume.py [gate] session 255f2c2d-3e7c-4b85-a988-040c966fd77c in arena-20260707T153743-… [gate] sealed 24 steps; 14 live checkpoints [gate] forking at cdba5afe-1394-4366-ac28-c6c2809f0977 [gate] resume rc=0 result='Done! All tests pass. The slugify function correctly: - Lowercases text and strips accents using Unicode decomposition -' [gate] cache_read_input_tokens on resumed turns: max=29921 OK: forked at cdba5afe…, resumed with cache_read=29921 tokens
A live worker, checkpointed on every streamed step, forked at a mid-run user turn, resumed in a sibling container — and 29,921 tokens of prefix served from cache. This is the tweet's step-8/step-10 rescue, executed: the child kept everything the parent had learned up to the fork and paid only for the new suffix.
A run's output is a proposal, not a side effect. The worker's changes exist as a diff against its baseline commit inside its own sandbox; Scope.diff() reads it, select() writes it out for application, and discard() throws the container away. Between held proposals and per-step checkpoints, the destructive verbs in this system all operate on copies — the only irreversible acts are the ones the worker performs against the outside world, which is exactly the class the phase-3 intent gate exists to catch before they fire.
The system so far has eyes (the live lane) and a time machine (scopes). What it grows next, in order: hands — the phase-3 control lane, where mid-run injection rides the worker's stdin, a PreToolUse hook turns every tool intent into an allow/deny decision, and denials land in the trace as dead-end steps; judgment — the phase-4 meta-agent tick loop and the phase-5/6 applications (compression first: its every mechanical dependency passed today, and it produces the demo artifact — a failed run forked, hinted, and passing in fewer steps); and receipts — the phase-7 Tree-GRPO leg feeding prime-rl, and the phase-8 benchmark tables lined up against the paper's.
| Component | Where | Status | Evidence |
|---|---|---|---|
| toolpath-live (streaming derivation) | toolpath · live/trace-lane · 911eaf9 | SHIPPED | 7 unit tests + fixture-replay roundtrip test |
| path watch / path fork | toolpath · live/trace-lane · 911eaf9, a601e2c | SHIPPED | CLI smoke gate; 4 fork tests incl. schema validation |
| arena --live (binary injection, session-dir mount) | arena · live/trace-lane · f87e8b3 | SHIPPED | drives both real-agent gates |
| drover trace.LiveTrace (local + exec transports) | drover · main · 44c025b | SHIPPED | pytest + real-run gate: live == import, 35/35 |
| drover scopes.Scope (checkpoint/revert/fork/select) | drover · main · c1e8563, b1d3adc | SHIPPED | 4 container tests + fork-resume gate: cache_read 29,921 |
| Snapshot refs merged into sealed docs; OverlayFS backend | drover / toolpath | PHASE 2 TAIL | — |
| control/ (inject, hook gate, handoff, discard) | drover | PHASE 3 | gate defined: denied canary intent → dead-end step |
| meta/ + apps/ (supervisor, compress, CRO, Tree-GRPO) | drover | PHASES 4–7 | bars set by the paper's numbers |
A long generation outlasts any idle window. The orchestrator knows when its worker exited; that is the seal signal, with idle demoted to an orphan-cleanup fallback.
The watcher lives in the sandbox and streams out over exec stdout. Identical on laptops and remote VMs, and immune to cross-VM cache coherence.
Separate GIT_DIR, untouched agent index — verified by test, because an agent that sees phantom commits will debug its own repo.
Only live-streamed steps earn snapshots — flushed steps would pin final state under mid-run ids and forks would restore the wrong world.
Installed path 0.14.0 backfills empty preamble timestamps that repo main preserves faithfully (known upstream bug, fix in flight elsewhere); both lanes of any comparison run the same build.
One meta-agent call separates today's machinery from the first demo: read a failed trace, emit {fork_step, hint}, rerun through the proven fork-resume loop, and pass the verifier in fewer steps — one Toolpath graph whose dead end is the original attempt. The mock on the plan page becomes a transcript here.