3.2 KiB
Context trim — design notes
What's shipped
Worker sessions are now resumed across iterations with claude --resume <sid>,
and the session JSONL is surgically trimmed between rounds so Anthropic's
prefix cache stays warm without paying for irrelevant history.
- Agent declares a
KEEP: <paths>line in.loop/notes.md. - Yoke locates
~/.claude/projects/<cwd-slug>/<sid>.jsonland rewrites it to retain only: bootstrap records, the initial user prompt,Readtool_use/tool_result pairs for kept paths, and attachments. Drops:thinking, intermediatetext, every non-Readtool_use,Reads of non-kept files, and the matchingtool_results. Re-links the parent-uuid chain across the gaps; validates tool_use ↔ tool_result pairing before commit; keeps a.bak. - Judge (brute) and scoper (saga) always run fresh — independence per behavioral-specification §2.1.
YOKE_DISABLE_SESSION_TRIM=1is the escape hatch.
What still needs adding
-
Format-drift guard. The Claude Code session JSONL is undocumented. A future CLI release could rename a field, change content-block shape, or move the file. The validator catches most damage post-trim, but pre-trim we should fingerprint the format (e.g., known top-level keys on bootstrap records) and bail if it drifts. Today we trust + bail on validate-fail; a positive check would be safer.
-
Recovery from
--resumefailure. If Claude rejects the resumed session (deleted, corrupted, version skew), the iteration aborts. We should detect this from the spawn's exit/early stream error and transparently retry once with no--resume(treat last_session_id as stale). -
Sandboxed runs. When
imageis set, the agent runs inside a Docker container — the session JSONL lives in the container's home, not the host's. Todaytrim_worker_sessionno-ops in that case (silent). Either mount the session dir into the container, or run the trim inside the container, or document the limitation. -
OpenCode backend. Trim is Claude-specific. OpenCode users get
--resumebenefits skipped (different session model). If OpenCode becomes a first-class target, we need an analogous trim or a reasoned-down equivalent. -
Fork policy. v1 has no forking: the trim alone bounds growth. But sessions still grow monotonically in the kept portion, and long-running tasks will eventually want a hard reset. A
context-fork-every Ndirective (or agent-declaredRESET: TRUE) would let users break the conversation cleanly at stage boundaries. -
Periodic-agent isolation. Periodics spawn fresh sessions but share the project's session directory. If a periodic ever needed its own resumable continuity (e.g., a reviewer agent that learns over runs), today there's no separate session-id tracking for it.
-
Saga handoff. Across saga cycles the scoper is fresh and reads
saga-log.mdto reconstruct context. A future variant could let the brute worker inside saga keep its session across cycles when the scoper produces a closely-related sub-plan — but only if the scoper signals it (otherwise context bleeds between unrelated chunks).
Next steps involve creating some test vectors to help make behavior standardized