Skip to content

Migrate documentation to Fern platform#1578

Closed
ramakrishnap-nv wants to merge 24 commits into
mainfrom
docs-fern-migration
Closed

Migrate documentation to Fern platform#1578
ramakrishnap-nv wants to merge 24 commits into
mainfrom
docs-fern-migration

Conversation

@ramakrishnap-nv

@ramakrishnap-nv ramakrishnap-nv commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator

Migrates cuOpt documentation from Sphinx/RST to the Fern platform. MDX pages in `fern/` are now the source of truth and edited directly.

What's included

  • `fern/` — MDX pages, `docs.yml` navigation, OpenAPI spec, images
  • Version switcher: 26.08 (current) through 25.05 (archived, redirects to `archive.docs.nvidia.com`)
  • Python API, C API, and REST API reference pages
  • `./build.sh docs` — starts local preview at http://localhost:3000
  • CI: `fern check` + broken-links check + PR preview comment + publish on merge

Before going to production

  • Get `FERN_TOKEN` from `#cdd-fern` Slack and add as a GitHub Actions secret
  • Run `fern login --email ` locally to enable the NVIDIA theme
  • Set up custom domain `docs.nvidia.com/cuopt` with the Fern team

ramakrishnap-nv and others added 14 commits July 9, 2026 14:16
- fern/convert_docs.py: Python script that converts all 62 Sphinx/RST
  docs to Fern MDX, handles pandoc 2.9 note/warning divs → Fern
  callout components, resolves literalinclude → embedded code blocks,
  rewrites image paths to flat fern/docs/images/, strips Sphinx-only
  directives (toctree, install-selector, autodoc, breathe).
- fern/docs.yml: full navigation tree auto-generated from RST toctrees,
  with NVIDIA green accent colors and API Reference section.
- fern/fern.config.json: org=nvidia-cuopt, version=5.67.1.
- fern/docs/pages/**: 62 converted MDX pages.
- fern/docs/images/**: all doc images copied flat.
- .github/workflows/fern-docs.yml: CI that re-converts RST→MDX on push
  and runs fern check; publishes on docs-fern-migration branch merges.
- C/C++ Doxygen reference stubbed pending Fern C++ library support.

fern check: 0 errors, 2 warnings (auth redirect + minor color contrast).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- fern/generators.yml: register OpenAPI spec (openapi/cuopt_spec.yaml)
  so fern check and fern generate --docs can serve the REST API reference
- fern/openapi/cuopt_spec.yaml: committed spec generated from FastAPI app
  without GPU (10 endpoints, 23 validated examples)
- fern/docs.yml: replace stub open-api page with a proper "api: REST API"
  nav entry that Fern renders as an interactive API reference
- fern/extract_python_api.py: AST-based Python docstring extractor (no
  imports, no GPU) generating MDX for routing, LP/QP, and MIP APIs;
  mirrors the classes/functions listed in the Sphinx autoclass:: directives
- fern/convert_docs.py: call OpenAPI generation + Python extraction from
  the main convert script so one command rebuilds everything
- .github/workflows/fern-docs.yml: add Python deps install step for
  OpenAPI spec generation; watch python/ source paths for changes

fern check: 0 errors, 8 warnings (7 are pre-existing OpenAPI example
mismatches in the FastAPI source; 1 is WCAG contrast auto-adjusted by Fern).

C/C++ Doxygen reference still stubbed pending Fern C++ library support.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The custom .. install-selector:: Sphinx directive is now fully supported
in Fern by reusing the existing vanilla JS + CSS widget unchanged:

- fern/docs/scripts/install-selector.{js,css}: copied from Sphinx _static/
- fern/docs/scripts/cuopt-install-version.js: generated at build time by
  convert_docs.py from cuopt_server version (replaces the Sphinx conf.py
  build-time injection of window.CUOPT_INSTALL_VERSION)
- fern/docs.yml: css/js entries load the widget and version script on
  every page so the selector is available wherever the div is placed
- fern/convert_docs.py: preprocessor now emits
  <div id="cuopt-install-selector" data-default-iface="..."> via RST
  raw:: html instead of a plain-text note stub; version script generation
  added alongside the OpenAPI spec generation

Result: install.mdx and all 4 quick-start pages (python/c/server/cli)
render the full interactive install selector with correct version numbers
and interface pre-selection, identical to the Sphinx site.

fern check: 0 errors, 8 warnings (unchanged).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ersion

- Fix <Note> inside list items: un-indent opening tag to break out of
  list item context (MDX can't parse JSX inside list items when closing
  tag is at column 0)
- Convert .. dropdown:: RST directives to <Accordion> MDX components
  in preprocessor (was becoming <div class="dropdown"> which broke
  fenced code blocks inside)
- Add postprocessor fallback converting <div class="dropdown"> to
  <Accordion> for any that slip through pandoc
- Add libraries: section in docs.yml and DOCS_YML_HEADER for Fern
  C++ (cuopt-c-api) and Python (cuopt-python-api) library docs
- Add Doxyfile.fern to cpp/ (Fern's input.path for C++ parsing)
- Include generated Fern Python library docs (static/python-docs)
  as "Python Distance Engine" folder in API Reference nav section

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
MDX's JSX parser is stricter than CommonMark and fails on patterns that
are valid in plain Markdown. All 62+ pages now pass the MDX parser.

Fixes applied in convert_docs.py post-processor and extract_python_api.py:
- Angle-bracket autolinks: <https://...> and <email@...> → proper links
- Comparison operators: `<=` in text → `&lt;=` (MDX parses `<` as JSX)
- Curly-brace math notation: {<=, =, >=} → \{...\}
- Placeholder tags in code blocks: <CUOPT_IMAGE>, <ip> → HTML entities
- Shell redirects in code blocks: `</dev/null` → `< /dev/null`

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Fern's server-side acorn processor rejects { } even inside fenced code
blocks, causing 500 errors on convex-features.mdx and milp-features.mdx.

- RST pre-processor (step 13): convert {<=, =, >=} math notation to
  (<=, =, >=) parenthesis form before pandoc — eliminates all { } from
  generated MDX
- Post-processor: simplify _escape_lt_outside_code now that { } are
  handled at the RST level
- Fix angle-bracket autolinks and email addresses → proper MD links
- All 62 MDX pages pass both MDX parse and Fern's acorn validation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…enAPI fixes

- Python API: prefix classes with 'class', methods/functions with 'def';
  use <hr /> separators between entries for visual scanning
- C API: extract_c_api.py now generates real content from headers (211 symbols);
  typedef entries labeled with 'typedef'; functions show bare prototype (no
  'function' prefix — matches cppreference/Doxygen convention); <hr /> separators
- Nav: index pages inside sections renamed to 'Overview' to eliminate duplicate
  section-name / page-name entries in the left nav
- REST API Reference moved under Server → Server API → Server API Overview
- OpenAPI spec post-processing: relax IdModel additionalProperties, fix
  health-endpoint examples (add error_result), fix incumbents examples
  (null cost/bound); prevents fern docs dev from exiting with code 1
- NVIDIA cuOpt logo SVGs added (dark/light variants)
- MutationObserver-based install selector widget for Next.js SPA timing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Converts the Sphinx/RST documentation to the Fern docs platform on the
docs-fern-migration branch.  Key changes across this session:

Conversion pipeline (fern/convert_docs.py, extract_*.py):
- Fix brace corruption: remove step 13 ({}→() broad replacement) and add
  prose-only { escaping that skips fenced code blocks and inline code spans
- Fix duplicate page headings: strip pandoc H1 BEFORE prepending frontmatter
  so the ^# regex anchors at the start of pandoc output, not after ---
- Fix inspect.cleandoc vs textwrap.dedent for Python docstring parsing so
  Parameters/Returns/Raises sections render correctly
- Fix .. dropdown:: dedent (textwrap.dedent instead of hardcoded 3-space strip)
  so list items inside Accordion blocks are flat, not nested
- Remove explicit H1 from extract_python_api.py and extract_c_api.py output
  (frontmatter title: is the heading; duplicate H1 caused double rendering)

Nav / docs.yml:
- Add _inject_nav_after, _rename_page, _remove_page helpers so curated nav
  fixes survive regeneration: REST API Reference after Server CLI, Settings
  pages under Python API, duplicate section/page names resolved, Swagger stub
  removed
- Split navigation into docs-v26-08.yml (required by Fern when versions is set)
- Add version switcher with all archived versions (26.06–25.05) pointing to
  archive.docs.nvidia.com via JS redirect pages

Install selector widget (fern/docs/scripts/install-selector.js):
- Full rewrite with lazy resolveVersion() and polling loop (150 ms, ~10 s)
  to survive Next.js async script injection race; pushState/replaceState hooks
  set up unconditionally

Python source (python/cuopt/cuopt/linear_programming/io/parser.py):
- Add NumPy-style docstring to toDict so it appears in the Python API reference

CI (.github/workflows/fern-docs.yml):
- Add cpp/**/*.h and cpp/**/*.hpp to path triggers (C API extractor reads headers)

build.sh:
- Replace old Sphinx/Doxygen docs target with Fern pipeline:
  checks for pandoc/node/jq, auto-installs pinned fern-api, runs
  convert_docs.py + fern check, prints fern docs dev command for preview

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add fern/requirements-docs.txt (fastapi, pydantic, pyyaml) as the single
  source of truth for Python docs dependencies; both build.sh and CI now
  install from it instead of inlining package names
- Update dependencies.yaml docs group: replace old Sphinx/Doxygen packages
  with Fern toolchain deps (jq, nodejs, pandoc, pyyaml, fastapi, pydantic)
  so conda environments include what ./build.sh docs actually needs
- build.sh: add npm presence check alongside node (npm is separate on some
  distros), with install hint pointing to nodejs.org and conda

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ./build.sh docs now runs convert_docs.py + fern check then launches
  fern docs dev (localhost:3000 preview) instead of just printing the command
- Add --publish-docs flag to publish to Fern cloud (nvidia-cuopt.docs.buildwithfern.com)
  via fern generate --docs; requires FERN_TOKEN env var, checked before running
- Add --publish-docs to VALIDARGS and help text

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- On every run: upload generated fern/docs.yml, docs-v*.yml, docs/pages/,
  and openapi/ as a GitHub Actions artifact (14-day retention) so reviewers
  can download and inspect exactly what will be published
- On pull_request: run fern generate --docs --preview to publish a temporary
  Fern preview URL that doesn't affect the live site; requires FERN_TOKEN
  secret, skipped silently if absent

Note: Fern has no native static HTML export — it is a Next.js SPA served via
Fern cloud. The artifact above contains the MDX source; the preview URL gives
a fully rendered browser view for sharing during PR review.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New non-blocking link-check job runs after convert-and-check, concurrently
  with publish (continue-on-error: true so broken external links don't block
  the live site update — check the job summary for failures)
- Skips fern/docs/pages/versions/ (JS redirect stubs, no real links)
- fern/.lycheeignore excludes hosts that reliably cause false positives in CI:
  localhost, YouTube (429), LinkedIn (bot block), NGC catalog (auth required),
  Azure Maps sample (401), raw.githubusercontent.com (429 bursts)
- --accept 429 treats rate-limit responses as passing (not a dead link)
- Uploads lychee-report.md as a 14-day artifact on every run

Note: fern check validates config schema only; it does not check URLs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Covers prerequisites, ./build.sh docs local preview, manual publish with
FERN_TOKEN, and a table of what each CI trigger does — addresses the gap
Andrew pointed out ("samples in the readme").

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…-links

- Add `global-theme: nvidia` to docs.yml (mandatory for NVIDIA Fern branding)
- Add GitHub navbar link to docs.yml header
- Fix accentPrimary light color to match NVIDIA green (#76B900)
- CI: split PR preview into two stages so FERN_TOKEN is never exposed to
  fork PRs; stage 2 runs via workflow_run in base-branch context
- CI: add `fern docs broken-links` step for internal link checking
- CI: stage 1 saves PR metadata artifact so stage 2 can post preview comment
- README: document fern login requirement, how to get FERN_TOKEN, custom
  domain requirement, and two-stage PR preview security model

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@copy-pr-bot

copy-pr-bot Bot commented Jul 15, 2026

Copy link
Copy Markdown

Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually.

Contributors can view more details about this message here.

ramakrishnap-nv and others added 6 commits July 15, 2026 14:45
MDX pages are now the source of truth. Removes:
- fern/convert_docs.py, extract_python_api.py, extract_c_api.py
- fern/requirements-docs.txt (pandoc, pyyaml, fastapi, pydantic)
- All conversion steps from build.sh and CI
- RST/C++/Python path triggers from CI (no longer affect docs)
- lychee link-check job (not needed for hand-edited MDX)
- pandoc/pyyaml/fastapi/pydantic from dependencies.yaml docs group

CI now: fern check + fern docs broken-links + PR preview + publish.
build.sh docs now: install fern CLI → fern check → fern docs dev.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
OpenAPI spec, Python API reference, and C API reference are derived from
code and regenerated by fern/generate_api_docs.py on every docs build.
RST→MDX conversion is still gone; hand-edited MDX pages are not touched.

- Restore fern/extract_python_api.py and fern/extract_c_api.py
- Add fern/generate_api_docs.py (orchestrates the three dynamic outputs)
- Restore fern/requirements-docs.txt (fastapi, pydantic, pyyaml)
- build.sh docs: run generate_api_docs.py before fern check
- CI: install Python deps, run generate_api_docs.py, then fern check
- Re-add C++/Python source paths to CI triggers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ci/build_docs.sh: replace Sphinx build with Fern pipeline
  (conda env already provides jq, nodejs, pyyaml, fastapi, pydantic via
  rapids-dependency-file-generator; Fern CLI installed via npm at pinned version)
  Generates API docs, runs fern check, then publishes (preview on PR,
  production on branch/nightly)
- build.sh docs: skip pip install when packages already present (conda);
  fall back to pip only when importing fails
- build.yaml / pr.yaml: remove Sphinx html artifact upload; switch to
  cpu node type (no GPU needed for docs)
- Remove .github/workflows/fern-docs.yml (superseded by existing docs-build jobs)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds explicit trigger to AGENTS.md so CI/workflow changes clearly map to
skills/cuopt-developer/ — surfacing the "prefer extending existing scripts"
rule before new workflow files or pip installs are created.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Python API: keep AST walking (no imports needed) but pipe docstrings
through numpydoc.docscrape.NumpyDocString, giving properly structured
Parameters / Returns / Raises / Examples sections in the generated MDX.

C API: replace fragile regex header parser with Doxygen XML pipeline.
Doxyfile targets the two public headers; XML is parsed with ElementTree
and rendered to MDX. Picks up 211 symbols vs ~80 before, handles @param,
@return, @brief, and enum values correctly.

Add numpydoc to requirements-docs.txt and dependencies.yaml docs group.
Add doxygen to dependencies.yaml docs group.
Gitignore cpp/build_split/ and fern/.doxygen-xml/ build directories.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ramakrishnap-nv and others added 4 commits July 15, 2026 16:38
…tom parsers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Python API: replace hardcoded file paths with PAGE_SOURCES config — each
entry lists directories to scan non-recursively. New .py files added to a
configured directory appear in the docs automatically without editing the
script.

C API: replace RST parser with fern/c_api_config.yaml for section
organization. Doxygen XML is still the symbol source; the YAML controls
section groupings and prose. Symbols not in the config auto-appear in
an "Uncategorized" section on the designated catchall page so new header
additions are never silently dropped. Added previously uncategorized
symbols (hyper diving/heuristic params, scaling constants, presolve
constants, deprecated quad create functions).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copies example source files from docs/cuopt/source/ into
fern/docs/pages/*/examples/ so they live alongside the MDX pages
that reference them. The old docs/ tree is left intact for now.

Adds fern/embed_examples.py which embeds example files as fenced
code blocks into the *-examples.mdx pages using idempotent
<!-- embed: examples/file --> / <!-- /embed --> markers. First run
upgrades bare link stubs; subsequent runs refresh code content
within the markers without disturbing surrounding prose.

Rewrites the C API example pages (convex-examples.mdx,
mip-examples.mdx) to use clean standalone link patterns and removes
the repetitive Sphinx-era "It is necessary to have the path..." boilerplate.

embed_examples.py is called from generate_api_docs.py on every build.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove:
- fern/.lycheeignore (lychee CI job was deleted)
- cpp/Doxyfile.fern and fern/Doxyfile.fern (remnants of abandoned
  fern docs md generate --local approach, superseded by fern/Doxyfile)
- fern/static/python-docs/ (auto-generated by fern docs md generate;
  replaced by extract_python_api.py)
- libraries: block from fern/docs.yml (referenced the deleted files)

Add distance_engine/ to the routing PAGE_SOURCES in extract_python_api.py
so WaypointMatrix is covered in the generated routing-api.mdx.
Remove the folder: ./static/python-docs nav entry from docs-v26-08.yml.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@ramakrishnap-nv

Copy link
Copy Markdown
Collaborator Author

@CodeRabbit review

@ramakrishnap-nv ramakrishnap-nv self-assigned this Jul 16, 2026
@ramakrishnap-nv ramakrishnap-nv added this to the 26.08 milestone Jul 16, 2026
@ramakrishnap-nv ramakrishnap-nv added the non-breaking Introduces a non-breaking change label Jul 16, 2026
@ramakrishnap-nv ramakrishnap-nv added the improvement Improves an existing functionality label Jul 16, 2026
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The documentation system is migrated to Fern, with CI publishing, generated C/Python/OpenAPI references, extensive API and deployment content, runnable examples, version navigation, installation commands, and local preview support.

Changes

Documentation platform and publishing

Layer / File(s) Summary
Fern build and publishing pipeline
.github/workflows/*, build.sh, ci/build_docs.sh, dependencies.yaml, README.md
Documentation builds now generate and validate Fern content, publish previews or production docs, and use CPU runners with Fern-specific tooling.
Generated API references
fern/Doxyfile, fern/extract_*.py, fern/generate_api_docs.py, fern/openapi/*
Doxygen, AST, and FastAPI-based generators produce C API, Python API, and OpenAPI documentation artifacts.
Site configuration and navigation
fern/docs.yml, fern/docs-v*.yml, fern/generators.yml, fern/fern.config.json
Fern site metadata, version mappings, navigation sections, and OpenAPI generator configuration are added.
Documentation content
fern/docs/pages/*
New guides cover installation, solver features and settings, C/Python APIs, routing, gRPC, server deployment, CLI usage, FAQs, releases, resources, and archived versions.
Examples and installation selector
fern/docs/scripts/*, fern/docs/pages/*/examples/*
Runnable C and Python examples, routing examples, Makefiles, embedded-example generation, and an interactive install command selector are added.

Estimated code review effort: 5 (Critical) | ~120 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.89% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: migrating documentation to the Fern platform.
Description check ✅ Passed The description matches the changeset by describing the Fern migration, included docs, CI, versioning, and preview/publish workflow.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs-fern-migration

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Due to the large number of review comments, Critical severity comments were prioritized as inline comments.

🟠 Major comments (35)
fern/docs/scripts/install-selector.js-372-382 (1)

372-382: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

No user-facing fallback if the install widget never resolves.

poll() gives up silently after ~10s if window.CUOPT_INSTALL_VERSION never becomes available, leaving #cuopt-install-selector empty. install-selector.css already defines a .cuopt-install-error state (border/background) that is never applied anywhere in this file.

🔧 Proposed fix: render an error state when polling gives up
   function poll(gen, remaining) {
     if (gen !== _pollGen) return;
     if (!isRendered()) render();
     if (isRendered() && remaining > 20) {
       remaining = 20;
     }
     if (remaining > 0) {
       _pollTimer = setTimeout(function () { poll(gen, remaining - 1); }, 150);
+    } else if (!isRendered()) {
+      var root = document.getElementById("cuopt-install-selector");
+      if (root) {
+        root.innerHTML =
+          '<div class="cuopt-install-selector-wrap cuopt-install-error">' +
+          "<code>Unable to load the install selector. Please refresh the page.</code></div>";
+      }
     }
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/scripts/install-selector.js` around lines 372 - 382, Update the
poll function so that when remaining reaches zero and the install widget still
has not rendered or resolved, it applies the existing cuopt-install-error state
to `#cuopt-install-selector`. Preserve the current polling and rendering behavior
for successful resolution, and only show the fallback after polling is
exhausted.
fern/docs/scripts/install-selector.js-200-239 (1)

200-239: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Silent CUDA-version substitution for the 12.x + UBI10 combination.

containerLib never defines a cu12-ubi10 variant, so selecting CUDA=12.x with the UBI10 variant silently falls back to the cu13-ubi10 command (Line 205's fallbackKey) while the UI still shows "12.x" checked — the user gets a CUDA 13 command with no indication of the substitution.

🐛 Proposed fix: disable CUDA 12.x when UBI10 variant is selected
   function updateVisibility(COMMANDS) {
     var method = getSelectedValue("cuopt-method");
     var iface = getSelectedValue("cuopt-iface");
     var allowed = SUPPORTED_METHODS[iface] || [];
+    var variant = getSelectedValue("cuopt-variant");
+    var cu12Radio = document.querySelector('input[name="cuopt-cuda"][value="cu12"]');
+    if (cu12Radio) {
+      var forceUbi10 = method === "container" && variant === "ubi10";
+      cu12Radio.disabled = forceUbi10;
+      if (forceUbi10 && cu12Radio.checked) {
+        var cu13Radio = document.querySelector('input[name="cuopt-cuda"][value="cu13"]');
+        if (cu13Radio) cu13Radio.checked = true;
+      }
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/scripts/install-selector.js` around lines 200 - 239, Update the
container selection logic around `cudaKey`, `fallbackKey`, and the
`cuopt-variant` value so CUDA 12.x cannot remain selected when `variant ===
"ubi10"`; disable or otherwise remove the CUDA 12.x option in the UI when UBI10
is selected, and ensure command generation does not silently substitute
`cu13-ubi10` while displaying CUDA 12.x.
build.sh-462-470 (1)

462-470: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Keep local documentation prerequisites consistent across the script and README.

The Fern generator requires a complete Python/Doxygen toolchain, but the script can skip or partially bootstrap it while the README does not tell contributors to install it.

  • build.sh#L462-L470: Require Python and the complete generator toolchain, including Doxygen and numpydoc, before running fern check; use the selected interpreter’s pip.
  • README.md#L33-L40: Document those prerequisites or direct contributors to the reproducible conda docs environment.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@build.sh` around lines 462 - 470, Update build.sh lines 462-470 to require
Python and validate the complete Fern generator toolchain, including Doxygen and
numpydoc, before running fern check or generate_api_docs; bootstrap dependencies
through the selected interpreter’s pip and do not silently proceed with missing
prerequisites. Update README.md lines 33-40 to document these prerequisites or
direct contributors to the reproducible conda documentation environment.
fern/generate_api_docs.py-88-90 (1)

88-90: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Fail the build when OpenAPI generation fails.

The broad catch only prints a warning, so the build continues with stale cuopt_spec.yaml and installation-version data. This can publish artifacts from different cuOpt versions. Propagate the failure after adding actionable context.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/generate_api_docs.py` around lines 88 - 90, Update the exception handler
in the OpenAPI generation flow to preserve the actionable context message while
propagating the original failure instead of continuing after the error. Ensure
generation failures cause the build to stop, preventing stale cuopt_spec.yaml
and installation-version data from being used.
fern/extract_c_api.py-191-195 (1)

191-195: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Fail generation when a target Doxygen XML file cannot be parsed.

Skipping the file creates a partial symbol table; configured symbols then become “documentation not found” placeholders and the command still exits successfully. Raise with the XML filename so incomplete C API references cannot be published.

Proposed fix
         try:
             tree = ET.parse(xml_file)
         except ET.ParseError as e:
-            print(f"  [WARN] XML parse error in {xml_file.name}: {e}")
-            continue
+            raise RuntimeError(
+                f"Failed to parse Doxygen XML {xml_file.name}: {e}"
+            ) from e

Also applies to: 373-376

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/extract_c_api.py` around lines 191 - 195, Update the ET.parse error
handling in the XML extraction flow to raise on ET.ParseError instead of
printing a warning and continuing, including the affected XML filename in the
raised error. Apply the same behavior to the additional parse-error handling
block noted in the comment so generation fails rather than publishing an
incomplete symbol table.
fern/generate_api_docs.py-100-113 (1)

100-113: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Complete the public contracts for the new documentation-generator entry points.

  • fern/generate_api_docs.py#L100-L113: add -> None; document generated artifacts and propagated failures.
  • fern/embed_examples.py#L122-L129: add -> None; document updated files and I/O failures.
  • fern/extract_c_api.py#L168-L180: precisely type the symbol map and document Doxygen/XML errors.
  • fern/extract_c_api.py#L504-L525: add -> None; document generated pages and YAML/Doxygen/I/O errors.
  • fern/extract_python_api.py#L421-L442: add -> None; document all parameters, file writes, and failures.
  • fern/extract_python_api.py#L477-L490: add -> None; document generated pages and failures.

As per coding guidelines, “Require type hints on new public Python functions and classes” and “Document new public Python APIs with meaningful docstring content covering parameters, returns, and raises.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/generate_api_docs.py` around lines 100 - 113, Complete the public
contracts for the six documented entry points: add -> None and meaningful
docstrings to main in fern/generate_api_docs.py, embed_all in
fern/embed_examples.py, the symbol-map function and page-generation function in
fern/extract_c_api.py, and the two public functions in
fern/extract_python_api.py. Document parameters where applicable, generated or
updated artifacts, and propagated YAML, Doxygen/XML, I/O, file-write, and
subprocess failures; precisely type the extract_c_api symbol map. Affected
sites: fern/generate_api_docs.py lines 100-113, fern/embed_examples.py lines
122-129, fern/extract_c_api.py lines 168-180 and 504-525, and
fern/extract_python_api.py lines 421-442 and 477-490.

Source: Coding guidelines

fern/embed_examples.py-90-110 (1)

90-110: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Reject unclosed embed blocks instead of truncating the page.

If <!-- /embed --> is absent, Line 97 reaches EOF and Line 99 advances beyond it. The script then writes only the prefix, deleting the rest of the MDX page. Raise before consuming or writing the file.

Proposed fix
             i += 1
             while i < len(lines) and lines[i].rstrip("\n") != _CLOSE:
                 i += 1
+            if i >= len(lines):
+                raise ValueError(
+                    f"Unclosed embed marker for examples/{rel} in {mdx_path}"
+                )
             i += 1  # skip the closing marker line
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/embed_examples.py` around lines 90 - 110, Update the existing
embed-marker handling around `_OPEN_RE.match` to detect when `_CLOSE` is not
found before end of file. Raise an error before consuming the remainder or
writing output, and only advance past the closing marker and replace the block
when the closing marker exists.
fern/openapi/cuopt_spec.yaml-171-188 (1)

171-188: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Document the binary solver-log response formats /cuopt/log/{id} accepts application/vnd.msgpack and application/zlib, but the 200 response in fern/openapi/cuopt_spec.yaml only advertises JSON. Add the missing media types to the response content and regenerate the spec.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/openapi/cuopt_spec.yaml` around lines 171 - 188, Update the 200 response
content for the /cuopt/log/{id} operation to advertise application/vnd.msgpack
and application/zlib alongside application/json, reusing the LogResponseModel
schema for the binary formats, then regenerate the OpenAPI spec.
fern/extract_python_api.py-285-390 (1)

285-390: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve parsed numpydoc sections. The numpydoc path drops sections it doesn’t render today: Attributes and other supported sections in public docstrings (for example in python/cuopt/cuopt/linear_programming/problem.py) disappear once has_content is true instead of falling back or being emitted.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/extract_python_api.py` around lines 285 - 390, Update the numpydoc
rendering flow around the parsed section handling in the doc conversion function
to preserve Attributes and every other supported section, rather than silently
dropping them when has_content is true. Include those sections in the content
detection and emit them in the generated MDX using the existing
section-formatting conventions; retain fallback to _doc_to_mdx only when no
supported parsed content exists.
fern/openapi/cuopt_spec.yaml-1175-1200 (1)

1175-1200: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Reconcile the LP example with SolutionData. The example puts reduced_cost on solution, but SolutionData doesn’t define it and has additionalProperties: false; add it to the schema (or move it under lp_statistics) or remove it from the example.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/openapi/cuopt_spec.yaml` around lines 1175 - 1200, Reconcile the LP
response example with the SolutionData schema: either define reduced_cost in
SolutionData with the correct type, move it under lp_statistics if that is the
intended model, or remove it from the example. Ensure the final example contains
no properties rejected by SolutionData’s additionalProperties: false.
fern/docs/pages/cuopt-cli/quick-start.mdx-11-15 (1)

11-15: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Include the help command.

This says the next step displays CLI options, but no command is shown. Add a fenced cuopt_cli --help invocation before the explanatory sentence.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-cli/quick-start.mdx` around lines 11 - 15, Add a fenced
command block containing the cuopt_cli --help invocation immediately before the
sentence explaining that the complete list of command-line arguments will be
displayed, preserving the surrounding quick-start guidance.
fern/docs/pages/cuopt-c/mip/mip-c-api.mdx-35-61 (1)

35-61: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Document the complete callback typedef signatures.

The reference lists only typedef names and parameter descriptions, not the callable C declarations. Add both full typedef void (*...)(...) signatures so users can implement compatible callbacks.

Based on supplied upstream contract in cpp/include/cuopt/mathematical_optimization/cuopt_c.h:776-845, both callback typedefs have required pointer qualifiers and a void return type.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-c/mip/mip-c-api.mdx` around lines 35 - 61, Add the
complete C callback declarations for cuOptMIPGetSolutionCallback and
cuOptMIPSetSolutionCallback, using typedef void (*...)(...) and preserving the
upstream parameter order, pointer qualifiers, and void return type. Place each
signature with its corresponding typedef documentation before the parameter
descriptions, without changing the existing parameter semantics.
fern/docs/pages/cuopt-server/server-api/server-cli.mdx-1-5 (1)

1-5: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Add the actual Server CLI reference. This page is just an intro today; add the command syntax, option list, env-var mapping, or a link to an authoritative generated reference so operators can find the supported flags.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-server/server-api/server-cli.mdx` around lines 1 - 5,
Add the actual cuOpt Server CLI reference to the “cuOpt Server CLI” page:
document the command syntax and supported options with their corresponding
environment-variable mappings, or link to an authoritative generated reference.
Replace the introductory-only content while preserving the page’s existing title
and scope.
fern/docs/pages/cuopt-grpc/advanced.mdx-46-104 (1)

46-104: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Add the missing walkthrough commands

The TLS, private-CA, Docker, and client setup sections only contain prose and headings. Add the fenced command examples for each flow so the page can be followed end to end.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-grpc/advanced.mdx` around lines 46 - 104, Add fenced,
executable command examples to the walkthrough sections in advanced.mdx: create
the private CA, issue client and server certificates, start the TLS server,
configure an authorized client, run the Docker gRPC server with a certificate
volume, bypass the entrypoint, and set the client environment variables. Ensure
examples use the documented flags and variables and form an end-to-end flow.
fern/docs/pages/cuopt-grpc/quick-start.mdx-23-73 (1)

23-73: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Restore the missing executable commands.

The page describes verification, bare-metal/Docker startup, remote environment exports, and Python/CLI execution, but none of those sections includes a command. This leaves the quick start non-actionable.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-grpc/quick-start.mdx` around lines 23 - 73, Restore the
executable shell commands throughout the cuOpt gRPC quick-start: add the binary
verification command, bare-metal and Docker server launch commands, client
remote environment exports, and Python/cuopt_cli run commands for both
repository-checkout and downloaded-file workflows. Ensure the commands match the
surrounding instructions, use the documented ports and image placeholder, and
include the local-run unset commands.
fern/docs/pages/cuopt-python/routing/examples/smoke_test_example.sh-37-49 (1)

37-49: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Register the task locations before solving.

task_locations is never passed to dm, so the documented tasks at locations 1, 2, and 3 are not modeled. Call dm.set_order_locations(task_locations) after configuring the cost matrix.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-python/routing/examples/smoke_test_example.sh` around
lines 37 - 49, Update the DataModel setup in the routing example to register
task_locations before solving by calling set_order_locations on dm after
configuring the cost and transit-time matrices. Preserve the existing
task_locations values and vehicle configuration.
fern/docs/pages/cuopt-python/convex/examples/mps_example.py-22-33 (1)

22-33: 📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Document and annotate the new public example functions.

All new non-underscore module-level functions need type hints and meaningful docstrings covering parameters, returns, and raised errors.

  • fern/docs/pages/cuopt-python/convex/examples/mps_example.py#L22-L33: annotate and document main.
  • fern/docs/pages/cuopt-python/convex/examples/solution_example.py#L31-L63: annotate main and expand its docstring with return/error behavior.
  • fern/docs/pages/cuopt-python/routing/examples/intra_factory_example.py#L52-L60: annotate and document build_cost_matrix.
  • fern/docs/pages/cuopt-python/routing/examples/intra_factory_example.py#L63-L91: annotate and document build_orders.
  • fern/docs/pages/cuopt-python/routing/examples/intra_factory_example.py#L94-L98: annotate and document build_fleet.
  • fern/docs/pages/cuopt-python/routing/examples/intra_factory_example.py#L101-L151: annotate and document build_data_model.
  • fern/docs/pages/cuopt-python/routing/examples/intra_factory_example.py#L154-L180: annotate and document print_schedule.
  • fern/docs/pages/cuopt-python/routing/examples/intra_factory_example.py#L183-L205: annotate and document main.
  • fern/docs/pages/cuopt-python/routing/examples/tsp_batch_example.py#L13-L19: annotate and document create_tsp_cost_matrix.
  • fern/docs/pages/cuopt-python/routing/examples/tsp_batch_example.py#L22-L51: annotate and document main.

As per coding guidelines, “Require type hints on new public Python functions and classes” and “Document new public Python APIs with meaningful docstring content covering parameters, returns, and raises.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-python/convex/examples/mps_example.py` around lines 22
- 33, All listed public example functions lack required API annotations and
documentation. In
fern/docs/pages/cuopt-python/convex/examples/mps_example.py:22-33, annotate and
document main; in
fern/docs/pages/cuopt-python/convex/examples/solution_example.py:31-63, annotate
main and document its return and raised-error behavior; in
fern/docs/pages/cuopt-python/routing/examples/intra_factory_example.py:52-60,
63-91, 94-98, 101-151, 154-180, and 183-205, annotate and add meaningful
docstrings to build_cost_matrix, build_orders, build_fleet, build_data_model,
print_schedule, and main; and in
fern/docs/pages/cuopt-python/routing/examples/tsp_batch_example.py:13-19 and
22-51, annotate and document create_tsp_cost_matrix and main. Ensure every
signature has appropriate parameter and return type hints, and each docstring
covers parameters, returns, and raised errors where applicable.

Source: Coding guidelines

fern/docs/pages/cuopt-python/mip/mip-api.mdx-5-5 (1)

5-5: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Populate the MIP Python API page from existing symbols fern/extract_python_api.py only scans python/cuopt/cuopt/linear_programming/mip, which doesn’t exist here, so this page falls back to the empty note. Point the MIP page at the actual Python modules that expose MIP APIs, or remove the nav entry if a separate MIP reference isn’t intended.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-python/mip/mip-api.mdx` at line 5, Update the MIP API
page configuration to scan the existing Python modules that expose MIP APIs
instead of the nonexistent linear_programming/mip directory, so
fern/extract_python_api.py discovers and renders their public symbols. If no
standalone MIP reference is intended, remove the page’s navigation entry
instead.
fern/docs/pages/cuopt-python/convex/examples/production_planning_example.py-39-40 (1)

39-40: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Type and document the public entry point.

Add -> None and document the return contract (and expected raises, if applicable), or make this a private script helper.

As per coding guidelines, “Require type hints on new public Python functions and classes” and “Document new public Python APIs with meaningful docstring content covering parameters, returns, and raises.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-python/convex/examples/production_planning_example.py`
around lines 39 - 40, Update the public main entry point to include a -> None
return annotation and expand its docstring to document the return contract and
any applicable exceptions; retain it as public unless converting it to a private
script helper is more appropriate.

Sources: Coding guidelines, Path instructions

fern/docs/pages/cuopt-server/client-api/sh-cli-build.mdx-13-25 (1)

13-25: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Restore the missing runnable client examples.

This page promises a server command plus direct JSON and file-based requests, but provides no commands or payloads. It cannot currently guide a user through building a thin client.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-server/client-api/sh-cli-build.mdx` around lines 13 -
25, Complete the “Invoking cuOpt Service” section with runnable server-start and
client-request examples: add the command to run the server, a direct JSON
request including a representative payload, and a file-based JSON request
showing the required file and invocation. Ensure the examples target the
/cuopt/request endpoint and reflect the documented shared data and result
directories.
fern/docs/pages/cuopt-server/nim-operator/configuration.mdx-46-46 (1)

46-46: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not conflate replica count with external exposure.

A LoadBalancer can expose a single-replica service externally; scaling capability is unrelated. Rephrase this as a deployment-option decision rather than calling it unnecessary.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-server/nim-operator/configuration.mdx` at line 46,
Revise the LoadBalancer note in the cuOpt service configuration documentation to
separate replica count from external exposure: state that the service currently
supports one pod instance while presenting LoadBalancer as an optional
deployment choice, not as unnecessary because scaling is unavailable.
fern/docs/pages/cuopt-server/nim-operator/index.mdx-9-14 (1)

9-14: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not advertise scaling for this deployment.

This contradicts configuration.mdx Line 56, which says cuOpt supports only a single pod per service. Remove “scaling” or explicitly state that this workload is single-replica.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-server/nim-operator/index.mdx` around lines 9 - 14,
Update the NIM Operator deployment overview to remove the claim that the
operator handles scaling, or explicitly describe the cuOpt workload as
single-replica. Keep the remaining lifecycle-management capabilities unchanged
and align the wording with the single-pod constraint documented in
configuration.mdx.
fern/docs/pages/cuopt-server/nim-operator/configuration.mdx-32-34 (1)

32-34: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reconcile the persistent-storage requirement.

One page says storage is optional for HTTP requests, while the other says it is required. State that storage is optional and document the specific filesystem dataset workflow that needs it.

  • fern/docs/pages/cuopt-server/nim-operator/configuration.mdx#L32-L34: retain the conditional requirement and identify the storage-backed workflow.
  • fern/docs/pages/cuopt-server/nim-operator/prerequisites.mdx#L39-L42: replace the unconditional requirement with the same conditional guidance.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-server/nim-operator/configuration.mdx` around lines 32
- 34, The persistent-storage documentation is inconsistent across the Nim
operator pages. In fern/docs/pages/cuopt-server/nim-operator/configuration.mdx
lines 32-34, retain the optional requirement and explicitly identify the
filesystem-based dataset workflow that needs storage; in
fern/docs/pages/cuopt-server/nim-operator/prerequisites.mdx lines 39-42, replace
the unconditional storage requirement with the same conditional guidance.
fern/docs/pages/faq.mdx-222-225 (1)

222-225: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Reconcile the routing-capacity guidance.

This claims standard CVRPTW instances can “easily” reach 15K locations on A100/H100, while Line 337 calls 10,000 the maximum on H100. Publish one validated, versioned benchmark envelope before users size deployments from this page.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/faq.mdx` around lines 222 - 225, Reconcile the conflicting
cuOpt capacity claims in the FAQ by replacing the unqualified “easily”
15K-location statement near the cuOpt resource estimates accordion and the
10,000-location guidance near the existing H100 limit with one validated,
versioned benchmark envelope. Ensure the published guidance consistently states
the supported location limit, GPU assumptions, and relevant constraints rather
than presenting contradictory maxima.
fern/docs/pages/license.mdx-1-3 (1)

1-3: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Restore the license content.

This published page has only a title, so users cannot determine cuOpt’s license terms. Add the license text or a canonical-license link.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/license.mdx` around lines 1 - 3, Restore the license content
in the cuOpt License page by adding the complete license text or a canonical
link to the license. Keep the existing title and ensure the published page
provides accessible license terms.
fern/docs/pages/cuopt-python/convex/examples/rotated_socp_example.py-28-56 (1)

28-56: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Document and annotate the new public entry points.

  • fern/docs/pages/cuopt-python/convex/examples/rotated_socp_example.py#L28-L56: change main to def main() -> None and add a meaningful docstring documenting its return behavior.
  • fern/docs/pages/cuopt-python/convex/examples/simple_lp_example.py#L32-L62: change main to def main() -> None and extend its docstring with return behavior.

As per coding guidelines, “Require type hints on new public Python functions and classes” and “Document new public Python APIs with meaningful docstring content covering parameters, returns, and raises.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-python/convex/examples/rotated_socp_example.py` around
lines 28 - 56, Update main in
fern/docs/pages/cuopt-python/convex/examples/rotated_socp_example.py lines 28-56
to return None explicitly in its type hint and add a meaningful docstring
documenting that it returns no value. Apply the same changes to main in
fern/docs/pages/cuopt-python/convex/examples/simple_lp_example.py lines 32-62,
extending its existing docstring with the return behavior; no parameters or
raises documentation is needed unless applicable.

Sources: Coding guidelines, Path instructions

fern/docs/pages/convex-features.mdx-59-121 (1)

59-121: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Restore the equations and examples lost during migration.

Lines 61-63 omit the quadratic-objective formula, and Lines 77-121 omit each quadratic/SOCP form and both promised Python examples. RST remnants such as :c, .note:, and double-backtick markup will also render incorrectly in MDX. Restore the source equations/examples and convert the directives to Fern MDX.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/convex-features.mdx` around lines 59 - 121, Restore the
missing quadratic-objective, quadratic-constraint, second-order cone, and
rotated-cone equations, along with both promised Python examples, in the
documentation section around “Quadratic Objectives” and “Quadratic Constraints.”
Convert remaining RST syntax such as :c references, .note blocks, and
double-backtick markup to valid Fern MDX while preserving the documented API
references and constraint semantics.
fern/docs/pages/cuopt-python/routing/routing-api.mdx-1200-1213 (1)

1200-1213: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use the defined distance variable in all three examples.

Each snippet defines distance but passes distances to cudf.DataFrame, causing an immediate NameError.

Also applies to: 1233-1247, 1269-1281

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-python/routing/routing-api.mdx` around lines 1200 -
1213, The routing examples around routing.Solve define the matrix as distance
but incorrectly reference distances; update all three affected cudf.DataFrame
constructions to use the existing distance variable consistently.
fern/docs/pages/cuopt-python/routing/routing-api.mdx-1122-1129 (1)

1122-1129: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Define data_model before using it.

This example declares locations, vehicles, and prizes but calls data_model.set_order_prizes(...) without constructing a routing.DataModel.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-python/routing/routing-api.mdx` around lines 1122 -
1129, Update the routing example before the set_order_prizes call to construct
data_model as a routing.DataModel using the declared locations and vehicles,
preserving the existing prizes setup and API usage.
fern/docs/pages/cuopt-c/convex/examples/lp_file_example.c-139-143 (1)

139-143: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Check allocation before passing the buffer to cuOpt.

Both examples pass a potentially null solution_values pointer to cuOptGetPrimalSolution.

  • fern/docs/pages/cuopt-c/convex/examples/lp_file_example.c#L139-L143: check for null, set status = CUOPT_OUT_OF_MEMORY, and jump to cleanup.
  • fern/docs/pages/cuopt-c/convex/examples/mps_file_example.c#L148-L152: apply the same allocation guard.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-c/convex/examples/lp_file_example.c` around lines 139 -
143, Add a null-allocation guard after assigning solution_values in the solution
retrieval flow: in fern/docs/pages/cuopt-c/convex/examples/lp_file_example.c
lines 139-143 and fern/docs/pages/cuopt-c/convex/examples/mps_file_example.c
lines 148-152, set status to CUOPT_OUT_OF_MEMORY and jump to DONE before calling
cuOptGetPrimalSolution when allocation fails.
fern/docs/pages/cuopt-c/convex/convex-examples.mdx-7-13 (1)

7-13: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Correct the local-build paths relative to the examples directory.

Both snippets point to paths that do not reach the repository’s cpp/ directory when make runs beside this Makefile.

  • fern/docs/pages/cuopt-c/convex/convex-examples.mdx#L7-L13: use absolute repository-root paths or explicitly state the required working directory.
  • fern/docs/pages/cuopt-c/convex/examples/Makefile#L37-L39: use paths such as ../../../../../../cpp/include and ../../../../../../cpp/build.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-c/convex/convex-examples.mdx` around lines 7 - 13, The
local-build instructions and Makefile use paths relative to the wrong working
directory. Update fern/docs/pages/cuopt-c/convex/convex-examples.mdx lines 7-13
to use repository-root paths or explicitly require running from the repository
root, and update fern/docs/pages/cuopt-c/convex/examples/Makefile lines 37-39 to
reference the cpp directory via paths such as ../../../../../../cpp/include and
../../../../../../cpp/build.
fern/docs/pages/cuopt-c/convex/examples/general_quadratic_example.c-167-170 (1)

167-170: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Return an error when solution allocation fails.

status still equals CUOPT_SUCCESS on this path, so main prints “Test completed successfully” after malloc fails.

Proposed correction
   if (solution_values == NULL) {
     printf("Error allocating solution values\n");
+    status = CUOPT_OUT_OF_MEMORY;
     goto DONE;
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-c/convex/examples/general_quadratic_example.c` around
lines 167 - 170, Update the solution_values allocation failure branch in main so
it assigns a non-success CUOPT status before jumping to DONE. Preserve the
existing error message and cleanup flow, ensuring main does not report
successful completion when malloc fails.
fern/docs/pages/cuopt-c/convex/examples/Makefile-56-69 (1)

56-69: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Run check-paths for direct example targets too.

make simple_lp_example is advertised, but only all depends on check-paths. With empty variables, -I and -L consume subsequent flags and produce misleading compiler/linker failures.

Proposed correction
-.PHONY: all clean help list
+.PHONY: all clean help list check-paths
 ...
-%: %.c
+%: %.c | check-paths
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-c/convex/examples/Makefile` around lines 56 - 69,
Ensure direct executable targets built by the pattern rule also depend on
check-paths, not only the all target. Update the pattern rule so invoking
targets such as simple_lp_example validates required paths before compilation,
while preserving the existing build command and output behavior.
fern/docs/pages/convex-settings.mdx-146-146 (1)

146-146: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use CUOPT_SAVE_BEST_PRIMAL_SO_FAR here. The current name doesn’t match the C API constant, so copying it as written will lead to a compile error.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/convex-settings.mdx` at line 146, Update the documented
parameter name in the PDLP settings description from
CUOPT_SAVE_BEST_PRIMAL_SOLUTION to CUOPT_SAVE_BEST_PRIMAL_SO_FAR, preserving the
surrounding explanation and behavior details.
fern/docs/pages/cuopt-python/routing/routing-api.mdx-73-98 (1)

73-98: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use the documented solver API here. Import routing for routing.DataModel, but keep solving via cuopt.Solver / solver.solve(); routing.Solve and DataModel.set_min_vehicles don’t match the documented API. Remove the duplicate set_min_vehicles and get_route calls.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-python/routing/routing-api.mdx` around lines 73 - 98,
Update the routing example to import and use the documented routing namespace
for routing.DataModel while retaining cuopt.Solver and solver.solve() for
solving. Remove any routing.Solve usage and DataModel.set_min_vehicles calls,
and delete the duplicate solver.set_min_vehicles and solution.get_route
invocations.
🧹 Nitpick comments (2)
fern/docs/scripts/install-selector.js (1)

285-297: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider the modern Clipboard API.

document.execCommand("copy") is deprecated; navigator.clipboard.writeText() (with this as a fallback for older browsers) would be more future-proof.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/scripts/install-selector.js` around lines 285 - 297, Update
copyToClipboard to use navigator.clipboard.writeText(out.value) when available,
while retaining document.execCommand("copy") as the fallback for older browsers.
Preserve the existing button text update and restoration behavior after a
successful copy.
fern/docs/pages/versions/v26-04.mdx (1)

1-8: 📐 Maintainability & Code Quality | 🔵 Trivial

Consider a shared redirect template instead of per-version duplication.

Content is correct and internally consistent. This boilerplate (title, inline redirect script, fallback link) is duplicated almost verbatim across v26-06.mdx (and likely the other archived-version pages). See consolidated comment below.
[medium]

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/versions/v26-04.mdx` around lines 1 - 8, Replace the
duplicated redirect markup in the archived-version page represented by
v26-04.mdx with a shared redirect template or reusable component, parameterized
by the version-specific archive URL and title. Update the other archived-version
pages, including v26-06.mdx, to use the same shared implementation while
preserving each page’s destination and fallback link.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: a05f0a1e-1240-476d-b4c0-5495d08cb89f

📥 Commits

Reviewing files that changed from the base of the PR and between d66bf29 and 502e943.

⛔ Files ignored due to path filters (52)
  • fern/docs/images/add_role.png is excluded by !**/*.png
  • fern/docs/images/aws1.png is excluded by !**/*.png
  • fern/docs/images/aws2.png is excluded by !**/*.png
  • fern/docs/images/aws3.png is excluded by !**/*.png
  • fern/docs/images/aws4.png is excluded by !**/*.png
  • fern/docs/images/azure1.png is excluded by !**/*.png
  • fern/docs/images/azure2.png is excluded by !**/*.png
  • fern/docs/images/azure3.png is excluded by !**/*.png
  • fern/docs/images/azure4.png is excluded by !**/*.png
  • fern/docs/images/azure5.png is excluded by !**/*.png
  • fern/docs/images/azure6.png is excluded by !**/*.png
  • fern/docs/images/cloud_functions.png is excluded by !**/*.png
  • fern/docs/images/cost_matrix.png is excluded by !**/*.png
  • fern/docs/images/cuOpt-managed.png is excluded by !**/*.png
  • fern/docs/images/cuOpt-self-hosted.png is excluded by !**/*.png
  • fern/docs/images/cuOpt_Collections_Image.png is excluded by !**/*.png
  • fern/docs/images/cuOpt_Stack.png is excluded by !**/*.png
  • fern/docs/images/cuopt_feature_diag.jpg is excluded by !**/*.jpg
  • fern/docs/images/cuopt_landing_page.png is excluded by !**/*.png
  • fern/docs/images/faq-01.png is excluded by !**/*.png
  • fern/docs/images/generate-personal-key.png is excluded by !**/*.png
  • fern/docs/images/genms_cuopt.png is excluded by !**/*.png
  • fern/docs/images/grpc-job-states.png is excluded by !**/*.png
  • fern/docs/images/grpc-process-model.png is excluded by !**/*.png
  • fern/docs/images/image1.png is excluded by !**/*.png
  • fern/docs/images/image2.png is excluded by !**/*.png
  • fern/docs/images/image3.png is excluded by !**/*.png
  • fern/docs/images/image4.png is excluded by !**/*.png
  • fern/docs/images/image5.png is excluded by !**/*.png
  • fern/docs/images/invite_user.png is excluded by !**/*.png
  • fern/docs/images/ms_cuopt.png is excluded by !**/*.png
  • fern/docs/images/nav-cloud-functions.png is excluded by !**/*.png
  • fern/docs/images/nav-landing-page.png is excluded by !**/*.png
  • fern/docs/images/nvidia-cuopt-logo-dark.svg is excluded by !**/*.svg
  • fern/docs/images/nvidia-cuopt-logo-light.svg is excluded by !**/*.svg
  • fern/docs/images/options_cuopt.png is excluded by !**/*.png
  • fern/docs/images/organization.png is excluded by !**/*.png
  • fern/docs/images/overview_cuopt.png is excluded by !**/*.png
  • fern/docs/images/route_map.png is excluded by !**/*.png
  • fern/docs/images/service_key_creation.png is excluded by !**/*.png
  • fern/docs/images/service_keys.png is excluded by !**/*.png
  • fern/docs/images/sh-cuOpt-stack.png is excluded by !**/*.png
  • fern/docs/images/shared_functions.png is excluded by !**/*.png
  • fern/docs/images/soft_stack.png is excluded by !**/*.png
  • fern/docs/images/users.png is excluded by !**/*.png
  • fern/docs/images/waypoint_graph.png is excluded by !**/*.png
  • fern/docs/pages/cuopt-c/convex/examples/qp_sample.mps is excluded by !**/*.mps
  • fern/docs/pages/cuopt-c/convex/examples/sample.lp is excluded by !**/*.lp
  • fern/docs/pages/cuopt-c/convex/examples/sample.mps is excluded by !**/*.mps
  • fern/docs/pages/cuopt-c/convex/examples/socp_sample.mps is excluded by !**/*.mps
  • fern/docs/pages/cuopt-c/mip/examples/mip_sample.mps is excluded by !**/*.mps
  • fern/docs/pages/cuopt-python/convex/examples/sample.mps is excluded by !**/*.mps
📒 Files selected for processing (127)
  • .github/workflows/build.yaml
  • .github/workflows/pr.yaml
  • .gitignore
  • AGENTS.md
  • README.md
  • build.sh
  • ci/build_docs.sh
  • dependencies.yaml
  • fern/Doxyfile
  • fern/c_api_config.yaml
  • fern/docs-v25-05.yml
  • fern/docs-v25-08.yml
  • fern/docs-v25-12.yml
  • fern/docs-v26-02.yml
  • fern/docs-v26-04.yml
  • fern/docs-v26-06.yml
  • fern/docs-v26-08.yml
  • fern/docs.yml
  • fern/docs/pages/convex-features.mdx
  • fern/docs/pages/convex-settings.mdx
  • fern/docs/pages/cuopt-c-api-reference.mdx
  • fern/docs/pages/cuopt-c/convex/convex-c-api.mdx
  • fern/docs/pages/cuopt-c/convex/convex-examples.mdx
  • fern/docs/pages/cuopt-c/convex/examples/Makefile
  • fern/docs/pages/cuopt-c/convex/examples/general_quadratic_example.c
  • fern/docs/pages/cuopt-c/convex/examples/lp_file_example.c
  • fern/docs/pages/cuopt-c/convex/examples/mps_file_example.c
  • fern/docs/pages/cuopt-c/convex/examples/rotated_socp_example.c
  • fern/docs/pages/cuopt-c/convex/examples/simple_lp_example.c
  • fern/docs/pages/cuopt-c/convex/examples/simple_qp_example.c
  • fern/docs/pages/cuopt-c/convex/examples/simple_socp_example.c
  • fern/docs/pages/cuopt-c/convex/index.mdx
  • fern/docs/pages/cuopt-c/index.mdx
  • fern/docs/pages/cuopt-c/mip/examples/Makefile
  • fern/docs/pages/cuopt-c/mip/examples/milp_mps_example.c
  • fern/docs/pages/cuopt-c/mip/examples/simple_milp_example.c
  • fern/docs/pages/cuopt-c/mip/index.mdx
  • fern/docs/pages/cuopt-c/mip/mip-c-api.mdx
  • fern/docs/pages/cuopt-c/mip/mip-examples.mdx
  • fern/docs/pages/cuopt-c/quick-start.mdx
  • fern/docs/pages/cuopt-cli/cli-examples.mdx
  • fern/docs/pages/cuopt-cli/index.mdx
  • fern/docs/pages/cuopt-cli/quick-start.mdx
  • fern/docs/pages/cuopt-grpc/advanced.mdx
  • fern/docs/pages/cuopt-grpc/api.mdx
  • fern/docs/pages/cuopt-grpc/examples.mdx
  • fern/docs/pages/cuopt-grpc/grpc-server-architecture.mdx
  • fern/docs/pages/cuopt-grpc/index.mdx
  • fern/docs/pages/cuopt-grpc/quick-start.mdx
  • fern/docs/pages/cuopt-python/convex/convex-api.mdx
  • fern/docs/pages/cuopt-python/convex/convex-examples.mdx
  • fern/docs/pages/cuopt-python/convex/examples/expressions_constraints_example.py
  • fern/docs/pages/cuopt-python/convex/examples/general_quadratic_example.py
  • fern/docs/pages/cuopt-python/convex/examples/mps_example.py
  • fern/docs/pages/cuopt-python/convex/examples/pdlp_warmstart_example.py
  • fern/docs/pages/cuopt-python/convex/examples/production_planning_example.py
  • fern/docs/pages/cuopt-python/convex/examples/qp_matrix_example.py
  • fern/docs/pages/cuopt-python/convex/examples/rotated_socp_example.py
  • fern/docs/pages/cuopt-python/convex/examples/simple_lp_example.py
  • fern/docs/pages/cuopt-python/convex/examples/simple_qp_example.py
  • fern/docs/pages/cuopt-python/convex/examples/simple_socp_example.py
  • fern/docs/pages/cuopt-python/convex/examples/solution_example.py
  • fern/docs/pages/cuopt-python/convex/index.mdx
  • fern/docs/pages/cuopt-python/index.mdx
  • fern/docs/pages/cuopt-python/mip/examples/incumbent_solutions_example.py
  • fern/docs/pages/cuopt-python/mip/examples/semi_continuous_example.py
  • fern/docs/pages/cuopt-python/mip/examples/simple_milp_example.py
  • fern/docs/pages/cuopt-python/mip/index.mdx
  • fern/docs/pages/cuopt-python/mip/mip-api.mdx
  • fern/docs/pages/cuopt-python/mip/mip-examples.mdx
  • fern/docs/pages/cuopt-python/quick-start.mdx
  • fern/docs/pages/cuopt-python/routing/examples/intra_factory_example.py
  • fern/docs/pages/cuopt-python/routing/examples/smoke_test_example.sh
  • fern/docs/pages/cuopt-python/routing/examples/tsp_batch_example.py
  • fern/docs/pages/cuopt-python/routing/index.mdx
  • fern/docs/pages/cuopt-python/routing/routing-api.mdx
  • fern/docs/pages/cuopt-python/routing/routing-examples.mdx
  • fern/docs/pages/cuopt-server/client-api/index.mdx
  • fern/docs/pages/cuopt-server/client-api/sh-cli-api.mdx
  • fern/docs/pages/cuopt-server/client-api/sh-cli-build.mdx
  • fern/docs/pages/cuopt-server/csp-guides/csp-aws.mdx
  • fern/docs/pages/cuopt-server/csp-guides/csp-azure.mdx
  • fern/docs/pages/cuopt-server/csp-guides/index.mdx
  • fern/docs/pages/cuopt-server/examples/index.mdx
  • fern/docs/pages/cuopt-server/examples/lp-examples.mdx
  • fern/docs/pages/cuopt-server/examples/milp-examples.mdx
  • fern/docs/pages/cuopt-server/examples/routing-examples.mdx
  • fern/docs/pages/cuopt-server/index.mdx
  • fern/docs/pages/cuopt-server/nim-operator/configuration.mdx
  • fern/docs/pages/cuopt-server/nim-operator/deployment.mdx
  • fern/docs/pages/cuopt-server/nim-operator/index.mdx
  • fern/docs/pages/cuopt-server/nim-operator/prerequisites.mdx
  • fern/docs/pages/cuopt-server/quick-start.mdx
  • fern/docs/pages/cuopt-server/server-api/index.mdx
  • fern/docs/pages/cuopt-server/server-api/server-cli.mdx
  • fern/docs/pages/faq.mdx
  • fern/docs/pages/index.mdx
  • fern/docs/pages/install.mdx
  • fern/docs/pages/introduction.mdx
  • fern/docs/pages/license.mdx
  • fern/docs/pages/milp-features.mdx
  • fern/docs/pages/mip-settings.mdx
  • fern/docs/pages/open-api.mdx
  • fern/docs/pages/release-notes.mdx
  • fern/docs/pages/resources.mdx
  • fern/docs/pages/routing-features.mdx
  • fern/docs/pages/system-requirements.mdx
  • fern/docs/pages/thirdparty_modeling_languages/index.mdx
  • fern/docs/pages/transition.mdx
  • fern/docs/pages/versions/v25-05.mdx
  • fern/docs/pages/versions/v25-08.mdx
  • fern/docs/pages/versions/v25-12.mdx
  • fern/docs/pages/versions/v26-02.mdx
  • fern/docs/pages/versions/v26-04.mdx
  • fern/docs/pages/versions/v26-06.mdx
  • fern/docs/scripts/cuopt-install-version.js
  • fern/docs/scripts/install-selector.css
  • fern/docs/scripts/install-selector.js
  • fern/embed_examples.py
  • fern/extract_c_api.py
  • fern/extract_python_api.py
  • fern/fern.config.json
  • fern/generate_api_docs.py
  • fern/generators.yml
  • fern/openapi/cuopt_spec.yaml
  • fern/requirements-docs.txt
  • python/cuopt/cuopt/linear_programming/io/parser.py

@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The pull request migrates cuOpt documentation from the existing build flow to Fern. It adds CI publishing, generated C/Python/OpenAPI references, extensive guides and examples, navigation and version redirects, an installation selector, and supporting documentation tooling.

Changes

Fern documentation migration

Layer / File(s) Summary
Fern build and publishing pipeline
.github/workflows/*, build.sh, ci/build_docs.sh, dependencies.yaml, fern/*
CI and local builds now generate, validate, preview, or publish documentation through Fern and its pinned CLI.
Site structure and documentation content
fern/docs*.yml, fern/docs.yml, fern/docs/pages/*
Fern navigation, version redirects, installation pages, API guides, feature references, server/gRPC guides, FAQs, release notes, and system requirements are added.
Examples and generated references
fern/docs/pages/*/examples/*, fern/extract_*.py, fern/openapi/*
C and Python examples, API extraction scripts, embedded example generation, and an OpenAPI specification are introduced.
Installation selector and site assets
fern/docs/scripts/*, fern/generate_api_docs.py, fern/embed_examples.py
Installation commands, selector interactions, version resolution, SPA rendering, and generated asset orchestration are implemented.

Estimated code review effort: 5 (Critical) | ~120 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.89% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: migrating documentation to the Fern platform.
Description check ✅ Passed The description matches the changeset and accurately describes the Fern documentation migration.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs-fern-migration

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Note

Due to the large number of review comments, Critical severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
fern/docs/pages/cuopt-python/quick-start.mdx (1)

21-24: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Embed the smoke test or correct the instructions.

The page provides only a link and an empty “Example Response” section, so users cannot copy a script directly from this guide as stated. Embed the command and output, or reword this as a link to the script.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-python/quick-start.mdx` around lines 21 - 24, Update
the quick-start section around the smoke_test_example.sh reference so it matches
the stated usage: either embed the complete smoke-test command and a
representative example response, or reword the text to clearly direct users to
the linked script instead of claiming it can be copied directly from the guide.
🟠 Major comments (30)
fern/c_api_config.yaml-58-64 (1)

58-64: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Correct the standard second-order cone formula.

The standard SOC is sum(x_i^2) <= x_0^2 with x_0 >= 0; the current text documents a different constraint.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/c_api_config.yaml` around lines 58 - 64, Update the quadratic-constraint
documentation note for cuOptAddQuadraticConstraint so the standard second-order
cone formula uses sum of the squared non-leading variables bounded by x_0
squared, with x_0 nonnegative. Leave the convex and rotated second-order cone
descriptions unchanged.
fern/docs/pages/cuopt-c/convex/convex-examples.mdx-382-406 (1)

382-406: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Check termination status before reading a primal solution.

These examples accept arbitrary files but unconditionally request the objective and primal vector. Mirror milp_mps_example.c: compute has_primal_solution, only access solution data when true, and check malloc before calling cuOptGetPrimalSolution.

Also applies to: 593-615

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-c/convex/convex-examples.mdx` around lines 382 - 406,
The example must verify termination status before accessing solution data.
Mirror milp_mps_example.c by computing has_primal_solution, conditionally
calling cuOptGetObjectiveValue and cuOptGetPrimalSolution only when true, and
checking solution_values allocation before using it; preserve the existing error
handling and result output for valid primal solutions.
build.sh-462-470 (1)

462-470: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not continue with stale generated API pages.

If Python is unavailable, this proceeds through validation and even publishing without regenerating the references. Also, bare pip may install dependencies for a different interpreter. Require ${PY} and install with "${PY}" -m pip.

Proposed fix
     PY=${PYTHON:-python3}
     if command -v "${PY}" &>/dev/null; then
         if ! "${PY}" -c "import fastapi, pydantic, yaml" 2>/dev/null; then
-            pip install --quiet -r "${REPODIR}/fern/requirements-docs.txt"
+            "${PY}" -m pip install --quiet -r "${REPODIR}/fern/requirements-docs.txt"
         fi
         "${PY}" "${REPODIR}/fern/generate_api_docs.py"
     else
-        echo "  [WARN] Python not found; skipping API doc generation."
+        echo "ERROR: Python is required to generate API documentation."
+        exit 1
     fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@build.sh` around lines 462 - 470, Update the API documentation generation
block around PY so missing Python causes the build to fail instead of continuing
to validation or publishing. Replace bare pip installation with the selected
interpreter’s “${PY} -m pip”, and preserve dependency installation and
generate_api_docs.py execution through that same interpreter.
fern/docs/pages/cuopt-c/convex/convex-c-api.mdx-127-127 (1)

127-127: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Replace CUOPT_ERROR with a documented status code

CUOPT_ERROR is not in the public status-code list on this page. Use one of the documented error constants, or add and document CUOPT_ERROR if it is meant to be part of the API. (Also applies to line 183.)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-c/convex/convex-c-api.mdx` at line 127, Update the
return documentation at both affected locations to use a status constant already
listed in the public API documentation, or add CUOPT_ERROR to that documented
status-code list if it is an intended public constant; keep the success/error
return description consistent.
fern/docs/pages/cuopt-c/convex/convex-c-api.mdx-108-108 (1)

108-108: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Restore the missing equations and API details in the convex C reference The four constructor entries are missing their optimization formulations, CUOPT_ERROR is missing from the status-code list, and cuOptGetErrorStatus / cuOptGetErrorString / cuOptGetPrimalSolution have no descriptive content.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-c/convex/convex-c-api.mdx` at line 108, The convex C
API reference is incomplete: update the four constructor entries following
“Create an optimization problem of the form” with their optimization equations,
add CUOPT_ERROR to the status-code list, and provide descriptions for
cuOptGetErrorStatus, cuOptGetErrorString, and cuOptGetPrimalSolution. Preserve
the existing reference structure and terminology.
fern/docs/pages/convex-features.mdx-61-121 (1)

61-121: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Restore the missing quadratic formulas and replace the legacy RST syntax. The equations after the “of the form” lines are still blank, and the :c\``/.note:markup won’t render as intended in this MDX page. The#simple-qp-example-python, #simple-qp-example-c, and #generic-example-with-normal-and-batch-mode` links also point to slugs that don’t exist here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/convex-features.mdx` around lines 61 - 121, The quadratic
objective and constraint sections in the MDX page are missing their formulas;
restore the displayed equations for each “of the form” statement, including
convex, concave, second-order cone, and rotated cone definitions. Replace legacy
`:c\`` and `.note:` RST markup with valid MDX/Markdown equivalents, and update
the referenced example links to anchors that exist in this page, including the
generic normal/batch example.
fern/docs/pages/cuopt-python/convex/examples/mps_example.py-22-33 (1)

22-33: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add a return annotation to the new entry point.

main is a new non-private function and should declare -> None.

Proposed fix
-def main():
+def main() -> None:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-python/convex/examples/mps_example.py` around lines 22
- 33, Update the new main function to declare an explicit None return
annotation, preserving its existing execution and output behavior.

Source: Coding guidelines

fern/docs/pages/cuopt-grpc/quick-start.mdx-23-71 (1)

23-71: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Restore the omitted gRPC command blocks. The migration retained introductory text but lost the executable commands required by all three guides.

  • fern/docs/pages/cuopt-grpc/quick-start.mdx#L23-L71: add binary verification, server launch, Docker, client-export, and example-run commands.
  • fern/docs/pages/cuopt-grpc/advanced.mdx#L11-L104: add flags, TLS/mTLS, CA, Docker, and client-configuration commands.
  • fern/docs/pages/cuopt-grpc/examples.mdx#L5-L9: add the required remote host and port exports.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-grpc/quick-start.mdx` around lines 23 - 71, Restore the
omitted executable command blocks in fern/docs/pages/cuopt-grpc/quick-start.mdx
(lines 23-71) for binary verification, bare-metal and Docker server launch,
client environment exports, and Python/CLI example runs. Add the documented
flags, TLS/mTLS and CA commands, Docker commands, and client configuration
commands in fern/docs/pages/cuopt-grpc/advanced.mdx (lines 11-104). Add the
required remote host and port exports in fern/docs/pages/cuopt-grpc/examples.mdx
(lines 5-9), preserving the surrounding guidance and documented command
behavior.
fern/docs/pages/cuopt-python/convex/convex-api.mdx-33-33 (1)

33-33: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Fix the API doc generator before publishing this page. Several generated sections still leak literal :py:meth:/:py:class: roles, escape <= inside examples, flatten .. deprecated:: into prose, and drop exception names in **Raises**; regenerate after fixing the renderer.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-python/convex/convex-api.mdx` at line 33, Fix the API
documentation renderer before regenerating this page: resolve literal :py:meth:
and :py:class: roles into proper links, preserve <= in example blocks, render ..
deprecated:: as a directive, and retain exception names in **Raises** sections.
Locate the renderer components responsible for these generated sections, then
regenerate the cuOpt Python API documentation.

Source: Coding guidelines

fern/docs/pages/cuopt-python/routing/routing-api.mdx-71-99 (1)

71-99: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Import routing in both Assignment examples. Both snippets call routing.DataModel without defining routing, so they fail immediately.

  • fern/docs/pages/cuopt-python/routing/routing-api.mdx#L71-L99: add from cuopt import routing before constructing the data model.
  • fern/docs/pages/cuopt-python/routing/routing-api.mdx#L169-L201: add the same import before constructing the data model.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-python/routing/routing-api.mdx` around lines 71 - 99,
Import the routing module in both Assignment examples before their
routing.DataModel calls: update
fern/docs/pages/cuopt-python/routing/routing-api.mdx lines 71-99 and 169-201
with the same cuopt routing import. No other changes are needed.
fern/docs/pages/cuopt-python/routing/routing-api.mdx-1201-1207 (1)

1201-1207: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use the declared matrix variable in both matching examples. Each example defines distance but passes undefined distances.

  • fern/docs/pages/cuopt-python/routing/routing-api.mdx#L1201-L1207: pass cudf.DataFrame(distance) to add_cost_matrix.
  • fern/docs/pages/cuopt-python/routing/routing-api.mdx#L1233-L1240: pass cudf.DataFrame(distance) to add_cost_matrix.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-python/routing/routing-api.mdx` around lines 1201 -
1207, The routing API examples use the undefined variable distances instead of
the declared distance matrix. Update both affected examples in
fern/docs/pages/cuopt-python/routing/routing-api.mdx (lines 1201-1207 and
1233-1240) so add_cost_matrix uses distance in cudf.DataFrame, preserving the
rest of each example.
fern/docs/pages/cuopt-python/routing/routing-api.mdx-1123-1128 (1)

1123-1128: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Initialize data_model before using it.

Line 1128 raises NameError; this fenced example never creates a routing.DataModel.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-python/routing/routing-api.mdx` around lines 1123 -
1128, Initialize a routing.DataModel instance before the set_order_prizes call
in the example, using the existing locations and vehicles context as required by
its constructor. Ensure data_model is defined before cudf.Series(prizes) is
passed to data_model.set_order_prizes.
fern/docs/pages/cuopt-server/examples/lp-examples.mdx-63-65 (1)

63-65: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Point the abort links to the MILP examples page.

These are same-page fragments, but neither target exists here. Link to the corresponding headings in milp-examples.mdx instead.

Also applies to: 101-103

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-server/examples/lp-examples.mdx` around lines 63 - 65,
Update the aborting-job references in the LP examples, including the occurrence
around the alternate abort section, to link to the corresponding headings in
milp-examples.mdx rather than using same-page fragment links. Preserve the
existing link text and point each reference at its matching MILP heading.
fern/docs/pages/cuopt-python/routing/routing-api.mdx-209-243 (1)

209-243: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Fix the non-runnable re-routing example.

Line 237 has an unterminated "service_time" key, and Line 241 passes distances, which is never defined. The snippet cannot be copied or executed as written.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-python/routing/routing-api.mdx` around lines 209 - 243,
Fix the construct_rerouting_model example by closing the service_time key string
in new_order_data and passing the defined new_distances variable instead of the
undefined distances name. Keep the example’s remaining parameters and flow
unchanged so it is directly runnable.
fern/docs/pages/cuopt-server/client-api/sh-cli-build.mdx-17-29 (1)

17-29: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Add the missing request and server-start examples.

The guide announces commands and direct-string/file examples, but none are present. Include runnable HTTP requests with endpoint, headers, payload/file handling, and the asynchronous response shape.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-server/client-api/sh-cli-build.mdx` around lines 17 -
29, Add the missing runnable server-start command and request examples in the
CLI guide section around the `/cuopt/request` documentation: include the
endpoint, required headers, a direct JSON payload example, a file-upload example
with data/result directory handling, and the asynchronous response shape. Ensure
the examples match the documented `-d` and `-r` server options and are
executable as presented.
fern/docs/pages/cuopt-server/nim-operator/index.mdx-9-14 (1)

9-14: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Make the scaling contract consistent.

  • fern/docs/pages/cuopt-server/nim-operator/index.mdx Lines 9-14: qualify scaling as a generic operator capability.
  • fern/docs/pages/cuopt-server/nim-operator/configuration.mdx Lines 46-56: state that cuOpt currently supports only one pod and does not support service scaling.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-server/nim-operator/index.mdx` around lines 9 - 14,
Make the scaling documentation consistent across both sites: in
fern/docs/pages/cuopt-server/nim-operator/index.mdx lines 9-14, qualify
automated scaling as a generic NIM Operator capability rather than a
cuOpt-supported feature; in
fern/docs/pages/cuopt-server/nim-operator/configuration.mdx lines 46-56,
explicitly state that cuOpt currently supports only one pod and does not support
service scaling.
fern/docs/pages/cuopt-server/examples/routing-examples.mdx-19-25 (1)

19-25: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Make initial-solution support consistent.

  • fern/docs/pages/cuopt-server/examples/routing-examples.mdx Lines 19-25: document the actual acceptance/rejection behavior for initial solutions.
  • fern/docs/pages/faq.mdx Lines 243-245: update the FAQ to match the supported behavior.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-server/examples/routing-examples.mdx` around lines 19 -
25, Update the initial-solution documentation to accurately describe the actual
acceptance and rejection behavior, replacing the incorrect claim that the
example solution is rejected because the problem is too small. Apply the
corresponding consistency update in fern/docs/pages/faq.mdx lines 243-245; both
documented locations must describe the same supported behavior.
fern/docs/pages/faq.mdx-222-225 (1)

222-225: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Resolve the contradictory routing capacity claims.

The FAQ says cuOpt can easily solve 15K locations on A100/H100, but later describes 10,000 locations as the maximum on an H100 SXM. Clarify the workload assumptions or replace one of the figures with a consistent, qualified estimate.

Also applies to: 335-339

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/faq.mdx` around lines 222 - 225, Resolve the conflicting
capacity statements in the cuOpt resource-estimates FAQ by aligning the
15K-location claim with the later H100 SXM 10,000-location maximum. Clarify the
workload or hardware assumptions for each estimate, or replace the figures with
one consistent, explicitly qualified capacity statement.
fern/docs/pages/cuopt-server/nim-operator/prerequisites.mdx-87-94 (1)

87-94: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not echo the NGC API key.

echo $NGC_API_KEY prints the secret to terminal logs and CI output. Replace it with a non-disclosing presence check such as test -n "${NGC_API_KEY:-}".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-server/nim-operator/prerequisites.mdx` around lines 87
- 94, Update the NGC API key prerequisite check in the deployment verification
list to avoid printing the secret. Replace the echo command with a
non-disclosing presence check using NGC_API_KEY that succeeds only when the
variable is set and non-empty.
fern/docs/pages/cuopt-server/nim-operator/configuration.mdx-32-34 (1)

32-34: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Make the storage requirement consistent.

  • fern/docs/pages/cuopt-server/nim-operator/configuration.mdx Lines 32-34: explain that persistent storage is optional for HTTP-based data transfer.
  • fern/docs/pages/cuopt-server/nim-operator/prerequisites.mdx Lines 39-42: remove the unconditional requirement or document the exact cases requiring storage.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-server/nim-operator/configuration.mdx` around lines 32
- 34, Align the storage guidance across both documentation sites: in
fern/docs/pages/cuopt-server/nim-operator/configuration.mdx lines 32-34, retain
that persistent storage is optional when data is transferred over HTTP; in
fern/docs/pages/cuopt-server/nim-operator/prerequisites.mdx lines 39-42, remove
the unconditional storage requirement or explicitly limit it to deployments that
pass datasets through the filesystem.
fern/docs/pages/cuopt-server/quick-start.mdx-17-60 (1)

17-60: 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Restore the omitted documentation content across the migration. Multiple pages retain empty placeholders where commands, outputs, API references, or configuration examples are required.

  • fern/docs/pages/cuopt-server/quick-start.mdx Lines 17-60: restore container and smoke-test commands.
  • fern/docs/pages/cuopt-server/examples/routing-examples.mdx Lines 13-49: restore response and HTTPS examples.
  • fern/docs/pages/cuopt-server/nim-operator/configuration.mdx Lines 22-80: add actual configuration values and manifests.
  • fern/docs/pages/cuopt-server/nim-operator/deployment.mdx Lines 7-75: add deployment, verification, and testing commands.
  • fern/docs/pages/cuopt-server/nim-operator/index.mdx Lines 32-44: add quick-start commands and navigation.
  • fern/docs/pages/cuopt-server/nim-operator/prerequisites.mdx Lines 25-68: add installation and verification commands.
  • fern/docs/pages/cuopt-server/server-api/index.mdx Line 5: add API navigation/content.
  • fern/docs/pages/cuopt-server/server-api/server-cli.mdx Line 5: add the CLI reference.
  • fern/docs/pages/faq.mdx Lines 102-108, 125-165, 195-200, and 439-449: restore troubleshooting commands and examples.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-server/quick-start.mdx` around lines 17 - 60, The
migration removed required documentation content across multiple cuOpt pages;
restore the omitted commands, outputs, references, configuration values,
manifests, and examples. Update fern/docs/pages/cuopt-server/quick-start.mdx
(17-60) with container and smoke-test commands; examples/routing-examples.mdx
(13-49) with response and HTTPS examples; nim-operator/configuration.mdx (22-80)
with configuration values and manifests; deployment.mdx (7-75) with deployment,
verification, and testing commands; index.mdx (32-44) with quick-start commands
and navigation; prerequisites.mdx (25-68) with installation and verification
commands; server-api/index.mdx (5) with API navigation/content; server-cli.mdx
(5) with the CLI reference; and faq.mdx (102-108, 125-165, 195-200, 439-449)
with the troubleshooting commands and examples.
fern/docs/pages/cuopt-server/nim-operator/configuration.mdx-46-46 (1)

46-46: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Replace the RST directive with Fern/MDX syntax.

.. note:: is an RST directive and will not render as a Fern note in this MDX page. Use Fern’s <Note> component or standard Markdown.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-server/nim-operator/configuration.mdx` at line 46,
Update the LoadBalancer guidance in the cuOpt configuration page to replace the
RST `.. note::` directive with Fern-supported MDX syntax, preferably the
`<Note>` component, while preserving the existing message.
fern/docs/pages/cuopt-python/convex/examples/production_planning_example.py-39-40 (1)

39-40: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Add the required public-function contract.

main is a new public Python function but has no return annotation, and its docstring does not document the return/raise contract.

Proposed fix
-def main():
-    """Run the production planning example."""
+def main() -> None:
+    """Run the production planning example.
+
+    Returns:
+        None.
+    """
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-python/convex/examples/production_planning_example.py`
around lines 39 - 40, Update the public function main to declare its return type
as None and expand its docstring to document the return and raise contract,
following the repository’s established public-function documentation
conventions.

Source: Coding guidelines

fern/docs/pages/system-requirements.mdx-62-68 (1)

62-68: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Correct the CUDA 12.9 driver floor.

CUDA 12.9 GA requires Linux driver 575.51.03+, not 570.42.01+. The current value can direct users to an unsupported runtime combination. (docs.nvidia.com)

-          - CUDA 12.9 with Driver 570.42.01+
+          - CUDA 12.9 with Driver 575.51.03+
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/system-requirements.mdx` around lines 62 - 68, Update the
CUDA 12.9 entry in the “CUDA & NVIDIA Driver combinations” list to require Linux
driver 575.51.03 or newer instead of 570.42.01, leaving the other version
requirements unchanged.
fern/docs/scripts/install-selector.css-6-8 (1)

6-8: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Increase the copy-button text contrast.

White on #76b900 is approximately 2.41:1, below WCAG’s 4.5:1 normal-text minimum and even its 3:1 large-text minimum. (w3.org)

Proposed fix
 `#cuopt-copy-btn.cuopt-install-copy-btn` {
-  color: `#fff` !important;
+  color: `#000` !important;
 }

Also applies to: 152-173

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/scripts/install-selector.css` around lines 6 - 8, Update the
copy-button color variables around --cuopt-nvidia-green and its hover/active
variants so the button background provides sufficient contrast with its white
text, meeting at least WCAG 4.5:1 for normal text across all interactive states.
fern/extract_python_api.py-438-441 (1)

438-441: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not HTML-escape operators inside fenced code.

This global replacement changes generated signatures and examples from x <= y to x &lt;= y, making displayed and copied Python code incorrect. Escape only prose/MDX text, not fenced regions.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/extract_python_api.py` around lines 438 - 441, Update the content
transformation after joining lines so the <= replacement applies only outside
fenced code blocks. Preserve operators inside fenced regions unchanged while
continuing to escape them in prose/MDX text, then write the selectively
transformed content through the existing dest.write_text call.
fern/generate_api_docs.py-88-90 (1)

88-90: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Make documentation generation fail closed.

Generation errors currently produce stale or incomplete API documentation while the pipeline continues successfully.

  • fern/generate_api_docs.py#L88-L90: re-raise OpenAPI/version generation failures.
  • fern/extract_c_api.py#L191-L195: fail if any Doxygen XML file cannot be parsed.
  • fern/extract_python_api.py#L85-L89: fail instead of treating an unparsable module as empty.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/generate_api_docs.py` around lines 88 - 90, Make documentation
generation fail closed: in fern/generate_api_docs.py around the OpenAPI/version
generation exception handler, re-raise the failure after reporting it; in
fern/extract_c_api.py around the Doxygen XML parsing handler, propagate any file
parse error instead of continuing; and in fern/extract_python_api.py around
module parsing, fail on unparsable modules rather than treating them as empty.
fern/embed_examples.py-90-103 (1)

90-103: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Fail before truncating an unterminated embed block.

When <!-- /embed --> is missing, this loop reaches EOF and replaces everything from the opening marker onward. Raise an error before writing the MDX file.

Proposed fix
             i += 1
             while i < len(lines) and lines[i].rstrip("\n") != _CLOSE:
                 i += 1
+            if i >= len(lines):
+                raise ValueError(
+                    f"{mdx_path}: missing {_CLOSE!r} for examples/{rel}"
+                )
             i += 1  # skip the closing marker line
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/embed_examples.py` around lines 90 - 103, Update the existing
embed-marker handling around _OPEN_RE and _CLOSE so it detects when the closing
marker is not found before EOF, raises an error, and aborts before modifying or
writing the MDX output; only skip and replace the block when _CLOSE is present.
fern/docs/scripts/install-selector.js-201-206 (1)

201-206: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not silently map CUDA 12 + UBI10 to a CUDA 13 image.

cu12-ubi10 is absent, so the fallback emits cu13-ubi10 while the UI still says CUDA 12.x. Disable that combination, select CUDA 13 explicitly, or report it as unsupported.

Minimal correctness fix
       var baseCuda = cuda || "cu12";
       var cudaKey = baseCuda + (variant === "ubi10" ? "-ubi10" : "");
-      var fallbackKey = (variant === "ubi10") ? "cu13-ubi10" : "cu12";
-      var c = data[release][cudaKey] || data[release][fallbackKey];
+      if (variant === "ubi10" && baseCuda !== "cu13") {
+        return "# UBI10 images require CUDA 13.x. Select CUDA 13.x.";
+      }
+      var c = data[release][cudaKey] || data[release].cu12;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/scripts/install-selector.js` around lines 201 - 206, Update the
fallback logic around `cudaKey`, `fallbackKey`, and `data[release]` so selecting
CUDA 12 with the `ubi10` variant never resolves to `cu13-ubi10`. Treat that
combination as unsupported or require an explicit CUDA 13 selection, while
preserving valid image resolution for other CUDA and variant combinations.
fern/openapi/cuopt_spec.yaml-3797-3801 (1)

3797-3801: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Use object defaults for DroppedTasks, and fix the vehicle_breaks example

  • dropped_tasks is a DroppedTasks object, but it defaults to [] in multiple response schemas. Use {} (or remove the default) so the spec matches the schema.
  • The third vehicle_breaks example omits required locations; add it or make the field optional if omission is intended.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/openapi/cuopt_spec.yaml` around lines 3797 - 3801, Update every response
schema property referencing DroppedTasks, including dropped_tasks, to use an
object default ({}) or remove the default instead of [] while preserving the
DroppedTasks schema type. Correct the third vehicle_breaks example by adding the
required locations field, unless the schema is intentionally changed to make
locations optional.
🧹 Nitpick comments (1)
fern/docs/pages/cuopt-c/convex/examples/simple_qp_example.c (1)

118-134: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the non-deprecated quadratic-objective flow.

The page says this example uses cuOptCreateProblem plus cuOptSetQuadraticObjective, but the source teaches deprecated cuOptCreateQuadraticProblem. Update the source and regenerate the embedded MDX.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@fern/docs/pages/cuopt-c/convex/examples/simple_qp_example.c` around lines 118
- 134, Update the simple QP example to use the non-deprecated cuOptCreateProblem
flow, then apply the quadratic objective through cuOptSetQuadraticObjective
instead of calling cuOptCreateQuadraticProblem. Regenerate the embedded MDX so
the documented example matches the updated source and stated API usage.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ci/build_docs.sh`:
- Around line 40-52: Update ci/build_docs.sh so fern/generate_api_docs.py and
fern check run without repository secrets, and remove Fern publishing from this
secret-bearing script. Move fern generate --docs --preview into a trusted
workflow_run or base-branch job, and ensure production fern generate --docs is
gated by an explicit trusted branch or event.

---

Outside diff comments:
In `@fern/docs/pages/cuopt-python/quick-start.mdx`:
- Around line 21-24: Update the quick-start section around the
smoke_test_example.sh reference so it matches the stated usage: either embed the
complete smoke-test command and a representative example response, or reword the
text to clearly direct users to the linked script instead of claiming it can be
copied directly from the guide.

---

Major comments:
In `@build.sh`:
- Around line 462-470: Update the API documentation generation block around PY
so missing Python causes the build to fail instead of continuing to validation
or publishing. Replace bare pip installation with the selected interpreter’s
“${PY} -m pip”, and preserve dependency installation and generate_api_docs.py
execution through that same interpreter.

In `@fern/c_api_config.yaml`:
- Around line 58-64: Update the quadratic-constraint documentation note for
cuOptAddQuadraticConstraint so the standard second-order cone formula uses sum
of the squared non-leading variables bounded by x_0 squared, with x_0
nonnegative. Leave the convex and rotated second-order cone descriptions
unchanged.

In `@fern/docs/pages/convex-features.mdx`:
- Around line 61-121: The quadratic objective and constraint sections in the MDX
page are missing their formulas; restore the displayed equations for each “of
the form” statement, including convex, concave, second-order cone, and rotated
cone definitions. Replace legacy `:c\`` and `.note:` RST markup with valid
MDX/Markdown equivalents, and update the referenced example links to anchors
that exist in this page, including the generic normal/batch example.

In `@fern/docs/pages/cuopt-c/convex/convex-c-api.mdx`:
- Line 127: Update the return documentation at both affected locations to use a
status constant already listed in the public API documentation, or add
CUOPT_ERROR to that documented status-code list if it is an intended public
constant; keep the success/error return description consistent.
- Line 108: The convex C API reference is incomplete: update the four
constructor entries following “Create an optimization problem of the form” with
their optimization equations, add CUOPT_ERROR to the status-code list, and
provide descriptions for cuOptGetErrorStatus, cuOptGetErrorString, and
cuOptGetPrimalSolution. Preserve the existing reference structure and
terminology.

In `@fern/docs/pages/cuopt-c/convex/convex-examples.mdx`:
- Around line 382-406: The example must verify termination status before
accessing solution data. Mirror milp_mps_example.c by computing
has_primal_solution, conditionally calling cuOptGetObjectiveValue and
cuOptGetPrimalSolution only when true, and checking solution_values allocation
before using it; preserve the existing error handling and result output for
valid primal solutions.

In `@fern/docs/pages/cuopt-grpc/quick-start.mdx`:
- Around line 23-71: Restore the omitted executable command blocks in
fern/docs/pages/cuopt-grpc/quick-start.mdx (lines 23-71) for binary
verification, bare-metal and Docker server launch, client environment exports,
and Python/CLI example runs. Add the documented flags, TLS/mTLS and CA commands,
Docker commands, and client configuration commands in
fern/docs/pages/cuopt-grpc/advanced.mdx (lines 11-104). Add the required remote
host and port exports in fern/docs/pages/cuopt-grpc/examples.mdx (lines 5-9),
preserving the surrounding guidance and documented command behavior.

In `@fern/docs/pages/cuopt-python/convex/convex-api.mdx`:
- Line 33: Fix the API documentation renderer before regenerating this page:
resolve literal :py:meth: and :py:class: roles into proper links, preserve <= in
example blocks, render .. deprecated:: as a directive, and retain exception
names in **Raises** sections. Locate the renderer components responsible for
these generated sections, then regenerate the cuOpt Python API documentation.

In `@fern/docs/pages/cuopt-python/convex/examples/mps_example.py`:
- Around line 22-33: Update the new main function to declare an explicit None
return annotation, preserving its existing execution and output behavior.

In `@fern/docs/pages/cuopt-python/convex/examples/production_planning_example.py`:
- Around line 39-40: Update the public function main to declare its return type
as None and expand its docstring to document the return and raise contract,
following the repository’s established public-function documentation
conventions.

In `@fern/docs/pages/cuopt-python/routing/routing-api.mdx`:
- Around line 71-99: Import the routing module in both Assignment examples
before their routing.DataModel calls: update
fern/docs/pages/cuopt-python/routing/routing-api.mdx lines 71-99 and 169-201
with the same cuopt routing import. No other changes are needed.
- Around line 1201-1207: The routing API examples use the undefined variable
distances instead of the declared distance matrix. Update both affected examples
in fern/docs/pages/cuopt-python/routing/routing-api.mdx (lines 1201-1207 and
1233-1240) so add_cost_matrix uses distance in cudf.DataFrame, preserving the
rest of each example.
- Around line 1123-1128: Initialize a routing.DataModel instance before the
set_order_prizes call in the example, using the existing locations and vehicles
context as required by its constructor. Ensure data_model is defined before
cudf.Series(prizes) is passed to data_model.set_order_prizes.
- Around line 209-243: Fix the construct_rerouting_model example by closing the
service_time key string in new_order_data and passing the defined new_distances
variable instead of the undefined distances name. Keep the example’s remaining
parameters and flow unchanged so it is directly runnable.

In `@fern/docs/pages/cuopt-server/client-api/sh-cli-build.mdx`:
- Around line 17-29: Add the missing runnable server-start command and request
examples in the CLI guide section around the `/cuopt/request` documentation:
include the endpoint, required headers, a direct JSON payload example, a
file-upload example with data/result directory handling, and the asynchronous
response shape. Ensure the examples match the documented `-d` and `-r` server
options and are executable as presented.

In `@fern/docs/pages/cuopt-server/examples/lp-examples.mdx`:
- Around line 63-65: Update the aborting-job references in the LP examples,
including the occurrence around the alternate abort section, to link to the
corresponding headings in milp-examples.mdx rather than using same-page fragment
links. Preserve the existing link text and point each reference at its matching
MILP heading.

In `@fern/docs/pages/cuopt-server/examples/routing-examples.mdx`:
- Around line 19-25: Update the initial-solution documentation to accurately
describe the actual acceptance and rejection behavior, replacing the incorrect
claim that the example solution is rejected because the problem is too small.
Apply the corresponding consistency update in fern/docs/pages/faq.mdx lines
243-245; both documented locations must describe the same supported behavior.

In `@fern/docs/pages/cuopt-server/nim-operator/configuration.mdx`:
- Around line 32-34: Align the storage guidance across both documentation sites:
in fern/docs/pages/cuopt-server/nim-operator/configuration.mdx lines 32-34,
retain that persistent storage is optional when data is transferred over HTTP;
in fern/docs/pages/cuopt-server/nim-operator/prerequisites.mdx lines 39-42,
remove the unconditional storage requirement or explicitly limit it to
deployments that pass datasets through the filesystem.
- Line 46: Update the LoadBalancer guidance in the cuOpt configuration page to
replace the RST `.. note::` directive with Fern-supported MDX syntax, preferably
the `<Note>` component, while preserving the existing message.

In `@fern/docs/pages/cuopt-server/nim-operator/index.mdx`:
- Around line 9-14: Make the scaling documentation consistent across both sites:
in fern/docs/pages/cuopt-server/nim-operator/index.mdx lines 9-14, qualify
automated scaling as a generic NIM Operator capability rather than a
cuOpt-supported feature; in
fern/docs/pages/cuopt-server/nim-operator/configuration.mdx lines 46-56,
explicitly state that cuOpt currently supports only one pod and does not support
service scaling.

In `@fern/docs/pages/cuopt-server/nim-operator/prerequisites.mdx`:
- Around line 87-94: Update the NGC API key prerequisite check in the deployment
verification list to avoid printing the secret. Replace the echo command with a
non-disclosing presence check using NGC_API_KEY that succeeds only when the
variable is set and non-empty.

In `@fern/docs/pages/cuopt-server/quick-start.mdx`:
- Around line 17-60: The migration removed required documentation content across
multiple cuOpt pages; restore the omitted commands, outputs, references,
configuration values, manifests, and examples. Update
fern/docs/pages/cuopt-server/quick-start.mdx (17-60) with container and
smoke-test commands; examples/routing-examples.mdx (13-49) with response and
HTTPS examples; nim-operator/configuration.mdx (22-80) with configuration values
and manifests; deployment.mdx (7-75) with deployment, verification, and testing
commands; index.mdx (32-44) with quick-start commands and navigation;
prerequisites.mdx (25-68) with installation and verification commands;
server-api/index.mdx (5) with API navigation/content; server-cli.mdx (5) with
the CLI reference; and faq.mdx (102-108, 125-165, 195-200, 439-449) with the
troubleshooting commands and examples.

In `@fern/docs/pages/faq.mdx`:
- Around line 222-225: Resolve the conflicting capacity statements in the cuOpt
resource-estimates FAQ by aligning the 15K-location claim with the later H100
SXM 10,000-location maximum. Clarify the workload or hardware assumptions for
each estimate, or replace the figures with one consistent, explicitly qualified
capacity statement.

In `@fern/docs/pages/system-requirements.mdx`:
- Around line 62-68: Update the CUDA 12.9 entry in the “CUDA & NVIDIA Driver
combinations” list to require Linux driver 575.51.03 or newer instead of
570.42.01, leaving the other version requirements unchanged.

In `@fern/docs/scripts/install-selector.css`:
- Around line 6-8: Update the copy-button color variables around
--cuopt-nvidia-green and its hover/active variants so the button background
provides sufficient contrast with its white text, meeting at least WCAG 4.5:1
for normal text across all interactive states.

In `@fern/docs/scripts/install-selector.js`:
- Around line 201-206: Update the fallback logic around `cudaKey`,
`fallbackKey`, and `data[release]` so selecting CUDA 12 with the `ubi10` variant
never resolves to `cu13-ubi10`. Treat that combination as unsupported or require
an explicit CUDA 13 selection, while preserving valid image resolution for other
CUDA and variant combinations.

In `@fern/embed_examples.py`:
- Around line 90-103: Update the existing embed-marker handling around _OPEN_RE
and _CLOSE so it detects when the closing marker is not found before EOF, raises
an error, and aborts before modifying or writing the MDX output; only skip and
replace the block when _CLOSE is present.

In `@fern/extract_python_api.py`:
- Around line 438-441: Update the content transformation after joining lines so
the <= replacement applies only outside fenced code blocks. Preserve operators
inside fenced regions unchanged while continuing to escape them in prose/MDX
text, then write the selectively transformed content through the existing
dest.write_text call.

In `@fern/generate_api_docs.py`:
- Around line 88-90: Make documentation generation fail closed: in
fern/generate_api_docs.py around the OpenAPI/version generation exception
handler, re-raise the failure after reporting it; in fern/extract_c_api.py
around the Doxygen XML parsing handler, propagate any file parse error instead
of continuing; and in fern/extract_python_api.py around module parsing, fail on
unparsable modules rather than treating them as empty.

In `@fern/openapi/cuopt_spec.yaml`:
- Around line 3797-3801: Update every response schema property referencing
DroppedTasks, including dropped_tasks, to use an object default ({}) or remove
the default instead of [] while preserving the DroppedTasks schema type. Correct
the third vehicle_breaks example by adding the required locations field, unless
the schema is intentionally changed to make locations optional.

---

Minor comments:
In `@fern/c_api_config.yaml`:
- Around line 27-30: Update the “Status Codes” intro in c_api_config.yaml to
qualify that status codes apply only to fallible or status-returning C API
functions, excluding generated destroy functions with no return value.
- Line 8: Update both MIP C API link references in the relevant documentation to
use the sibling-directory target ../mip/mip-c-api instead of mip-c-api, then
regenerate the affected page.

In `@fern/docs-v26-08.yml`:
- Around line 1-200: Update the release-version configuration associated with
docs-v26-08 so the documentation site continues to use 26.06 as the Latest
version until launch. Do not promote 26.08 in the Latest pointer; preserve the
existing 26.08 documentation navigation content.

In `@fern/docs/pages/convex-features.mdx`:
- Line 69: Update the links in the convex features documentation: replace the
broken Python and C anchors with the specified cuOpt page paths and anchors, and
update the self-hosted references near the “simple-qp” examples to target the
cuOpt server LP examples page and its generic normal/batch mode anchor.

In `@fern/docs/pages/convex-settings.mdx`:
- Around line 144-146: Update the “Save Best Primal So Far” section for
CUOPT_SAVE_BEST_PRIMAL_SOLUTION by adding a paragraph before the four conditions
and converting the escaped asterisks into Markdown bullet items. Preserve the
existing condition text and ensure Fern renders four separate list entries.
- Around line 172-178: The precision documentation has contradictory default
values: the `default` mode is defined as `-1`, but the Note says the default is
`0` (`single`). Update the Note to state `-1` and consistently identify it as
the default precision mode.

In `@fern/docs/pages/cuopt-c/convex/convex-c-api.mdx`:
- Around line 809-819: Update the source comments for cuOptGetErrorStatus,
cuOptGetErrorString, and cuOptGetPrimalSolution so their generated API
documentation includes behavior descriptions, parameter documentation, and
return-value documentation; keep the existing signatures unchanged.

In `@fern/docs/pages/cuopt-c/convex/convex-examples.mdx`:
- Line 1119: Update the Convex Features links in the affected documentation
entries to use the correct relative target ../../convex-features from this
directory, including both occurrences, while preserving the surrounding text.

In `@fern/docs/pages/cuopt-c/convex/examples/general_quadratic_example.c`:
- Around line 167-170: In general_quadratic_example.c at lines 167-170, set
main()’s status to a non-success value before jumping to DONE when
solution_values allocation fails. In lp_file_example.c at lines 139-140 and
mps_file_example.c at lines 148-149, check solution_values for NULL before
calling cuOptGetPrimalSolution and set the failure status before cleanup,
preserving the existing success path for valid allocations.

In `@fern/docs/pages/cuopt-c/convex/examples/Makefile`:
- Around line 59-69: Update the Makefile’s pattern rule for executable targets
so every compilation target also depends on the check-paths validation target,
ensuring direct builds and parallel builds wait for check-paths before invoking
the compiler. Preserve the existing build commands and all target behavior.
- Around line 37-39: Update the commented INCLUDE_PATH and LIBCUOPT_LIBRARY_PATH
examples in the Makefile to use repository-relative paths that correctly reach
the root-level cpp directory from this examples directory, while preserving the
existing local-build guidance.

In `@fern/docs/pages/cuopt-c/convex/examples/simple_lp_example.c`:
- Around line 190-193: Set status to CUOPT_OUT_OF_MEMORY before each
solution-buffer allocation failure jumps to DONE, preserving the error status
for main: fern/docs/pages/cuopt-c/convex/examples/simple_lp_example.c:190-193,
simple_qp_example.c:183-186, and simple_socp_example.c:167-170. Apply the same
fix to the rotated-SOCP and general-quadratic embedded sources at
fern/docs/pages/cuopt-c/convex/convex-examples.mdx:1285-1288 and 1498-1501, and
the simple-MILP source at fern/docs/pages/cuopt-c/mip/mip-examples.mdx:190-193,
then regenerate the embedded examples.

In `@fern/docs/pages/cuopt-cli/quick-start.mdx`:
- Around line 11-15: Restore the missing CLI workflow snippets: in
fern/docs/pages/cuopt-cli/quick-start.mdx:11-15, add the cuopt_cli --help
command beneath the introduction; in
fern/docs/pages/cuopt-cli/cli-examples.mdx:16-34, add the commands and
representative output blocks for the documented examples, or remove claims that
output follows if no output is shown.

In `@fern/docs/pages/cuopt-python/convex/convex-examples.mdx`:
- Line 84: Remove or populate the empty generated-output placeholders: in
fern/docs/pages/cuopt-python/convex/convex-examples.mdx at lines 84-84, populate
or remove every repeated “response is as follows” section; in
fern/docs/pages/cuopt-python/mip/mip-examples.mdx at lines 84-84, populate or
remove all three empty response sections; and in
fern/docs/pages/cuopt-python/routing/routing-examples.mdx at lines 308-308, add
the promised batch sample output or remove its heading.
- Line 285: Update the “Convex Features” link in the rotated second-order cone
example to target the root feature page at the correct relative path, rather
than resolving under cuopt-python/convex. Keep the link text and surrounding
explanation unchanged.

In `@fern/docs/pages/cuopt-python/convex/examples/pdlp_warmstart_example.py`:
- Around line 54-55: Update the public main() entrypoint with a -> None return
annotation and expand its docstring to describe its behavior, including that it
returns None and which relevant errors may propagate. Keep the documentation
aligned with the function’s actual parameters and execution flow.

In `@fern/docs/pages/cuopt-python/convex/examples/qp_matrix_example.py`:
- Line 30: Annotate the public main entry points with explicit None return
types: update main in
fern/docs/pages/cuopt-python/convex/examples/qp_matrix_example.py at lines 30-30
and main in fern/docs/pages/cuopt-python/convex/examples/simple_socp_example.py
at lines 30-30 to include -> None.

In `@fern/docs/pages/cuopt-python/convex/examples/simple_lp_example.py`:
- Around line 32-33: Update the simple LP example’s main function to annotate a
None return type and expand its docstring to explicitly document that it returns
None.

In `@fern/docs/pages/cuopt-python/mip/examples/incumbent_solutions_example.py`:
- Around line 46-62: Update IncumbentCallback.__init__ and get_solution with
type annotations matching the GetSolutionCallback contract, including the
callback inputs and None return type. Expand the IncumbentCallback class
docstring to document the constructor arguments and state that get_solution
returns None.

In `@fern/docs/pages/cuopt-python/mip/mip-api.mdx`:
- Line 5: Update the MIP API page to reference the shared linear-programming API
documentation instead of rendering the empty API placeholder. Configure the page
to use the existing linear-programming reference and preserve the intended MIP
API symbols if they are defined there.

In `@fern/docs/pages/cuopt-server/csp-guides/csp-aws.mdx`:
- Around line 41-43: Update the self-hosted quickstart links in
fern/docs/pages/cuopt-server/csp-guides/csp-aws.mdx (lines 41-43) and
fern/docs/pages/cuopt-server/csp-guides/csp-azure.mdx (lines 47-49) to target
the “Container from NVIDIA NGC” heading in
fern/docs/pages/cuopt-server/quick-start.mdx, replacing the fragment-only
anchors with the correct page-relative link.

In `@fern/docs/pages/cuopt-server/examples/lp-examples.mdx`:
- Line 15: Correct the heading text in the LP examples documentation from
“Genric” to “Generic,” leaving the rest of the heading unchanged.

In `@fern/docs/pages/cuopt-server/nim-operator/index.mdx`:
- Line 30: Fix the broken documentation links across all listed sites: in
fern/docs/pages/cuopt-server/nim-operator/index.mdx lines 30-30, link to
prerequisites; in deployment.mdx lines 104-106, link to configuration; in
prerequisites.mdx lines 96-98, link to deployment; in
examples/routing-examples.mdx lines 53-75, link to the actual aborting sections
or pages; and in faq.mdx lines 343-375, link to convex-features#batch-mode.

In `@fern/docs/pages/introduction.mdx`:
- Line 63: Correct the spelling of “perfomed” to “performed” in the PDLP
description while leaving the rest of the text unchanged.

In `@fern/docs/pages/license.mdx`:
- Around line 1-3: Update the license page front matter section so the page
includes the applicable cuOpt license terms or a link to the canonical license
material, rather than only displaying the “cuOpt License” title. Preserve the
existing page title and ensure the published content is accessible from this
page.

In `@fern/docs/pages/milp-features.mdx`:
- Around line 53-65: Update both the “Incumbent Example” and “Logging Callback
Example” links in the MILP features documentation to target
cuopt-server/examples/milp-examples#incumbent-and-logging-callback instead of
resolving against milp-features.mdx.

In `@fern/docs/pages/routing-features.mdx`:
- Around line 34-37: Update the time-window note near the “All time windows”
statement to make the UTC January 1970–2038 conversion conditional on values
being Unix seconds. Clarify that for minutes or other caller-selected units, the
int32 range remains [0, 2^31-1] in that chosen unit.

In `@fern/openapi/cuopt_spec.yaml`:
- Around line 2037-2043: Update the third vehicle_breaks example entry in both
example blocks to include the required locations field, using null or a valid
list consistent with the surrounding example data.

In `@README.md`:
- Around line 56-82: Update the Fern documentation instructions to accurately
describe ./build.sh docs: API documentation generation, fern check, and fern
generate --docs or --preview, without claiming it starts a localhost:3000
server. Replace the CI workflow reference with ci/build_docs.sh, and align the
surrounding CI/publishing description with the implemented pipeline.

---

Nitpick comments:
In `@fern/docs/pages/cuopt-c/convex/examples/simple_qp_example.c`:
- Around line 118-134: Update the simple QP example to use the non-deprecated
cuOptCreateProblem flow, then apply the quadratic objective through
cuOptSetQuadraticObjective instead of calling cuOptCreateQuadraticProblem.
Regenerate the embedded MDX so the documented example matches the updated source
and stated API usage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

Comment thread ci/build_docs.sh
Comment on lines +40 to +52
rapids-logger "Generate dynamic API docs (OpenAPI spec, Python API, C API)"
python fern/generate_api_docs.py

rapids-logger "Validate docs (fern check)"
fern check

if [[ "${RAPIDS_BUILD_TYPE:-branch}" == "pull-request" ]]; then
rapids-logger "Publishing Fern preview for PR review"
fern generate --docs --preview
else
rapids-logger "Publishing Fern docs to production"
fern generate --docs
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🔴 Critical | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## File map"
git ls-files 'ci/build_docs.sh' 'ci/*' 'pr.yaml' 'build.yaml' | sed 's#^`#-` #'

echo
echo "## Outline of relevant files"
for f in ci/build_docs.sh pr.yaml build.yaml; do
  if [[ -f "$f" ]]; then
    echo "### $f"
    wc -l "$f"
    sed -n '1,220p' "$f" | cat -n
    echo
  fi
done

echo "## Search for Fern and related gating"
rg -n --hidden --no-ignore-vcs -S 'FERN_TOKEN|fern generate|fern check|workflow_run|pull-request|branch|build_docs\.sh|generate_api_docs\.py' ci pr.yaml build.yaml .github 2>/dev/null || true

Repository: NVIDIA/cuopt

Length of output: 24037


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "## Relevant workflow files"
fd -a -t f 'build.yaml|pr.yaml|build_docs.sh' . ci .github 2>/dev/null || true

echo
echo "## Search for CI invocations and secrets"
rg -n -S 'build_docs\.sh|FERN_TOKEN|fern generate|fern check|workflow_run|pull_request|pull-request|secrets\.' ci .github pr.yaml build.yaml 2>/dev/null || true

Repository: NVIDIA/cuopt

Length of output: 12462


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in ci/build_docs.sh pr.yaml build.yaml; do
  if [[ -f "$f" ]]; then
    echo "### $f"
    nl -ba "$f" | sed -n '1,220p'
    echo
  fi
done

Repository: NVIDIA/cuopt

Length of output: 211


🌐 Web query:

RAPIDS ci pr.yaml build.yaml RAPIDS_BUILD_TYPE Fern docs build_docs.sh

💡 Result:

In the RAPIDS ecosystem, pr.yaml and build.yaml serve as the primary GitHub Actions workflow entry points, managing CI jobs for pull requests and main/release branches respectively [1]. These workflows orchestrate build processes by invoking various CI scripts, such as those located in the ci/ directory, and by utilizing standardized shared workflows [2][3][4][5]. Key components related to your query include: RAPIDS_BUILD_TYPE: This environment variable is used to specify the context of a build, typically taking values such as branch, nightly, or pull-request [3][6]. It is passed into CI jobs to configure build parameters, artifact handling, and other environment-specific logic [2][3]. Fern and Documentation Builds: RAPIDS has been migrating its documentation infrastructure from Sphinx to Fern [7][8]. This transition involves the following key components: fern/build_docs.sh: A wrapper script introduced to handle Fern-based documentation workflows, supporting modes such as check, preview, publish, and dev [7][8]. It manages the generation of API references and runs validation checks (e.g., fern check) [7][9]. ci/build_docs.sh: While previously used to run Sphinx-based documentation builds [5][10], this script has been updated in many repositories to integrate with or be replaced by the Fern-based documentation flow, ensuring documentation is correctly built and validated during CI [7][8]. build.sh: A local build script often updated to set relevant environment variables (like FERN_DOCS_DIR) and invoke fern/build_docs.sh [7][8][11]. These components together enable a standardized, reproducible CI process where documentation validation and builds are integrated alongside code builds and testing [7][8][12].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in .github/workflows/build.yaml .github/workflows/pr.yaml; do
  echo "### $f"
  sed -n '200,260p' "$f" | cat -n
  echo
done

echo "### build.yaml docs-related context"
sed -n '210,245p' .github/workflows/build.yaml | cat -n

echo "### pr.yaml docs-related context"
sed -n '425,450p' .github/workflows/pr.yaml | cat -n

Repository: NVIDIA/cuopt

Length of output: 8248


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "### build.yaml trigger + top-level permissions"
sed -n '1,120p' .github/workflows/build.yaml | cat -n
echo

echo "### pr.yaml trigger + top-level permissions"
sed -n '1,120p' .github/workflows/pr.yaml | cat -n

Repository: NVIDIA/cuopt

Length of output: 10198


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "### build.yaml docs job"
sed -n '215,235p' .github/workflows/build.yaml | cat -n
echo

echo "### pr.yaml docs job"
sed -n '432,446p' .github/workflows/pr.yaml | cat -n

Repository: NVIDIA/cuopt

Length of output: 1686


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -S 'FERN_TOKEN|fern-api|fern config|fern/fern.config.json|preview|publish.*Fern|Fern preview|Fern docs' .github/workflows ci . 2>/dev/null || true

Repository: NVIDIA/cuopt

Length of output: 3145


🏁 Script executed:

#!/bin/bash
set -euo pipefail

for f in .github/workflows/build.yaml .github/workflows/pr.yaml; do
  echo "### $f"
  awk 'NR>=210 && NR<=245 {printf "%4d  %s\n", NR, $0}' "$f"
  echo
done

Repository: NVIDIA/cuopt

Length of output: 3249


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "### build.yaml: trigger + permissions"
awk 'NR>=1 && NR<=80 {printf "%4d  %s\n", NR, $0}' .github/workflows/build.yaml
echo

echo "### pr.yaml: trigger + permissions"
awk 'NR>=1 && NR<=90 {printf "%4d  %s\n", NR, $0}' .github/workflows/pr.yaml

Repository: NVIDIA/cuopt

Length of output: 7067


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "### workflow_run / Fern docs references"
rg -n -S 'workflow_run|FERN_TOKEN|Fern preview|publish.*Fern|buildwithfern|preview' .github/workflows README.md build.sh ci/build_docs.sh fern 2>/dev/null || true

echo
echo "### README docs section"
awk 'NR>=24 && NR<=90 {printf "%4d  %s\n", NR, $0}' README.md

Repository: NVIDIA/cuopt

Length of output: 5200


Separate Fern generation from secret-bearing publish jobs. .github/workflows/build.yaml and .github/workflows/pr.yaml call ci/build_docs.sh with secrets: inherit, so fern/generate_api_docs.py runs with repository secrets available. Keep generation secretless and run fern generate --docs --preview from a trusted workflow_run/base-branch job; gate production publishing on an explicit trusted branch/event too.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ci/build_docs.sh` around lines 40 - 52, Update ci/build_docs.sh so
fern/generate_api_docs.py and fern check run without repository secrets, and
remove Fern publishing from this secret-bearing script. Move fern generate
--docs --preview into a trusted workflow_run or base-branch job, and ensure
production fern generate --docs is gated by an explicit trusted branch or event.

Sources: Coding guidelines, Path instructions

@ramakrishnap-nv

Copy link
Copy Markdown
Collaborator Author

Superseded by #1582 which implements the custom AST-based generator approach instead of the Fern native libraries: approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

improvement Improves an existing functionality non-breaking Introduces a non-breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant