Skip to main content
This page is the single reference for every automatic check that runs against this repo, whether it is triggered by a pull request or runs on its own schedule. It does not duplicate the general mechanics already covered in Mintlify deployment and CI/CD - only what each check covers and how to act on it.

Per-PR checks

Every auto-fix check on this page shares one behavior worth knowing about, first confirmed live on #272: because this repo is public, a workflow’s own GITHUB_TOKEN push lands its own re-triggered run in “action required” instead of running automatically - GitHub gates it behind a one-click manual approval (Actions tab > the pending run > Approve and run) rather than silently re-running. This isn’t a failure and doesn’t mean anything is broken: the fix commit has already landed by this point, and approving just lets the check confirm (correctly) that there’s nothing left to do. Safe to leave unapproved indefinitely if the check isn’t a required status for merging.

Database enum sidebarTitle auto-fix

Only triggers on a PR touching en/database/tables/enums/**, a tree wholly generated by an external ADO pipeline (see #192) with no source file in this repo. Every page’s title follows one fixed shape, Enum values for <Name>, which otherwise renders unabbreviated in the sidebar. Unlike every other check on this page, this one doesn’t just warn or fail - it derives a short sidebarTitle from <Name>, and if any changed page in the PR is missing it, pushes a fix commit directly onto the PR branch. Only files matching the exact Enum values for <Name> shape are touched; anything else is left alone rather than guessed at. Because the fix is idempotent (a page that already has sidebarTitle is left untouched), the fix commit’s own push re-triggers this same check but produces no further commit - it self-terminates rather than looping. Skipped entirely for PRs from a fork, since the default token can’t push back to a fork’s branch.

MDO-provider title/sidebarTitle auto-fix

Only triggers on a PR touching en/api/mdo-providers/reference/**, a tree wholly generated by an external ADO pipeline (see #192) with no source file in this repo. Most page titles are short, but 36 of 421 (at the time of writing) share one structured shape - relationssearchlistprovider<entity><entity?><active|passive>, from a closed 5-entity vocabulary (appointment, contact, document, person, sale). Unrecased, that shape reads poorly as a page title and, unabbreviated, renders as one very long unbroken string in the sidebar - two separate problems, fixed in two separate fields. This check PascalCases every recognized word and rewrites title in full (e.g. relationssearchlistproviderappointmentappointmentpassive -> RelationsSearchListProviderAppointmentAppointmentPassive, preserving every part of the name), then separately derives a short sidebarTitle that drops the shared relationssearchlistprovider prefix - redundant information once a page is already inside this tree in the sidebar - and space-joins the rest (-> “Appointment Appointment Passive”). Like the other auto-fix checks on this page, it pushes a fix commit directly onto the PR branch if any changed page is missing either field, rather than just warning or failing. Only the confirmed relationssearchlistprovider* shape is touched - a handful of other long, irregular one-off names in this same tree (e.g. ticketselectionwithstaticmenu) don’t share this pattern and are deliberately left alone rather than guessed at. Idempotent (a page that already has both fields set is left untouched, so the fix commit’s own push produces no further commit), and skipped entirely for PRs from a fork, since the default token can’t push back to a fork’s branch.

Reserved version frontmatter auto-fix

Only triggers on a PR touching .md/.mdx files (repo-wide, apart from a short list of excluded generated/reference paths - see the workflow file for the current list). Mintlify’s search back end treats version as a reserved search-filter field and 400s on the non-string value our own version property produced - so the property was renamed to so_version repo-wide (see issue #254). Like the two auto-fix checks above, this doesn’t just warn - it rewrites version: to so_version: directly in any changed file’s frontmatter and pushes a fix commit onto the PR branch, so an external pipeline that reintroduces the old key gets corrected automatically rather than needing a human to notice a warning and fix it by hand. The rename is a pure key swap - the value and every other frontmatter line are left untouched. Idempotent (a file that already uses so_version: is left alone, so the fix commit’s own push produces no further commit), and skipped entirely for PRs from a fork, since the default token can’t push back to a fork’s branch.

Reference-page overflow auto-fix

Triggers on a PR touching either maintained list (tools/ci/wide-mode-pages.txt, tools/ci/code-wrap-pages.txt) or the three generated reference trees they can name pages from (en/database/tables/, en/api/archive-providers/reference/, en/api/mdo-providers/reference/). Generated tables and code samples in these trees sometimes render wider than the content column and visually spill into the right TOC panel - not reliably predictable per page from the outside, so this doesn’t try to classify every page automatically. Instead, two small human-curated lists name the pages that need a fix, and this check re-applies the fix to every listed page on every run (not just this PR’s changed files), so a future ADO regen that drops the fix gets it re-added automatically:
  • wide-mode-pages.txt - pages that get Mintlify’s mode: "wide" frontmatter (hides the right TOC, keeps the left sidebar). An existing, different mode: value on a listed page is left untouched and reported as a conflict rather than overwritten.
  • code-wrap-pages.txt - pages whose fenced code blocks get wrapped in a <div className="wrap-code-samples"> marker, which style.css scopes a white-space: pre-wrap override to. Used instead of mode: "wide" where losing the TOC was judged worse than a wrapped code line; deliberately not a site-wide CSS change, since most multi-line indented code elsewhere in the docs relies on the default white-space: pre to avoid unexpected mid-line breaks.
Append a page path to either list (no extension - the tool resolves .mdx/.md itself, preferring .mdx if both exist) whenever a new overflowing page is found or reported. Both fixes are idempotent, and both are skipped entirely for PRs from a fork, since the default token can’t push back to a fork’s branch.

OpenAPI conversion auto-fix

Only triggers on a PR touching api-sources/openapi/agent/** or api-sources/openapi/rest/** - hand-maintained Swagger 2.0 sources refreshed by an external NetServer/ADO build, not authored in this repo. Mintlify renders OpenAPI 3, so every source file has a converted counterpart under openapi/agent/ or openapi/rest/, plus an entry in config/nav-restful-agent-openapi.json or config/nav-restful-rest-openapi.json wiring it into navigation - both are workaround output this repo generates and commits ahead of issue #147’s native OpenAPI 3 pipeline. Before this check existed, a source refresh had no mechanism forcing the derived output to be regenerated in the same PR, so it silently went stale (confirmed on PR #232, which refreshed every source file but left openapi/ and both nav files untouched for days). For each PR, the check converts only the added/modified source files (not a full re-conversion of every spec) via tools/convert-swagger-to-openapi.ps1, removes the output for any deleted source file, then regenerates both nav files from the current openapi/{agent,rest}/ directory listing so a newly added or removed spec is wired into (or dropped from) navigation without a manual edit. If any of that produces a real diff, it’s pushed back onto the PR branch as a fix commit, same as the other auto-fix checks on this page. The converter also works around one known upstream bug: two source files (Swagger-v1-QuoteAgent.json, Swagger-v1-Selection.json) $ref a schema definition that the NetServer Swagger generator omits from the same file, which otherwise makes conversion fail outright. The converter copies the missing definition in from a sibling file that still has it, against a throwaway in-memory copy - the tracked api-sources/ file itself is never edited, since that folder is pipeline-owned. This whole check, plus tools/convert-swagger-to-openapi.ps1 itself, is a workaround for the lack of a native OpenAPI 3 pipeline output - see issue #297. Once #147 lands, delete this workflow and the converter script outright rather than trying to keep them in sync with a pipeline that no longer needs them; tools/ci/generate-openapi-nav.py is the one piece that may be worth keeping as a standing nav-drift check regardless of how the underlying specs get produced.

Recent-pages sync auto-fix

Triggers on a PR touching index.mdx itself, or anything under en/**/integrations/**. The homepage’s “What’s new” list is driven by index.mdx’s own recent_pages frontmatter - see Metadata properties for the property’s shape - and resolved into a separate <RecentPages items={[...]} /> call in the page body, baked in as a literal prop rather than fetched at runtime. Each run: detects brand-new pages this PR added under en//integrations/ only (not repo-wide - reference trees like database//automation/crmscript/reference/ regenerate too often to be a useful signal) and adds them; stamps a missing since with today’s date, and refreshes a pinned entry’s since if this PR touched that entry’s own target page; drops any entry whose target is generated: true; drops non-pinned entries older than 120 days; caps the combined list at 7, with pinned entries getting guaranteed slots that still count against the cap. If any of that changes either the frontmatter or the body call, both are rewritten and pushed back onto the PR branch as a fix commit, same as the other auto-fix checks on this page. Idempotent (a page already in sync produces no further commit), and skipped entirely for PRs from a fork, since the default token can’t push back to a fork’s branch.

Markdownlint

Lints only the .md/.mdx files changed in a PR (or pushed directly to main) using this repo’s own .markdownlint.yaml rules. Results appear in the workflow run’s log in the GitHub Actions tab - a flagged line does not block the merge, but is worth fixing before requesting review. See markdownlint for how to interpret and fix a specific rule violation, and how to run the same linter locally.

Landing page template guard

Checks only the .mdx files changed in a PR (or pushed directly to main) for a mode: "custom" landing page that mixes the two custom-landing Blueprint templates’ card-body markup: a category-landing page (id="category-landing") containing a subcategory-style linklist block, or a subcategory page (id="subcategory") containing a category-landing-style concept-links list. style.css only styles .linklist under #subcategory, so a mismatch like this renders with unstyled, browser-default markup instead of the intended layout, without tripping any other check, since the two templates are only inconsistent with each other, not individually invalid MDX. It never fails the check - a hit shows up as a warning annotation on the relevant line in the PR’s Files Changed tab.

Release-notes API structure guard

Only triggers on a PR touching release-notes/*/api/**. release-notes/{major}/api/ uses a flat structure - generated files sit directly under MAJOR/api/, using their original generated filename, with no per-minor-version subfolder (see Add or update release notes). This check warns when a changed file sits one directory level deeper than that instead - release-notes/{major}/api/{subfolder}/.... Historical dotted-version trees (release-notes/10.1/api/, release-notes/9.2/api/, etc.) use their own, different, frozen structure and are excluded by design - the check’s path match requires a digit-only major version, which those don’t have. It never fails the check - a hit shows up as a warning annotation on the PR’s Files Changed tab, naming the file.

Vale

Prose-style linting (tone, terminology, formatting), configured entirely by this repo’s .vale.ini - no separate setup needed once the add-on is toggled on in the Mintlify dashboard. Set to Warning level to match markdownlint’s advisory-only posture. Results show on the PR’s checks list from Mintlify’s own GitHub App.

Build validation - why there is no separate mint validate step

mint validate is a build/schema validator (docs.json schema, MDX parse errors, OpenAPI spec validation) - it is unrelated to Vale and does not check broken links or accessibility. Those are separate CLI commands (mint broken-links, mint a11y). It is not run as its own GitHub Action here because the PR preview deployment already performs the equivalent build validation on every PR, live, as part of generating the preview - adding a duplicate mint validate Action would just re-check what the preview build already checked. A failed build already surfaces as the red “Mintlify Deployment” check described in Deployment. Mintlify’s Broken Links add-on scans the whole site’s internal links (not external URLs) on every PR and reports results the same way as the Vale check above. It is set to Warning level for the same advisory-first reasoning as the other checks.
A Mintlify community report (October 2025) describes a case where a page serving a 404 still returned an HTTP 200 status, which could make this check under-report a real broken link. Do not treat “no broken links flagged” here as a guarantee - see the scheduled check and fallback tool below for a second opinion.

CRMScript reference drift

Only triggers on a PR touching api-sources/crmscript/**, the generated en/automation/crmscript/reference/**, or either generator script - not on every PR like the checks above. It regenerates the reference fresh from source and fails if the result does not match what is committed, catching both directions of drift with one mechanism: a source .yml edited without regenerating, and a generated .mdx hand-edited directly without touching its source. The failure message names the specific source file to check. See Update the CRMScript reference for the full mechanism and why this one is blocking rather than advisory - api-sources/crmscript/*.yml also feeds the CRMScript interpreter’s own built-in intellisense, so a stale source is a product-facing risk, not just a docs one.

Stale generated pages

Covers three content trees generated by a pipeline outside this repo: en/api/archive-providers/reference/, en/api/mdo-providers/reference/, and en/database/tables/. Each has a matching nav-<tree>.json that gets rewritten whenever new or changed pages are pushed. When a source item on the generator side is deleted or renamed, the push removes its entry from the nav file, but nothing else removes the now-unreferenced page from this repo - it stays as a live, unlinked page indexed by site search. Unlike the CRMScript check above, there is no source file in this repo to regenerate from, so this only checks one direction: any page on disk that is no longer referenced by its tree’s nav file fails the check, naming the file. Pages not marked generated: true in frontmatter are never touched, even if they look stale - fix by either deleting the file (run tools/ci/find-stale-generated-pages.py --delete locally) or adding it back to the relevant nav-*.json if it turns out to be a real nav omission rather than an actual deletion or rename. A per-PR link check only catches breaks introduced by that PR. A separate, Mintlify-hosted automation periodically re-scans the entire site, catching drift from any source - including direct admin-bypass pushes that skip PR review entirely. Active since August 11, 2026, first run August 15, 2026 (nextRunAt confirmed via mint automations list).
  • Type: broken-link-detection
  • Cadence: 0 6 1,15 * * - the 1st and 15th of each month, run at 06:00. Standard cron has no native “every 2 weeks” field; this is the closest non-drifting approximation of a biweekly cadence (actual gaps land at 13-16 days depending on the month).
  • Auto-merge: off. When the automation finds and fixes a broken link, it opens a PR like any other change - it goes through the same manual review as everything else in this repo, it does not merge itself.
  • What it does: for each broken internal link, it checks whether the target page was renamed or moved and updates the link, or - if the target was removed entirely - edits the surrounding copy to remove or replace the reference.
  • Cost: billed in Mintlify credits per run (rough public estimate: ~285 credits/run) - a real operating cost, not a free background job.
Setup record (issue #81):
mint automations list confirms it registered with status: active, no automerge field (off by default), and the cron/type above. tools/triage-broken-links.py (built during #129) plus the mint broken-links CLI remain the trusted manual method for a broken-link sweep, separating genuine breaks from known false positives. Reach for this:
  • Right after a large structural change (a folder move, a nav overhaul) rather than waiting for the next scheduled automation run.
  • As a second opinion if the scheduled automation or the per-PR add-on reports “no breaks found” but something looks off - see the HTTP-200-masking-a-404 caveat above.