Run the full round-trip
// GUIDE · ROUND-TRIP
Reproduce, fix, verify, open both PRs — in one orchestrated loop.
The Vivarium round-trip skill walks an AI agent and a human through the full path from an upstream bug report to a draft fix PR. Phases 1-5 of the round-trip automation plan ship the underlying tooling; this guide is the human-readable companion to the `round-trip` Claude Code skill.
// 0 · WHAT THIS GUIDE COVERS
End-to-end orchestration of the round-trip loop.
This guide describes the round-trip loop in human-readable form:
what happens at each stage, what is automated, and what stays a
human decision. The machine-readable orchestration itself lives
in .claude/skills/round-trip/SKILL.md — auto-loaded
by Claude Code when its triggers match; you usually do not read
it directly.
If you only want to scaffold a recipe — without the full fix- and-PR loop — use the Getting started guide instead.
This guide is still under iteration. Concrete examples grow as the maintainer exercises the loop on real upstream issues; expect this page to fill out over time.
// 1 · PREREQUISITES
What you need installed and configured.
Run gh auth login if not already done. The skill calls gh issue view, gh pr create, gh workflow run, and gh run download; repo is the minimum scope.
See Use from your AI agent. The round-trip skill invokes search_upstream_issues, prepare_new_recipe, verify_and_report_fix, and (Layer 2) create_fork_pr.
Vivarium uses Sapling as its SCM rather than Git directly. The skill drives sl addremove / sl commit / sl amend / sl pr submit for the Vivarium-side PR.
A classic PAT with write:packages scope, stored per the one-time setup mise run ghcr:login documents. Used by mise run branch-fix:publish at Stage 5.5.
// 2 · THE FLOW AT A GLANCE
Ten stages, with a layer-dependent verdict path.
Stages 0 – 5 are layer-independent; the path branches at Stage 6 depending on whether the recipe is Layer 1 (WASM in-browser) or Layer 2 (Docker). Layer 3 (record-replay) is currently out of scope for the fixed-verdict capture — see the cheat sheet below.
Stage 0 Pre-flight (project activity, issue exists, no linked PR)
Stage 1 Scaffold (prepare_new_recipe + mise run recipes:new)
Stage 2 Implement reproduction (human + AI)
Stage 3 Capture unfixed verdict (verify_and_report_fix)
Stage 4 Open the Vivarium PR (sl pr submit, label ai: generated)
Stage 5 Fork upstream + push fix branch (human)
Stage 5.5 Layer 2 only: build & push branch-fix image
(mise run branch-fix:publish)
Stage 6 Capture fixed verdict
- Layer 1: prepare_fix_candidate → CI wheel build →
live recipe page (visual confirm by human)
- Layer 2: verify_and_report_fix with branch_image →
branch-fix-verdict.yml + artefact
Stage 7 Update Vivarium PR with fixed verdict
(Layer 2 only; sl amend + sl pr submit)
Stage 8 Open upstream draft PR
- Layer 1: commands returned by prepare_fix_candidate
- Layer 2: create_fork_pr (dry_run: false)
Stage 9 Final Vivarium-side commit
(Layer 2 only; sl amend + sl pr submit)// 3 · INVOKING THE SKILL
One sentence, the agent does the rest.
Tell your AI agent (Claude Code, Cursor, Cline) something like:
Run the full round-trip on https://github.com/owner/repo/issues/N. It is a Layer 2 bug; the title is "short title"; base image is
node:26-slim.
The agent picks up the round-trip skill (auto-loaded
when its trigger conditions match) and walks you through each
stage. At every hand-off back to you (Stages 2, 5, sometimes 6
for Layer 1) you confirm and the agent continues. On any failure
the skill sets roundtrip.json#/status to
"blocked" and stops — see Troubleshooting
below.
// 4 · LAYER 1 vs LAYER 2 CHEAT SHEET
The fixed-verdict path differs; everything else lines up.
| Layer 1 (WASM) | Layer 2 (Docker) | |
|---|---|---|
| Unfixed verdict source | In-browser Pyodide / Ruby.wasm / php-wasm, captured by
Playwright against | Deployed |
| Fix delivery | Fork branch → CI wheel build (fires on Vivarium PR merge
via | Fork branch → contributor builds the Docker image locally → GHCR push |
| Fixed verdict source | Live recipe page renders baseline + fix-candidate side-by-side; human confirms visually |
|
| Upstream PR opening | Commands returned by |
|
Layer 3 (record-replay): verify_and_report_fix
rejects Layer 3 verify_fixed with an informative
error — branch-fix-verdict.yml only handles
src/layer2_docker/<slug>/. Workflow extension
to handle src/layer3_thirdway/<slug>/ is
tracked separately.
// 5 · TROUBLESHOOTING
When the skill bails with status: blocked.
Any stage failure flips
roundtrip.json#/status to
"blocked" and stops the skill. A
subsequent /round-trip invocation on the same slug
refuses to resume until the human clears it.
To resume:
Read
roundtrip.json#/notes[]for the failure reason and stage number.Fix the underlying issue (typically: re-run the failed command manually with verbose flags to see what actually went wrong).
Edit
roundtrip.json— setstatusback to its expected value (likely"verifying"or"verified"depending on how far you got) and bumpupdated_at.Re-invoke
/round-trip. The skill re-readsroundtrip.jsonand resumes from the appropriate stage (thecomputeNextActionstate machine inverify_and_report_fixpicks the resume point).
Found something this guide didn't cover? File an issue against
aletheia-works/vivarium
so we can fold the gap back into this page.