fix: stabilise the export harness and publish what was assembled - #352
Open
jackye1995 wants to merge 3 commits into
Open
fix: stabilise the export harness and publish what was assembled#352jackye1995 wants to merge 3 commits into
jackye1995 wants to merge 3 commits into
Conversation
The first published build dropped docs/.cursor/ silently: actions/upload-artifact skips hidden files by default, so the assembled tree had 268 files and the `assembled` branch had 267. Editor configuration is not site content and should not be published, but it should not vanish by accident either. The assembler now excludes dot-prefixed paths deliberately and names what it dropped, so the assembled tree and the published tree are the same thing — which is the guarantee the whole pipeline rests on.
Two problems found while verifying the first publish to `assembled`. The published branch had 267 files where the assembler produced 268: actions/upload-artifact skips hidden files by default and silently dropped docs/.cursor/. The first attempt excluded dotfiles from the assembly instead, which was wrong — mint export carries that file today, so removing it would have quietly deleted a published file at cutover. The harness caught that, which is the strongest evidence so far that it works. The upload now includes hidden files, and the assembler publishes what it assembled. The harness itself was intermittently failing on identical trees. Mintlify renders the OpenAPI reference non-deterministically: response code blocks come out syntax-highlighted on one run and plain on the next, ~2 KB across ~78 fragments. One comparison passed, the next failed, on byte-identical input. A gate that fails at random is one people learn to route around. That subtree is now compared for presence but not for bytes, and only that subtree. It gives up nothing about the assembler, which passes openapi.yml through byte-identically and cannot influence one render differently from the other; a page appearing or disappearing is still caught. Verified: five consecutive comparisons pass, an authored-page change is caught, a reference page being removed is caught, and a reference page's contents are knowingly not.
* feat: anchor the tables pages
First area of the anchor pass. Every section heading in docs/tables now carries
an explicit `{#anchor}` — 114 of them — which is the identity Enterprise
overlays attach to from A5 and which survives the heading being reworded.
Anchors are taken from the ids the site already renders, not derived from the
heading text. That distinction turned out to matter: Mintlify applies smart
quotes before slugifying, so `## What's next?` renders as `what’s-next` with a
curly apostrophe, and a derived slug would have silently changed the id and
broken every existing deep link to it. Reading the ids back from `mint export`
makes the pass correct by construction rather than by reimplementing rules we
would have to keep in sync.
Headings that begin with a number need their period escaped. `### 1. Setup`
renders with its number until an explicit anchor is added, at which point
Mintlify re-parses the text, treats the number as an ordered list marker, and
drops it from both the heading and the table of contents. 117 headings across 17
pages start this way, so the pass would have quietly renumbered a good deal of
the site.
Verified: the exported site is unchanged. All six existing deep links into
tables still resolve.
* feat: anchor the remaining pages
Completes the anchor pass. 805 of 810 section headings across the authored pages
now carry an explicit `{#anchor}`, the identity Enterprise overlays attach to
from A5 and the one thing that survives a heading being reworded.
Three more cases the tables pilot had not reached, each of which would have
corrupted anchors silently:
Setext headings. Eleven h2s in the reranking pages are written as text over a
rule rather than with hashes. Mintlify gives them ids like any other heading, so
a parser that only saw hashes consumed the rendered ids out of order and handed
every later heading on the page the wrong anchor — plausible names attached to
the wrong sections. They are rewritten to hashes, which renders identically, and
a strict count check now refuses to write anything when source headings and
rendered ids disagree.
Headings below h4. Mintlify emits no id for h5, so there is nothing to read back
and nothing to preserve. The eight in the corpus, all API method names on one
page, keep their generated markup and stay unanchored.
Ampersands. Mintlify keeps `&` in a generated id but strips it from an explicit
anchor, so `observability-&-performance` cannot be written down: any anchor set
on those headings changes the id and breaks links to it. Five headings join two
words this way; they keep their generated id. If A5 needs to attach to one,
rewording the heading is the honest fix rather than silently moving it.
Verified: the exported site is unchanged.
* refactor: retitle headings whose anchors carried punctuation
Eighteen headings across twelve pages produced anchors containing `&`, `/`, or
curly quotes. Ampersands were the pressing case — Mintlify keeps `&` in a
generated id but strips it from an explicit anchor, so those five headings could
not be anchored at all — but slashes made anchors read like paths and curly
quotes made them non-ASCII, and neither belongs in a key that Enterprise
overlays will be written against.
The punctuation is incidental in every case, so the headings say the same thing
without it: "Observability & performance" becomes "and", "S3 / GCS / Azure Blob"
becomes a comma list, "What's next?" becomes "Next steps". Nothing linked to any
of the old anchors, so nothing breaks.
Underscores and the plus in `analyze_plan`, `explain_plan`, `max_pooling`,
`approx_mode`, `torch_col` and `100B+ row scale` are left alone. Those
characters are part of an API name or a quantity rather than punctuation, they
are safe in a URL fragment, and renaming them would misname the thing the
heading documents.
All 810 headings now carry an anchor. The twelve pages whose rendered output
changed are exactly the twelve retitled here.
* refactor: retitle the last headings whose anchors held identifiers
Six headings named an API identifier or a quantity directly — `analyze_plan`,
`explain_plan`, `approx_mode`, `torch_col`, `max_pooling`, `100B+ row scale` —
so their anchors carried an underscore or a plus.
Renaming the identifier would have misnamed what the section documents, so the
headings now describe what the section does and the identifier stays in the
prose, where it was already being used: `analyze_plan` appears 14 times in that
page, `explain_plan` 11, `max_pooling` 9. Nothing about the API is lost, and
the heading reads better for it.
Every anchor in the corpus is now plain `[a-z0-9-]`.
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.
Both problems here were found by verifying the first publish to
assembledrather than trusting green CI.The published tree was not the assembled tree
The assembler produced 268 files; the published branch had 267.
actions/upload-artifactskips hidden files by default and silently droppeddocs/.cursor/.My first fix excluded dotfiles from the assembly instead. That was wrong —
mint exportcarries that file today, so excluding it would have quietly deleted a published file at cutover. The harness caught it immediately, which is the best evidence yet that the harness earns its keep. The upload now setsinclude-hidden-files: true, and the assembler publishes exactly what it assembled.Deciding a file is "not really content" is how a byte-comparability guarantee turns into a list of exceptions.
The harness was intermittently failing on identical trees
Worse, and the reason this PR matters. Mintlify renders the OpenAPI reference non-deterministically: response code blocks come out syntax-highlighted on one run and plain on the next — ~2 KB across ~78 fragments, on top of the per-build React keys already normalised.
It is intermittent. Byte-identical trees, run 1
EQUIVALENT, run 2DIFFERENT. In CI that is a gate failing at random, which is precisely the failure mode this project's design warns about: "false positives train engineers to route around the gate."api-reference/rest/**is now compared for presence but not for bytes, and only that subtree. This gives up nothing about the assembler:openapi.ymlthrough byte-identically, so both sides feed Mintlify the same specmake assemble, and covers the spec fileVerified