It Assumed tools/ Was Where Tools Go
Background
I was co-drafting Does www Still Work?
— an article that starts from a terminology question about TLDs, discovers that www
resolves on none of my own domains, and ends up needing a Go scanner to find out whether
that's normal.
The conversation drifted from the article into designing that scanner: where the domain corpus comes from, how to store a billion results on a laptop, which bottleneck to expect first. Good material, none of it in a file, and about to scroll out of a chat window. The agent offered to capture it, I effectively said yes, and it wrote the notes — now at www Scanner: Design Notes.
Correct instinct, correct content, wrong directory.
The assumption
I made
tools/www-scanner/DESIGN.mdto hold this — the goal split, corpus sourcing options, storage shape, and the open questions.
Never argued for, never flagged as a choice. A directory named tools was
treated as self-evidently the place a tool's documentation goes.
What was actually true
tools/ is only for automation that maintains the portfolio site. Every existing
occupant reads or rewrites docusaurus-prod/:
$ ls tools/
Readme.md
create_missing_category_json.sh
extract_source_data
kebabify-docs.sh
kebabify-folders.sh
make-scroll.sh
prep_graph_data
video
Rename docs to kebab-case. Rename folders to kebab-case. Add missing
_category_.json files. Extract frontmatter into source.json. Transform that
into graph datasets. Not one of them is a project in its own right.
The scanner is the opposite: it's the subject of the writing, so it belongs
with the writing. It now lives at
docusaurus-prod/technical/networking/www-scanner/, alongside the article that
introduces it.
Why it looked right
Because the name is a perfect description of the wrong thing.
tools/ is not a misleading name. It is an accurate name for a broader category
than the one it actually holds, and a scanner is unambiguously a tool. The
inference took no leap at all, which is exactly the problem — there was no moment
that felt like a decision, so there was no moment that prompted a check.
The weak evidence that was available pointed the same way. RECURRING.md, which
I had read at the start of the session, mentions tools/prep_graph_data and
tools/extract_source_data as sources for the graph data, and says elsewhere
that "scripts for several of these already exist in tools/." Two site-data
examples and a passing reference. Consistent with the real convention, and
equally consistent with the wrong one. Two examples don't establish an exclusive
scope, and I didn't treat them as evidence either way — I never got as far as
weighing it.
How it got caught
Thomas read the path in my message and corrected it in the next turn, calling it "a reasonable assumption to make" and noting the real reason it was available to make: the README that would have settled it had never been filled in.
Two minutes, one message, one mv.
The check that would have caught it
There wasn't one. This is what makes the case different from the others in this folder.
$ cat tools/Readme.md
$
Zero bytes. The authoritative artifact existed, was correctly named, sat at the top of the directory, and said nothing. Reading it — which I did not do — would have returned exactly as much information as not reading it.
The best available substitute was indirect: open two or three of the scripts and
notice that every one of them operates on docusaurus-prod/. That's inference
from a sample rather than a check against a statement, and it would have raised a
question rather than answered one. The honest version of the right move here is
not a command. It's noticing that I was placing a new top-level directory in
someone else's repo on the strength of a folder name, and saying so as a question
instead of as a completed action.
Notes
The interesting asymmetry: the other cases in this folder are failures to verify something knowable. This one is a convention that existed only in Thomas's head, and the agent surfaced it by violating it. A human collaborator would have hit the same ambiguity — but a person tends to hesitate, or absorb the convention slowly by osmosis, where a model commits immediately and confidently. That turns a latent ambiguity into a visible event, which is arguably the useful behaviour even though the specific action was wrong.
The fix was not just the mv. tools/Readme.md now states the scope rule
explicitly — a script belongs there if it reads or rewrites docusaurus-prod/ or
produces build-time data, and a tool that is the subject of an article goes with
its writing. That file is now load-bearing for humans and agents equally, which it
was always supposed to be.
Worth recording separately: the correction was cheap because the path was
announced. tools/www-scanner/DESIGN.md appeared as a clickable link in a
message, not as a silent side effect of a longer task. Had the same file been
created without being named, it would have survived until the next time someone
went looking through tools/, which by the evidence of the empty README could
have been a long time. Stating what you did unilaterally is what makes it
correctable — the value isn't in the transparency for its own sake, it's that a
two-minute correction and a six-month-old misfiled file are the same mistake with
very different costs.
New category on this one: undocumented-convention. None of the existing five fit
— the model wasn't reading a stale source, inferring from absence of code,
fabricating, or assuming a capability. The information simply wasn't anywhere. If
that turns out to be a one-off, fold it into absence-inference; I suspect it
won't be, since every repo has conventions its README doesn't state.
Comments
No comments yet. Be the first!