Consumer inventory — proving who calls this hub#
Why a grep was not enough#
Three deletions in this repository have had to be restored. Every one of them was justified the same way: a search found no caller. The search was right about the machine it ran on and wrong about the world — the caller lived in a repository that was not checked out there.
That failure mode cannot be fixed by grepping harder. A hub cannot see its consumers, so the list of them has to be declared, kept under review, and walked from a clean clone every time the question is asked.
The consumer inventory#
Two files, one workflow.
Piece |
Path |
|---|---|
The declared list of consumers and of the entry-point classes |
|
The checker that clones them and grades the entry points |
|
The weekly run that produces the report |
|
A failed weekly run files or updates a GitHub issue titled
consumer-inventory: dangling hub references, labelled documentation, with
out/consumer-inventory.md as the body (the issue-filing step in that workflow,
if: failure(), job-scoped issues: write). It updates the open issue instead
of opening a second one, and it does not suppress the failure: the run is still
red. This exists because the answer changes when a consumer changes, which this
repository never sees — so the only reader of a Monday-morning red run would
otherwise be whoever happened to open the Actions tab.
Run it against clones:
python3 linux/scripts/verify_consumer_inventory.py --report out/consumer-inventory.md
Run it against checkouts you already have, with no network at all:
python3 linux/scripts/verify_consumer_inventory.py --offline \
--local-root /c/GitHub --report out/consumer-inventory.md
--local-root DIR picks up DIR/<name> for every consumer whose name matches a
directory there; --local NAME=PATH names one explicitly. Under --offline a
consumer with neither is a failure, not a skip.
What counts as reachable#
The report grades every entry point into exactly one of four states, and the distinction that matters is between the second and the third:
Verdict |
Meaning |
What it licenses |
|---|---|---|
reached by a consumer |
Some repository other than this one executes it |
Changing it is a breaking change for the named repos |
hub-internal only |
This repository executes it; nobody else names it |
Refactor freely; it is not published surface |
mentioned, never reached |
Named in prose or in a comment, run by nothing |
Deleting it breaks a document, not a build |
named by nobody |
No repository in the inventory names it at all |
The candidate list for deletion |
A hit is reached when it sits somewhere that runs: a uses: value, a run:
line, a source/Import-Module/include() call. It is mentioned when it
sits in a Markdown or reStructuredText page, in a .allow row, or on a line
that opens a comment. A hub script named in a consumer’s changelog keeps nothing
alive, and a report that counted it would hand back the same false confidence
the grep did.
Entry points are declared, not guessed#
entry_point_classes in the inventory expands globs into the concrete entry
points to grade. A class that expands to zero files fails the run — a silently
empty class would quietly shrink the surface being examined.
Two classes carry an alias, because their entry points are not reached by
path at all:
windows-module— a consumer writesResolve-BuildModulePath -Name 'WindowsBuild.Common'. Grading on the path alone reported all twenty-two modules dead.cmake-module— a consumer puts the hub’scmake/onCMAKE_MODULE_PATHand writesinclude(Sanitizers).
An alias hit is discarded when the consumer owns a file of that basename: its own module shadows the hub’s, so the reference is not evidence about the hub.
What makes the run fail#
Only integrity failures — never the verdicts themselves. The counts are a report for a human; these are defects:
A consumer cannot be obtained. The clone failed, the checkout is missing, or
--offlinewas given without a local path for it. A skip here would turn “no caller found” into a lie shaped exactly like the truth.A consumer is not a git checkout, or has no tracked files. A partial tree would under-report callers.
A dangling reference. An executable line in any scanned repository names a hub path that does not exist. Comments are exempt: a comment recording that a path was removed is prose about the hub, not a broken call.
The inventory does not parse, or declares no self consumer. Without a row marked
self, nothing can separate hub-internal use from a real caller.
Keeping the list true#
The inventory is only as good as its consumers array, so the file carries a
second array, unconfirmed, for repositories that an audit has named but
nobody has verified. The checker prints how many are still open on every
successful run. Each row must end one of two ways: promoted into consumers
with confirmed: true, or deleted because the repository does not exist.
Treat a named by nobody verdict as a lead, not a licence, while that array is
non-empty. It is a statement about the repositories in the list — nothing more.