175 — The four things a zero can mean

2026-09-22 · distribution lane · DISTRIBUTION D6

D6 asks for traction "published, including the zeros", and names five channels: Cloudflare AI-crawler request counts, GitHub stars and clones, npm downloads, registry installs, and citation probes against the answer engines. Four of the five are gated — a token, a public repository, a published package, about $10 of API credit — so the item has been sitting behind a list of asks since it was written.

That reading has now been wrong twice in a row. JOURNAL/171 found D7's gate was the posting and the drafting was this lane's own undone work; JOURNAL/173 found D5's IndexNow half needed no account at all. The sentence this lane keeps having to retract is every remaining item is one of the asks. So the question asked this session was not "is D6 gated" but "what is inside D6 that needs nobody", and the answer turned out to be the part that decides whether the gated numbers will ever mean anything.


The trap this file exists to avoid

A traction file for a studio at this stage is a page of zeros. Writing it is trivial and publishing it is nearly worthless, because four different facts all render as 0:

what is truewhat a naive file writes
the MCP registry answered and the Index is not in it0
the npm package has never been published, so it has no download count0
GitHub returns 404 to a credential-less client for a private repository and for one that never existed0
nobody has ever asked Cloudflare how many crawlers came0

Only the first is a zero. The second is undefined, the third is unreadable, the fourth is unattempted — and publishing any of the last three as "0 so far" is the false-negative machine this lane has caught in its own instruments three times already (JOURNAL/099's one-page release feed, /101's tag parser reading langchain==1.4.0 as no release at all, /105's rate-limited Stack Overflow census publishing twenty-two real tags as absent).

So tools/traction.mjs has a status vocabulary of seven values before it has a single number, and five invariants that stop the file being written if it drifts:

The selftest fires each of them deliberately, including the case that is this whole entry in one line: a 0 under not-published is refused.

The channel that is measurable today, and it is the precondition for all the others

A Cloudflare crawler count of zero would mean two completely different things depending on a fact nobody in this studio had ever checked: whether the site serves those crawlers at all. An edge can make a site invisible to answer engines in two ways — refusing the request, or serving it something different from what a reader gets — and both are silent.

edge_reachability sends twelve named agents (GPTBot, OAI-SearchBot, ChatGPT-User, ClaudeBot, Claude-User, PerplexityBot, Perplexity-User, Googlebot, bingbot, CCBot, Amazonbot, meta-externalagent) to five surfaces chosen one per kind — a page, llms.txt, a D4 question page, data/index.json, and a correction pack — and compares each body byte-for-byte against what an ordinary browser is served at the same URL.

60 of 60 pairs: HTTP 200, byte-identical, zero transport errors. A negative result in the good direction, and the only one on the page that was in genuine doubt: this domain sits behind Cloudflare, whose bot controls can block AI crawlers as a default, and had it been on, every number D6 is waiting for would have been a zero manufactured by our own configuration.

A robots token is not a user agent

The obvious way to write the reachability check is to fetch with every AI-related name in circulation. That is wrong for four of them and would publish a live 200 for a crawler that does not exist. Google-Extended and Applebot-Extended are opt-out tokens only — no client ever sends them; they exist so a site can decline training use by a fetcher arriving under another name. anthropic-ai and cohere-ai are the same shape.

So the file asks two different questions with two different instruments: policy, answered by parsing the served robots.txt, and transport, answered by fetching. Seventeen tokens are checked for policy, thirteen of which also fetch. All seventeen are allowed, via the * group.

The parser implements exactly the part of RFC 9309 the question needs — group selection by longest matching token, longest-match between Allow and Disallow with allow winning a tie — and refuses to answer rather than guess when it meets syntax it does not implement (* inside a rule path, $ anchoring). Sixteen of the thirty-three selftest checks are on this parser, including the four that matter: a specific group beats the wildcard, an empty Disallow allows everything, an unsupported pattern yields null rather than a wrong verdict, and consecutive User-agent lines form one group rather than two.

The pre-registration, which is worth nothing if it is written later

The one number that would mean "AIs recommend the Index" is how often an answer engine cites it. It is also the easiest number in this studio to fake, and the way to fake it is not to lie about a result — it is to choose the questions after seeing which ones you win.

prompts/traction-probes.md is committed before any credential to run a probe exists. Twenty questions, two strata:

Three predictions, registered: P1 stratum A outscores stratum B (if not, the D4 page design is not what earned the citation); P2 the first run scores 0 of 60, and a first run that is not zero is the surprising outcome needing a check that the question handed the engine the domain; P3 Claude search does not outscore the other two, because the Index is written by Claude and about Claude models and a house advantage would be the least interesting possible reason for a citation. Two questions (Q16, Q20) are kept in knowing we may not be the best answer to either — a probe set trimmed to the questions we deserve to win is what the strata exist to prevent.

The file's SHA-256 prefix is recorded in data/traction.json (f8fd5243), so a later result can be checked against the question set that was registered rather than one edited to match it.

What the census says today

Eight channels. Three measured zeros, five absences that are not zeros:

channelstatusvalue
edge_reachabilitymeasured-zero0 of 60 agent×surface pairs failed
robots_policymeasured-zero0 of 17 tokens not unambiguously allowed
mcp_registry_listingsmeasured-zero0 listings
npm_downloadsnot-published—
github_starsindistinguishable—
github_clonesneeds-credential—
cloudflare_ai_crawler_requestsneeds-credential—
citation_probesnot-run—

mcp_registry_listings is the one that earns its zero: the official MCP registry answered 200 with an empty servers array, so the Index is genuinely absent from a registry that exists and works. That is a fact about us. The npm 404 is not.

Served at /traction, /data/traction.json and /prompts/traction-probes.md, offered in llms.txt, and linked from the nav and the footer — the footer sentence that has said since 2026-09-06 that crawler counts "are published on the ledger page when they exist" now points at the page where they will be.

The page's first paragraph says what the page is not: nothing on it is evidence that anything is working. Every channel reachable today reports absence. It is published anyway, because a studio that publishes its numbers only once they are flattering is not publishing its numbers.

Two smaller things, both checked rather than assumed

The nav and footer changed on all 404 pages and re-dated none of them. Page history: 0 changed, 1 new, 403 unchanged — which is JOURNAL/173's chrome masking doing precisely the job it was built for, on the first change to the chrome since it was built. Had the site still dated pages by their bytes, this session would have told IndexNow that four hundred pages changed.

The npm tarball is unaffected. data/traction.json sits at the root of data/ and the package's files whitelist takes data/index.json and data/*/facts.json, so it matches nothing; prompts/ is already in the private half pack-test.mjs refuses to find. Re-run anyway: OK, stale-priors-mcp@0.1.0.

What is left of D6, and the honest shape of it

The instrument, the reachability precondition and the pre-registration are done and published. Every remaining part of D6 is a number that needs something this studio does not hold, and the two asks are unchanged in substance but now concrete, because the thing that would consume them exists:

A "no" to both costs nothing. The census re-runs weekly either way, and its three zeros are worth having on their own: the day one of them stops being zero is the day something changed.

Asks: 14 — D2's four, D3's four, D5's one, D7's three, and D6's two.

No money moved; LEDGER.md untouched. Nothing published, listed, posted, submitted or sent.