Contributing & editing the docs#

HJCD-IK is a batched GPU IK solver built on GRiD (kinematics codegen) and GLASS (single-block / warp-scoped CUDA linear algebra). The canonical contributor entry points are the repository’s CLAUDE.md (architecture + mental model) and the debugging guide (recurring traps + validation checklist).

Before you start#

  • Initialize required pinned submodules: bash scripts/setup/bootstrap.sh.

  • Set up a dev environment (venv, deps, codegen, build, and the docs toolchain) with ./scripts/setup/setup_dev.sh.

Workflow#

  • Branch from main; keep PRs focused. Short, single-line commit messages; no Co-Authored-By footer.

  • Changes that belong upstream — kinematics in GRiD, linear algebra in GLASS — should be PR’d to those repos rather than patched locally. Keep HJCD-IK thin and the dependencies modular.

Discipline#

  • Never hand-edit csrc/generated/grid.cuh. It is GRiD codegen output. Regenerate it with python scripts/codegen/generate_grid.py <urdf> -t <target> and rebuild — see Custom robot (GRiD codegen workflow).

  • Keep LM math warp-scoped. LM refinement is warp-per-candidate; use warp primitives (__shfl_*_sync / __syncwarp, grid::ee_pose_inner_warp, glass::warp::) for its math. Coarse search is candidate-per-block: its per-warp scratch needs warp fences and its shared candidate state needs block barriers. See The HJCD-IK algorithm.

  • No regressions. Run python benchmark/hjcd_ik_bench.py --skip-grid-codegen before/after kernel changes and compare to the committed baseline. Isolate timing runs (no concurrent GPU load).

Tests#

  • pytest tests/ — numerical regression, independent FK, collision policy, Python API, codegen, and signed-receipt policy checks. Install .[dev,codegen] and use the default collision-enabled Panda.

  • Native API and CLI tests are separate CTest checks (not claimed as outcomes in the Python receipt). Configure with -DHJCDIK_BUILD_NATIVE_TESTS=ON; see Installation & Quickstart. They require Python and a CUDA GPU; malformed-input cases explicitly hide the GPU to check validation order.

  • For synchronization changes, also use Compute Sanitizer’s Racecheck and Synccheck. Passing numerical tests or Memcheck alone does not establish shared-memory ordering correctness.

Editing the docs#

This site is built with Sphinx + the PyData theme, with the C++/CUDA API reference generated by Doxygen and bridged in via Breathe. Narrative pages are Markdown (via MyST) or reStructuredText.

docs/
  Doxyfile            Doxygen config (XML only; input = ../csrc)
  Makefile            `make all` = doxygen + sphinx-build
  requirements.txt    Sphinx + Breathe + pydata-sphinx-theme + myst + sphinx-design
  source/
    conf.py           Sphinx config (theme, breathe, extensions)
    index.rst         docs landing page (grid cards + toctree)
    _static/          logo, favicon, custom.css, paper/ (committed paper figures)
    user_guide/       getting_started/ · concepts/ · tutorials/ · benchmarks/
    api_reference/    python.rst (hand-written) + kernel/collision.rst (.. doxygenfile::)
    developer_guide/  this section
docs/development/     un-published support docs (agent_debugging_guide, STARTUP_PROMPT)

Build locally#

./scripts/setup/setup_dev.sh        # installs the docs toolchain into .venv (+ doxygen via apt)
source .venv/bin/activate

make -C docs all                    # docs only → docs/build/html/index.html
#   — or —
./scripts/build_site.sh             # full site → _site/ (landing at /, docs under /docs/)

scripts/build_site.sh is the same script CI runs, so a local build matches the deployed site exactly.

Conventions#

  • C++/CUDA API is generated from in-source /** ... */ doc-comments. To document a new public symbol, add the doc-comment in the header and ensure its file has a .. doxygenfile:: entry under api_reference/. Doxygen runs with EXTRACT_ALL=NO, so only documented symbols appear.

  • Python API (api_reference/python.rst) is hand-authored — the compiled hjcdik extension is not imported at build time (CI has no GPU), so keep that page in sync with csrc/bindings/pybind_module.cpp by hand.

  • Benchmark figures/tables are committed static assets under _static/paper/, taken from the camera-ready paper. Do not embed locally-generated benchmark output — see Examples & Results.

Deploy#

Deployment is automatic: any push to main touching docs/**, csrc/**, or examples/** triggers .github/workflows/gh-pages.yml, which runs scripts/build_site.sh and publishes _site/ to GitHub Pages. Pull requests build the site without deploying. Merge reviewed changes to main to publish (or dispatch the workflow on main). Requirements: Settings → Pages → Source must be “GitHub Actions”. Landing-page assets under docs/landing/ and published paper figures/tables need not change when updating /docs/.

Release checks#

Run the full tests, example/quickstart tests, header freshness check, native CTest checks, and strict docs build after the final edits. Validate a wheel built from the source archive in a separate environment. Record a fresh signed GPU proof from a clean checkout after committing the test manifest. The manifest binds implementation, dependencies, examples, and executable documentation. Do not remove user files just to obtain a clean recording tree.

The proof accepts an ancestor commit only while its source fingerprint still matches. Preserve that ancestor with a merge commit, or regenerate the proof after a rebase/squash; never assume a pre-rewrite receipt remains valid. Verify the final merge candidate and check dependency commits are published. GPU tests remain local/signed until a self-hosted runner is available; a docs build or signature check is not a new GPU test execution.