Reconstructing Environments From Trajectories
Given a directory of terminal/code-agent trajectories (tool-call logs with file reads/writes/edits and shell commands), turn each into a reusable environment:
- Parse trajectory
τinto an ordered list of file/tool operations. - Replay operations, but for every
Write/Edit, restore the pre-edit file content (found in precedingReador diff context) instead of the agent's final version — this yields a partial, unsolved workspace. - Run a completion agent over the partial workspace to synthesize missing files, configs, and dependencies (without ever revealing the agent's original fix).
- Validate the workspace boots/builds; if not, iterate completion.
- Re-query the environment: reconstruct the original task, synthesize new single-workspace tasks, cross-workspace tasks, and multi-round sessions.
- Attach an agent-authored executable verifier to each new task; discard any task-trajectory pair whose tests don't pass.
Progress:
- Step 1: Ingest trajectory and extract tool-execution history (Read/Write/Edit/Bash calls)
- Step 2: Deterministic replay — roll back agent's own edits to reconstruct pre-agent file states
- Step 3: Agentic completion — fill gaps (missing files, deps, configs) without solution leakage
- Step 4: Sanity-check the recovered workspace is executable
- Step 5: Re-query — generate tasks along vanilla, breadth (cross-workspace), and depth (multi-round) axes
- Step 6: Verify — agent writes an executable test/verifier for each new task
- Step 7: Filter — keep only environments where solved trajectories pass all verifiers
Step 1 — Extract tool-execution history. Parse the trajectory into a sequence of typed operations. Read(path) reveals file content at that point in time; Write(path, content) / Edit(path, diff) reveal both prior and posterior states. Preserve ordering — later replay depends on operation sequence, not just final diffs.
Step 2 — Deterministic replay. For every file the agent touched, reconstruct the version that existed before the agent's first modification (using the content shown in the earliest Read, or by inverting the recorded diff). Do NOT replay the agent's own fix — that's the solution, and leaking it defeats the purpose of building a re-solvable environment. The result is a partial workspace: correct in structure, but missing anything the agent never touched (e.g., untouched sibling files, lockfiles, hidden config).
Step 3 — Agentic completion. Because replay only recovers what appears in the trajectory, dispatch a completion agent to inspect the partial workspace (imports that resolve to nothing, config referencing absent files, package manifests without lockfiles) and generate the missing pieces plausibly. Constrain this agent explicitly: it must not reconstruct or hint at the original fix, only supply neutral scaffolding/dependencies needed for the workspace to run.
Step 4 — Sanity-check. Attempt to build/boot the workspace (install deps, run existing tests if any). If it fails, feed the error back into the completion agent for another pass. Cap retries; discard environments that never stabilize.
Step 5 — Re-query (task synthesis). Generate tasks in four modes:
- Reconstructed intent: recover the original task the trajectory was solving.
- New single-workspace task: propose a different task on the same recovered workspace.
- Breadth (cross-workspace): mine directional dependency relations between environments recovered from related trajectories (e.g., one project references or could import from another) and synthesize tasks spanning multiple workspaces — porting a feature, wiring two components together, using one repo as a reference implementation for another.
- Depth (multi-round): after an initial task is solved, run a user-simulator agent that inspects the resulting workspace state and issues a grounded follow-up — either a new requirement building on the change, or (if verification failed) a fix request referencing the actual failure. Repeat for several rounds, feeding real verifier output back as user-visible feedback each round.
Step 6 — Verification. For every synthesized task, have an agent write an executable verifier (tests, assertions, or scripted checks) inside the container, grounded in the actual recovered workspace state, not the abstract task description.
Step 7 — Filter. Roll out a candidate solution (e.g., with a strong teacher model) against each task; run the verifier. Keep only (environment, task, verifier) triples where all checks pass. Discard everything else rather than trying to fix it — filtering is cheaper and safer than debugging synthetic tasks.
Example 1: Single trajectory → reusable environment
Input: A trajectory shows Read("src/utils.py") returning old content, then Edit("src/utils.py", diff) adding a caching decorator, then Bash("pytest tests/test_utils.py") passing.
Output: Recovered workspace contains src/utils.py in its pre-edit state (no caching decorator). Completion agent notices tests/test_utils.py imports pytest_cache_helpers, which was never read/written in the trajectory, and generates a plausible stub/dependency for it so the test suite is importable. Original task reconstructed as: "Add caching to utils.py functions to reduce redundant computation; existing tests must pass."
Example 2: Breadth expansion Input: Two recovered environments — Repo A (a logging library) and Repo B (a web service) — where B's trajectory history shows it referencing patterns similar to A's public API. Output: New cross-workspace task: "Port the structured-logging module from Repo A into Repo B's request pipeline, replacing its ad-hoc print statements, while keeping Repo B's existing tests green." Verifier checks Repo B's test suite plus new assertions that log output is structured JSON.
Example 3: Depth expansion
Input: Round 1 task "Fix the null-pointer bug in parse_config" is solved and verified.
Output: User-agent inspects the diff, sees parse_config now handles nulls but ignores malformed YAML, and issues Round 2: "Now that nulls are handled, can you also make it raise a clear error on malformed YAML instead of crashing?" New verifier added for the YAML-error case; both rounds' verifiers must pass together.
- Always hold back the agent's own edits during replay — the whole value of the environment is that it starts unsolved.
- Prefer filtering failed synthetic tasks over trying to repair them; verifier-based rejection is more reliable than manual QA at scale.
- Ground every multi-round follow-up in the actual current workspace/diff/test-failure state, not an abstract plan — this is what makes depth expansion realistic rather than scripted.
- When mining cross-workspace dependencies, look for genuine directional relationships (one project could plausibly import/reference the other), not arbitrary pairings — this preserves realism.
- Re-solve each new task with a strong model rather than reusing the original agent's trajectory as ground truth; re-solving in the reconstructed environment is far more valuable than imitating the raw trajectory.
- Keep completion agents strictly scoped to "make it runnable," never "make it correct" — solution leakage silently invalidates the task.
- Replaying the agent's final edits by mistake, which bakes the solution into the "unsolved" environment and makes every downstream task trivial or invalid.
- Letting the completion agent infer and pre-apply the fix when filling gaps (e.g., "helpfully" adding the exact missing function the original task required).
- Treating trajectory imitation as sufficient signal — a single frozen demonstration cannot be verified or re-queried, so training on raw imitated trajectories underperforms training on re-solved, verified environments.
- Skipping the executable sanity-check step and shipping workspaces that don't actually build, which silently corrupts downstream verifier results.
- Building multi-round tasks from scripted, pre-planned follow-ups instead of state-grounded ones, producing unrealistic dialogues that don't reflect real iterative development.
- Pairing cross-workspace tasks between unrelated repos just to hit a quota, producing synthetic-feeling "combine X and Y" tasks with no genuine dependency logic.