The loop#
The two arrows that matter are the verification one and the discard one. Here is what flowed through them in one month.
Verification beats plausibility#
Four review claims from the month, all of which sounded reasonable, all of which died on contact with the machine:
| The claim | The two-minute disproof |
|---|---|
“yazi --version does not parse the config, so it is useless as a canary” | replayed a broken config through YAZI_CONFIG_HOME: broken exits 1, clean exits 0 |
| “the tmux throwaway-server check will pollute resurrect’s saved sessions” | ran it three times; the save directory did not change at all |
“tmux.conf is missing bind C-a send-prefix” | it is on line 43 |
| “you should add this rg option” | the option was already in the config; the reviewer had not read the file |
# claim: yazi --version does not parse the config
# method: replay a broken config in isolation, watch the exit code
YAZI_CONFIG_HOME="$broken" yazi --version; echo "$?" # 1
YAZI_CONFIG_HOME="$clean" yazi --version; echo "$?" # 0# claim: tmux.conf is missing send-prefix
grep -n 'send-prefix' ~/.tmux.conf # 43:bind C-a send-prefixA plausible answer and a correct answer look identical on the page. The only visible difference is whether you ran the check, and the check consistently costs about two minutes. That ratio, two minutes against a wrong config shipped, is the entire economics of the verification habit.
But the research side finds real gold#
If the previous section makes the AI sound like a liability, here is the other direction, because both halves of the loop earn their keep.
The research pass discovered that my entire ripgrep config had been dead the whole time: RIPGREP_CONFIG_PATH was never exported. A config file, carefully maintained, read by nothing.
export RIPGREP_CONFIG_PATH="$HOME/.config/ripgrep/config"The more important discovery was that enabling it blindly would have caused an incident. The dormant config contained output flags like --pretty and --context. The moment the config went live, every scripted and piped rg call on the machine would inherit pretty-printing and context lines. So activation had to start with a cleanup, and the principle went into the file as a comment:
# Output Format
# =============
# Deliberately EMPTY: this config shapes what gets searched, never how
# results print. Output flags (--pretty/--column/--context) would leak
# into piped and scripted rg calls the moment the config is active.The same research flow also uncovered that herdr splits its config reading between client and server under --remote, something a month of local usage had not surfaced. That one gets its own post next in this series.
The dormant-tool pattern, three times in one month#
The dead ripgrep config was not a one-off. The same shape appeared three times:
- A mergiraf merge driver, fully defined in git config, whose activating
gitattributesline was never written. Dormant for a year. - television installed, with zero wiring into the shell.
- The ripgrep config above, never exported.
Installed but not wired is the most expensive kind of tool: you paid the full selection cost and collected none of the return. All three now have pairing tests, on the principle that a definition and its activation must exist together or the check goes red:
# mergiraf must be wired end-to-end: the attributes line without the
# driver (or vice versa) is a dormant config.
run_test "mergiraf attributes/driver pairing" \
"grep -q 'merge=mergiraf' $HOME/.config/git/attributes && \
grep -q 'merge \"mergiraf\"' $HOME/.config/git/config"television additionally got a role declaration, so it does not blur into fzf’s territory:
# television's explicit role: full-text CONTENT search entry point
# (fzf owns filename/history flows — no overlap, one entry each)
if command -v tv &> /dev/null; then
alias tvt='tv text'
fiWho does what: the delegation economics#
The division of labor that settled in: the frontier model plans, verifies, and commits. Cheaper models run well-specified batch work. In practice that meant opus ran audits and migrations, including the bootstrap idempotency audit that surfaced 12 defects in one pass (one of them a nested-symlink bug that got reproduced in a sandbox before anyone touched the fix). sonnet handled mechanical batches: README splitting, doc generation, migrations.
Small config edits stayed in the main loop, because writing a delegation spec for a two-line change costs more than the change.
The trust signal that actually moved the needle was not capability. It was whether an agent stops. One agent was asked to modify a README section that had, unbeknownst to the spec, already moved into docs/. It declined to guess, came back, and asked. Delegation volume went up after that, because an agent that halts on spec-reality mismatches is one you can hand bigger specs.
The multi-agent hazard that actually happened#
Two Claude sessions were working on the same yadm repo. Each swept the other’s staged files into its own commit. This happened twice, and the second time is the instructive one: a file staged in advance got carried away by two unrelated commits in the same evening.
The root cause is not a bug anywhere. All sessions share the single yadm index, and yadm commit takes everything currently staged, regardless of who staged it. The tool behaves exactly as documented. The information “who staged this” simply does not exist in the system, so no tool-side fix is possible.
Which is why the fix is procedural, and why it graduated from “remember to check” to a mandatory step after the recurrence:
yadm diff --cached --name-onlyBefore every commit, no exceptions, plus a one-committer-at-a-time rule. A mistake that recurs in the same evening does not get fixed by resolving to remember harder. It gets fixed by an extra line in the procedure.
The month in numbers#
About 30 single-concern commits across five PRs (#54, #63, #64, #66, #69). The test suite grew from 74 checks to 105. Six documentation pages got extracted. And every incident in this post exists in the suite as a named test, which by now is the house style of this whole series.
Lessons#
- A plausible answer and a correct answer are indistinguishable until you run the check. The check costs two minutes; budget for all of them.
- Research and verification are the same loop running in opposite directions. One finds what you cannot see, the other kills what is not true.
- Installed but not wired is worse than not installed. Pair every definition with its activation in a test.
- A config file decides what gets searched, never how results print. The second half of that sentence is where the incident was hiding.
- Judge an agent by whether it stops when the spec and the repo disagree. The one that asks is the one that gets more work.
- When a process error recurs on the same evening, stop relying on memory and add a line to the procedure.
References#
- ripgrep configuration (
RIPGREP_CONFIG_PATHsemantics) - mergiraf (the syntax-aware merge driver)
- television
- yazi (the exit-code canary from the previous post)
- The repo, PRs, and test suite: nickboy/dotfiles
