Skip to main content

Module check_guide_links

Module check_guide_links 

Expand description

cargo dev check-guide-links — every guide citation names a live page.

§Why this is a separate command

An earlier sweep de-internalised the public rustdoc: it replaced docs/design/… citations with links to the guide. With no site deployed it had to use the repository form — a github.com/…/blob/main/docs/<page>.md URL — which resolves but points at the source file rather than at the published page, and pins a moving main rather than a version. A later sweep moved all 131 of them — 127 in the six documented crates, 4 republished onto generated pages — to crate::markdown::SITE_PAGE_PREFIX, and this command is what keeps them swept.

It earns its place on the second check. Nothing in the tree notices today when a doc comment cites a guide page that has been renamed or deleted: rustdoc does not resolve URLs, mkdocs build --strict never sees a doc comment, and check-api-links checks the API map rather than prose. A citation of concepts/storage/ after that page is renamed is a link that looks right in every review and 404s for every reader.

§The four checks

  1. No repository form survives. No file spells any of REPOSITORY_DOCS_PREFIXES — both of GitHub’s, the file form and the directory form. The sweep stays swept: a doc comment written next year cannot quietly reintroduce a repository link, which is how the first 131 accumulated.

  2. Every site-absolute citation names latest, and a page and anchor that exist. A …/latest/<section>/<page>/ URL is parsed back to docs/<section>/<page>.md; its fragment is checked against the heading anchors the site renders for that page. This is the check nothing else in the tree can make.

    The scan keys on the site root, so it finds a citation naming any version segment and then requires the segment to be markdown::SITE_VERSION. Keying on the whole …/latest/ literal — which is what it once did — meant it could only ever see the citations that were already right: …/atune/dev/concepts/nonexistent/ was not a citation to it at all, and passed every check while naming nothing. The exceptions are VERSION_EXEMPT and are printed on every green run.

  3. No generated page under docs/ carries a site-absolute URL. Rule (4)’s invariant, checked over the files on disk rather than trusted: crate::markdown::site_links_page_relative is what makes such a URL page-relative, so one surviving means the rewrite did not fire — the page was hand-edited, the citation arrived in a spelling the rewrite refuses (an autolink or bare prose, neither of which has a page-relative form), or the rewrite no longer runs at all. The list of generated pages comes from generate_all::generators, never from a constant here, so a tenth generator is covered by existing.

  4. No doc comment of a registry crate cites the internal corpus. A sweep took 341 such lines out of the five crates that reach crates.io or PyPI and nothing stood guard over the result, so the invariant held only until somebody edited a doc comment. See REGISTRY_CRATES — including for the half that is counted rather than gated, and why.

§What this command covers, and what it does not

It reads every UTF-8 file in the repository except the directories in SKIPPED, symbolic links included and each target walked once, so a citation in a doc comment, a README, a page, a workflow, a manifest comment or a runtime message string is all equally in scope. That breadth is the point: the 131 occurrences the sweep found lived in .rs, .md and .pyi files, and two of them were format! strings a reader sees at run time rather than doc comments at all.

Nothing is exempt. The internal plan at the repository root is kept off the site by mkdocs.yml, which publishes only docs/, but it obeys the same four rules: a decision about links names the rule rather than quoting a form the checks reject.

A site URL under one of NOT_A_PAGE is skipped by check 2, and that is a genuine gap rather than a tidy exclusion — see the constant.

Three things it cannot see, each already owned elsewhere:

  • whether a page-relative link resolves. mkdocs build --strict with validation.links.not_found and validation.links.anchors does that, on every build, which is the whole reason rules (3) and (4) emit relative links at all (D38 sub-decision 3).
  • whether a generated page equals what its generator would write. generate-all --mode check does that. This command reads the file on disk, so the two are a pair in the same sense --mode check and check-api-links are: a hand-edited page that reintroduced an absolute URL fails here, and a generator that would emit one fails there.
  • whether a docs.rs URL is right. atune_derive cannot use an intra-doc link — atune depends on it, so the reverse dependency does not exist — so its three citations are hand-spelled docs.rs URLs and must stay absolute. Nothing here or anywhere else resolves them; the anchor they name was verified against a real cargo doc tree by hand.

Constants§

CHECKER 🔒
This command’s name, for fail-closed error messages.
DOCS_DIR 🔒
Where a guide page lives, for turning a site URL back into a file.
INTERNAL_CORPUS 🔒
The internal plan’s file name, as a doc comment would spell it.
NOT_A_PAGE 🔒
Site paths that are not published from a docs/**.md page, so check 2 has no file to look for.
REGISTRY_CRATES 🔒
The crates whose doc comments may not cite the internal plan.
REPOSITORY_DOCS_PREFIXES 🔒
The repository forms the first guide citations used, since swept away.
SKIPPED 🔒
Directory names never descended into.
VERSION_EXEMPT 🔒
Files allowed to name a version segment other than latest, with the reason.

Functions§

check_generated_pages 🔒
Check 3: no generated page under docs/ publishes a site-absolute URL.
check_internal_corpus 🔒
Check 4: no doc comment of a registry crate cites the internal corpus.
check_page_exists 🔒
Check 2: the page and optional anchor a site-absolute citation names exist.
check_repository_form 🔒
Check 1: no repository form appears anywhere.
cites_corpus 🔒
Does this line cite the internal corpus from a rendered doc comment?
collect_files 🔒
Every file under directory, skipping SKIPPED directory names.
crate_of 🔒
The crate a crates/<name>/src/… path belongs to.
has_unsafe_page_path 🔒
Whether a citation can escape the guide tree when mapped back to a source page.
heading_ids 🔒
The heading anchors MkDocs’ toc extension renders: each heading’s slug.
is_intraword_underscore 🔒
Whether the underscore run holding chars[index] has an alphanumeric character on both sides.
page_source 🔒
The docs/ source file a site URL’s path came from.
read_scanned_file 🔒
Reads one discovered file, skipping only content that is not UTF-8.
relative_to_root 🔒
A path as the repository-relative, /-separated string a message should name.
report_internal_corpus 🔒
Prints what the published /api/rust/ tree still carries, and from where.
run
Runs the four checks, reporting every failure rather than the first.
site_citations 🔒
Every site-absolute citation on one line, as (version segment, page path).
strip_heading_markup 🔒
Removes Markdown link destinations and inline formatting before slugging.
unclassifiable 🔒
Wraps a message as this command’s fail-closed error.
wrong_version 🔒
A citation naming a version segment this tree may not write.