Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# FILE: .github/workflows/docs.yml
name: docs

on:
push:
branches: [main]
paths:
- "src/**"
- "docs/**"
- "scripts/gen_api.py"
- "scripts/sphinx_compat.py"
- "mkdocs.yml"
- "requirements-docs.txt"
- ".github/workflows/docs.yml"
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

# Let one deploy finish rather than cancelling mid-publish.
concurrency:
group: pages
cancel-in-progress: false

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.12"
cache: pip

- name: Install deps
run: |
pip install -r requirements.txt
pip install -r requirements-docs.txt

- name: Regenerate reference pages + nav from source
run: python scripts/gen_api.py

- name: Build site
# NOT --strict: griffe flags the unannotated public parameters as
# warnings, which would fail the build out of the box. Add --strict once
# annotation coverage is up.
run: mkdocs build

- uses: actions/upload-pages-artifact@v3
with:
path: site

deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,9 @@ __marimo__/

# opencode-mem preseed (ephemeral, regenerate per-repo)
lab-notes/memories.json

# --- Docs (generated by scripts/gen_api.py) ---
site/
docs/reference/
docs/SUMMARY.md
docs/_nav_api.yml
18 changes: 18 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,24 @@ joint space**.
backend test "didn't run", that's why. Requires Python ≥3.12; CI matrix is
3.12–3.14.
- Demos: `python -m demos.demo_*`.
- **Docs** (API reference is generated, not hand-written):
- `make docs` — install the docs toolchain (`requirements-docs.txt`).
- `make docs-serve` — regenerate reference + serve at http://127.0.0.1:8000.
- `make docs-build` — regenerate reference + build static `site/`.
- `scripts/gen_api.py` walks each subpackage's `__all__` and emits one page
per subpackage plus the nav — **adding an export is all it takes** for it to
appear in the docs. Subpackages without `__all__` (`components.py`,
`utils/`) fall back to an AST scan of their source files.
- Generated output (`docs/reference/`, `docs/SUMMARY.md`, `site/`) is
gitignored. Prose pages are hand-written and ordered in
`docs/_nav_prose.md`.
- `scripts/sphinx_compat.py` is a griffe extension that makes the Sphinx-flavored
docstring markup (`:class:`, `:math:`, `.. math::`) render instead of leaking
as literal text. Removing it silently breaks all math **without failing the
build** — the key must stay under `options:` in `mkdocs.yml`.
- `.github/workflows/docs.yml` deploys to GitHub Pages on push to `main`.
It does **not** use `--strict`: griffe flags the many unannotated public
parameters as warnings, so `--strict` is red out of the box.
- `make compile SCENARIO=<scenario.toml>` — e2e scenario → verified `.so`:
`scripts/gen_scenario.py` (zig-free: trace+compose+lower to an isolated
path) then `scripts/build_scenario.py` (zig build + oracle + stamp + verify).
Expand Down
19 changes: 19 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.PHONY: test test-quick test-functional test-all test-integration lint install build \
release-patch release-minor release-major changelog \
docs docs-serve docs-build \
test-controllers test-estimators test-plants test-trajectories test-armrobot \
test-components test-array-backend test-batched-adapter test-controllability test-factories \
test-linearization test-adversarial test-mcp-server test-mcp-functional \
Expand Down Expand Up @@ -129,6 +130,24 @@ lint:
ruff check .
pyright src/shinro/utils/ src/shinro/components.py src/shinro/controllers/ src/shinro/estimators/ src/shinro/trajectories/ src/shinro/plants/

# --- Docs -------------------------------------------------------------------
# The API reference pages AND their nav are generated from each subpackage's
# __all__ (see scripts/gen_api.py), so there is no symbol list to maintain.

# Install the docs toolchain.
docs:
pip install -r requirements-docs.txt

# Regenerate the reference and serve with live reload at http://127.0.0.1:8000
docs-serve:
python3 scripts/gen_api.py
mkdocs serve

# Regenerate the reference and build the static site into site/
docs-build:
python3 scripts/gen_api.py
mkdocs build

# Run an individual test group by short name, e.g. `make test-controllers`
test-controllers:
python3 -m pytest tests/test_controllers.py -v --tb=short
Expand Down
19 changes: 19 additions & 0 deletions docs/_nav_prose.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Hand-maintained navigation for the PROSE pages.
#
# Format is mkdocs-literate-nav markdown (NOT yaml):
# * [Title](path.md)
# * Section title
# * [Sub page](sub/page.md)
#
# Edit this file to add or reorder prose pages — it is safe from regeneration.
# scripts/gen_api.py reads it, appends the generated "API Reference" section, and
# writes the combined result to docs/SUMMARY.md (a build artifact — never edit
# SUMMARY.md or docs/_nav_api.yml by hand).

* [Home](index.md)
* [Quickstart](quickstart.md)
* [How it works](how-it-works.md)
* [Components](components.md)
* [Testing](testing.md)
* [MCP server](mcp_server.md)
* [Codegen](codegen.md)
59 changes: 59 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
---
title: Home
---

# shinro

Whole-body control framework: controllers, plants, estimators, trajectories, and
a MuJoCo-backed simulation factory.

`shinro` is built on **five abstract base classes** — `Controller`, `Plant`,
`StateEstimator`, `TrajectoryGenerator`, and `PhysicsEngine` — with concrete
implementations assembled from TOML config via registry-based factories, and a
swappable numpy/torch array backend.

## Start here

<div class="grid cards" markdown>

- **[Quickstart](quickstart.md)** — install and run your first simulation end to end.
- **[How it works](how-it-works.md)** — the ABC model, factories, and the compose/lower pipeline.
- **[Components](components.md)** — how config-driven components are declared and validated.
- **[API Reference](reference/components.md)** — every exported symbol, generated from source.

</div>

## Layout

| Package | Contents |
|---|---|
| [`shinro.components`](reference/components.md) | The five ABCs and the `ConfigDriven` mixin |
| [`shinro.trajectories`](reference/trajectories.md) | Reference path generators |
| [`shinro.controllers`](reference/controllers.md) | LQR, PID, MPC, MPPI, SMC, RL adapters |
| [`shinro.estimators`](reference/estimators.md) | Kalman filter, Luenberger observer |
| [`shinro.plants`](reference/plants.md) | Robot models |
| [`shinro.factories`](reference/factories.md) | Registry-based TOML factories, `Scenario` |
| [`shinro.utils`](reference/utils.md) | Array backend, linearization, controllability |
| [`shinro.simulation`](reference/simulation.md) | Robot simulation factory |

## Install

```bash
pip install -e ".[mujoco,media]" # MuJoCo + plotting for the demos
```

## How this reference stays current

The **API Reference** section is generated, not written by hand.
`scripts/gen_api.py` walks each subpackage's `__all__` and emits one page per
subpackage, so **adding an export is all it takes** for it to appear here on the
next build. A subpackage without `__all__` falls back to an AST scan of its
source files.

```bash
python scripts/gen_api.py # regenerate reference page + nav
mkdocs serve # preview at http://127.0.0.1:8000
```

Prose pages are hand-written and listed in `docs/_nav_prose.yml`. The generated
nav is composed into `docs/SUMMARY.md`, which is a build artifact.
20 changes: 20 additions & 0 deletions docs/javascripts/mathjax.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// FILE: /mnt/E/sabrina-sandbox/docs-poc/docs/javascripts/mathjax.js
window.MathJax = {
tex: {
inlineMath: [["\\(", "\\)"], ["$", "$"]],
displayMath: [["\\[", "\\]"], ["$$", "$$"]],
processEscapes: true,
processEnvironments: true
},
options: {
ignoreHtmlClass: ".*|",
processHtmlClass: "arithmatex"
}
};

document$.subscribe(() => {
MathJax.startup.output.clearCache();
MathJax.typesetClear();
MathJax.texReset();
MathJax.typesetPromise();
});
99 changes: 99 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# FILE: mkdocs.yml
# API reference site for shinro.
#
# python scripts/gen_api.py && mkdocs build
# python scripts/gen_api.py && mkdocs serve # live reload
#
# The reference pages AND the reference nav are generated by scripts/gen_api.py
# from each subpackage's __all__. Only prose pages are declared by hand below.

site_name: shinro
site_description: Whole-body control framework — controllers, plants, estimators, trajectories, and a MuJoCo-backed simulation factory.
docs_dir: docs
site_dir: site
use_directory_urls: true

theme:
name: material
features:
- navigation.sections
- navigation.indexes
- navigation.top
- content.code.copy
- content.code.annotate
- search.suggest
- search.highlight
- toc.follow
palette:
- media: "(prefers-color-scheme: light)"
scheme: default
toggle:
icon: material/weather-night
name: Switch to dark mode
- media: "(prefers-color-scheme: dark)"
scheme: slate
toggle:
icon: material/weather-sunny
name: Switch to light mode

plugins:
# literate-nav lets docs/_nav_api.yml supply the reference section, so the
# generated pages never need a hand-edited nav entry.
- literate-nav:
nav_file: SUMMARY.md
- search
- mkdocstrings:
handlers:
python:
# Read the source tree directly — no install needed.
paths:
- src
options:
# Normalizes Sphinx-only markup (:math:, .. math::, :class:) that
# would otherwise render as literal text.
# GOTCHA: this key MUST live under options:, not beside paths:.
# Placed at handler level it is silently ignored — you get a green
# build with broken math.
extensions:
- scripts/sphinx_compat.py
docstring_style: google
show_source: true
show_root_heading: false
show_root_full_path: false
show_symbol_type_heading: true
show_symbol_type_toc: true
members_order: source
separate_signature: true
show_signature_annotations: true
signature_crossrefs: true
merge_init_into_class: true
docstring_section_style: table
filters:
- "!^_"

# Strict mode is intentionally NOT used in CI: griffe reports the unannotated
# public parameters (see README) as warnings, so --strict is red out of the box.
# Tighten annotations first, then add --strict to the workflow.
validation:
links:
absolute_links: ignore
unrecognized_links: ignore

markdown_extensions:
- admonition
- attr_list
- md_in_html
- pymdownx.details
- pymdownx.superfences
- pymdownx.highlight:
anchor_linenums: true
- pymdownx.inlinehilite
- pymdownx.snippets
- pymdownx.arithmatex:
generic: true
- toc:
permalink: true

extra_javascript:
- javascripts/mathjax.js
- https://unpkg.com/mathjax@3/es5/tex-mml-chtml.js
6 changes: 6 additions & 0 deletions requirements-docs.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# FILE: requirements-docs.txt
# Docs toolchain. Kept separate from requirements-dev.txt so the CI test matrix
# doesn't pull a web toolchain.
mkdocs-material>=9.5
mkdocstrings[python]>=0.26
mkdocs-literate-nav>=0.6
Loading
Loading