Documents zdocs does not build

A documentation set almost always references material that lives somewhere else: an upstream project’s manual, a vendor’s API reference, a corporate document behind another URL. zdocs models those as first-class registry entries — declared, grouped and navigable exactly like local documents — that simply produce no build target.

There are three of them, and which one to use depends entirely on what the remote side publishes. The decision record is 0005. Remote documents are three kinds, not one; the fields are in The registry schema.

sphinx-external — a remote Sphinx site

Any Sphinx site publishes objects.inv, so a remote peer can be a full intersphinx target: :external+<prefix>: references into it resolve, and break the build when they are wrong.

The engine does not fetch anything here. It adds the site to intersphinx_mapping and lets Sphinx’s own intersphinx do the work — mature, cached, retrying machinery that already exists and that no engine code should be reimplementing.

doxygen-external — a remote Doxygen site

Doxygen has no equivalent capability: a tag file must be a local file. So for this kind the engine downloads it, at build time, in the same stage local tag files are produced, and stores it under the engine’s own conventional name regardless of what the remote publisher calls it.

That is why this kind needs two separate fields — the site’s URL, and the tag file’s URL. Doxygen tag-file names are not standardised the way objects.inv is, so one cannot be derived from the other, and each is validated independently so that supplying one never masks forgetting the other.

Because the download is wired into the same stage-one gate every local document already waits on, existing documents pick up the dependency without any per-consumer wiring.

The recurring hazard

Every one of these kinds means “produces no local build output”, and several places in the engine need to know that. Historically they each asked the question by comparing against external alone — so adding a kind silently missed them.

The most expensive instance built the navigation sidebar shared by both toolchains: a remote peer’s sidebar link rendered as a local URL that would never exist, with a completely green test suite, because nothing asserted on where a nav entry actually pointed. When touching this area, audit every place that asks “is this document local?”, not only the dispatch that obviously needs changing.

Testing without the internet

The test suite never reaches the network. Remote peers in the fixtures are file:// URLs serving checked-in content, which keeps the suite offline, deterministic and fast; the real upstream URLs appear only in documentation and comments.