Reasoning: why the rules are what they are

The rubric states bars; this page states reasons. Each section is one decision the tooling made, the evidence it rests on, and what would change the decision.

1. Extractive descriptions beat generated ones

An index description exists so that a routing model can decide, without fetching, whether the page answers its question. That decision is made on tokens: the flag name, the error string, the endpoint path. A description written by a model reads better and drops exactly those tokens; a description cut from the page’s own first sentences keeps them. The hub’s _description takes the page’s lead sentences, trims to MAX_DESC_CHARS = 180, and prefers a sentence that contains a backticked token. The generator survey on the tooling page shows the alternative: crawl-based generators that hand every page to a small model produce fluent, interchangeable descriptions that no keyword search distinguishes.

What would change it: a consumer that embeds descriptions rather than matching tokens. None of the measured consumers does; see §5.

2. Size is a producer-side problem

Consumers do not truncate gracefully. Cursor’s moderators put the instability threshold for an indexed file at 50–60k tokens; Fern dropped llms-full.txt because it “exceeded most model context windows”; Mantine replaced a 2.2 MB inline file with a 45 KB link list after users said it “clogs the AI’s context window” (evidence, spec §3.2). Every producer that survived contact with consumers split: Mintlify recurses into /_llms/ sub-indexes past 100,000 characters, Nuxt publishes a ~5K-token and a ~1M-token file, Starlight emits llms-small.txt. So the hub publishes a ladder — index ≤ 10 KB, small ≤ 200,000 characters, full unbounded — and prints the token count of every file in the manifest and in the X-Markdown-Tokens header, so a reader can choose a rung before fetching.

3. Anchors make facts checkable

A claim without a place to verify it is a rumour with a URL. The facts line carries url#anchor, and the anchor must resolve to a heading that exists on the page (attribute C6). This is the difference between a facts file and a summary: a summary asks to be trusted; a facts line can be spot-checked in one fetch. The lint checks anchors deterministically; the passes sample facts for truth (P8) only after the anchors resolve, because a true claim with a dead anchor is still unverifiable.

4. The facts file is the trusted layer

Raw page text is untrusted input — the spec repository’s own issue #152 found that 42.3% of a 100-file sample tried to steer the reader (evidence). The facts layer is where the hub applies its filters: steering phrases are rejected by pattern (STEER_RES, attribute P4), secrets and private keys by pattern (attribute P5 — both checked in pass P9), residue from page chrome by pattern. What remains is typed (UNIT_TYPES), anchored, and bounded in size. The query layer prefers it: hub_query_docset(layer=auto) answers from <key>__facts when one exists and falls back to raw chunks only when it does not.

5. Two hops, from the index alone

The spec’s own test is the bar: “test your file by asking an agent questions about your content, giving it only your llms.txt as a starting point.” The rubric makes it numeric — attribute R5, pass P12: ten questions, an agent that starts from the index and may follow links, at least eight answered correctly in at most two hops (below eight is a Medium, below six a High; the facts file is judged on the same questions at seven, attribute R6). Two, because the consumers that demonstrably fetch these files are coding agents pointed at them (the Claude-Code user agent out-fetched every AI retrieval bot bar two in Ahrefs’ 137,210-domain log study), and an agent that needs a third hop has already spent more context than the index saved.

The evidence page holds the numbers: adoption at roughly 5–10% of the general web by mid-2026 and rising 8.8× year on year, yet 97% of valid files received zero AI requests in a month of logs, Google says it does not read the file, and a 300k-domain model found no relationship between having one and being cited. The rules on this site therefore optimise for the reader that exists — an agent handed the URL — and none of them promise rankings. A rule that only pays off if speculative crawlers arrive would be a rule about a reader nobody has measured.

7. Why the rubric is deterministic first

Every attribute names its measure: deterministic, model judgment, or live. The lint implements the deterministic passes P0–P3, P5–P7, P9 and P14 with no model call and gates CI on them; the model, live and family passes (P4, P8, P10–P13, P15) run under /ldo when someone asks. This ordering is principle 4 of the platform — the cheap path first — and it is why this site can lint its own llms family on every build without spending a token.