Repository navigation
docs: add MkDocs Material documentation site - #110
Conversation
Builds a unified documentation site covering the Python and MATLAB implementations, the algorithm specification, and the example notebooks. Auto-generated API reference for both languages: Python via mkdocstrings (NumPy docstrings), MATLAB via a custom gen-files script that parses each `sid*.m` H1 header. The 11 example notebooks are executed at build time and shipped with rendered outputs plus a Binder launch badge. Site is built and (on `main`) deployed to GitHub Pages by `.github/workflows/docs.yml`.
Maintainer decision: adapt this PR — do not close it, do not restructure it from scratchThis PR predates a lot of movement on Required restructure: move the site source out of
|
Adapts the docs-site PR in place per the maintainer decision on #110, rather than closing or rebuilding it. The PR's content was essentially intact -- almost everything regenerates from source -- so this is a restructure plus the four blockers, not a rewrite. Merge resolution: - .gitignore: union of both sides. - docs/TODO.md and docs/roadmap_python.md: the instruction said to keep them at their original paths, but #197 (merged ~3h after the review was posted) had deleted TODO.md outright and archived roadmap_python.md to docs/plans/2026-07-29-python-port-phase-log.md. Accepted main's side for both: nothing to restore, nothing to publish. This satisfies the "no dev-tracking on the public site" blocker more completely than restoring them would have. - docs/roadmap.md: restored to its canonical path (the PR had moved it to docs/about/roadmap.md), carrying main's rewritten language-neutral catalogue. CLAUDE.md, docs/REVIEW_CONTEXT.md and CONTRIBUTING.md reference it by path. Restructure -- site source out of docs/: - All site source moved docs/ -> docsite/ (index.md, about/, api/, concepts/, examples/, getting-started/, hooks/, javascripts/, spec/, stylesheets/). docs/ now holds only internal engineering docs: DESIGN.md, REVIEW_CONTEXT.md, roadmap.md, decisions/, analyses/, plans/. Future internal docs can neither break the site build nor leak into the site. - mkdocs.yml: docs_dir, edit_uri, snippets base_path, hooks paths retargeted. Include paths needed no change -- docsite/ sits at the same depth docs/ did. Generator scripts needed no change -- they use REPO_ROOT plus virtual mkdocs_gen_files paths, so they are source-dir agnostic. - Removed roadmap/python-roadmap/TODO from the public nav, with a comment recording that publishing any internal doc is a separate deliberate decision. Blockers: - docs.yml now builds with --strict, so link rot fails the build instead of shipping silently (this is what the 39 pre-existing link warnings were). - docs.yml runs on pull_request, so a PR that breaks the docs is caught before merge; deploy is split into its own job gated on main and never runs for a PR. Deleted the hardcoded claude/plan-sid-docs-website-vFMRn trigger. - permissions scoped per job (workflow default {}, contents:read to build, contents:write only to deploy) instead of workflow-wide contents:write. Non-blockers taken: - Changelog page now mirrors the root CHANGELOG.md (added in 0.2.0) and links both per-language release notes, instead of only python/RELEASE_NOTES.md. The hook's INCLUDE_SOURCES map had to follow, or the included links would break the now-strict build. - New scripts/check_python_api_pages.py runs as a gen-files script and fails the build if sid.__all__ and docsite/api/python/ disagree in either direction, or if a stub is missing from SUMMARY.md. Closes the hole where a newly exported function silently misses the site. Verified it catches both a missing page and an orphan page. - Repo URL derived from mkdocs.yml repo_url in both the link-rewrite hook (via the config it already receives) and build_matlab_examples.py (via mkdocs_gen_files.config, falling back when standalone), instead of hardcoded in three places. - exclude_docs: hooks/ -- mkdocs was copying the hook .py files AND their __pycache__/*.pyc into the published site as static assets. Verified: mkdocs build --strict exits 0 from a clean tree (was 39 warnings), all 11 notebooks execute, both API references generate, and no internal document (decisions/analyses/plans/DESIGN/REVIEW_CONTEXT/roadmap/todo) appears anywhere under site/. ruff clean on the changed scripts and hooks. Refs #110
… gate Self-review of the adaptation (fresh-context subagent) found two bugs I had introduced plus five improvements. All addressed: Bugs (mine): - rewrite_external_links.py interpolated a pathlib.Path into the GitHub URL, so on Windows it emitted ".../blob/main/docs\DESIGN.md" -- real 404s. Confirmed in the built site (docs\decisions\ADR-*, .github\workflows\*, spec\SPEC.md), then fixed with as_posix() and confirmed zero backslash URLs remain. CI builds on Linux so the deployed site was unaffected; local previews were broken. My INCLUDE_SOURCES switch newly surfaced it on the changelog page. - build_matlab_examples.py: narrowing the config lookup to (ImportError, AttributeError) -- which I did to satisfy ruff BLE001 -- broke standalone runs from any cwd but the repo root, because mkdocs_gen_files.config loads mkdocs.yml and raises ConfigurationError. The broad catch is correct here and is now justified in a comment with an explicit noqa; the script is meant to run standalone from anywhere. Improvements: - check_python_api_pages.py no longer keeps a hand-listed NON_FUNCTION_EXPORTS set -- that just relocated the hardcoded manifest the gate exists to remove. It now partitions sid.__all__ by inspect.isfunction, so a new result type routes to the results.md check instead of demanding a stub (previously it would have failed every docs build with the wrong remedy, or been silently exempted). Verified both scenarios behave correctly. - Same gate now also checks the two hand-written index manifests (docsite/api/index.md, docsite/api/python/index.md) and results.md coverage -- a missing table row is invisible to the strict build. - inject_binder_badge.py derives owner/repo from repo_url; this was the third of the three hardcoded-URL sites the review named, so item 7 is now complete rather than partly done. - Dropped the duplicate "# Changelog" H1: the included CHANGELOG.md supplies its own, which produced two top-level ToC entries (about/contributing.md already avoids this by having no local H1). - CONTRIBUTING.md documents the docs//docsite/ split, why it exists, that publishing an internal doc is a deliberate nav change, and how to build the site locally. The restructure's whole point is that a future contributor or agent cannot break or leak into the site -- that rule needs to live where they actually read it, not only in a mkdocs.yml comment. Left alone deliberately: two ruff nits (FURB188, SIM114) in scripts/build_matlab_api.py, which is untouched original PR content, flagged by rules outside the project's pinned set (E4,E7,E9,F,I) and outside CI's lint scope. Fixing them would be unrelated churn. Verified: mkdocs build --strict exits 0; no backslash URLs in the built site; single H1 on the changelog page; ruff clean under the project's rule set on every file I touched; 30 relative links resolve. Refs #110
|
Adapted in place per the decision — restructure + all four blockers + all four non-blockers, in One instruction was stale — please confirm my callStep 3 said So the merge surfaced a rename/delete and a rename/rename conflict on exactly those two. I read the instruction's intent as "internal dev docs stay internal, at their canonical paths, off the public site" and applied it to today's
Verified the merge is purely additive vs Restructure + blockers
Two extras worth flagging: mkdocs was publishing the hook Self-review found two bugs I introduced — fixed in
|
Re-review of the adaptation (commits
|
Re-review non-blocker 1. The index-table leg used `if name not in text`, which a
longer sibling satisfies: `spectrogram` is present in `spectrogram_plot`, so a
dropped `(python/spectrogram.md)` row passed the check. The gate was weaker than
its SUMMARY leg, which already matched the link form.
Each index page is now paired with its own link template -- `(python/{name}.md)`
for docsite/api/index.md, `({name}.md)` for docsite/api/python/index.md, since
the two link with different prefixes -- and the failure message names the exact
link it expected.
Verified against the reviewer's own example: deleting the `(python/spectrogram.md)`
row now fails with a precise message, where before it passed.
Refs #110
|
Both non-blockers taken — 1. Index-table check tightened. You were right that it was the loose leg. Reproduced your exact example: deleting the That leg is now as tight as the SUMMARY one, which is what made the gap visible. 2. PR description refreshed. It described the pre-adaptation state throughout —
3. Noted, no action — agreed on both: Ready to merge whenever you are. The one-time Pages setup (Settings → Pages → source |
Summary
Adds a unified MkDocs Material documentation site covering Python and MATLAB/Octave, the algorithm specification, and the example notebooks. API reference is generated for both languages — Python via
mkdocstrings(NumPy docstrings), MATLAB via agen-filesscript that parses eachsid*.mH1 header. The 11 example notebooks execute at build time and ship with rendered outputs plus a Binder launch badge.Originally opened 2026-05-15 and adapted in place (not rebuilt) after review — see the maintainer decision and the adaptation commits
194768f+70bfc8b. Because almost everything regenerates from source, the PR's content survived ~170 commits of drift onmain.Layout:
docsite/is the site,docs/stays internalThe site source lives in its own top-level
docsite/directory, not indocs/.docs/is the home of internal engineering documents (ADRs, analyses, plans,DESIGN.md,REVIEW_CONTEXT.md, the function catalogue) and keeps growing; sharing a directory meant those documents were swept into the public site and their relative links broke the strict build.With the split, a new internal document can neither leak onto the site nor break its build. Publishing anything from
docs/is a deliberatenavchange, never a side effect of the build config — recorded inmkdocs.ymland in a newCONTRIBUTING.mdsection that also documents the local build command.What's in this PR
mkdocs.yml,requirements-docs.txtdocsite/— landing, getting-started, concepts, Python API stubs, examples, spec includes, about, hooks, stylesheets, MathJax configscripts/build_matlab_api.py— parses everymatlab/sid/sid*.mH1 header into a page (standalone + gen-files dual-mode)scripts/build_matlab_examples.py,scripts/link_notebook_examples.pyscripts/check_python_api_pages.py— new: fails the build ifsid.__all__and the Python API reference disagree in either direction, or if a stub is missing from the nav or the index tables.github/workflows/docs.yml— strict build on every PR and push; deploy togh-pagesgated onmainCONTRIBUTING.md— thedocs/↔docsite/split and how to build locallyBuild results
Reproduced locally on a clean tree at head, and green in CI on this PR.
mkdocs build --strictspec/)404.html)site/CI behaviour
Build site (strict)runs on every pull request — a PR that breaks the docs now fails before merge instead of after.Deploy to GitHub Pagesis a separate job, gated onmainand skipped for PRs (visible in this PR's checks), and publishes the exact artefact the build job tested. Permissions are{}at workflow level withcontents: readfor build andcontents: writeonly for deploy.Portability to Sphinx
Authored pages stick to plain CommonMark, the MATLAB H1 parser is standalone, notebooks/docstrings are untouched. A future Sphinx migration should be mechanical (config + nav rewrite + admonition/tab syntax pass) rather than a content rewrite.
Test plan
main, CI deploys togh-pagesgh-pages/ rootNotes
mkdocs-gen-files's opportunisticimport properdocs.replacement_warning. Suppressed in CI viaDISABLE_MKDOCS_2_WARNING=true.ruffto docs deps later.mikeversioning, a scheduled external-link checker, and publishing ADRs under a Development section.