docs(fern): custom Python/C API doc generator#1582
Conversation
- 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 → `<=` (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>
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>
…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>
Move all Fern docs build steps (Node check, Fern CLI install, API doc generation, fern check, publish/preview) out of build.sh into a dedicated fern/build_docs.sh. build.sh now delegates to that script with a single call. Also removes fern/requirements-docs.txt since the conda environment is always activated before building, making the pip fallback unnecessary. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
MDX skeleton files (convex-c-api.mdx, mip-c-api.mdx) are now the source of truth for page structure. Each symbol has a <!-- symbol: NAME --> marker in its chosen location; the script fills in Doxygen content between markers. If a symbol exists in the headers but has no marker in any skeleton, the build errors with a list of unplaced symbols. This forces developers to consciously place every new API symbol in the docs rather than silently accumulating it in an uncategorized section. Drops fern/c_api_config.yaml — structure now lives in the MDX files. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- extract_python_api.py: add .pyx regex parser, __all__-based filtering,
cross-file dedup, ordering via `order` list in PAGE_SOURCES, suppress
headings for *_wrapper.pyx (enums-only, no functions), PascalCase enum
member fix
- extract_c_api.py: migrate symbol markers from <!-- --> to {/* */} JSX
comment format; accept legacy HTML form during migration
- embed_examples.py: same marker migration to {/* */}; remove dead
`changed` variable assignments
- Add __all__ to 7 __init__.py files for clean public API surface
- Rewrite VType/CType/sense/SolutionStatus docstrings as NumPy Attributes
sections so member descriptions render correctly
- PAGE_SOURCES ordering matches existing RST docs (WaypointMatrix first,
then Vehicle Routing, Assignment, utils/enums inline)
- Exclude fern/openapi/cuopt_spec.yaml from verify-hardcoded-version hook
(file is auto-generated from VERSION)
- Remove leftover fern/static/python-api/ (abandoned libraries: approach)
and untracked .pyi stubs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Changes to ci/build_docs.sh should not trigger test_cpp, test_python_conda, or test_python_wheels. Replace the old !docs/** exclusion (Sphinx tree, now deleted) with !fern/** in test_cpp and test_python_conda so Fern-only changes don't trigger those test suites. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
Three issues found during deletion audit: 1. Example files for server, CLI, and gRPC were deleted with the Sphinx tree but not ported to the fern tree. The MDX pages link to them and ci/test_doc_examples.sh discovers them by path. Restored 23 files from git history at e75dfff^ into fern/docs/pages/{cuopt-server,cuopt-cli, cuopt-grpc}/examples/. Also updated stale 2025 copyright headers to 2025-2026 (auto-fixed by verify-copyright hook). 2. The 'docs' file-key block was removed from dependencies.yaml, breaking ci/build_docs.sh which calls rapids-dependency-file-generator --file-key docs. Restored with the Fern-appropriate includes (cuda_version, depends_on_libcuopt, depends_on_cuopt, docs, py_version). 3. pydocstyle was checking fern/ example scripts (previously covered by the docs/ exclusion). Added fern/ to the pydocstyle exclude list in .pre-commit-config.yaml. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
…endent The Fern docs extractors work without cuopt installed: - extract_python_api.py reads .py/.pyx source via AST (no imports) - extract_c_api.py reads Doxygen XML (no imports) - OpenAPI spec is committed to fern/openapi/cuopt_spec.yaml; cuopt_server import in generate_api_docs.py is try/except-guarded Changes: - ci/build_docs.sh: remove rapids-download-from-github calls for conda_cpp and conda_python artifacts; remove --prepend-channel flags - dependencies.yaml: simplify files.docs to only include docs + py_version (no depends_on_libcuopt, depends_on_cuopt, depends_on_cuopt_server) - pr.yaml: docs-build needs [changed-files] only (not conda-python-build); remove build_docs condition from conda-cpp-build and conda-python-build - build.yaml: docs-build has no needs (runs independently of python-build) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
generate_api_docs.py imports cuopt_server (via sys.path) to regenerate fern/openapi/cuopt_spec.yaml. cuopt_server depends on cuopt -> libcuopt, so the docs build needs the conda artifacts from conda-cpp-build and conda-python-build. Restores: - ci/build_docs.sh: artifact download for conda_cpp and conda_python channels - dependencies.yaml: depends_on_libcuopt + depends_on_cuopt in files.docs - pr.yaml: build_docs condition on conda-cpp-build and conda-python-build; docs-build needs [conda-python-build, changed-files] - build.yaml: docs-build needs [python-build] Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (8)
fern/docs/pages/cuopt-server/examples/milp/examples/abort_job_example.py (1)
24-25: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winAdd required annotations and contract documentation to all new public Python functions.
fern/docs/pages/cuopt-server/examples/milp/examples/abort_job_example.py#L24-L25: annotatemain() -> Noneand document its behavior/errors.fern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.py#L46-L69: annotaterepollandmain, documenting parameters, returns, and errors.fern/docs/pages/cuopt-server/examples/milp/examples/incumbent_callback_example.py#L35-L36: annotatemain() -> Noneand document its behavior/errors.fern/docs/pages/cuopt-server/examples/routing/examples/basic_routing_example.py#L46-L69: annotaterepollandmain, documenting parameters, returns, and errors.fern/docs/pages/cuopt-server/examples/routing/examples/initial_solution_example.py#L30-L31: annotatemain() -> Noneand document its behavior/errors.As per coding guidelines, new public Python functions require type hints and meaningful parameter, return, and raise documentation.
🤖 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/milp/examples/abort_job_example.py` around lines 24 - 25, Update main in fern/docs/pages/cuopt-server/examples/milp/examples/abort_job_example.py (lines 24-25) and incumbent_callback_example.py (lines 35-36), plus initial_solution_example.py (lines 30-31), with explicit -> None annotations and docstrings describing behavior and raised errors. Update repoll and main in basic_milp_example.py (lines 46-69) and basic_routing_example.py (lines 46-69) with complete type annotations and meaningful documentation for parameters, return values, and raised errors.Source: Coding guidelines
fern/docs/pages/cuopt-server/examples/routing/examples/initial_solution_example.py (1)
43-72: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winDelete saved solutions in a
finallyblock.Because the initial solutions are retained server-side, any exception during upload, solving, printing, or later processing skips lines 70–71 and leaks saved solutions. Track successfully created IDs and clean them up in
finally.🤖 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/initial_solution_example.py` around lines 43 - 72, Wrap the initial-solution upload, reuse solve, and subsequent processing in a try/finally block, tracking each successfully created request ID as it becomes available. Move cleanup into finally and delete only the IDs that were successfully created, including handling partial failures during upload or solving.fern/docs/pages/cuopt-server/examples/routing/examples/initial_solution_example.sh (1)
30-50: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winValidate
reqIdbefore reusing or deleting it.If the solve fails or the response lacks an ID,
jqcan produce an empty value ornull; the script then sends invalid follow-up requests and reports success. Addset -euo pipefailand reject empty/nullIDs before line 40.🤖 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/initial_solution_example.sh` around lines 30 - 50, Harden the script around the reqId extraction by enabling set -euo pipefail near the start, then validate reqId before the Step 2 reuse and Step 3 deletion commands. Reject both empty and null values so follow-up cuopt_sh calls do not run or report success without a valid identifier.fern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.py (1)
53-60: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winUse the response key as the polling completion signal.
Both polling helpers require
reqIdandresponse, but the documented completed responses contain onlyresponse.
fern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.py#L53-L60: break when"response"is present.fern/docs/pages/cuopt-server/examples/routing/examples/basic_routing_example.py#L54-L61: break when"response"is present.🤖 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/milp/examples/basic_milp_example.py` around lines 53 - 60, The polling completion checks in the MILP example’s repoll loop and the routing example’s corresponding repoll loop currently require both “reqId” and “response”; update both sites—fern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.py lines 53-60 and fern/docs/pages/cuopt-server/examples/routing/examples/basic_routing_example.py lines 54-61—to break whenever the repolled solution contains “response”, while preserving the existing polling flow.fern/docs/pages/cuopt-server/examples/milp/examples/abort_job_example.sh (1)
28-34: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winDo not report success when aborting fails.
A failed
cuopt_shcommand is followed by the success message and a zero exit status. Addset -euo pipefailor check the command status before printing confirmation.Based on learnings, this repository prefers
set -uin Bash scripts.🤖 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/milp/examples/abort_job_example.sh` around lines 28 - 34, Update the abort-job script to enable Bash unset-variable protection with set -u and ensure the success message is printed only when cuopt_sh completes successfully, preserving the command’s failure status instead of reporting a false success.Source: Learnings
fern/docs/pages/cuopt-server/examples/routing/examples/basic_routing_example.sh (1)
28-34: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winPropagate routing-command failures.
When
cuopt_shfails, cleanup succeeds and the script exits 0. Addset -euo pipefailbefore invoking the CLI.Based on learnings, this repository prefers
set -uin Bash scripts.🤖 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/basic_routing_example.sh` around lines 28 - 34, Add strict Bash error handling before the cuopt_sh invocation in the routing example, using the repository-preferred set -u while also ensuring command and pipeline failures propagate so cleanup cannot mask a failed routing command. Keep the existing cuopt_sh and cleanup behavior unchanged.Source: Learnings
fern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.sh (1)
50-59: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winFail the example when
cuopt_shfails.If the server request fails,
rm -f data.jsonbecomes the successful final command and hides the failure. Addset -euo pipefailbefore invoking the CLI.Based on learnings, this repository prefers
set -uin Bash scripts.🤖 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/milp/examples/basic_milp_example.sh` around lines 50 - 59, Add `set -u` before the `cuopt_sh` invocation in the example script so unset variables fail early, and ensure the CLI failure remains the script’s exit status rather than being masked by cleanup. Preserve the existing `cuopt_sh` command and cleanup behavior.Source: Learnings
fern/docs/pages/cuopt-cli/examples/milp/examples/basic_milp_example.sh (1)
43-47: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winPropagate
cuopt_clifailures.If the solver is unavailable or returns an error, the script continues to
rm -fand exits successfully. Addset -euo pipefailnear the top, or explicitly check the solver status before cleanup.Based on learnings, this repository prefers
set -uin Bash scripts.🤖 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/examples/milp/examples/basic_milp_example.sh` around lines 43 - 47, Add `set -u` near the top of basic_milp_example.sh and explicitly check the cuopt_cli invocation’s exit status so solver failures propagate as a nonzero script exit while still allowing cleanup to run as intended.Source: Learnings
🤖 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 `@fern/docs/pages/cuopt-grpc/examples/remote_lp_demo.py`:
- Around line 24-25: The objective coefficient for VAR1 is positive in both LP
examples; update the coefficient array in
fern/docs/pages/cuopt-grpc/examples/remote_lp_demo.py lines 24-25 and the JSON
coefficients in
fern/docs/pages/cuopt-server/examples/lp/examples/basic_lp_example.sh lines
32-35 to use -0.2 while preserving VAR2's 0.1 value.
In `@fern/docs/pages/cuopt-server/examples/lp/examples/warmstart_example.py`:
- Around line 14-16: Align the warm-start documentation with the solver_config
value used in the example: update the docstring near the warm-start instructions
to describe the same `presolve` representation configured in the example’s
solver_config. Keep the code behavior unchanged unless the documented form is
the intended API value.
In `@fern/docs/pages/cuopt-server/examples/lp/examples/warmstart_example.sh`:
- Line 44: Update the maximize field in the warmstart example payload to use the
JSON boolean false instead of the string "False", matching the solver payload
contract and other MILP examples.
---
Outside diff comments:
In `@fern/docs/pages/cuopt-cli/examples/milp/examples/basic_milp_example.sh`:
- Around line 43-47: Add `set -u` near the top of basic_milp_example.sh and
explicitly check the cuopt_cli invocation’s exit status so solver failures
propagate as a nonzero script exit while still allowing cleanup to run as
intended.
In `@fern/docs/pages/cuopt-server/examples/milp/examples/abort_job_example.py`:
- Around line 24-25: Update main in
fern/docs/pages/cuopt-server/examples/milp/examples/abort_job_example.py (lines
24-25) and incumbent_callback_example.py (lines 35-36), plus
initial_solution_example.py (lines 30-31), with explicit -> None annotations and
docstrings describing behavior and raised errors. Update repoll and main in
basic_milp_example.py (lines 46-69) and basic_routing_example.py (lines 46-69)
with complete type annotations and meaningful documentation for parameters,
return values, and raised errors.
In `@fern/docs/pages/cuopt-server/examples/milp/examples/abort_job_example.sh`:
- Around line 28-34: Update the abort-job script to enable Bash unset-variable
protection with set -u and ensure the success message is printed only when
cuopt_sh completes successfully, preserving the command’s failure status instead
of reporting a false success.
In `@fern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.py`:
- Around line 53-60: The polling completion checks in the MILP example’s repoll
loop and the routing example’s corresponding repoll loop currently require both
“reqId” and “response”; update both
sites—fern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.py
lines 53-60 and
fern/docs/pages/cuopt-server/examples/routing/examples/basic_routing_example.py
lines 54-61—to break whenever the repolled solution contains “response”, while
preserving the existing polling flow.
In `@fern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.sh`:
- Around line 50-59: Add `set -u` before the `cuopt_sh` invocation in the
example script so unset variables fail early, and ensure the CLI failure remains
the script’s exit status rather than being masked by cleanup. Preserve the
existing `cuopt_sh` command and cleanup behavior.
In
`@fern/docs/pages/cuopt-server/examples/routing/examples/basic_routing_example.sh`:
- Around line 28-34: Add strict Bash error handling before the cuopt_sh
invocation in the routing example, using the repository-preferred set -u while
also ensuring command and pipeline failures propagate so cleanup cannot mask a
failed routing command. Keep the existing cuopt_sh and cleanup behavior
unchanged.
In
`@fern/docs/pages/cuopt-server/examples/routing/examples/initial_solution_example.py`:
- Around line 43-72: Wrap the initial-solution upload, reuse solve, and
subsequent processing in a try/finally block, tracking each successfully created
request ID as it becomes available. Move cleanup into finally and delete only
the IDs that were successfully created, including handling partial failures
during upload or solving.
In
`@fern/docs/pages/cuopt-server/examples/routing/examples/initial_solution_example.sh`:
- Around line 30-50: Harden the script around the reqId extraction by enabling
set -euo pipefail near the start, then validate reqId before the Step 2 reuse
and Step 3 deletion commands. Reject both empty and null values so follow-up
cuopt_sh calls do not run or report success without a valid identifier.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 4a1e1444-2bf5-474f-8987-baea2b6e8065
⛔ Files ignored due to path filters (2)
fern/docs/pages/cuopt-grpc/examples/remote_lp_demo.mpsis excluded by!**/*.mpsfern/docs/pages/cuopt-server/examples/lp/examples/sample.mpsis excluded by!**/*.mps
📒 Files selected for processing (23)
.pre-commit-config.yamldependencies.yamlfern/docs/pages/cuopt-cli/examples/lp/examples/basic_lp_example.shfern/docs/pages/cuopt-cli/examples/lp/examples/solver_parameters_example.shfern/docs/pages/cuopt-cli/examples/milp/examples/basic_milp_example.shfern/docs/pages/cuopt-grpc/examples/remote_lp_demo.pyfern/docs/pages/cuopt-server/examples/lp/examples/basic_lp_example.pyfern/docs/pages/cuopt-server/examples/lp/examples/basic_lp_example.shfern/docs/pages/cuopt-server/examples/lp/examples/batch_mode_example.shfern/docs/pages/cuopt-server/examples/lp/examples/lp_datamodel_example.pyfern/docs/pages/cuopt-server/examples/lp/examples/mps_datamodel_example.pyfern/docs/pages/cuopt-server/examples/lp/examples/mps_file_example.pyfern/docs/pages/cuopt-server/examples/lp/examples/warmstart_example.pyfern/docs/pages/cuopt-server/examples/lp/examples/warmstart_example.shfern/docs/pages/cuopt-server/examples/milp/examples/abort_job_example.pyfern/docs/pages/cuopt-server/examples/milp/examples/abort_job_example.shfern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.pyfern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.shfern/docs/pages/cuopt-server/examples/milp/examples/incumbent_callback_example.pyfern/docs/pages/cuopt-server/examples/routing/examples/basic_routing_example.pyfern/docs/pages/cuopt-server/examples/routing/examples/basic_routing_example.shfern/docs/pages/cuopt-server/examples/routing/examples/initial_solution_example.pyfern/docs/pages/cuopt-server/examples/routing/examples/initial_solution_example.sh
🚧 Files skipped from review as they are similar to previous changes (1)
- .pre-commit-config.yaml
There was a problem hiding this comment.
Caution
Inline review comments failed to post. This is likely due to GitHub's internal server error or limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (8)
fern/docs/pages/cuopt-server/examples/milp/examples/abort_job_example.py (1)
24-25: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick winAdd required annotations and contract documentation to all new public Python functions.
fern/docs/pages/cuopt-server/examples/milp/examples/abort_job_example.py#L24-L25: annotatemain() -> Noneand document its behavior/errors.fern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.py#L46-L69: annotaterepollandmain, documenting parameters, returns, and errors.fern/docs/pages/cuopt-server/examples/milp/examples/incumbent_callback_example.py#L35-L36: annotatemain() -> Noneand document its behavior/errors.fern/docs/pages/cuopt-server/examples/routing/examples/basic_routing_example.py#L46-L69: annotaterepollandmain, documenting parameters, returns, and errors.fern/docs/pages/cuopt-server/examples/routing/examples/initial_solution_example.py#L30-L31: annotatemain() -> Noneand document its behavior/errors.As per coding guidelines, new public Python functions require type hints and meaningful parameter, return, and raise documentation.
🤖 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/milp/examples/abort_job_example.py` around lines 24 - 25, Update main in fern/docs/pages/cuopt-server/examples/milp/examples/abort_job_example.py (lines 24-25) and incumbent_callback_example.py (lines 35-36), plus initial_solution_example.py (lines 30-31), with explicit -> None annotations and docstrings describing behavior and raised errors. Update repoll and main in basic_milp_example.py (lines 46-69) and basic_routing_example.py (lines 46-69) with complete type annotations and meaningful documentation for parameters, return values, and raised errors.Source: Coding guidelines
fern/docs/pages/cuopt-server/examples/routing/examples/initial_solution_example.py (1)
43-72: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winDelete saved solutions in a
finallyblock.Because the initial solutions are retained server-side, any exception during upload, solving, printing, or later processing skips lines 70–71 and leaks saved solutions. Track successfully created IDs and clean them up in
finally.🤖 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/initial_solution_example.py` around lines 43 - 72, Wrap the initial-solution upload, reuse solve, and subsequent processing in a try/finally block, tracking each successfully created request ID as it becomes available. Move cleanup into finally and delete only the IDs that were successfully created, including handling partial failures during upload or solving.fern/docs/pages/cuopt-server/examples/routing/examples/initial_solution_example.sh (1)
30-50: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winValidate
reqIdbefore reusing or deleting it.If the solve fails or the response lacks an ID,
jqcan produce an empty value ornull; the script then sends invalid follow-up requests and reports success. Addset -euo pipefailand reject empty/nullIDs before line 40.🤖 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/initial_solution_example.sh` around lines 30 - 50, Harden the script around the reqId extraction by enabling set -euo pipefail near the start, then validate reqId before the Step 2 reuse and Step 3 deletion commands. Reject both empty and null values so follow-up cuopt_sh calls do not run or report success without a valid identifier.fern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.py (1)
53-60: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winUse the response key as the polling completion signal.
Both polling helpers require
reqIdandresponse, but the documented completed responses contain onlyresponse.
fern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.py#L53-L60: break when"response"is present.fern/docs/pages/cuopt-server/examples/routing/examples/basic_routing_example.py#L54-L61: break when"response"is present.🤖 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/milp/examples/basic_milp_example.py` around lines 53 - 60, The polling completion checks in the MILP example’s repoll loop and the routing example’s corresponding repoll loop currently require both “reqId” and “response”; update both sites—fern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.py lines 53-60 and fern/docs/pages/cuopt-server/examples/routing/examples/basic_routing_example.py lines 54-61—to break whenever the repolled solution contains “response”, while preserving the existing polling flow.fern/docs/pages/cuopt-server/examples/milp/examples/abort_job_example.sh (1)
28-34: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winDo not report success when aborting fails.
A failed
cuopt_shcommand is followed by the success message and a zero exit status. Addset -euo pipefailor check the command status before printing confirmation.Based on learnings, this repository prefers
set -uin Bash scripts.🤖 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/milp/examples/abort_job_example.sh` around lines 28 - 34, Update the abort-job script to enable Bash unset-variable protection with set -u and ensure the success message is printed only when cuopt_sh completes successfully, preserving the command’s failure status instead of reporting a false success.Source: Learnings
fern/docs/pages/cuopt-server/examples/routing/examples/basic_routing_example.sh (1)
28-34: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winPropagate routing-command failures.
When
cuopt_shfails, cleanup succeeds and the script exits 0. Addset -euo pipefailbefore invoking the CLI.Based on learnings, this repository prefers
set -uin Bash scripts.🤖 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/basic_routing_example.sh` around lines 28 - 34, Add strict Bash error handling before the cuopt_sh invocation in the routing example, using the repository-preferred set -u while also ensuring command and pipeline failures propagate so cleanup cannot mask a failed routing command. Keep the existing cuopt_sh and cleanup behavior unchanged.Source: Learnings
fern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.sh (1)
50-59: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winFail the example when
cuopt_shfails.If the server request fails,
rm -f data.jsonbecomes the successful final command and hides the failure. Addset -euo pipefailbefore invoking the CLI.Based on learnings, this repository prefers
set -uin Bash scripts.🤖 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/milp/examples/basic_milp_example.sh` around lines 50 - 59, Add `set -u` before the `cuopt_sh` invocation in the example script so unset variables fail early, and ensure the CLI failure remains the script’s exit status rather than being masked by cleanup. Preserve the existing `cuopt_sh` command and cleanup behavior.Source: Learnings
fern/docs/pages/cuopt-cli/examples/milp/examples/basic_milp_example.sh (1)
43-47: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winPropagate
cuopt_clifailures.If the solver is unavailable or returns an error, the script continues to
rm -fand exits successfully. Addset -euo pipefailnear the top, or explicitly check the solver status before cleanup.Based on learnings, this repository prefers
set -uin Bash scripts.🤖 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/examples/milp/examples/basic_milp_example.sh` around lines 43 - 47, Add `set -u` near the top of basic_milp_example.sh and explicitly check the cuopt_cli invocation’s exit status so solver failures propagate as a nonzero script exit while still allowing cleanup to run as intended.Source: Learnings
🤖 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 `@fern/docs/pages/cuopt-grpc/examples/remote_lp_demo.py`:
- Around line 24-25: The objective coefficient for VAR1 is positive in both LP
examples; update the coefficient array in
fern/docs/pages/cuopt-grpc/examples/remote_lp_demo.py lines 24-25 and the JSON
coefficients in
fern/docs/pages/cuopt-server/examples/lp/examples/basic_lp_example.sh lines
32-35 to use -0.2 while preserving VAR2's 0.1 value.
In `@fern/docs/pages/cuopt-server/examples/lp/examples/warmstart_example.py`:
- Around line 14-16: Align the warm-start documentation with the solver_config
value used in the example: update the docstring near the warm-start instructions
to describe the same `presolve` representation configured in the example’s
solver_config. Keep the code behavior unchanged unless the documented form is
the intended API value.
In `@fern/docs/pages/cuopt-server/examples/lp/examples/warmstart_example.sh`:
- Line 44: Update the maximize field in the warmstart example payload to use the
JSON boolean false instead of the string "False", matching the solver payload
contract and other MILP examples.
---
Outside diff comments:
In `@fern/docs/pages/cuopt-cli/examples/milp/examples/basic_milp_example.sh`:
- Around line 43-47: Add `set -u` near the top of basic_milp_example.sh and
explicitly check the cuopt_cli invocation’s exit status so solver failures
propagate as a nonzero script exit while still allowing cleanup to run as
intended.
In `@fern/docs/pages/cuopt-server/examples/milp/examples/abort_job_example.py`:
- Around line 24-25: Update main in
fern/docs/pages/cuopt-server/examples/milp/examples/abort_job_example.py (lines
24-25) and incumbent_callback_example.py (lines 35-36), plus
initial_solution_example.py (lines 30-31), with explicit -> None annotations and
docstrings describing behavior and raised errors. Update repoll and main in
basic_milp_example.py (lines 46-69) and basic_routing_example.py (lines 46-69)
with complete type annotations and meaningful documentation for parameters,
return values, and raised errors.
In `@fern/docs/pages/cuopt-server/examples/milp/examples/abort_job_example.sh`:
- Around line 28-34: Update the abort-job script to enable Bash unset-variable
protection with set -u and ensure the success message is printed only when
cuopt_sh completes successfully, preserving the command’s failure status instead
of reporting a false success.
In `@fern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.py`:
- Around line 53-60: The polling completion checks in the MILP example’s repoll
loop and the routing example’s corresponding repoll loop currently require both
“reqId” and “response”; update both
sites—fern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.py
lines 53-60 and
fern/docs/pages/cuopt-server/examples/routing/examples/basic_routing_example.py
lines 54-61—to break whenever the repolled solution contains “response”, while
preserving the existing polling flow.
In `@fern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.sh`:
- Around line 50-59: Add `set -u` before the `cuopt_sh` invocation in the
example script so unset variables fail early, and ensure the CLI failure remains
the script’s exit status rather than being masked by cleanup. Preserve the
existing `cuopt_sh` command and cleanup behavior.
In
`@fern/docs/pages/cuopt-server/examples/routing/examples/basic_routing_example.sh`:
- Around line 28-34: Add strict Bash error handling before the cuopt_sh
invocation in the routing example, using the repository-preferred set -u while
also ensuring command and pipeline failures propagate so cleanup cannot mask a
failed routing command. Keep the existing cuopt_sh and cleanup behavior
unchanged.
In
`@fern/docs/pages/cuopt-server/examples/routing/examples/initial_solution_example.py`:
- Around line 43-72: Wrap the initial-solution upload, reuse solve, and
subsequent processing in a try/finally block, tracking each successfully created
request ID as it becomes available. Move cleanup into finally and delete only
the IDs that were successfully created, including handling partial failures
during upload or solving.
In
`@fern/docs/pages/cuopt-server/examples/routing/examples/initial_solution_example.sh`:
- Around line 30-50: Harden the script around the reqId extraction by enabling
set -euo pipefail near the start, then validate reqId before the Step 2 reuse
and Step 3 deletion commands. Reject both empty and null values so follow-up
cuopt_sh calls do not run or report success without a valid identifier.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: 4a1e1444-2bf5-474f-8987-baea2b6e8065
⛔ Files ignored due to path filters (2)
fern/docs/pages/cuopt-grpc/examples/remote_lp_demo.mpsis excluded by!**/*.mpsfern/docs/pages/cuopt-server/examples/lp/examples/sample.mpsis excluded by!**/*.mps
📒 Files selected for processing (23)
.pre-commit-config.yamldependencies.yamlfern/docs/pages/cuopt-cli/examples/lp/examples/basic_lp_example.shfern/docs/pages/cuopt-cli/examples/lp/examples/solver_parameters_example.shfern/docs/pages/cuopt-cli/examples/milp/examples/basic_milp_example.shfern/docs/pages/cuopt-grpc/examples/remote_lp_demo.pyfern/docs/pages/cuopt-server/examples/lp/examples/basic_lp_example.pyfern/docs/pages/cuopt-server/examples/lp/examples/basic_lp_example.shfern/docs/pages/cuopt-server/examples/lp/examples/batch_mode_example.shfern/docs/pages/cuopt-server/examples/lp/examples/lp_datamodel_example.pyfern/docs/pages/cuopt-server/examples/lp/examples/mps_datamodel_example.pyfern/docs/pages/cuopt-server/examples/lp/examples/mps_file_example.pyfern/docs/pages/cuopt-server/examples/lp/examples/warmstart_example.pyfern/docs/pages/cuopt-server/examples/lp/examples/warmstart_example.shfern/docs/pages/cuopt-server/examples/milp/examples/abort_job_example.pyfern/docs/pages/cuopt-server/examples/milp/examples/abort_job_example.shfern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.pyfern/docs/pages/cuopt-server/examples/milp/examples/basic_milp_example.shfern/docs/pages/cuopt-server/examples/milp/examples/incumbent_callback_example.pyfern/docs/pages/cuopt-server/examples/routing/examples/basic_routing_example.pyfern/docs/pages/cuopt-server/examples/routing/examples/basic_routing_example.shfern/docs/pages/cuopt-server/examples/routing/examples/initial_solution_example.pyfern/docs/pages/cuopt-server/examples/routing/examples/initial_solution_example.sh
🚧 Files skipped from review as they are similar to previous changes (1)
- .pre-commit-config.yaml
🛑 Comments failed to post (3)
fern/docs/pages/cuopt-grpc/examples/remote_lp_demo.py (1)
24-25: 🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win
Objective coefficient sign error for VAR1 across two example files. Both files describe the same LP problem (minimize
-0.2*VAR1 + 0.1*VAR2) but use positive0.2for VAR1's objective coefficient. All other examples in this PR (MPS files, LP files, Python server examples) correctly use-0.2. With the wrong sign, the solver minimizes0.2*x1 + 0.1*x2, yielding x=[0,0] and objective=0 instead of the expected-0.36.
fern/docs/pages/cuopt-grpc/examples/remote_lp_demo.py#L24-L25: changec = np.array([0.2, 0.1], dtype=np.float64)toc = np.array([-0.2, 0.1], dtype=np.float64).fern/docs/pages/cuopt-server/examples/lp/examples/basic_lp_example.sh#L32-L35: change"coefficients": [0.2, 0.1]to"coefficients": [-0.2, 0.1].📍 Affects 2 files
fern/docs/pages/cuopt-grpc/examples/remote_lp_demo.py#L24-L25(this comment)fern/docs/pages/cuopt-server/examples/lp/examples/basic_lp_example.sh#L32-L35🤖 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/examples/remote_lp_demo.py` around lines 24 - 25, The objective coefficient for VAR1 is positive in both LP examples; update the coefficient array in fern/docs/pages/cuopt-grpc/examples/remote_lp_demo.py lines 24-25 and the JSON coefficients in fern/docs/pages/cuopt-server/examples/lp/examples/basic_lp_example.sh lines 32-35 to use -0.2 while preserving VAR2's 0.1 value.fern/docs/pages/cuopt-server/examples/lp/examples/warmstart_example.py (1)
14-16: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Docstring and code disagree on
presolvevalue.The docstring (lines 14–16) instructs users to set
"presolve": "off", but the code (line 61) uses"presolve": 0. Users following the docstring may use the string form while the example uses the integer form. Align the docstring with the code (or vice-versa) to avoid confusion.🔧 Proposed fix — update docstring to match code
To use warm start with PDLP, presolve must be explicitly disabled. - Set "presolve": "off" in solver_config, as presolve transforms the problem + Set "presolve": 0 in solver_config, as presolve transforms the problem and the warm start solution from the original problem cannot be applied.Also applies to: 58-62
🤖 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/warmstart_example.py` around lines 14 - 16, Align the warm-start documentation with the solver_config value used in the example: update the docstring near the warm-start instructions to describe the same `presolve` representation configured in the example’s solver_config. Keep the code behavior unchanged unless the documented form is the intended API value.fern/docs/pages/cuopt-server/examples/lp/examples/warmstart_example.sh (1)
44-44: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Encode
maximizeas a JSON boolean.
"False"is a string, while the other MILP examples usefalse/True. Sendfalsehere to match the solver payload contract.Suggested fix
- "maximize": "False", + "maximize": false,📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements."maximize": false,🤖 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/warmstart_example.sh` at line 44, Update the maximize field in the warmstart example payload to use the JSON boolean false instead of the string "False", matching the solver payload contract and other MILP examples.
- Accept verify-copyright auto-fixes: example files renamed from docs/ correctly revert to 2025 (git tracks original creation year) - Add missing comma in copyright: 2024-2026 NVIDIA → 2024-2026, NVIDIA in python/cuopt/cuopt/linear_programming/io/__init__.py - Exclude .mdx files from verify-hardcoded-version (same as .md): documentation version references in MDX are intentional - Exclude fern/docs.yml and fern/docs-v*.yml from verify-hardcoded-version: these version switcher configs have intentional display-name version strings Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
custom-job.yaml constructs the runner label as linux-{arch}-{node_type}.
With arch=amd64 and node_type=cpu-amd64-latest-4, the label becomes
linux-amd64-cpu-amd64-latest-4 (amd64 doubled), which has no matching runner.
Correct node_type is cpu4, producing linux-amd64-cpu4.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
fern generate --docs --preview requires authentication even for preview builds. custom-job.yaml does not expose FERN_TOKEN to the script environment, so CI fails with "Authentication required". Fall back to fern check only when FERN_TOKEN is not set. fern check already ran and passed; docs are validated. Preview publishing can be enabled later by injecting FERN_TOKEN via container-options. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
Separate the preview publish from the docs validation (docs-build). docs-build validates via generate_api_docs.py + fern check using the rapidsai conda runner. docs-preview is a lightweight ubuntu-latest job that publishes a stable preview URL (keyed by branch name) and posts it as a PR comment using FERN_TOKEN. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
The fern-api/setup-fern-cli and thollander/actions-comment-pull-request
pinned-SHA uses caused startup_failure (GitHub couldn't compile the
workflow). Replace both with plain run: steps: install fern via npm and
post the PR comment via gh pr comment. Also fix template-injection
findings by using GITHUB_HEAD_REF / GITHUB_REF_NAME env vars instead
of inline ${{ }} expansions in the run block.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
The merge with main added CUOPT_MIP_RINS and 8 CUOPT_MIP_HYPER_SUBMIP_*
constants (recursive sub-MIP heuristic params) to constants.h.
generate_api_docs.py requires every header symbol to have a
{/* symbol: NAME */}{/* /symbol */} marker in the MDX skeleton.
Add CUOPT_MIP_RINS after CUOPT_MIP_REDUCED_COST_STRENGTHENING and
add a new "MIP Sub-MIP Hyper Parameters" section for the SUBMIP symbols.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
mlubin
left a comment
There was a problem hiding this comment.
How can we preview the docs as generated by this PR?
| @@ -1,4 +1,4 @@ | |||
| // SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights | |||
| // SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. | |||
There was a problem hiding this comment.
This change isn't correct. "reserved" is still on the line below. Occurs in many files.
You can build it locally and I am also working on an option to create a preview, still working on that, |
global-theme: nvidia was referenced in fern/docs.yml but the theme was never uploaded to the Fern org, causing `fern generate --docs --preview` to fail with "Global theme not found". Remove the reference so publishing succeeds without a custom theme. Also add `|| true` to the URL grep line in the docs-preview run block so that bash's `set -e` does not abort the step when grep exits 1 (no match). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
- fern.config.json: change organization from "nvidia-cuopt" to "nvidia" (the nvidia-cuopt subdomain is the docs URL, not the owning Fern org) - fern/docs.yml: restore global-theme: nvidia now that the theme is uploaded to the nvidia org on Fern cloud - .gitignore: exclude fern/theme/ — it is a local staging directory produced by `fern docs theme export` and already uploaded; the files are copies of what is already tracked under fern/docs/ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
global-theme: nvidia is a shared org-wide theme for all NVIDIA Fern docs. Referencing it from cuopt docs.yml (and uploading cuopt-specific assets as that theme) accidentally overwrote branding for other NVIDIA docs sites. Remove the reference; cuopt styling is already defined inline in docs.yml (colors, logo, CSS, JS). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
cuOpt does not have its own logo — branding comes from the shared global-theme: nvidia (org-level theme managed by NVIDIA/Fern). - Remove logo block (dark/light SVGs) and colors from docs.yml - Remove the logo SVG files that are no longer referenced - Keep css/js entries for the install-selector widget, which is cuopt-specific functionality not covered by the global theme - Restore global-theme: nvidia reference Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
ci/build_docs.sh: use rapids-is-release-build (same gate as docker image publish) so that fern generate --docs runs only on tagged releases (v*.*.* tags). PR and branch builds run fern check only. fern/build_docs.sh, build.sh: add --check flag that runs generate_api_docs + fern check and exits cleanly, suitable for CI validation without starting the interactive local dev server. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
Conflict in python/cuopt/cuopt/routing/__init__.py: take main's cleanup (GPU-requiring utilities removed from public re-exports per #1591) while keeping the explanatory comment from this branch. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
- Add continue-on-error: true so a failed preview does not block PR merge - Remove || true from fern generate so actual failures show as failed instead of silently passing (the job was always green even when fern exited non-zero) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
With bash -e, OUTPUT=$(fern ...) exits immediately on fern failure before echo "$OUTPUT" can run, making the logs silent. Capture the exit code via || fern_exit=$? so the output always prints, then re-exit with the real code at the end. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Ramakrishna Prabhu <ramakrishnap@nvidia.com>
Replaces the abandoned Fern `libraries:` native generation approach with a custom AST + Cython regex generator that properly handles NumPy docstrings, Cython enums, and `all`-based public API filtering.
Summary
🤖 Generated with Claude Code