2026-10-19, Jacks-iMac. What the MacBook chat wrote down about its own wasted time, measured against what this Mac actually does, with the one mechanical change that came out of it.
session-audit/analyze.py here already carried it, so the 6% figure below is sound, but my own parser did not. Re-measured on this session keyed on message.id: record-split ratio 2.41, tool turns 128, batched 42, rate 32.8%. The first version of batch_streak_gate.py carried the same bug and would have fired forever on a well-batched session; it is fixed and re-proved on 8 of 8 controls, two of which are fully-batched sessions that must stay quiet.Measured by session-audit over the 30 most recent sessions in ~/.claude/projects/-Users-drwu/.
| Measure | Observed | Target | Reading |
|---|---|---|---|
| Parallel tool-call rate | 6% | above 40% | The dominant waste. Nearly every independent call is its own round trip. |
| Bash share of all tool calls | 8,413 | n/a | Bash is 9 of every 10 calls, so batching Bash is where the whole gain sits. |
| Agent dispatches | 0 | n/a | Correct here. Standing policy forbids subagents without permission. |
| Output tokens, 30 sessions | 8,624,650 | n/a | Each serialized turn re-pays the per-turn overhead. |
| Model mix | 99% Opus | n/a | Matches the standing instruction to use Opus for all work. |
Ten mistakes, each paired with a fix. Six are about picking the wrong route and paying for it in round trips.
| # | The waste | The fix it recorded |
|---|---|---|
| 1 | Judged "unused" from one machine's record, while the switch covers the whole account | Read every machine's record before flipping anything |
| 2 | Summarized 32 items in five groups covering only 26 | List every name, or use groups that cover all of them |
| 3 | Globbed chat logs; the guard blocked both reads | Name each file by its full path |
| 4 | Used PIPESTATUS in zsh, which has no such variable, so a check never ran | Drop the pipe and read the exit status directly |
| 5 | Its grep is ugrep and rejected a bounded-repeat pattern | Search large files with a short Python script |
| 6 | Tried the browser pane, which had no sign-in | Go straight to the signed-in browser |
| 7 | Read a missing switch on a reloaded page as a failure | Verify from the list count, not the item page |
| 8 | Watched a folder for 25 minutes | Read the application log and wait for the window to come forward |
| 9 | Ran the voice gate in hard mode without the local-only flag | Pass the flag that keeps the check on the machine |
| 10 | Spent almost four minutes thinking about a yes-or-no question | Answer from the numbers first, in a few short lines |
Batching has been a hard gate in CLAUDE.md since the 2026-07-19 session audit, and it has a memory file of its own. Both are prose. Here is what prose produced:
CLAUDE.md, since 2026-07-19 : "independent tool calls go out in ONE block, target above 40%" measured 2026-10-19 : 540 of 9,009 turns batched = 6% one session the same day : 64 tool turns, 0 batched = 0.0%
The first three read a signal the audit measured. The fourth reads one the audit does not measure at all, found by parsing this session's own transcript. Each prints a single line, and returns zero on every path, so none of them can block a tool call. Each was run against inputs with known answers in both directions before being wired.
Counts tool calls per assistant turn and speaks when four turns in a row have each carried one call, then stays quiet until the next multiple of four. A batched turn clears the run.
3 singles -> quiet (expected quiet) 4 singles -> FIRED (expected fire) 5 singles -> quiet (expected quiet, between thresholds) 8 singles -> FIRED (expected fire) 4 then batched -> quiet (expected quiet) 5 of 5 correct, plus malformed stdin / empty payload / missing file all exit 0
Flags a command that writes a file through a shell redirect: echo, printf, a cat heredoc, or tee. Silent for /dev/null and for throwaway fixtures under the scratchpad, where a redirect is the right tool.
POSITIVES (5 of 5 fired) echo into a home file echo "hi" > ~/notes.txt append into the vault echo "x" >> Brandon-Vault/Daily/2026-10-19.md cat heredoc into a .py cat > ~/x.py <<'EOF' tee into a report python3 run.py | tee _outputs/r.txt printf into a file printf "a\n" > ~/a.txt NEGATIVES (9 of 9 stayed quiet) echo to /dev/null heredoc to python stdin curl -o /dev/null echo into the scratchpad tee into the scratchpad plain ls grep piped to tail a bare 2>&1 a comparison operator in a test 14 of 14 correct, plus 3 malformed-input cases all exit 0
Counts reads per real path per session and speaks on the third read, then every third after it. Different spellings of one file collapse to a single count, and a read that asked for a line range is told so rather than scolded.
reads 1, 2 -> quiet reads 4, 5 -> quiet read 7 -> quiet read 3 -> FIRED read 6 -> FIRED a second path counted on its own, firing on its own third read 10 of 10 correct, state file held 7 and 3, plus 4 malformed-input cases all exit 0
Speaks when a command failed because its invocation was guessed: a wrong flag position, a wrong subcommand, a binary this Mac does not have, a path belonging to the other Mac, a zsh glob that matched nothing, or a validator refusing the record shape it was handed. Each message carries the specific remedy rather than a scold.
POSITIVES (6 of 6 fired, every one a failure this session really produced) argparse flag position unrecognized arguments: --json wrong subcommand invalid choice: 'list' binary absent command not found: jq other-Mac path can't open ai-tells-corpus/ai_tells_gate.py zsh unmatched glob no matches found: ~/.claude/skills/*clean* validator shape refusal evidence id(s) do not resolve to a record NEGATIVES (5 of 5 stayed quiet) plain success an http 200 check a passing gate the word error used in prose a file listing 11 of 11 correct, plus 3 malformed-input cases all exit 0 KNOWN FALSE POSITIVE, disclosed: reading a log that QUOTES a failure fires it. The cost is one extra line, since it nudges and never blocks.
| Anti-pattern | Measured | Measured by | State |
|---|---|---|---|
| Serialized tool calls | 6% | session-audit (fixed meter) | Running check, PostToolUse, corrected 2026-10-19 |
| Shell redirects in place of the Write tool | 493 | session-audit | Running check, PreToolUse |
| Re-reading a file already read | 35 worst case | session-audit | Running check, PostToolUse |
| Calls spent guessing an invocation | 12 of 126, 9.5% | transcript parsed by hand | Running check, PostToolUse |
session-audit reports batching, redirects, duplicate reads, skill and agent counts, and cache health. It has no measure for a call that failed because its flags were guessed, so nothing counted those until this session's transcript was parsed directly: 12 of 126 tool results, 9.5%, five of them a validator rejecting a record shape and three a wrong flag or subcommand. A scorecard only governs what it thinks to count, which is the same lesson one layer up from the prose gates.Three limits remain, none of them hidden. Every check is a nudge rather than a refusal, chosen so that a block never breaks a legitimate pipeline. The fourth fires on a log that merely quotes a failure. And whether the session that wired them loaded them is now settled: it did not, proven by probe at 14:46, because the settings watcher only watches directories that held a settings file when the session began. A new session loads all four.