Repo discoverability for humans and agents

Your repo has a scripts directory nobody opens, and somebody rebuilt one of the files in it last month. An agent does the same thing, on every task, and bills you for the rediscovery.

There is a scripts directory in your repo with eleven files in it. You wrote four. Nobody has opened the other seven this year, and last month somebody wrote a ninth thing that does what the third one already did, slightly differently, because looking took longer than writing.

The hour is not the loss. The loss is that the rule now has two implementations, they disagree in one edge case, and the disagreement will surface as a bug report eight months from now that nobody can reproduce.

The same rule with and without an index On the left, three people look for an encoded rule that is not in any index. Two of them find it; the third does not and writes a second version, so the repository ends up with two implementations that disagree. On the right, an index sends all three to the same one. not in the index in the index the script a second one two versions, quietly disagreeing the script one version, everyone on it
Nobody rebuilds a thing on purpose. They rebuild it because looking took longer than writing, which is a statement about the index rather than about them. Illustrative — the shape of the argument, not measured data.

Encoding is half the job

A rule you have written down and encoded is not yet a rule your team follows. It is a rule you follow, and a file the next person has to stumble over.

Everything in this series so far has been about the first half: reason once, encode, replay. Turning a runbook into a command only pays if the second person knows the command exists, and that turns out to be a separate problem with a separate fix.

Three things make an encoded rule survive contact with a second person, and only the third one is usually missing:

  what it means fails when
a name says what it does, not how it does it it is called utils
a location the first place someone would look it lives where its author happened to be
an index one file that names everything it is a wiki page from 2023

The second reader changed the economics

This used to be a politeness problem. A colleague who cannot find your script loses an afternoon, once, and you feel vaguely bad about it.

An assistant that cannot find your script rediscovers the repository from scratch, on every task, forever. It gets there, you paid for it, and you will pay again next session, because nothing it worked out was written down anywhere.

That is the shift worth internalising. Discoverability stopped being courtesy and became a per-task cost with a recurring bill.

Four registries, four questions

Deskspace, a Spring Boot and React service I keep as a reference implementation, answers each of them with a file and a lookup tool rather than with a document somebody is supposed to read:

toolbox/tool_mapping.py list         # what tools exist, by key
toolbox/arch_map.py get booking      # where the code lives, and what may depend on it
toolbox/lexicon.py search "checkstyle"  # how we solved this before
toolbox/check_readmes.py             # does every directory explain itself

The architecture map is the clearest case. A package structure is a fact about the repository, so it belongs in a file rather than in a model’s reasoning. Ask an assistant to add a validation rule with no map and it opens half a dozen files to infer a layout that has not changed since the repo was created, then does it again next session. Ask with a map and it is told.

The lexicon is the only one of the four that makes the repository better over time rather than merely keeping it green. Gates stop bad things escaping; a record of how a recurring problem was solved stops the same afternoon being spent twice. Every entry in that one cost somebody real time: that a bare checkstyle:check silently runs Sun’s ruleset, that one code generator breaks against the current TypeScript, that two adapters onto the same upstream collide on a bean name at context startup rather than at compile time.

An index is load-bearing, so it drifts

The index is the piece that keeps working after everyone who built the thing has moved on, which is exactly why it decays unnoticed. Nothing breaks when an index goes stale. The build passes. The tests pass. The only symptom is somebody rebuilding something, months later, in another directory.

So the registry is checked rather than trusted. That repository fails its own build when a tool exists on disk without being registered, and when the architecture map disagrees with the actual package tree:

$ toolbox/tool_mapping.py check
  FAIL  coverage_gaps.py exists but is not registered in mapping.json:
        an unregistered tool is an undiscoverable tool

$ toolbox/arch_map.py check
  FAIL  map lists slice 'billing', no such package in src/main/java

Both directions fail differently. Something on disk missing from the index gets rebuilt. Something in the index missing from disk is worse: it sends the next reader, or the next agent, confidently to a place that does not exist, which is more expensive than having no map at all.

The way this check fails is the point

Moving those scripts into one directory broke the checker in the most instructive way available. It kept globbing the old path, and globbing a directory that no longer exists yields nothing, so nothing was ever unregistered, so the check reported ok.

Forever. The build was green and the index was unenforced, and there is no symptom for that.

What caught it was not the check. It was a test asserting that the check fails when a tool is unregistered. The happy-path test still passed and told us nothing, which is the general shape: a gate with only a happy-path test proves that it runs, not that it gates.

Write the index for both readers

There is no version of this that serves a person onboarding and not an assistant starting a task. Both arrive with no context, both need to know what already exists before building anything, and both give up in the same way when the answer is buried.

That is convenient rather than profound, but it settles an argument that used to take a while: there is no separate machine-readable index to maintain. There is the index, and it is checked, and the human-facing README is generated from it so the two cannot disagree.

The test

Delete the person who wrote it. Can the next one find it in under a minute, without asking anybody, starting from the file they were already going to open?

If the answer is no, the thing is not encoded yet. It is stored, which is not the same, and storage without retrieval is how a team ends up paying to keep a decision it no longer benefits from.


If your team keeps solving the same problem in two directories because nobody could find the first solution, that’s the work I do.


Working through this in your own team?

I help engineering teams adopt AI coding assistants without giving up engineering rigour, and design the architecture underneath. If that's on your plate, let's talk.