The loop that never told anyone what it was costing
Some systems keep reporting success long after the thing you care about has stopped being true.
Orientation
This is the week fifteen update to Mastering Claude Code, covering the week of the twenty-fourth of August 2026. It is the diff: what changed in the guide, why, and which chapters were touched. The guide itself stays current at claude-guide.sauer.com.au; this is just the delta since last week.
The headline
Six changes this week, and the spine running through all of them is a system that keeps reporting success long after the thing you actually care about has stopped being true.
A schedule that had quietly become a continuous process. A resume brief naming a position many rounds out of date. A test log that looked clean because the run was killed before it could fail. A filter the system never read. A hook standing guard at a door the work had stopped using. In every one of them the machinery is running, the runs are succeeding, nothing is erroring, and the answer coming out the other end is wrong in a way that nothing in the system is built to notice.
Why these ones
Three of them came from one incident.
A long-running unattended review loop was ticking on a fixed thirty-minute timer. It turned out that each tick took one to three hours. Fixed timers do not queue: each tick started the instant the previous one ended, so a schedule written as twice an hour had in fact been a single continuous process running around the clock, for days. It consumed most of a whole day’s model allowance, and nothing in the system said so. There was no budget on it, no ceiling and no alarm. The first real measurement of what it cost was the user running out of usage in the middle of the afternoon and asking why. Two days later it happened again.
The same loop resumed from a hand-written brief that named a fixed round to continue from. It had kept naming that round long after the loop had moved dozens of rounds past it. Several separate sessions in a single week opened by noticing the contradiction, working out the real position from the report file and the commit log, and writing a paragraph explaining the correction. Every one of those recoveries was correct. Not one of them could fix the file, so the next session paid the same cost again.
The rest came out of ordinary work. A test suite killed at two-thirds left a log with no failure lines in it at all, so searching that log for failures read as a pass. An interface returned the same four records for a real user, a different user, and a user that does not exist: its filter was never read, and the conclusions drawn from it were right only by luck. And a set of files written from a shell into a mirrored directory were never seen by the hook that was supposed to capture them, because that hook watches the file-writing tool and a shell redirect is not one. A scheduled sync then overwrote the directory and both files were gone within hours, with nothing anywhere reporting a failure.
What changed in the guide
Chapter one, CLAUDE.md. One new behavioural default: a finding already handled by a standing process is not an event. Before surfacing housekeeping (a credential that looks stale, a file that should have been cleaned up, something that leaked into a log) check whether anything already owns it on a schedule. If something does, the finding is not news. Raising it manufactures a decision the user has already made, hands them work that is not theirs, and pushes the thing they actually asked about further down the reply.
Chapter four, hooks. A new failure mode: a tool-event hook has a shell-shaped blind spot. Nearly everything a file-write hook watches for can also be done from a shell, and only the tool call is visible to it. The guard fires faithfully on the one path it was written for, which is worse than having no guard at all, because it looks like coverage. This gets sharpest when the environment itself steers toward the shell. Two defences: scope the hook by effect as well as by tool, and for anything whose loss would be silent, verify from the far side afterwards rather than concluding the write landed because nothing complained.
Chapter six, persistence. A new failure mode: the brief that resumes the loop is not the state of the loop. A position baked into a launch prompt is true exactly once. Position is task state, and task state belongs in an artefact the work itself writes (the report file, the commit log, the tree), never in the standing text that launches it. A resume prompt should either regenerate its position from that artefact every time, or name no position at all and simply say: read the report and continue from what it says. With a short-timescale companion: a figure measured early in a long turn can go stale before the same turn ends, so anything volatile gets re-read at compose time, or goes out with the time it was taken.
Chapter seven, async. A new failure mode: a schedule shorter than the job is not a schedule. The tell is in the timestamps: consecutive runs whose start time is the previous run’s end time rather than the next tick. Measure one real run and make the interval exceed it with room to spare, or drop the fixed tick for a self-paced loop that re-arms only on completion. And give anything unattended that calls a model in a loop a daily budget it reports against, so the cost is visible before it is felt. One closing note: when you find such a loop running away, that is a decision, not a status update. The line offering to kill it belongs in the first two sentences, not at the bottom of the analysis that found it.
Chapter nine, tool discipline. Two new failure modes. First, a killed run leaves a clean log. A suite terminated partway never reaches its failures and never prints its summary, so searching the log for failure markers returns nothing and reads exactly like a pass. Gate on the exit code, and treat the log as evidence about what failed, never as evidence that nothing did. There is a companion cause that produces this exact signature: starting a second heavy job alongside one already running, on a machine with room for either but not both. The kernel removes one, and what comes back is not an error about resources; it is a truncated, entirely reasonable-looking log. Second, a filter the system silently ignores. Prove a filter works by asking it for something that must return nothing. And never use a relevance-ranked search to establish a negative: a ranked search returning nothing is a ranking function declining to surface anything, and it looks identical to a genuinely empty set. When the conclusion is that something does not exist, enumerate the set and count it.
Also folded in
Two entries landed mid-week as bare commits without a week file, and this week’s file carries them.
From the twenty-seventh of August, chapter four: a discovered credential with more privilege than the task needs is not permission to use it. A design that keeps a permission away from the assistant is describing a control, not a technicality to route around. Finding a more privileged credential lying about is a discovery to report, not a lever to pull. And a companion finding from the same incident: verify what a live-fire attempt actually did before writing the postmortem, or two separate failures collapse into one wrong story.
From the twenty-ninth of August, chapter nine: reaching for discovery before the source that already has a name. When a specific, documented, live source exists for a question, that source is the first tool call. One session ran dozens of tool calls of memory search, transcript grep, network probes and web scraping on a question that had one obvious documented owner, and produced no answer at all until the user broke in to redirect it.
Housekeeping
Week four has rolled off the ten-week archive into the older summary, and its week file has been deleted.
The cards
