fix(docs): order llms-full.txt by the navigation tree - #201
Merged
Conversation
`llms-full.txt` enumerated `source.getPages(LANG)` and joined the result unsorted, so page order was whatever order the loader finished reading files in. That is stable inside one build and not across builds: two consecutive builds of an untouched tree emitted the same 79 pages with the whole `configure/` group and the whole `deploy/` group swapped. Order by `source.getPageTree(LANG)` — `meta.json` order, the site navigation — rather than by a sort. Sorting would be deterministic and worse: the order pages appear in this file is read, and alphabetical would scatter `build/`, `deploy/` and `operate/` through a flat A-to-Z list. `llms.txt` already walks the tree, so the index and the full text now agree on sequence. Reproducibility falls out of that. Membership is unchanged: same 79 page blocks, same 93 `#`-prefixed lines, same 798 heading lines, same 646 link targets, and the sorted line multiset of the served body is byte-identical to the old one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G5zjYc2BoFV2NjKBBapC7C
hotlong
marked this pull request as ready for review
August 26, 2026 02:06
This was referenced Aug 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #196
llms-full.txtenumeratedsource.getPages(LANG)and joined the result unsorted, so the order pages appear in was whatever order the loader happened to finish reading files in. Stable inside one build, not across builds.What changed
One file,
apps/docs/app/llms-full.txt/route.ts. The route now walkssource.getPageTree(LANG)—meta.jsonorder, which is the site navigation — withflattenTree, and resolves each tree node back to its page withsource.getNodePage. Everything else about the route is untouched: each page's text is still resolved against that page's own URL throughabsoluteLinks(text, pageUrl), exactly as landed in #178 (9a1a7ad).Two smaller things in the same file, both consequences of the enumeration moving:
LANGpin's doc comment namedsource.getPages()as the call whose language argument is mandatory. It now namessource.getPageTree()too, because that is the call this route makes, and dropping the argument from it has the identical 335-pages-over-7-locales failure. Wording pinned to the sibling comment inllms.txt.getNodePagereturnsundefinedfor a node it cannot resolve. This throws rather than filtering. A silently dropped page is a worse defect than the one being fixed here, and this is the only place a drop could enter.Why the navigation tree, not a sort
Per the grading comment on the card. Unlike
sitemap.xml, where entry order carries nothing to a crawler, the order pages appear in this file is read — it is one long document. So a deterministic order is necessary and not sufficient: alphabetical would be reproducible and worse than the accident it replaces, scatteringbuild/,deploy/andoperate/through a flat A-to-Z list.llms.txtalready walks the tree, so the index and the full text now agree on sequence rather than contradicting each other. Reproducibility falls out of fixing the meaning.Verification
All builds are
pnpm run buildinapps/docs, measured on.next/server/app/llms-full.txt.body. The two "after" builds are on the final commit,8d1cfed.Determinism, the card's reproduction inverted
origin/main9a1a7ad, untoucheda6b849f121bf34b9cc4496fc3d1925bdee95ebfdeaf07dd42ac70440b3df67c680f7471b18f552854fb5798824e69a06641088fada2fd7e68653995c0ed328858d1cfed, untouchede84953ee1066becf3a6fae11099f7cd3c3179009ffe5435a2cd34f14c6cea310e84953ee1066becf3a6fae11099f7cd3c3179009ffe5435a2cd34f14c6cea310The defect reproduces on this tree, with the card's exact signature: the two baseline bodies first diverge at the 17th
#heading, where the wholeconfigure/group and the wholedeploy/group trade places. After the change, two consecutive builds are byte-identical.Membership unchanged
#-prefixed lines35c58edea210d75f...35c58edea210d75f...The last row is the strong form of the claim: sorting the body's lines before hashing makes the hash blind to sequence and sensitive to everything else, so a permutation of whole page blocks is the only edit that leaves it unchanged. It is identical across all four builds above.
The
#-prefixed line count breaks down as 79 page titles plus 14 shell comments inside fenced code blocks. Reading the 79 per-page prerenders in the same build (.next/server/app/llms.mdx/**) gives 79 page titles and the same 14 in-fence lines, with zero pages leaving a fence unclosed — so that split is a property of each page's own text, not of the order they are concatenated in.Three independent counts agree that the page set is 79 and unchanged: the 79 prerendered
llms.mdxbodies, the locale-surface gate's oracle (79 logical docs page(s), derived fromcontent/docs/), and the 12meta.jsonfiles checked directory by directory against the 79 English.mdxfiles. No orphan page — nothing thatgetPages(LANG)returns is unreachable from ameta.json— so the stop-and-report condition on the card did not arise.The resulting order is the navigation
llms.txtlists its sections in this order: Overview, Use, Build, Configure, Deploy, Operate, Resources, Reference.llms-full.txtnow opens with the five root-level pages in rootmeta.jsonorder — ObjectOS, Why ObjectOS, Extend Existing Systems, Quickstart, Architecture — and the first section after them is Use, the same onellms.txtlists first: Using ObjectOS, Working with records, Using views, Dashboards, Approvals, Notifications, Profile and settings. That isuse/meta.jsonverbatim. Build, Configure, Deploy, Operate, Resources and Reference follow in the same sequence as the index.Gates
pnpm run type-check(fumadocs-mdx,next typegen,tsc --noEmit)pnpm run buildCompiled successfully in 34.9s, 996 static pagesnode .github/scripts/check-locale-surface.mjsevery advertised URL has a source file, and every source file is advertised—sitemap.xml346 advertised / 346 expected / 0 unexpected / 0 missing / 0 duplicatedpnpm turbo run test3 self-test(s) passedcheck-translation-ownership.mjsEvery gate above was run on
8d1cfed, exceptturbo run testand the ownership check, whose inputs this diff does not touch.Cards in flight
apps/docs/app/sitemap.ts. No file intersection, and per the grading comment the two are deliberately not the same decision. It stays open; nothing here addresses it.robots.tsblocks/llms.txtfrom every crawler, and the file it blocks is titled "# Documentation" #170's grouping work stops being contradicted by an arbitrary sequence in the full-text file.Generated by Claude Code