In a long loop, the model's context will be compacted, reset, or swapped for a fresh session. What only existed in the conversation vanishes or comes back as a summary, mixing fact and guess. The way out: disposable session, state in files and in git, and every cycle starts by rereading. You build a cycle like this and interrupt it on purpose.
2The list of items with passes, the progress file, and the git log
3Interrupt and resume without redoing or skipping
4Git as undo and as the loop's history
Goal: build a disposable cycle that rereads the state from a file, does one item, verifies, and commits, and resume after an interruption without redoing anything.
01 · A disposable session, a state that stays
Click each step of the cycle: what it reads and what it leaves recorded.
Lesson 501 · A disposable session, a state that staysClick each step of the cycle: what it reads and what it leaves recorded.
The session ends or drops; the next one starts by rereading the files and picks up from the first pending item.
1/6
New session
It could be a /clear, a compaction, a fresh codex exec, Ralph calling again, or someone else taking over. The design starts from the worst case: the session remembers nothing and can be interrupted midway.
Scroll the page: each step below lights up its part of the diagram.
1/6
New session
It could be a /clear, a compaction, a fresh codex exec, Ralph calling again, or someone else taking over. The design starts from the worst case: the session remembers nothing and can be interrupted midway.
2/6
Rereads the state
In Anthropic's long-running harness (11/26/2025), every session starts like this: where am I (pwd), what has been done (git log and the progress file), what is the next item, and a basic test before coding. The item list is JSON with the passes field; the post says the model overwrites JSON less than Markdown.
3/6
Does one item
Picks the first pending item and does only that one. In Anthropic's post, later sessions may only change the passes field; they do not rewrite or delete items from the list.
4/6
Verifies and marks
An item only becomes passes: true if its verification passed. The line in progress says when and what the result was. If it failed, the item stays pending and the reason is recorded.
5/6
Commit
The commit is the checkpoint: if the next session drops, nothing that was verified is lost; if an item came out wrong, git revert undoes it. LOOP-R uses the same principle for process versions ("git is the promotion and rollback mechanism"; details in course 5).
6/6
Rereads the folder, not the conversation
The session is disposable; the state is not. Whatever has to survive a compaction, a reset, or a model switch goes into a file and a commit before the end of the cycle.
The execucao-longa kit takes the idea to seven files (goal, plan, state, progress, failures, decisions, canal): it is lesson 1 of course 2.
02 · A disposable cycle in Python
Each run is a "session" that remembers nothing: it rereads, does one item, verifies, records, and commits. No model: the action is writing a file.
Terminal · set up the folder
mkdir -p ~/ensaio-loop/estado && cd ~/ensaio-loop/estado && git init -q
cat > features.json <<'EOF'
[
{"id":"f1","descricao":"ler o CSV","passes":false},
{"id":"f2","descricao":"contar linhas","passes":false},
{"id":"f3","descricao":"gravar o resumo","passes":false}
]
EOF
git add -A && git commit -qm inicio
ciclo.py
#!/usr/bin/env python3
"""A cycle that starts from zero every time: rereads the state from files, does ONE item, records and commits."""
import json, subprocess, sys, datetime, pathlib
estado = pathlib.Path("features.json")
itens = json.loads(estado.read_text())
pendentes = [i for i in itens if not i["passes"]]
if not pendentes:
print("nada pendente: objetivo cumprido")
sys.exit(0)
item = pendentes[0]
print(f"releu features.json: {len(itens) - len(pendentes)} feitos, {len(pendentes)} pendentes")
print(f"faz: {item['id']} ({item['descricao']})")
pathlib.Path(f"{item['id']}.txt").write_text(item["descricao"] + "\n") # the "action"
item["passes"] = pathlib.Path(f"{item['id']}.txt").exists() # the "verification"
estado.write_text(json.dumps(itens, ensure_ascii=False, indent=2) + "\n")
agora = datetime.datetime.now().strftime("%Y-%m-%d %H:%M")
with open("progress.md", "a") as f:
f.write(f"| {agora} | {item['id']} | passes={item['passes']} |\n")
subprocess.run(["git", "add", "-A"], check=True)
subprocess.run(["git", "commit", "-qm", f"feito: {item['id']}"], check=True)
print(f"commit: feito: {item['id']}")
Terminal · run, "crash" and resume
python3 ciclo.py
# close the terminal here, open another one and go back to the folder
cd ~/ensaio-loop/estado
python3 ciclo.py && python3 ciclo.py && python3 ciclo.py
git log --oneline
The hashes will differ on your machine; the order and the messages will not.
Swap the "action" line for a call to the agent (codex exec or claude -p) and the "verification" line for a test that actually runs. The rest (reread, one item, mark only with proof, commit) stays the same. The verification in this toy version is weak on purpose: it only checks that the file exists (level 2 on the scale from lesson 6).
03 · Interrupt midway and watch it resume
Each task is a cycle. Run it, interrupt it, and run it again: whatever already has a commit is not redone.
pending (passes: false)
in this session
passes: true + commit
verification failed
Illustrative simulation in the browser. The failure is intentional: an item without proof does not become passes: true.
04 · Practice
On your machine. It doesn't use up quota: there is no model in the cycle.
E1 · Three sessions, three commits
10 min
Set up the folder, paste in the ciclo.py, and run it once. Close the terminal, open another one, and run it until you see "nada pendente".
Done when: The last run prints nada pendente: objetivo cumprido, and git log --oneline | wc -l → 4.
E2 · The check that fails
15 min
Add item f4 "arquivo vazio" and change the check to require a non-empty file (stat().st_size > 0). Make f4's action write an empty file and run it.
Done when:python3 -c "import json;print([i['passes'] for i in json.load(open('features.json'))])" → [True, True, True, False], and tail -1 progress.md ends with passes=False |.
E3 · The list from a job of your own
15 min
Pick a real task that takes several hours and break it into at least 5 verifiable items in a features.json, all with passes: false, in a project folder with git.
Done when:python3 -c "import json;d=json.load(open('features.json'));print(len(d)>=5, any(i['passes'] for i in d))" → True False, and git log --oneline -1 -- features.json shows the commit of the list.
05 · Lesson quiz
Question 1 of 4
After a compaction, the summary says "f3 done", but features.json shows f3 with passes: false and there is no commit for f3. Which one counts?competency
Correct
The summary mixes what is confirmed with guesses. What has proof is what is in the file with a commit. Marking it without checking is exactly the shortcut the list exists to prevent.
Not that one
The summary mixes what is confirmed with guesses. What has proof is what is in the file with a commit. Marking it without checking is exactly the shortcut the list exists to prevent.Review: A disposable session, a state that stays
Question 2 of 4
Why does Anthropic's harness post keep the list of items in JSON and not in Markdown?
Correct
That is the reason given in the post itself: with JSON the model tends to just change the passes field, instead of rewriting the list. Later sessions can only change that field.
Not that one
That is the reason given in the post itself: with JSON the model tends to just change the passes field, instead of rewriting the list. Later sessions can only change that field.Review: A disposable session, a state that stays
Question 3 of 4
What is the advantage of one commit per item instead of one commit at the end?
Correct
If the session drops, what was verified is saved; if an item came out wrong, git revert undoes only that one. A single commit at the end loses everything in a crash and mixes right with wrong.
Not that one
If the session drops, what was verified is saved; if an item came out wrong, git revert undoes only that one. A single commit at the end loses everything in a crash and mixes right with wrong.Review: A disposable cycle in Python
Question 4 of 4
In the simulation, the session dropped in the middle of an item. What happens to that item on resume?competency
Correct
Without verification and without a commit, there is no proof it finished: it goes back to pending and is redone. What already has a commit is not redone.
Not that one
Without verification and without a commit, there is no proof it finished: it goes back to pending and is redone. What already has a commit is not redone.Review: Interrupt midway and watch it resume
Quiz complete
You got {a} of {n} right. Get them all right and the lesson is marked as complete.
Choose one answer. The explanation appears after you try.
06 · In three sentences
Disposable sessionDesign for the worst case: the next session remembers nothing and may drop in the middle.
Reread before you actThe list with passes, the progress file, and git log say where you stopped; the conversation summary does not.
One item, one proof, one commitpasses only becomes true with verification, and each verified item becomes a resume point.