F01 — Fork, clone, and Doctor safety
Choose the commands you use
Operating system
CodeArbiter host
Know before you begin
No prior Academy lesson is required. Complete five Academy Home setup steps before Prepare. New here? Stop on this page until you have created your personal GitHub fork, cloned that fork, installed Academy, chosen and installed your CodeArbiter host, and run Home Doctor in the clone. An expected missing upstream finding proceeds to F01; this lesson repairs that boundary. Those steps require Git 2.39 or newer, Python 3.11 or newer, and Claude Code, Codex, or Pi.
Work only in the arbiter-academy fork and clone you prepared from Home. A fork is the GitHub copy you own. A clone is its local working copy. In that clone, origin must mean your fork and upstream must mean the official arbiterForge/arbiter-academy repository. You fetch updates from upstream, but this lesson makes pushing there fail locally.
Begin on a clean main: clean means the repository has no staged or unstaged changes. Keep the Installed Academy commands available in a Native terminal for preparation, Doctor, Check, and Reset. Use that terminal for a command you run directly. When a command appears for your Claude Code, Codex, or Pi harness, its single leading ! passes that shell command to the terminal. CodeArbiter commands never use !.
What you will prove
You will create one numbered attempt, make push routing safe, pass both Doctors, and commit only the bounded Doctor report through CodeArbiter. Then the externally installed Academy verifier will read the committed report and current Git configuration before recording progress. It does not trust code imported from this learner checkout.
The evidence report must decode to exactly these three values (formatting whitespace may differ):
{"schema_version":1,"safe_for_push_labs":true,"effective_push_remote":"origin"}
Prepare safely
Prepare a numbered attempt
Run the installed Academy Prepare command from the clone. Begin only from a clean main branch. The <attempt> shown in later branch names means the number Academy prints; do not type the angle-bracket placeholder.
Preparation creates and switches to an isolated numbered branch while preserving main.
You · Native terminal · Windows
$academy = "$env:LOCALAPPDATA\ArbiterAcademy\preview-0.30\Scripts\arbiter-academy.exe"
& $academy --repository (Get-Location).Path prepare F01-fork-clone-doctor
You · Native terminal · macOS
academy="${XDG_DATA_HOME:-$HOME/.local/share}/arbiter-academy/preview-0.30/bin/arbiter-academy"
"$academy" --repository "$PWD" prepare F01-fork-clone-doctor
You · Native terminal · Linux
academy="${XDG_DATA_HOME:-$HOME/.local/share}/arbiter-academy/preview-0.30/bin/arbiter-academy"
"$academy" --repository "$PWD" prepare F01-fork-clone-doctor
Academy prints a prepared branch named academy/F01-fork-clone-doctor/<attempt> and switches the repository to it.
If Prepare stops, preserve its message. Return to Recovery for the matching dirty-worktree, wrong-branch, remote, or existing-attempt path before retrying.
The prepared branch is the only place where this lesson evidence may be committed.
The branch printed by Academy has the form academy/F01-fork-clone-doctor/ATTEMPT_NUMBER. Here, ATTEMPT_NUMBER means the number Academy prints, such as 1; it is not text you type literally.
Inspect fetch and push routing
Run the command for your operating system and execution surface. Read every fetch and push line before changing a remote.
Inspection distinguishes the fork you own from the official repository you only fetch from.
You · Native terminal · Windows
git remote -v
You · Native terminal · macOS
git remote -v
You · Native terminal · Linux
git remote -v
You · Claude Code harness · Windows
!git remote -v
You · Claude Code harness · macOS
!git remote -v
You · Claude Code harness · Linux
!git remote -v
You · Codex harness · Windows
!git remote -v
You · Codex harness · macOS
!git remote -v
You · Codex harness · Linux
!git remote -v
You · Pi harness · Windows
!git remote -v
You · Pi harness · macOS
!git remote -v
You · Pi harness · Linux
!git remote -v
Git prints the current fetch and push URLs for origin and any upstream remote.
If Git reports that this is not a repository, stop and return to the cloned arbiter-academy root. If a remote is absent, continue with the repair actions; do not invent a URL.
You can name which repository each remote reaches and whether it is used for fetch or push.
Practice
Repair only the fact each action names, then inspect the result. Do not copy a guessed owner, remove a remote to silence a diagnostic, or make the official repository a push destination.
Point origin at your fork
Replace <your-account> with the GitHub owner shown on your fork, then run the command for your operating system and execution surface.
origin must be a repository you control before any lesson can safely push.
You · Native terminal · Windows
git remote set-url origin https://github.com/<your-account>/arbiter-academy.git
You · Native terminal · macOS
git remote set-url origin https://github.com/<your-account>/arbiter-academy.git
You · Native terminal · Linux
git remote set-url origin https://github.com/<your-account>/arbiter-academy.git
You · Claude Code harness · Windows
!git remote set-url origin https://github.com/<your-account>/arbiter-academy.git
You · Claude Code harness · macOS
!git remote set-url origin https://github.com/<your-account>/arbiter-academy.git
You · Claude Code harness · Linux
!git remote set-url origin https://github.com/<your-account>/arbiter-academy.git
You · Codex harness · Windows
!git remote set-url origin https://github.com/<your-account>/arbiter-academy.git
You · Codex harness · macOS
!git remote set-url origin https://github.com/<your-account>/arbiter-academy.git
You · Codex harness · Linux
!git remote set-url origin https://github.com/<your-account>/arbiter-academy.git
You · Pi harness · Windows
!git remote set-url origin https://github.com/<your-account>/arbiter-academy.git
You · Pi harness · macOS
!git remote set-url origin https://github.com/<your-account>/arbiter-academy.git
You · Pi harness · Linux
!git remote set-url origin https://github.com/<your-account>/arbiter-academy.git
Git updates origin without printing output; a later git remote -v shows your account for both origin URLs.
If Git says origin does not exist, stop: this is not the expected fork clone. Return to Home and clone your fork rather than adding a guessed origin.
Live Git configuration identifies origin as a non-official arbiter-academy repository.
Set the official fetch remote
Run the idempotent command for your operating system and execution surface. It adds upstream when absent and corrects its fetch URL when present.
upstream gives the clone a stable read path to the official Academy without changing origin.
You · Native terminal · Windows
$null = git remote get-url upstream 2>$null; if ($LASTEXITCODE -eq 0) { git remote set-url upstream https://github.com/arbiterForge/arbiter-academy.git } else { git remote add upstream https://github.com/arbiterForge/arbiter-academy.git }
You · Native terminal · macOS
git remote get-url upstream >/dev/null 2>&1 && git remote set-url upstream https://github.com/arbiterForge/arbiter-academy.git || git remote add upstream https://github.com/arbiterForge/arbiter-academy.git
You · Native terminal · Linux
git remote get-url upstream >/dev/null 2>&1 && git remote set-url upstream https://github.com/arbiterForge/arbiter-academy.git || git remote add upstream https://github.com/arbiterForge/arbiter-academy.git
You · Claude Code harness · Windows
!$null = git remote get-url upstream 2>$null; if ($LASTEXITCODE -eq 0) { git remote set-url upstream https://github.com/arbiterForge/arbiter-academy.git } else { git remote add upstream https://github.com/arbiterForge/arbiter-academy.git }
You · Claude Code harness · macOS
!git remote get-url upstream >/dev/null 2>&1 && git remote set-url upstream https://github.com/arbiterForge/arbiter-academy.git || git remote add upstream https://github.com/arbiterForge/arbiter-academy.git
You · Claude Code harness · Linux
!git remote get-url upstream >/dev/null 2>&1 && git remote set-url upstream https://github.com/arbiterForge/arbiter-academy.git || git remote add upstream https://github.com/arbiterForge/arbiter-academy.git
You · Codex harness · Windows
!$null = git remote get-url upstream 2>$null; if ($LASTEXITCODE -eq 0) { git remote set-url upstream https://github.com/arbiterForge/arbiter-academy.git } else { git remote add upstream https://github.com/arbiterForge/arbiter-academy.git }
You · Codex harness · macOS
!git remote get-url upstream >/dev/null 2>&1 && git remote set-url upstream https://github.com/arbiterForge/arbiter-academy.git || git remote add upstream https://github.com/arbiterForge/arbiter-academy.git
You · Codex harness · Linux
!git remote get-url upstream >/dev/null 2>&1 && git remote set-url upstream https://github.com/arbiterForge/arbiter-academy.git || git remote add upstream https://github.com/arbiterForge/arbiter-academy.git
You · Pi harness · Windows
!$null = git remote get-url upstream 2>$null; if ($LASTEXITCODE -eq 0) { git remote set-url upstream https://github.com/arbiterForge/arbiter-academy.git } else { git remote add upstream https://github.com/arbiterForge/arbiter-academy.git }
You · Pi harness · macOS
!git remote get-url upstream >/dev/null 2>&1 && git remote set-url upstream https://github.com/arbiterForge/arbiter-academy.git || git remote add upstream https://github.com/arbiterForge/arbiter-academy.git
You · Pi harness · Linux
!git remote get-url upstream >/dev/null 2>&1 && git remote set-url upstream https://github.com/arbiterForge/arbiter-academy.git || git remote add upstream https://github.com/arbiterForge/arbiter-academy.git
upstream exists and its fetch URL is https://github.com/arbiterForge/arbiter-academy.git.
If Git rejects the command, run the inspection action again and preserve its exact output. Do not remove a remote until you understand what it points to.
The official repository is reachable through upstream for fetch operations.
Disable pushes to upstream
Run the command for your operating system and execution surface. DISABLED is an intentional non-network push target.
A disabled upstream push URL turns an accidental upstream push into a local failure.
You · Native terminal · Windows
git remote set-url --push upstream DISABLED
You · Native terminal · macOS
git remote set-url --push upstream DISABLED
You · Native terminal · Linux
git remote set-url --push upstream DISABLED
You · Claude Code harness · Windows
!git remote set-url --push upstream DISABLED
You · Claude Code harness · macOS
!git remote set-url --push upstream DISABLED
You · Claude Code harness · Linux
!git remote set-url --push upstream DISABLED
You · Codex harness · Windows
!git remote set-url --push upstream DISABLED
You · Codex harness · macOS
!git remote set-url --push upstream DISABLED
You · Codex harness · Linux
!git remote set-url --push upstream DISABLED
You · Pi harness · Windows
!git remote set-url --push upstream DISABLED
You · Pi harness · macOS
!git remote set-url --push upstream DISABLED
You · Pi harness · Linux
!git remote set-url --push upstream DISABLED
Git updates the push URL without printing output; git remote -v later shows upstream (push) as DISABLED.
If Git says upstream does not exist, complete the preceding upstream action first. Never substitute the official GitHub URL as the push URL.
Live Git configuration makes upstream unusable as a push destination.
Make origin the default push remote
Run the command for your operating system and execution surface.
Explicit push routing avoids relying on a changing branch or Git default.
You · Native terminal · Windows
git config remote.pushDefault origin
You · Native terminal · macOS
git config remote.pushDefault origin
You · Native terminal · Linux
git config remote.pushDefault origin
You · Claude Code harness · Windows
!git config remote.pushDefault origin
You · Claude Code harness · macOS
!git config remote.pushDefault origin
You · Claude Code harness · Linux
!git config remote.pushDefault origin
You · Codex harness · Windows
!git config remote.pushDefault origin
You · Codex harness · macOS
!git config remote.pushDefault origin
You · Codex harness · Linux
!git config remote.pushDefault origin
You · Pi harness · Windows
!git config remote.pushDefault origin
You · Pi harness · macOS
!git config remote.pushDefault origin
You · Pi harness · Linux
!git config remote.pushDefault origin
Git writes the setting without printing output; git config --get remote.pushDefault prints origin.
If the later inspection prints another name or nothing, run this action once more from the attempt repository and inspect for repository-local configuration overrides.
remote.pushDefault resolves ordinary pushes through origin.
Ask CodeArbiter to inspect the host boundary
Ask the agent in your active harness to run the host-native Doctor command. Pi users may use the fallback when direct dispatch is unavailable.
Host Doctor confirms CodeArbiter activation and enforcement separately from Academy lesson evidence.
Your agent · Claude Code harness · All operating systems
/ca:doctor
Your agent · Codex harness · All operating systems
$ca-doctor
Your agent · Pi harness · All operating systems
/ca-doctor
Your agent · Pi harness · All operating systems
/skill:ca-doctor
Host Doctor reports that the active host owns its CodeArbiter commands and that repository enforcement is enabled.
If Host Doctor reports an installation, ownership, or enforcement failure, stop. Repair that host boundary before generating or committing Academy evidence.
A passing Host Doctor is a prerequisite; it is not the Academy report or checkpoint.
Generate the bounded Academy Doctor report
Run the installed Academy Doctor command for F01. Do not continue to the evidence commit if Doctor fails.
Academy Doctor recomputes the lesson-safe remote facts and writes only the bounded report.
You · Native terminal · Windows
$academy = "$env:LOCALAPPDATA\ArbiterAcademy\preview-0.30\Scripts\arbiter-academy.exe"
& $academy --repository (Get-Location).Path doctor F01-fork-clone-doctor
You · Native terminal · macOS
academy="${XDG_DATA_HOME:-$HOME/.local/share}/arbiter-academy/preview-0.30/bin/arbiter-academy"
"$academy" --repository "$PWD" doctor F01-fork-clone-doctor
You · Native terminal · Linux
academy="${XDG_DATA_HOME:-$HOME/.local/share}/arbiter-academy/preview-0.30/bin/arbiter-academy"
"$academy" --repository "$PWD" doctor F01-fork-clone-doctor
Academy Doctor passes and creates .codearbiter/reports/academy/F01-doctor.json.
If Doctor fails, do not stage or commit the report. Return to the named remote or host action, correct only that boundary, and run both Doctors again.
The report is newly generated from live Git configuration.
Doctor failure forbids the evidence commit. Continue only after Host Doctor passes and Academy Doctor creates .codearbiter/reports/academy/F01-doctor.json from the live repository state.
Inspect the exact report bytes
Run the command for your operating system and execution surface, then compare all three fields with the expected result before staging.
Reading the report prevents stale or malformed learner-controlled evidence from crossing the commit gate.
You · Native terminal · Windows
Get-Content -Raw -LiteralPath .codearbiter/reports/academy/F01-doctor.json
You · Native terminal · macOS
cat -- .codearbiter/reports/academy/F01-doctor.json
You · Native terminal · Linux
cat -- .codearbiter/reports/academy/F01-doctor.json
You · Claude Code harness · Windows
!Get-Content -Raw -LiteralPath .codearbiter/reports/academy/F01-doctor.json
You · Claude Code harness · macOS
!cat -- .codearbiter/reports/academy/F01-doctor.json
You · Claude Code harness · Linux
!cat -- .codearbiter/reports/academy/F01-doctor.json
You · Codex harness · Windows
!Get-Content -Raw -LiteralPath .codearbiter/reports/academy/F01-doctor.json
You · Codex harness · macOS
!cat -- .codearbiter/reports/academy/F01-doctor.json
You · Codex harness · Linux
!cat -- .codearbiter/reports/academy/F01-doctor.json
You · Pi harness · Windows
!Get-Content -Raw -LiteralPath .codearbiter/reports/academy/F01-doctor.json
You · Pi harness · macOS
!cat -- .codearbiter/reports/academy/F01-doctor.json
You · Pi harness · Linux
!cat -- .codearbiter/reports/academy/F01-doctor.json
The report decodes to {"schema_version":1,"safe_for_push_labs":true,"effective_push_remote":"origin"}; whitespace may differ but no other field is present.
If any field or value differs, leave the report uncommitted and run Academy Doctor again after correcting live Git configuration.
You have personally checked the exact file that the external verifier will later read.
Stage only the Doctor report
Run the command for your operating system and execution surface. Do not use git add . or add another path.
The lesson commit must contain only its bounded evidence report.
You · Native terminal · Windows
git add -- .codearbiter/reports/academy/F01-doctor.json
You · Native terminal · macOS
git add -- .codearbiter/reports/academy/F01-doctor.json
You · Native terminal · Linux
git add -- .codearbiter/reports/academy/F01-doctor.json
You · Claude Code harness · Windows
!git add -- .codearbiter/reports/academy/F01-doctor.json
You · Claude Code harness · macOS
!git add -- .codearbiter/reports/academy/F01-doctor.json
You · Claude Code harness · Linux
!git add -- .codearbiter/reports/academy/F01-doctor.json
You · Codex harness · Windows
!git add -- .codearbiter/reports/academy/F01-doctor.json
You · Codex harness · macOS
!git add -- .codearbiter/reports/academy/F01-doctor.json
You · Codex harness · Linux
!git add -- .codearbiter/reports/academy/F01-doctor.json
You · Pi harness · Windows
!git add -- .codearbiter/reports/academy/F01-doctor.json
You · Pi harness · macOS
!git add -- .codearbiter/reports/academy/F01-doctor.json
You · Pi harness · Linux
!git add -- .codearbiter/reports/academy/F01-doctor.json
Git stages only .codearbiter/reports/academy/F01-doctor.json and prints no output.
If staging fails, confirm the exact report path and that Academy Doctor succeeded. If another path is already staged, unstage it without discarding its work before continuing.
The proposed evidence boundary contains one path.
Review and approve the proposed boundary
Ask your agent to show the staged path and proposed CodeArbiter commit boundary. Confirm that only the F01 Doctor report is included, then supply any genuine approval the commit gate requests.
The learner approves what will become durable evidence; the agent owns the governed commit operation.
You · Claude Code harness · All operating systems
Show the staged path list and staged diff. Do not commit. Report whether the staged path list is exactly .codearbiter/reports/academy/F01-doctor.json and whether the report is the Doctor evidence I prepared. Do not stage, unstage, or modify anything.
You · Codex harness · All operating systems
Show the staged path list and staged diff. Do not commit. Report whether the staged path list is exactly .codearbiter/reports/academy/F01-doctor.json and whether the report is the Doctor evidence I prepared. Do not stage, unstage, or modify anything.
You · Pi harness · All operating systems
Show the staged path list and staged diff. Do not commit. Report whether the staged path list is exactly .codearbiter/reports/academy/F01-doctor.json and whether the report is the Doctor evidence I prepared. Do not stage, unstage, or modify anything.
The proposed boundary names only .codearbiter/reports/academy/F01-doctor.json, and any requested approval is an informed learner decision.
If another path appears, do not approve. Ask the agent to preserve and unstage the unrelated work, then review the boundary again.
Your approval applies only to the one-report commit.
Let the agent commit through CodeArbiter
Ask the agent in your active harness to invoke the host-native CodeArbiter commit gate. The learner does not run git commit for this evidence.
The commit gate verifies and records the exact approved boundary.
Your agent · Claude Code harness · All operating systems
/ca:commit
Your agent · Codex harness · All operating systems
$ca-commit
Your agent · Pi harness · All operating systems
/ca-commit
Your agent · Pi harness · All operating systems
/skill:ca-commit
CodeArbiter creates one commit whose changed path is only .codearbiter/reports/academy/F01-doctor.json.
If the gate blocks, preserve its finding and correct that boundary. Do not bypass the gate, run git commit directly, or commit when either Doctor failed.
The attempt branch now contains durable, governed learner evidence.
Confirm the attempt is clean
Run the command for your operating system and execution surface after the evidence commit.
External Check rejects uncommitted or staged state because it cannot reconstruct that state later.
You · Native terminal · Windows
git status --short
You · Native terminal · macOS
git status --short
You · Native terminal · Linux
git status --short
You · Claude Code harness · Windows
!git status --short
You · Claude Code harness · macOS
!git status --short
You · Claude Code harness · Linux
!git status --short
You · Codex harness · Windows
!git status --short
You · Codex harness · macOS
!git status --short
You · Codex harness · Linux
!git status --short
You · Pi harness · Windows
!git status --short
You · Pi harness · macOS
!git status --short
You · Pi harness · Linux
!git status --short
Git prints nothing.
If Git prints a path, preserve the evidence commit. Resolve or safely preserve that uncommitted path before Check; do not reset the attempt commit.
The worktree and index match the committed attempt.
Recognize success
The Doctor report contains only schema_version, safe_for_push_labs, and effective_push_remote. The evidence commit changes only .codearbiter/reports/academy/F01-doctor.json. Immediately before Check, git status --short prints nothing. No output is the expected successful result: the attempt is clean.
Check
Run the external Academy Check
Run the installed Academy Check command for F01. This invokes the externally installed verifier, not code imported from the learner checkout.
An external verifier independently reads the committed report and the current live Git configuration.
You · Native terminal · Windows
$academy = "$env:LOCALAPPDATA\ArbiterAcademy\preview-0.30\Scripts\arbiter-academy.exe"
& $academy --repository (Get-Location).Path check F01-fork-clone-doctor
You · Native terminal · macOS
academy="${XDG_DATA_HOME:-$HOME/.local/share}/arbiter-academy/preview-0.30/bin/arbiter-academy"
"$academy" --repository "$PWD" check F01-fork-clone-doctor
You · Native terminal · Linux
academy="${XDG_DATA_HOME:-$HOME/.local/share}/arbiter-academy/preview-0.30/bin/arbiter-academy"
"$academy" --repository "$PWD" check F01-fork-clone-doctor
Check prints checkpoint F01-fork-clone-doctor: passed; progress: .academy/progress.json.
Check failure preserves the clean committed attempt and its failure. Correct the named live boundary or run Reset for a numbered retry; do not delete the attempt commit.
Only after the external verifier reads the committed report and live Git configuration does it write .academy/progress.json.
A pass contains checkpoint F01-fork-clone-doctor: passed; progress: .academy/progress.json. The progress record is written only after the external verifier independently reads the clean, committed report and live Git configuration. A report by itself, a Host Doctor pass, or an Academy Doctor pass does not complete the lesson.
Recover or continue
If Check fails, preserve the clean committed attempt. Read the failed predicate, compare it with the matching action's expected result and recovery, and change only that boundary. Check failure never requires deleting the evidence commit.
Hint 1
Start with origin, upstream, and remote.pushDefault. Name where each push would go before changing it.
Hint 2
Both the committed report and the current Git configuration must be safe. Regenerate the report after changing a remote.
Hint 3
If an attempt mixes unrelated files into the evidence commit, preserve it and use Reset. A new numbered attempt is safer than rewriting evidence history.
Return to main after success
After Check passes, run the command for your operating system and execution surface.
Returning to the base branch leaves the completed attempt preserved for audit and later review.
You · Native terminal · Windows
git switch main
You · Native terminal · macOS
git switch main
You · Native terminal · Linux
git switch main
You · Claude Code harness · Windows
!git switch main
You · Claude Code harness · macOS
!git switch main
You · Claude Code harness · Linux
!git switch main
You · Codex harness · Windows
!git switch main
You · Codex harness · macOS
!git switch main
You · Codex harness · Linux
!git switch main
You · Pi harness · Windows
!git switch main
You · Pi harness · macOS
!git switch main
You · Pi harness · Linux
!git switch main
Git switches to main and the numbered F01 attempt branch remains available.
If Git refuses because of uncommitted work, stop and preserve it. Do not force the switch or delete the completed attempt branch.
The completed attempt remains separate from main.
Create a preserved numbered retry
Use this only when you need another attempt: run the installed Academy Reset command for F01.
Reset archives the current attempt ref and prepares the next unused numbered branch without erasing evidence.
You · Native terminal · Windows
$academy = "$env:LOCALAPPDATA\ArbiterAcademy\preview-0.30\Scripts\arbiter-academy.exe"
& $academy --repository (Get-Location).Path reset F01-fork-clone-doctor
You · Native terminal · macOS
academy="${XDG_DATA_HOME:-$HOME/.local/share}/arbiter-academy/preview-0.30/bin/arbiter-academy"
"$academy" --repository "$PWD" reset F01-fork-clone-doctor
You · Native terminal · Linux
academy="${XDG_DATA_HOME:-$HOME/.local/share}/arbiter-academy/preview-0.30/bin/arbiter-academy"
"$academy" --repository "$PWD" reset F01-fork-clone-doctor
Academy preserves the prior attempt under an archive ref and prints the next academy/F01-fork-clone-doctor/<attempt> branch.
If Reset stops, preserve its message and current branch. Resolve only the named dirty-state or repository boundary before retrying; never force-reset or delete the prior attempt.
The failed attempt commit remains reachable while the new attempt starts from the clean lesson base.
After Check passes, return to main when you want to leave the completed attempt untouched. The next Academy lesson appears on the course home only after its guided rewrite and acceptance evidence are complete. Do not use unpublished source exercises as a substitute for the next guided lesson. Use Reset only to preserve a failed attempt and prepare the next number.
Understand the mechanism
The report is deliberately small and learner-controlled; it records no username, URL, credential, email, local path, or terminal transcript. The verifier therefore checks two independent sources: the exact report committed on the numbered branch and the live Git configuration at Check time. Changing either after Doctor breaks the proof. Keeping preparation, the governed evidence commit, clean state, and external verification separate makes the result reconstructable instead of merely plausible.