2026-09-08 · programming · testing · devops · opensource
The Blind Spot Was the Rule I Wrote to Avoid False Positives
I maintain a linter for a configuration format. Its stated principle is on the first screen of the README:
A finding exists only if the documentation says the thing errors, is skipped, or is ignored.
One consequence of that principle is a list of things it deliberately does not check. The clearest entry:
Unknown keys. The documentation says the published schema lags the CLI, so checking this would flag every new feature.
That is a good rule. I still think it is a good rule. It is also the reason my own products shipped a broken line in four places for several days.
The linter passed
Before adding a chapter to a paid guide, I ran the linter against every configuration my own products ship.
product/kit No problems (5 files checked)
product/oss No problems (4 files checked)
publish/quartet No problems (4 files checked)
publish/mdlinkcheck No problems (4 files checked)
Green everywhere. So I opened the files and read them, which is the only reason this post exists.
# .claude/agents/coder.md
---
name: coder
description: ...
tools: *
model: inherit
---
tools: *. I wrote that months ago meaning "this one gets everything".
The documentation says the field takes exact tool names, or the server-level
patterns mcp__<server> and mcp__<server>__*. A bare * is not among them.
It also says that when an entry resolves to nothing, the subagent refuses to
launch, returning an error naming the unresolved entries.
And the documented way to say "everything" is to omit the field.
I cannot prove from here that tools: * fails — I would have to observe a
launch. What I can say is that it is not a documented pattern, and that omitting
the field expresses the same intent with no ambiguity. So I removed the line.
Four copies had it. Two of them were public.
Why the linter could not see it
This is the part worth keeping.
The rule "do not check whether a tool name exists" is correct: the set of tools grows, a checker can only hold a snapshot, and a snapshot would report every tool released after it as unknown. One false finding and nobody reads the output again.
But that rule was written as "do not look at the tools field", and the
thing I needed to catch was not a name at all.
- Checking whether
Bashis a real tool → needs a current list → goes stale - Checking whether
*is a valid entry → needs no list → cannot go stale
* is not a tool name in any version. It never will be. The question is about
the syntax of the field, and I had filed it under identity of the values,
where my own rule told me not to look.
The fix is nine lines and cites the same documentation page:
warn .claude/agents/coder.md:4
`tools: *` is not a documented pattern. Omit `tools` to inherit every
tool available to subagents.
why: https://code.claude.com/docs/en/sub-agents
To keep the no-false-positives promise honest, the clean fixtures now include
the two things that must not warn: a file with tools omitted, and a file
with disallowedTools: mcp__github, which is a documented pattern. The test
requires zero findings on that directory. 71 tests became 73.
The shape of this mistake
A rule that says "don't check X because it produces false positives" quietly becomes "don't look at X". Those are not the same rule, and the gap between them is exactly where a checkable case can sit unchecked.
I have started asking one question about every exclusion I have written:
Is there a sub-case here that needs no external knowledge?
For unknown settings keys, the answer is genuinely no — you cannot tell a typo
from a new feature without the current schema. For tools, the answer was yes,
and I had not asked.
The other thing I would do differently: a green run on your own code is not evidence about your own code. It is evidence about the intersection of your code and the rules you happened to write. Reading the files took four minutes and found what four green runs did not.
I publish the configuration for splitting Claude Code into separate personas —
Architect, Coder, Reviewer, Conflict Resolver — under MIT. Copy it, run
./setup.sh, and it works. It does not depend on your tech stack.
https://github.com/quintetkit/quartet
I built one real tool using nothing but this workflow. Every Issue, PR, review and merge is still there. The parts that went wrong were not deleted.
https://github.com/quintetkit/mdlinkcheck
The version that adds a UI Designer persona, review criteria, a per-Issue parallel execution script and a 10-chapter guide is on the product page.
The full kit — five personas, the scripts and the complete guide — is available here.
https://quintetkit.gumroad.com/l/quintet
The workflow itself is available
Quartet, the four-persona version, is published free under MIT. Quintet adds a UI Designer persona, review criteria, a per-Issue parallel execution script, and a 10-chapter guide.
See the free version Product page