Failures in disguise
Concurrency and defaults fail in disguise. The real cause never shows up in the error.
This is the weekly diff for Mastering Claude Code: what changed in the guide this week and why. If you already read the guide, this is everything you need to catch up.
The headline
Concurrency and defaults fail in disguise. This week’s two big lessons share a shape: the real cause never appears in the error message. Two assistant sessions working the same codebase collide, and the collision surfaces as something else entirely: an out-of-memory kill, a silent lane conflict, a merge that looks clean while dropping code. And a harness’s default retention setting quietly deletes material two months before the archive job downstream would have collected it. No error, ever, just an archive that stays empty. Chapter eight gains the collision failure mode, chapter six the retention one, and chapter one picks up two behavioural defaults about momentum and attention.
Parallel sessions colliding in another failure’s clothes
The trigger was a week of genuinely parallel work, with several sessions running against the same codebase at once. Three separate incidents, and in every one the visible failure pointed somewhere other than the cause.
First: two sessions running test suites on one machine killed each other. Each suite’s startup step tears down any stale test containers under the shared default project name, so starting suite B destroys suite A’s containers mid-run. The dying suite reports a kill signal that looks exactly like the machine running out of memory. Nothing in the system logs says “your sibling did this”; you can spend an hour hunting a memory leak that does not exist.
Second: the coordination layer failed open. There was a lane-claim registry precisely so concurrent sessions could see each other’s territory, but it was unreachable from one of the machines, and an unreachable registry doesn’t stop anyone. Each session simply believed it held the lane alone. A guardrail that fails open is invisible right up until the collision it existed to prevent.
Third, and nastiest: a feature branch merged cleanly against a mainline that had refactored the same files wholesale. Not one conflict marker. But the automatic resolution took the mainline’s rewrites, and most of the branch’s additions vanished silently. Only two orphaned tests even hinted at it, and only because the code they tested was gone.
The chapter-eight failure mode distils the disciplines. Give each concurrent run its own namespace: test project names, ports, and a working copy each (a worktree per session, never a shared checkout). Treat an unexplained kill signal as “check for a sibling” before debugging the code. And after any merge where the other side heavily refactored shared files, search the merged tree for your branch’s key symbols before trusting it. The line worth memorising: a conflict-free merge is not a content-preserving merge.
Two retention windows, and the shorter one runs upstream
An archive-everything pipeline was discovered to be archiving almost nothing. The design was reasonable: a sweeper that archives any session transcript older than ninety days. What nobody had enumerated was the harness’s own built-in cleanup: thirty days, hard delete, on by default. Every transcript was purged two months before the sweeper would have collected it. The pipeline ran happily for months, reporting no errors, because deletion is a default and defaults don’t announce themselves.
The giveaway, once someone looked, was almost comic: the oldest surviving file was exactly thirty days old, precisely the harness’s default retention period. That’s the audit in one check: if the oldest surviving item is exactly as old as some tool’s default retention window, that tool is winning, and your archive is losing.
The chapter-six failure mode: when you build anything archival, enumerate every cleanup already acting on the source (the harness’s own retention setting first) and make the upstream window outlast the downstream sweep, or disable it outright.
Two behavioural defaults: momentum and attention
Chapter one’s defaults table gains two rows, both from the same stretch of real work.
Finish the slice. An assistant finished each build increment by asking “want me to continue?” when the phase plan was already agreed. Worse, it offered the final infrastructure step (the DNS record, the certificate, the service registration, all credentials in hand) as an optional “say the word” extra. From the user’s side this reads as being made to do project management for work already delegated. The default: when the plan is agreed and work remains, work through to done; a standard follow-on step the assistant already holds the keys for is part of the work, not an optional extra to offer back. Ship the whole vertical slice, not the eighty percent that leaves the user wiring the last mile.
The question outranks the instruction. When one message carries both an instruction and a question, the answer comes first. The question is what’s blocking the user’s next thought, while the instruction is delegation that doesn’t need their attention. Start the instruction as background work and lead the reply with the answer. Serialising the human behind the delegated task wastes the one resource the whole setup exists to protect.
Where to read more
The full guide lives at claude-guide.sauer.com.au. This week’s changes are in chapters one, six, and eight of the full guide.
The cards
