The boring difference between a demo and a working harness is whether you can recover after the model gets lost.
Demos always work. The agent makes the right tool call, the test passes, the diff is clean, applause. Real sessions are messier. The model chases a bad approach for ten turns, the context window fills with dead ends, the human comes back from lunch and finds Pi cheerfully implementing the wrong thing in a worktree that nobody asked for. Recovery is the property that makes the harness useful when this happens, instead of just another window to close.
The earlier posts in this series built the loop up: hands, tools, project context, filesystem state, verification, hooks, subagents. The last primitive is what to do when the loop produces nonsense — and how Pi's session model makes that survivable instead of catastrophic.

Sessions as the black box
Pi saves every session under ~/.pi/agent/sessions/. Full transcript, tool calls, file edits, output, the whole thing. The flag set worth knowing:
pi -c # continue the most recent session
pi -r # resume a specific session (interactive picker)
The framing that makes this useful: sessions are not mystical memory. They are evidence. Every prompt, every tool call, every shell output, every edit is recorded. When the model gets lost, the session log is what tells you where it got lost — not "what was it thinking," because the model doesn't think, but "which tool call produced the result that misled the next step."
This is the same architecture argument as the black-box recorder in my memory series. The black box doesn't make the agent smarter. It makes the next agent — or the next session, or the human watching — able to figure out what happened without replaying the disaster from memory.
Compaction is the discipline
The other lever is /compact. It summarizes the current session, frees context, and writes the summary back into the session log. Useful when the context window is getting noisy with intermediate output that doesn't decide the next step.
/compact summarize the current parser state, failing tests, and next safe step
The trick to using /compact well: be explicit about what should survive. The default summary will hit the headlines, but the things you want preserved are usually specific: the current diff, the last command run, the failing test name, the hypothesis you've rejected, the next thing to try. A vague compact ("summarize the session") produces vague summaries. A specific one produces a usable handoff note.
After compaction, inspect what survived. If something load-bearing didn't, re-emit it. If the summary captured the wrong frame ("the agent was trying to add subtotal support" when really it had moved on to error handling), correct it before the next prompt. The compacted summary becomes the model's working memory; getting it wrong is more expensive than getting the original prompt wrong.
This is the coding-agent version of the memory ladder: the raw session log is the black box, /compact is lossy compression, search over prior sessions is retrieval, and durable repo docs are canon. Mixing those up is how you end up treating a compacted summary like evidence, or treating a one-off session trace like a rule every future agent should obey. The harness needs all four. It just needs them in the right order.
A handoff template
After enough sessions where the recovery was the work, I settled on a handoff template I keep pasting at the bottom of compaction notes:
## Current diff
## Last command run
## Result
## Last known good behavior
## Hypothesis rejected
## Next smallest safe step
Six fields. None of them is "what was the model thinking." All of them are evidence the next session — same model, different model, human, whatever — can act on without context. When a session needs to hand off (because the human is going to bed, because the context is too noisy, because a different model is going to take over), this template usually beats prose.
The most valuable field is "Hypothesis rejected." It's the cheapest way to prevent the next agent from rediscovering the same dead end. It's also the field that pure prose summaries skip the most often.
Recovery, not restart
The temptation when a session goes sideways is to Ctrl+C and start fresh. Sometimes that's right — when the context is genuinely corrupted, or when the approach was so wrong that no fragment of the session is salvageable.
Most of the time it's wrong. Recovery beats restart because the session almost certainly has some useful evidence in it. The model ran tests. It read files. It hit some failures that were real and some that were artifacts of the wrong approach. Throwing the whole transcript away costs you all of that.
The recovery move:
- Stop the current run.
- Read the session log for the last useful tool call (the last one that produced evidence, not the last one that produced confidence).
/compactfrom that point forward with the handoff template.- Restart the loop with the compacted state, not the original prompt.
This is slower than a fresh start in the short term. It's much faster than re-deriving the evidence in the long term.
When to restart anyway
There's a class of failure where restart genuinely beats recovery: when the original prompt was wrong. If the spec was misframed, no amount of recovering the session helps — you'll end up solving the wrong problem more efficiently. If the model's first three tool calls show it understood the task differently than you intended, fix the prompt and restart. Don't try to course-correct mid-session; the model will keep referencing the original framing.
Rule of thumb: recover when the evidence is right and the path is wrong. Restart when the framing is wrong and the evidence isn't worth keeping.
The series, ending
This is the last post in the Pi harness series. Eight primitives, one toy repo, no claim that any of this ends the design conversation. The arc was deliberate:
- The model has no hands — give the model a repo and tools instead of a paste wall.
- Tools are the agent — the loop is read, edit, run, inspect, repeat.
- Project context is a tool —
AGENTS.mdis executable steering, not decoration. - The filesystem beats the transcript — pass references, not paste walls.
- Verification is the product — make the harness, not the human, check the work.
- Hooks are where taste enters — warnings before cages, project rules before personal ones.
- Subagents only when they pay rent — fork when evidence will resolve it, not for the diagram.
- This post — sessions, compaction, recovery, handoff.
None of these primitives is novel by itself. The argument the series is making is about order — that the boring infrastructure matters more than the model upgrades, that the harness is the agent, and that the path from "demo" to "workflow" is mostly composed of unremarkable scaffolding that nobody pitches you on.
A useful coding agent is mostly the boring parts. The series ends here. The toy repo is still in tiny-ledger. The next thing worth doing is wiring this same shape into a repo that matters.
Exercise
For tiny-ledger, one last time:
- Run a session where you intentionally let the model chase a bad approach for 8-10 turns.
/compactwith the handoff template. Inspect what survived.- Resume from the compacted state and recover. Note whether the rejected hypothesis was preserved.
- Compare the recovery to what a clean restart would have cost. Was the saved evidence worth the messier session?
If the answer is consistently "restart was cheaper," your sessions might not be capturing the evidence at the right granularity. If the answer is "recovery was cheaper," congratulations — you have a harness instead of a chat window.