diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ba5636bab6..ade9f591b4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -135,6 +135,11 @@ repos: language: system pass_filenames: false files: ^(VERSION|\.claude-plugin/marketplace\.json|\.cursor-plugin/plugin\.json|gemini-extension\.json)$ + - id: vale + name: Vale docs prose lint + entry: vale + language: system + files: ^docs/cuopt/source/.*\.(rst|md)$ - id: validate-skills name: Validate agent skills entry: ci/utils/validate_skills.sh diff --git a/.vale.ini b/.vale.ini new file mode 100644 index 0000000000..7d4b11968d --- /dev/null +++ b/.vale.ini @@ -0,0 +1,5 @@ +StylesPath = ci/vale/styles +MinAlertLevel = error + +[docs/cuopt/source/**/*.{rst,md}] +BasedOnStyles = cuOpt diff --git a/ci/vale/styles/cuOpt/Headings.yml b/ci/vale/styles/cuOpt/Headings.yml new file mode 100644 index 0000000000..9d80fcdbe8 --- /dev/null +++ b/ci/vale/styles/cuOpt/Headings.yml @@ -0,0 +1,28 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Section headings under docs/cuopt/source use title case (Chicago style, so +# short prepositions and conjunctions stay lowercase). +extends: capitalization +message: "Heading '%s' should use title case." +level: error +scope: heading +match: $title +style: Chicago + +# Terms that keep their own casing. +# +# Every entry here is load-bearing: removing any one of them makes a real +# heading fail. Do not add a term speculatively. Exceptions match whole words +# and a single match makes Vale skip the ENTIRE heading, so a needless entry +# silently disables the check for every heading that mentions it. +# +# `ci/utils/check_vale_rule.sh` guards against that; run it after editing. +exceptions: + - cuOpt + - cuDSS + - gRPC + - mTLS + - (cuopt) + - cuopt-server + - solver_configs diff --git a/conda/environments/all_cuda-129_arch-aarch64.yaml b/conda/environments/all_cuda-129_arch-aarch64.yaml index 82ad4010c5..80a7d6554a 100644 --- a/conda/environments/all_cuda-129_arch-aarch64.yaml +++ b/conda/environments/all_cuda-129_arch-aarch64.yaml @@ -22,6 +22,7 @@ dependencies: - cupy>=14.0.1,!=14.1.0 - cxx-compiler - cython>=3.0.3 +- docutils>=0.21 - doxygen=1.9.1 - fastapi - gcc_linux-aarch64=14.* @@ -81,6 +82,7 @@ dependencies: - sysroot_linux-aarch64==2.28 - tbb-devel - uvicorn==0.34.* +- vale=3.17.0 - zlib - pip: - nvidia-sphinx-theme diff --git a/conda/environments/all_cuda-129_arch-x86_64.yaml b/conda/environments/all_cuda-129_arch-x86_64.yaml index b293e2d8c0..d7629c1b1e 100644 --- a/conda/environments/all_cuda-129_arch-x86_64.yaml +++ b/conda/environments/all_cuda-129_arch-x86_64.yaml @@ -22,6 +22,7 @@ dependencies: - cupy>=14.0.1,!=14.1.0 - cxx-compiler - cython>=3.0.3 +- docutils>=0.21 - doxygen=1.9.1 - fastapi - gcc_linux-64=14.* @@ -81,6 +82,7 @@ dependencies: - sysroot_linux-64==2.28 - tbb-devel - uvicorn==0.34.* +- vale=3.17.0 - zlib - pip: - nvidia-sphinx-theme diff --git a/conda/environments/all_cuda-133_arch-aarch64.yaml b/conda/environments/all_cuda-133_arch-aarch64.yaml index 1cb8efbe75..d3072b8be1 100644 --- a/conda/environments/all_cuda-133_arch-aarch64.yaml +++ b/conda/environments/all_cuda-133_arch-aarch64.yaml @@ -22,6 +22,7 @@ dependencies: - cupy>=14.0.1,!=14.1.0 - cxx-compiler - cython>=3.0.3 +- docutils>=0.21 - doxygen=1.9.1 - fastapi - gcc_linux-aarch64=14.* @@ -81,6 +82,7 @@ dependencies: - sysroot_linux-aarch64==2.28 - tbb-devel - uvicorn==0.34.* +- vale=3.17.0 - zlib - pip: - nvidia-sphinx-theme diff --git a/conda/environments/all_cuda-133_arch-x86_64.yaml b/conda/environments/all_cuda-133_arch-x86_64.yaml index c49b656860..c227032e4c 100644 --- a/conda/environments/all_cuda-133_arch-x86_64.yaml +++ b/conda/environments/all_cuda-133_arch-x86_64.yaml @@ -22,6 +22,7 @@ dependencies: - cupy>=14.0.1,!=14.1.0 - cxx-compiler - cython>=3.0.3 +- docutils>=0.21 - doxygen=1.9.1 - fastapi - gcc_linux-64=14.* @@ -81,6 +82,7 @@ dependencies: - sysroot_linux-64==2.28 - tbb-devel - uvicorn==0.34.* +- vale=3.17.0 - zlib - pip: - nvidia-sphinx-theme diff --git a/dependencies.yaml b/dependencies.yaml index fe16140fd9..ee873f1294 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -787,6 +787,10 @@ dependencies: - clang==20.1.8 - clang-tools=20.1.8 - &doxygen doxygen=1.9.1 # pre-commit hook needs a specific version. + - vale=3.17.0 # docs prose linter, run by the vale pre-commit hook. + # Vale parses .rst by shelling out to docutils' rst2html; without it + # the vale hook fails with "rst2html not found". + - docutils>=0.21 docs: common: - output_types: [conda] diff --git a/docs/cuopt/README.md b/docs/cuopt/README.md index a6570eb1a0..5593d881a3 100644 --- a/docs/cuopt/README.md +++ b/docs/cuopt/README.md @@ -31,3 +31,34 @@ Then, navigate a web browser to the IP address or hostname of the host machine a http://:8000 ``` Now you can check if your docs edits formatted correctly, and read well. + +## Prose Style Checks + +Headings under `docs/cuopt/source/` use **title case**, enforced by +[Vale](https://vale.sh/) through the `vale` pre-commit hook. The rule lives in +`ci/vale/styles/cuOpt/Headings.yml` and follows Chicago style, so short +prepositions and conjunctions stay lowercase: + +- `Connect and Solve`, `Where to Find Examples`, `Working with Incumbent Solutions` +- not `Connect and solve`, `Where To Find Examples` + +Run it directly with: + +```bash +vale docs/cuopt/source +``` + +Product names, acronyms, and API identifiers that must keep their own casing +(`cuOpt`, `gRPC`, `mTLS`, `solver_configs`) are listed under `exceptions` in +that file. + +**Keep that list narrow, and only add a term once a real heading needs it.** +Exceptions match whole words, and a single match makes Vale skip the *entire* +heading — so a needless entry silently disables the check for every heading +that mentions it, with no visible symptom. After editing the list, confirm the +rule still catches a violation: + +```bash +printf '# T\n\n## Process model\n' > /tmp/vale-check.md +vale --config=.vale.ini /tmp/vale-check.md # must report an error +``` diff --git a/docs/cuopt/source/cuopt-c/convex/convex-examples.rst b/docs/cuopt/source/cuopt-c/convex/convex-examples.rst index a57cd67b8a..70211660a5 100644 --- a/docs/cuopt/source/cuopt-c/convex/convex-examples.rst +++ b/docs/cuopt/source/cuopt-c/convex/convex-examples.rst @@ -3,7 +3,7 @@ Convex Optimization C API Examples ================================== -LP Example With Data +LP Example with Data -------------------- This example demonstrates how to use the LP solver in C. More details on the API can be found in :doc:`C API `. diff --git a/docs/cuopt/source/cuopt-c/mip/mip-examples.rst b/docs/cuopt/source/cuopt-c/mip/mip-examples.rst index d5b9fb8869..624e4b001a 100644 --- a/docs/cuopt/source/cuopt-c/mip/mip-examples.rst +++ b/docs/cuopt/source/cuopt-c/mip/mip-examples.rst @@ -2,7 +2,7 @@ MIP C API Examples =================== -Example With Data +Example with Data ----------------- This example demonstrates how to use the MIP solver in C. More details on the API can be found in :doc:`MIP C API `. @@ -75,7 +75,7 @@ You should see the following output: Test completed successfully! -Example With MPS File +Example with MPS File --------------------- This example demonstrates how to use the cuOpt solver in C to solve an MPS file. diff --git a/docs/cuopt/source/cuopt-grpc/advanced.rst b/docs/cuopt/source/cuopt-grpc/advanced.rst index a092f026c3..0dc289a4b5 100644 --- a/docs/cuopt/source/cuopt-grpc/advanced.rst +++ b/docs/cuopt/source/cuopt-grpc/advanced.rst @@ -13,7 +13,7 @@ For RPC summaries and server behavior, see :doc:`api` and :doc:`grpc-server-arch Configuration Parameters ======================== -``cuopt_grpc_server`` (host or explicit container command) +``cuopt_grpc_server`` (Host or Explicit Container Command) ------------------------------------------------------------ Run ``cuopt_grpc_server --help`` for the full list. Typical flags (also passable inside ``CUOPT_GRPC_ARGS`` when using the container entrypoint): diff --git a/docs/cuopt/source/cuopt-grpc/grpc-server-architecture.md b/docs/cuopt/source/cuopt-grpc/grpc-server-architecture.md index 450947de6c..57dc471c48 100644 --- a/docs/cuopt/source/cuopt-grpc/grpc-server-architecture.md +++ b/docs/cuopt/source/cuopt-grpc/grpc-server-architecture.md @@ -4,19 +4,19 @@ NVIDIA cuOpt's **`cuopt_grpc_server`** uses one **main process** (gRPC front end Implementation details (IPC layout, C++ source map, chunked transfer internals) live in the contributor reference: **`cpp/docs/grpc-server-architecture.md`** in the NVIDIA cuOpt repository. -## Process model +## Process Model ![gRPC Server Process Model](images/grpc-process-model.png) -## Job lifecycle (summary) +## Job Lifecycle (Summary) **Submit** → the server assigns a job id and queues work. **Process** → a worker pulls the problem, solves on the GPU, and streams the result back. **Retrieve** → the client uses status and result RPCs (including chunked download when needed). See [gRPC API (reference)](api.rst) for RPC names. -## Job states +## Job States ![gRPC Server Job States](images/grpc-job-states.png) -## Logs, capacity, and workers +## Logs, Capacity, and Workers | Topic | Detail | |-------|--------| @@ -24,14 +24,14 @@ Implementation details (IPC layout, C++ source map, chunked transfer internals) | Default caps | Up to **100** queued jobs and **100** stored results (server compile-time limits). | | Workers | Recommended: **1 worker process per GPU**. Higher values are possible depending on the problems being solved but there is no specific guidance at this time. | -## Fault tolerance and cancellation +## Fault Tolerance and Cancellation - If a **worker process crashes**, jobs it was running are marked **FAILED**; the server can spawn replacement workers (see contributor doc for details). - **`CancelJob`** cancels **queued** jobs immediately (the worker skips them). If the solver has already started, the **worker process is killed** and the job is marked **CANCELLED**; a replacement worker is spawned automatically. - **Ctrl-C / SIGTERM** cancels active jobs, kills worker processes, and shuts the server down without waiting for an in-flight solve to finish. - **`DeleteResult`** also cancels a queued or running job (same kill/skip behavior as ``CancelJob``), then removes all server-side state for that ``job_id``. -## Further reading +## Further Reading - [Advanced configuration](advanced.rst) — `cuopt_grpc_server` **command-line flags**, TLS, Docker (`CUOPT_SERVER_TYPE`, `CUOPT_GRPC_ARGS`), and **client** environment variables (authoritative for operators). - [gRPC API (reference)](api.rst) — `CuOptRemoteService` RPC overview. diff --git a/docs/cuopt/source/cuopt-python/mip/mip-examples.rst b/docs/cuopt/source/cuopt-python/mip/mip-examples.rst index 1c76598be1..e44695bdcf 100644 --- a/docs/cuopt/source/cuopt-python/mip/mip-examples.rst +++ b/docs/cuopt/source/cuopt-python/mip/mip-examples.rst @@ -28,7 +28,7 @@ The response is as follows: Objective value = 303.0 -Semi-continuous Variable Example +Semi-Continuous Variable Example -------------------------------- :download:`semi_continuous_example.py ` diff --git a/docs/cuopt/source/cuopt-python/routing/routing-examples.rst b/docs/cuopt/source/cuopt-python/routing/routing-examples.rst index 3bc5400c4b..c506312678 100644 --- a/docs/cuopt/source/cuopt-python/routing/routing-examples.rst +++ b/docs/cuopt/source/cuopt-python/routing/routing-examples.rst @@ -4,7 +4,7 @@ Routing Examples This section contains examples for the cuOpt routing Python API. -Intra-factory Transport +Intra-Factory Transport ----------------------- A capacitated pickup-and-delivery problem with time windows (PDPTW) for a fleet diff --git a/docs/cuopt/source/cuopt-server/examples/lp-examples.rst b/docs/cuopt/source/cuopt-server/examples/lp-examples.rst index 3ec25a79f9..f42da06930 100644 --- a/docs/cuopt/source/cuopt-server/examples/lp-examples.rst +++ b/docs/cuopt/source/cuopt-server/examples/lp-examples.rst @@ -208,7 +208,7 @@ The response would be as follows: } -Using MPS or LP file directly +Using MPS or LP File Directly ----------------------------- The self-hosted client accepts both MPS and LP format files — the client @@ -276,7 +276,7 @@ the client dispatches on the file extension (``.mps`` / ``.qps`` vs ``.lp``, including ``.gz`` / ``.bz2`` compressed variants). For solver settings see :doc:`convex optimization parameters <../../convex-settings>` and :doc:`MIP parameters <../../mip-settings>`. -MPS format +MPS Format ~~~~~~~~~~ :download:`mps_datamodel_example.py ` @@ -285,7 +285,7 @@ MPS format :language: python :linenos: -LP format +LP Format ~~~~~~~~~ :download:`lp_datamodel_example.py ` @@ -294,7 +294,7 @@ LP format :language: python :linenos: -Expected output (either example, same problem instance) +Expected Output (Either Example, Same Problem Instance) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: text diff --git a/docs/cuopt/source/cuopt-server/examples/routing-examples.rst b/docs/cuopt/source/cuopt-server/examples/routing-examples.rst index 763dc6fc59..fdef42f318 100644 --- a/docs/cuopt/source/cuopt-server/examples/routing-examples.rst +++ b/docs/cuopt/source/cuopt-server/examples/routing-examples.rst @@ -282,7 +282,7 @@ Please refer to the :ref:`aborting-cli` in the MIP examples for more details. .. note:: Please use solver settings while using .mps files. -To enable HTTPS +To Enable HTTPS ---------------- * In the case of the server using public certificates, simply enable https. diff --git a/docs/cuopt/source/faq.rst b/docs/cuopt/source/faq.rst index 90b45d5a24..eb04ff6c1b 100644 --- a/docs/cuopt/source/faq.rst +++ b/docs/cuopt/source/faq.rst @@ -177,7 +177,7 @@ General FAQ while openssl x509 -noout -text; do :; done < test.pem.txt -gRPC remote execution (``cuopt_grpc_server``) +gRPC Remote Execution (``cuopt_grpc_server``) ----------------------------------------------- .. dropdown:: Where are log files for the gRPC server / StreamLogs? diff --git a/docs/cuopt/source/hidden/mps-api.rst b/docs/cuopt/source/hidden/mps-api.rst index ec2be8df66..6590bf785c 100644 --- a/docs/cuopt/source/hidden/mps-api.rst +++ b/docs/cuopt/source/hidden/mps-api.rst @@ -2,7 +2,7 @@ cuOpt MPS/LP Parser API Reference =============================== -MPS/QPS/LP parser +MPS/QPS/LP Parser ------------------- .. autofunction:: cuopt.linear_programming.io.Read diff --git a/docs/cuopt/source/hidden/parser_example.rst b/docs/cuopt/source/hidden/parser_example.rst index 9f79545e80..7b0e215ee8 100644 --- a/docs/cuopt/source/hidden/parser_example.rst +++ b/docs/cuopt/source/hidden/parser_example.rst @@ -1,5 +1,5 @@ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -cuOpt problem file parser example +cuOpt Problem File Parser Example ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/cuopt/source/resources.rst b/docs/cuopt/source/resources.rst index 145e750864..c121fa9f61 100644 --- a/docs/cuopt/source/resources.rst +++ b/docs/cuopt/source/resources.rst @@ -33,5 +33,5 @@ Please note that you need to choose a `Runtime` as `GPU` in order to run the not `Blogs `_ ---------------------------------------------------------------------------- -Contact us - cuopt@nvidia.com +Contact Us - cuopt@nvidia.com ----------------------------- diff --git a/docs/cuopt/source/system-requirements.rst b/docs/cuopt/source/system-requirements.rst index 26dcf84b22..d6ea01ef19 100644 --- a/docs/cuopt/source/system-requirements.rst +++ b/docs/cuopt/source/system-requirements.rst @@ -95,7 +95,7 @@ Container * `nvidia-container-toolkit `_ needs to be installed -Thin-client for Self-Hosted +Thin-Client for Self-Hosted ---------------------------- * OS: Linux