Rust crate apps/majordomus-cli dokumentuje každou položku, kterou exportuje, ve vlastním zdrojovém kódu, a rustdoc tuto dokumentaci vykreslí do reference: jedna stránka na exportovanou položku, zdroj, z něhož byla každá stránka sestavena, a vyhledávání nad vším. Tento dokument popisuje, jak se tato reference vytváří, servíruje, kontroluje, publikuje a ověřuje — a co dělat, když některá z těchto fází selže.
Rozhodnutím je ADR 86; pravidlem je project.the-crate-reference-is-published. Chování tak, jak je implementováno a testováno; kde se tento dokument a skripty rozcházejí, dokument se mýlí a mění se ve stejném commitu.
Účel
Reference je vlastní výpověď crate o sobě samém, v commitu: k čemu je každý veřejný modul, typ, funkce a konstanta, příklady, které cargo test --doc spouští, a zdroj vedle každé stránky. Publikuje se na https://majordomus.dev/rustdoc/ a servíruje ji jakýkoli běžící majordomus serve na /rustdoc/, ze stejných bajtů.
Je to generovaná referenční dokumentace a podléhá uzavření dokumentace: zdroj, generování, povrch, route, odkazy, testy, deployment a veřejné URL jsou každé rozhodnuty spustitelnou kontrolou. Úspěšné cargo doc prokazuje první dvě a nic za nimi — dokud tento repozitář crate měl, kontrola vykreslila referenci při každém běhu a zahodila ji a každá route, kterou čtenář mohl zkusit, odpověděla 404.
Čím není:
- Není to slib kompatibility. Crate je
publish = false. Jeho veřejným kontraktem je registr schopností, který měří ADR 51; jeho položky v Rustu se mohou změnit v libovolném release. Říká to úvodní stránka na/rustdoc/. - Ne druhý soupis. Nic zde nevypisuje moduly ani položky crate. Soupisem, který čtenář prochází, je publikovaný strom a
majordomus quality rustdocvypisuje ten, který kontrola změřila. Seznam jednoho či druhého zapsaný do tohoto dokumentu by zastaral hned, jak crate získá modul.
Architektura
flowchart TD src["crate source<br>module and item documentation<br>missing_docs with -D warnings"] producer["scripts/rust-check --doc<br>the gate's own cargo doc line"] tree["target/web/rustdoc/<br>rustdoc pages, surface.json, index.html"] discover["web::discover<br>surface rustdoc at /rustdoc,<br>declared from the crate"] webjson["docs/generated/web.json<br>the committed topology"] serve["majordomus serve<br>answers /rustdoc/"] check["majordomus quality rustdoc<br>the tree against the crate's inventory"] build["scripts/site-build<br>composes every published static surface"] public["site/public/rustdoc/<br>and /build.json surfaces"] sitecheck["scripts/site-check<br>and scripts/ci/link-check"] deploy["scripts/site-deploy<br>pushes gh-pages"] live["the public site<br>/rustdoc/"] verify["scripts/pages verify-rustdoc<br>pages.yml and the pages-live gate"] src --> producer --> tree discover --> webjson discover --> serve tree --> serve tree --> check webjson --> build tree --> build build --> public --> sitecheck public --> deploy --> live --> verify
Zdroj. Dokumentací jsou komentáře //! a /// crate. Pokrytí je stávající politika a nic nového: #![warn(missing_docs)] v lib.rs s -D warnings v kontrole činí nedokumentovaný export selháním sestavení a kontrola rust-quality drží příklady a tenkou dokumentaci na project.rust-public-api-quality (QUALITY.md).
Producent. scripts/rust-check --doc spouští krok cargo doc -D warnings — tentýž řádek, který spouštějí plný a CI režim onoho skriptu, a jediný řádek cargo doc v něm, což drží případ 77 — a předává výstup. Ptá se cargo, kde je jeho cílový adresář, místo aby hádalo (sdílený CARGO_TARGET_DIR nebo .cargo/config.toml jej mohou přesunout), vyprázdní target/web/rustdoc/, aby v něm nic z dřívější kopie nepřežilo, zkopíruje tam stránky a zapíše dva vlastní soubory:
surface.json, deklarace (web-surface/v1): idrustdoc, připojení/rustdoc, producent, dostupnostboth, kategoriedocumentation, viditelnostpublicabuilt_from, commit checkoutu, který ho sestavil — tentýž commit, který sestavení dostane jakoMAJORDOMUS_BUILD_COMMIT, takže ho uvádí i stránka konstantyCOMMITv crate;index.html, vstupní stránka, protože rustdoc zapisuje index pro každý crate a žádný v kořeni svého výstupu. Jmenuje verzi a plný commit, který dokumentuje. Každý odkaz do stromu je na ní relativní, takže stejné bajty fungují na publikovaném webu i na běžícím serveru; jediný odkaz ze stromu ven je veřejná adresa webu, čtená zsite/config.toml, protože relativní../by strom opustil aquality rustdocto na jakékoli jeho stránce odmítne.
Knihovna se dokumentuje přes své veřejné položky a spustitelný soubor tak, jak cargo dokumentuje jakýkoli binární cíl — jeho vlastními položkami, protože binárka nic neexportuje — přičemž vlastní zdrojové stránky rustdocu zůstávají pro obojí. Neexistuje žádné --document-private-items a žádné druhé vyvolání pro publikaci: publikuje se to, co kontrola dokázala.
Povrch. Povrch se deklaruje objevením z crate, tak jako se deklaruje servírovaná dokumentace z site/config.toml: je v topologii, kdykoli je crate, ať producent běžel, nebo ne, takže domovská stránka, majordomus web list a commitnuté docs/generated/web.json nikdy nezávisejí na stavu jednoho checkoutu. built_from se čte z surface.json producenta a z commitnuté projekce je z tohoto důvodu vynecháno. Připojení je vlastní, nejvyšší úrovně; WEB.md vysvětluje, proč ho /docs, /api a /reference nemohly pojmout.
Obsluha. majordomus serve odpovídá na /rustdoc/ z target/web/rustdoc/ přes web::files, tentýž hlídaný statický server, který používá /docs/. Nikdy nespouští cargo: když strom chybí, /rustdoc/ odpoví 503 s uvedením scripts/rust-check --doc a domovská stránka ukazuje povrch jako nesestavený, místo aby nabízela odkaz, který jistě selže.
Integrita. majordomus quality rustdoc čte vykreslený strom proti quality::source::Inventory, měření syntaktického stromu crate vlastních exportovaných položek — inventáři, který už používá pravidlo kvality, ne seznamu vedenému pro tuto kontrolu. Každá exportovaná položka musí mít svou stránku na trase odvozené z její cesty a druhu; žádná stránka položky nesmí existovat bez položky; strom musí nést svůj surface.json a jeho built_from musí být HEAD; index knihovny musí nést její identitu (<title>majordomus_cli - Rust</title>); musí být přítomna aktiva indexu; každý interní odkaz se musí přeložit; a žádná stránka nesmí jmenovat cestu na stroji ani tajemství. Stránky spustitelného souboru se posuzují stejným průchodem nad inventářem vlastního binárního cíle. Končí 0 při čistém výsledku, 10 s nálezy a 12, když není žádný strom k posouzení.
Dva druhy nerozřešených odkazů patří rustdocu, ne crate. Každý je pojmenovaná třída (RustdocLinkClass), určená tím, kde odkaz stojí, počítaná pod counts.accepted_links s jejími odkazy, stránkami a každým odlišným odkazem tak, jak je napsán, a nikdy není zjištěním:
inherited-documentation: relativní odkaz uvnitř docblocku, který rustdoc zkopíroval z jiného crate — dokumentace implementace uvedené pod Auto Trait Implementations nebo Blanket Implementations traitu, který nedokumentuje žádná stránka tohoto stromu (hlavička implementace neodkazuje na žádnou stránku traitu stromu). Text je z cizího crate, psaný relativně k jeho vlastním stránkám — tracingovédispatcher#setting-the-default-subscriber,super::Subscriber,crate::Span,super::Span::current()— takže se nerozliší nikde pod/rustdoca nic v tomto crate to nezmění. Tentýž odkaz kdekoli jinde na stránce, v implementaci, kterou crate píše sám, nebo pod implementací traitu tohoto crate, je zjištěnílink. Na stromu z 2026-09-24: 4705 odkazů na 941 stránkách.unwritten-implementors: skript implementors, který stránka traitu načítá —trait.impl/<crate>/<path>/trait.<Name>.js, pro právě ten trait, který stránka dokumentuje — když rustdoc žádný nezapsal. Rustdoc na něj odkazuje z každé stránky traitu a zapisuje jej jen tehdy, když dokumentované crate mají implementory k výpisu; stránka vykresluje implementory vlastního crate inline a je úplná i bez něj. Jakýkoli jiný chybějící skript, stylesheet nebo soubor je zjištění. Na stromu z 2026-09-24: jedno,majordomus_cli/capability/handler/trait.Handler.html.
Obojí je vidět na veřejném webu a je to zde přiznáno místo skrytí: následování jednoho z zděděných odkazů odpoví 404 a požadavek stránky traitu na její nenapsaný skript implementorů odpoví v síťovém logu prohlížeče 404. Ani jedno neztrácí nic z dokumentace tohoto crate a počty v reportu říkají, kolik jich je, takže změna v kterémkoli je vidět.
Skládání. scripts/site-build zkopíruje každý publikovaný statický povrch kromě samotného webu do svého výstupu na mount povrchu, po Zola a po průchodu přístupnosti webu. Seznam se čte z docs/generated/web.json (mj_web_composed v lib/common.sh), takže ho žádný řádek nepojmenovává. Publikovaný povrch, jehož artefakt chybí, odmítne build s exitem 12 a pojmenuje svého producenta; mount, který už web sám vyplňuje, je odmítnut s exitem 10, protože jedna cesta má jednoho vlastníka. Build také zaznamená každý složený povrch s commitem, který deklaroval jeho producent, pod surfaces v /build.json, jediném identitním souboru, který web servíruje.
Posouzení složeného stromu. Kontrakt stránek webu v scripts/site-check posuzuje stránky, které Zola vykresluje. Stránky pod mountem složeného povrchu — odvozeným ze stejné topologie — se z něj vyjímají, protože jejich markup patří toolchainu; posuzuje je quality rustdoc. Odkaz ze stránky webu do /rustdoc/ rozhoduje scripts/ci/link-check proti složenému stromu jako interní soubor jako každý jiný.
Odkazy z webu. Stránka každého vestavěného modulu pod /registry/modules/ odkazuje na stránku, na které reference tento modul dokumentuje, jako „reference crate“ ve své provenienci. Mapování modulu na jeho stránku je vlastní kontrole: quality::rustdoc::module_routes drží moduly, které crate exportuje, a odvozuje stránku každého z inventáře crate — routy, které report vypisuje pod modules, z nichž každou kontrola vyžaduje od stromu — a majordomus generate tuto odpověď přenáší do datové sady registru webu jako rustdoc u každého modulu (povrch, cesta modulu v crate, stránka v rámci povrchu). Modul, kterému rustdoc nedává stránku, deklarovaný pub(crate) nebo soukromý, žádnou nenese, takže nevznikne odkaz, který by mohl odpovědět 404. Šablona neodvozuje žádnou routu: spojuje toto pole s povrchy, které build složil a které scripts/site-build zaznamenává s jejich mounty v data/build.json, a odkazuje přes get_url na mount, na kterém build referenci složil. Build, jehož topologie referenci postrádá, nebo prostý zola serve bez build.json, neodkazuje na nic. Stránky modulů Cockpitu jsou samostatný renderer a zde nejsou pokryty.
Lokální použití
scripts/rust-check --doc # produce target/web/rustdoc (or: just rustdoc)
majordomus quality rustdoc # the integrity check over that tree
majordomus quality rustdoc --tree DIR # the same check over another copy of it
majordomus web explain rustdoc # the surface: mount, producer, built_from, provenance
majordomus serve # then open /rustdoc/ on the URL it logs
scripts/site-build # the site, with the reference composed at /rustdoc
scripts/site-check # the static checks over the composed site
scripts/site-build odmítne běžet, dokud neběžel producent, a řekne to s příkazem ke spuštění. To je záměr: web sestavený bez povrchu, který topologie zveřejňuje, je tichá ztráta, jíž má tento návrh zabránit.
Strom je ignorován a nikdy se necommituje. Vkládá commit, ze kterého byl sestaven, takže je po každém commitu zastaralý, a kontrola to říká.
Validace
| co | kde běží | co odmítá |
|---|---|---|
kontrola rust-check (scripts/rust-check --ci) | job rust validačního workflow | varování dokumentace v kroku cargo doc -D warnings, který také vytváří strom |
kontrola rustdoc (majordomus quality rustdoc), která vyžaduje rust-check | úloha rust | jakékoli zjištění integrity nad stromem, který běh vytvořil, a žádný strom vůbec |
web-topology (majordomus web validate) | úloha rust | povrch kolidující s jiným nebo vnořený do jiného |
kontrola site-build: scripts/site-build | úloha site a publikace | publikovaný povrch, jehož artefakt chybí; mount, který vyplňuje sám web |
kontrola site-build: scripts/site-check, sekce 13m | úloha site a publikace | složený povrch chybí v sestavení, nenese surface.json, deklaruje jiné id nebo mount než topologie, nebo je sestaven z jiného commitu než sestavení; /build.json s ním nesouhlasí |
scripts/ci/link-check | spouští site-check | odkaz ze stránky webu do /rustdoc/, který složený strom neobsahuje |
| případy 486–490 a 492 | shellová sada | každá fáze záměrně rozbita a její odmítnutí pozorováno |
testy quality::rustdoc, web::discover a site, tests/http_serve.rs | cargo test | jeden fixture na každý způsob selhání; deklarace přítomná dříve, než producent běží; modul, který crate neexportuje, nelinkovaný nikde; strom servírovaný celý přes skutečný socket |
Šest případů, každý jedna fáze:
| případ | fáze | co rozbíjí |
|---|---|---|
486 | kompozice | build webu bez artefaktu reference a s ním |
487 | zastaralost | strom sestavený z jiného commitu, při kontrole a při veřejném ověření |
488 | objevitelné a dosažitelné | povrch dříve, než producent běží; /rustdoc/ přes obsluhovaný socket |
489 | nasazení | složený web nasazený do holého remote a co nese publikovaná větev |
490 | úplnost | modul přidaný do fixture crate, který se stane povinnou stránkou, aniž by cokoli uváděl |
492 | odkazováno | stránka webu každého vestavěného modulu proti route modulů kontroly, s komponovanou referencí i bez ní |
bash test/run.sh 486_rustdoc_composition 487_rustdoc_staleness 488_rustdoc_discoverable \
489_rustdoc_deploy 490_rustdoc_new_module 492_rustdoc_module_links
cargo test --manifest-path apps/majordomus-cli/Cargo.toml quality::rustdoc
cargo test --manifest-path apps/majordomus-cli/Cargo.toml site::tests
cargo test --manifest-path apps/majordomus-cli/Cargo.toml web::discover
cargo test --manifest-path apps/majordomus-cli/Cargo.toml --test http_serveNasazení
Strom se vyrábí v CI a skládá při buildu; nikdy se necommituje a job nasazení nenese žádný toolchain Rustu.
Publikace začíná na pushi, jehož cesty mohou změnit publikované bajty, a tyto cesty odvozuje scripts/pages paths z modelu kontrol, nikdy se nepíší do workflow. U reference musí zahrnovat zdroje cratu, manifest, lock soubor a build skript, pin toolchainu, producenta a jeho akci; scripts/pages paths je příkaz, který říká, zda ano.
- Job
rustdocv.github/workflows/pages.ymlje samostatný job, který nasazovací job potřebuje. Vytváří strom pomocí složené akce.github/actions/rustdoc— téže akce, kterou používají joby validačního workflow sestavující web, takže oba workflow jej nemohou sestavit odlišně — z nasazovaného commitu a předává jej nasazovacímu jobu jako artefakt téhož běhu. Oba běží jeden po druhém: sestavení webu složí strom a kontroly webu posoudí složený výstup, takže ani jedno nemůže začít, dokud neexistuje. Doba běhu jobu a stažení jeho stromu jsou řádkemrustdocz fází, které nasazovací job měří. - Skládání. Úloha deploy stáhne ten strom do
target/web/rustdoc/předscripts/pages build, jehožscripts/site-buildjej složí na/rustdocpřesně jako lokálně, ascripts/pages checknad složeným výstupem spustí každou statickou kontrolu. - Publikace.
scripts/site-deploypushne složenésite/publicdogh-pages, stejnou jedinou cestou nasazení jako dříve. Na mechanismu se nic nezměnilo; strom, který pushuje, nyní nese referenci. - Veřejná verifikace, vynucená. Jakmile web servíruje nasazený commit,
scripts/pages verify-rustdoc --commit SHApřečte veřejnou referenci:/build.jsona/rustdoc/surface.jsonmusí jmenovat tento commit, úvodní stránka jej musí jmenovat, index knihovny musí být rustdocí s odpovídajícími stylopisy a skripty, stránka modulu a vyhledávací index musí odpovídat a konstantaCOMMITsamotného cratu musí jmenovat tento commit. Je to tvrdý krok jobu deploy, spouštěný až když je známo, že web commit servíruje, takže nasazení s chybějící, rozbitou nebo zastaralou veřejnou referencí selže. - Poté.
scripts/ci/pages-check, kontrolapages-live, nese sekci, která klade stejnou otázku živému webu při každé plné validaci a přifinish, protože běh zrušený před ověřovacím krokem nemohl nic nahlásit.
Řešení problémů
Položka nemá stránku, nebo stránka nemá položku
majordomus quality rustdoc # names the item, the route it expected, and why
jq -r .built_from target/web/rustdoc/surface.json; git rev-parse HEAD
Když se oba commity liší, strom je starší než položka: spusťte scripts/rust-check --doc. Když se shodují a nález trvá, položka je exportována, ale rustdoc jí na odvozené trase nedává stránku — obvykle kvůli #[doc(hidden)], re-exportu vykreslenému inline nebo aktualizaci toolchainu, která změnila konvenci tras rustdocu. Rozhodněte, zda má být položka veřejná (majordomus quality report ukáže, co vidí politika). Pravidlo trasy, které je pro připnutý rustdoc špatné, se opraví v quality::rustdoc, ve stejné změně jako připnutí v rust-toolchain.toml, pokud ho aktualizace posunula — nikdy výjimkou po jednotlivých položkách.
Odkaz je rozbitý
majordomus quality rustdoc # a link inside the reference that does not resolve
scripts/ci/link-check # a link from a site page into /rustdoc/
Uvnitř reference je rozbitý intra-doc odkaz v komentáři /// už varováním, které krok cargo doc -D warnings mění v chybu. Odkaz, který jím projde, je obvykle doc komentář odkazující na soubor repozitáře cestou relativní ke zdrojovému souboru: ta se na forge vyřeší a pod /rustdoc nikde. Odkazujte raději na publikovanou stránku nebo URL forge, u zdroje. Ze stránky webu nález jmenuje stránku a cíl; opravte odkaz v kanonickém dokumentu, ze kterého byla promítnuta, nikdy v site/content/.
Dokumenty jsou zastaralé
majordomus web explain rustdoc # built_from, beside the checkout's HEAD
majordomus quality rustdoc # refuses a tree built from another commit or none
Spusťte scripts/rust-check --doc. Před kopírováním vyprázdní target/web/rustdoc/ a před buildem vyprázdní vlastní dokumentační adresář cargo, když je cílový adresář cargo tímto checkoutem: rustdoc zapisuje do toho adresáře přes cokoli, co zbylo po dřívějším běhu, a ponechává zdrojovou stránku souboru, který crate už nemá, a každý shard vyhledávacího indexu, který kdy zapsal — změřeno 2026-09-24 s rustdoc 1.98.1, 489 shardů v opakovaně používaném adresáři proti 430 v čerstvém. Když je cílový adresář sdílen s jinými checkouty (CARGO_TARGET_DIR), není na producentovi, aby jej vyprazdňoval, takže --doc odmítne s exit 12 a jmenuje příkaz, který dá tomuto checkoutu vlastní adresář; plné režimy skriptu spustí své kontroly a řeknou, že nic nebylo předáno. Zjištění orphan-page z quality rustdoc po lokálním buildu ze sdíleného adresáře se odstraní stejně, nebo ručním vyprázdněním, když jej žádný jiný checkout nepoužívá:
cargo clean --doc --manifest-path apps/majordomus-cli/Cargo.toml && scripts/rust-check --docChybí assety
majordomus quality rustdoc # names every asset the index links and the tree lacks
Vyhledávací index, stylesheety, skripty a fonty jsou vlastní soubory rustdocu vedle stránek. Strom, který je nemá, byl zkopírován částečně nebo převzat z jiného adresáře, než do kterého zapisoval cargo. Sestavte jej znovu z čistého adresáře dokumentace se stejným řádkem cargo clean --doc jako výše; producent se cargo ptá na jeho cílový adresář, místo aby hádal, takže kopíruje to, co cargo zapsal.
Zdrojová revize je špatná
jq -r .built_from target/web/rustdoc/surface.json
grep -o '[0-9a-f]\{40\}' target/web/rustdoc/majordomus_cli/constant.COMMIT.html | head -n 1
curl -fsS https://majordomus.dev/build.json | jq '{commit, surfaces}'
scripts/pages verify-rustdoc --commit "$(git rev-parse HEAD)" --timeout 0
Revizi, ze které byl strom sestaven, jmenují dvě hodnoty: built_from, kterou zapisuje producent, a konstanta COMMIT crate, kterou rustdoc vykresluje na své stránce. Producent obě zapisuje z jedné hodnoty: předá buildu commit, který zaznamenává, jako MAJORDOMUS_BUILD_COMMIT, protože build.rs čte commit jen tehdy, když se změní zdrojové soubory crate, manifest, lock soubor nebo tato proměnná, a po commitu, který se jich netýká, běžný cargo doc ponechá zkompilovaný starší commit. Obě hodnoty se tedy rozcházejí jen tehdy, když byl strom složen ze dvou buildů — z kopie výstupu jiného běhu nebo ze stránek zkopírovaných ručně, nikoli producentem. Sestavte jej znovu producentem; volající, který musí dokumentovat jiný commit než HEAD, nastaví proměnnou sám a built_from pak pojmenuje i tento commit:
scripts/rust-check --doc
MAJORDOMUS_BUILD_COMMIT="<sha>" scripts/rust-check --doc
Na veřejném webu je commit v /build.json commit, z něhož byl web sestaven, a surfaces[].built_from commit, který deklaroval producent každého složeného povrchu. Když se liší, nasazení složilo strom z jiného buildu — obnovené cache nebo artefaktu jiného běhu. Úloha rustdoc musí strom vytvořit z commitu, který nasazuje; po odstranění příčiny spusťte publikaci znovu dispatchem workflow pages.
Veřejné ověření selhává
sha="$(git rev-parse HEAD)"
scripts/pages verify --commit "$sha" --timeout 0 # is the site serving it at all?
scripts/pages verify-rustdoc --commit "$sha" --timeout 0 # and is its reference whole?
scripts/ci/pages-check # what the pages-live gate sees
Čtěte je v tomto pořadí. Pokud selže verify, web ještě neservíruje commit — fronta Actions nebo vlastní build Pages GitHubu, což pokrývá GITHUB_PAGES_PERFORMANCE.md — a reference problémem není. Pokud verify projde a verify-rustdoc selže, zjištění pojmenovává, co je špatně: reference chybí na /rustdoc/ (log nasazení nemá řádek == compose rustdoc, takže strom nebyl získán), index nebo konstantní stránka odpovídá jinou identitou nebo jiným commitem, nebo chybí stránka. Opravte příčinu a spusťte publikaci znovu; ověření se nikdy neprominuje, aby byl běh zelený.