Skip to content

Commit 7db8842

Browse files
igerberclaude
andcommitted
test: CI-enforced docs IA guards (tests/test_docs_ia.py)
Structural invariants protecting the #703 information architecture - all valid-Sphinx states the -W build cannot catch: 1. docs/index.rst root toctree = exactly the 5 section landing pages (a 6th entry regrows the navbar "More" dropdown). 2. Every tutorial notebook registered in docs/tutorials/index.rst with BOTH a short-labeled toctree entry (<=40 chars) and a grid card, in the SAME group section; duplicates anywhere in the file are counted. 3. Homepage "Supported Estimators" table 1:1 with the api/index.rst Estimators autosummary, compared by OBJECT IDENTITY (a same-named distinct class cannot satisfy parity; submodule/re-export aliases match). Full list-table row blocks are parsed, so multiline or empty first cells fail loudly. 4. No class documented only under :no-index: (dead :class: xrefs - the pre-#703 RDD failure mode): every :no-index:'d autoclass (any indentation, nested api/ dirs included) must resolve to the same object as a stub-generating (:toctree:) autosummary entry; committed class stubs may not carry :no-index: themselves. Parsers are directive-scoped (contiguous option blocks, :toctree:-gated autosummary, module-shadow-aware qualname resolution) with negative fixtures per failure shape; scope is explicitly bounded to the RST conventions this repo uses. Mutation-verified: seeded violations of each invariant fail. Wired into the docs-tests doc-snippets job + path filters; conventions documented in CONTRIBUTING.md ("Docs IA invariants"), CLAUDE.md, /docs-check 5b, and CHANGELOG. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tt9ZXdhHdGsBvRTkNWb39M
1 parent 709ddf6 commit 7db8842

6 files changed

Lines changed: 702 additions & 1 deletion

File tree

.claude/commands/docs-check.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,28 @@ For each major feature, verify a tutorial covers it:
202202

203203
Check each tutorial file exists and is non-empty.
204204

205+
### 5b. Docs IA Registration Check (post-#703 information architecture)
206+
207+
The site navigation contract is CI-enforced by `tests/test_docs_ia.py` (docs-tests
208+
workflow). Run it directly for immediate feedback:
209+
210+
```bash
211+
PYTHONPATH=. DIFF_DIFF_BACKEND=python pytest tests/test_docs_ia.py -q
212+
```
213+
214+
What it pins (fix at the source listed, never by widening the test):
215+
1. `docs/index.rst` has ONE toctree = the 5 section landing pages. New top-level
216+
pages join a section landing page (`getting_started` / `practitioners` /
217+
`tutorials/index` / `user_guide` / `api/index`), never the root.
218+
2. Every `docs/tutorials/*.ipynb` is registered in `docs/tutorials/index.rst`
219+
twice: a short-labeled toctree entry (`Label <stem>`, <= 40 chars) in its
220+
group AND a `grid-item-card` with `:link: <stem>`.
221+
3. Homepage "Supported Estimators" table rows match the `api/index.rst`
222+
Estimators autosummary 1:1 - new estimators need BOTH.
223+
4. Any `autoclass` documented with `:no-index:` on a module page needs a
224+
canonical autosummary entry in `api/index.rst`, else `:class:` xrefs to it
225+
render as dead text.
226+
205227
### 6. Cross-Reference Check
206228

207229
For estimators added to the codebase, verify they have:

.github/workflows/docs-tests.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ on:
88
- 'diff_diff/**'
99
- 'tests/test_doc_snippets.py'
1010
- 'tests/test_doc_deps_integrity.py'
11+
- 'tests/test_docs_ia.py'
1112
- 'tests/test_v4_matrix.py'
1213
# tests/conftest.py is auto-loaded by pytest for the snippet
1314
# test run and mutates sys.path + MPLBACKEND (conftest.py:14, 18);
@@ -27,6 +28,7 @@ on:
2728
- 'diff_diff/**'
2829
- 'tests/test_doc_snippets.py'
2930
- 'tests/test_doc_deps_integrity.py'
31+
- 'tests/test_docs_ia.py'
3032
- 'tests/test_v4_matrix.py'
3133
- 'tests/conftest.py'
3234
- 'pyproject.toml'
@@ -81,6 +83,14 @@ jobs:
8183
# step does not install diff_diff.
8284
run: PYTHONPATH=. DIFF_DIFF_BACKEND=python pytest tests/test_doc_deps_integrity.py -v
8385

86+
- name: Run docs IA structural guards
87+
# Pins the #703 information architecture: single 5-section root
88+
# toctree, tutorial dual-registration (short-label toctree entry +
89+
# landing-page card), homepage estimator-table parity with the API
90+
# catalog, and no :no-index:-only classes (dead cross-references).
91+
# All four are valid-Sphinx states the -W build cannot catch.
92+
run: PYTHONPATH=. DIFF_DIFF_BACKEND=python pytest tests/test_docs_ia.py -v
93+
8494
- name: Run v4 deprecation-matrix enforcement
8595
# Asserts every docs/v4-deprecations.yaml row's status against reality
8696
# at HEAD (schema: docs/v4-design.md section 11). Runs here so

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4040
purpose-phrasing, restoring the case as a genuinely clean negative control.
4141

4242
### Added
43+
- **Internal: CI-enforced docs IA guards (`tests/test_docs_ia.py`).** Four structural
44+
invariants protecting the #703 information architecture, all valid-Sphinx states the
45+
`-W` build cannot catch: the root toctree stays exactly the 5 section landing pages
46+
(a 6th entry regrows the navbar "More" dropdown); every tutorial notebook is
47+
registered in `docs/tutorials/index.rst` with BOTH a short-labeled toctree entry
48+
(<= 40 chars) and a landing-page card; the homepage "Supported Estimators" table
49+
stays 1:1 with the `api/index.rst` Estimators autosummary; and no class is
50+
documented only under `:no-index:` (which renders `:class:` cross-references as
51+
dead text - the pre-#703 RDD failure mode). Runs in the docs-tests `doc-snippets`
52+
job; conventions documented in CLAUDE.md, CONTRIBUTING.md, and `/docs-check` 5b.
4353
- **Internal: 4.0 diagnostic-family amendment to the design spec.** `docs/v4-design.md`
4454
gains section 3.5 formalizing a third object kind - diagnostics: the library's
4555
existing "Diagnostics & Sensitivity" family (parallel-trends testing, placebo

CLAUDE.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,11 @@ When adding new functionality, the source of truth is:
152152
- **`docs/tutorials/*.ipynb`** for hands-on examples. New notebooks are registered in
153153
`docs/tutorials/index.rst` (toctree entry with a short display label + a card in the
154154
matching group), NOT in `docs/index.rst` - the root toctree lists only the 5 section
155-
landing pages so the navbar stays at 5 links.
155+
landing pages so the navbar stays at 5 links. These IA invariants (plus homepage
156+
estimator-table parity with the API catalog, and the rule that any class documented
157+
with `:no-index:` on a module page keeps a canonical autosummary entry in
158+
`docs/api/index.rst`) are CI-enforced by `tests/test_docs_ia.py`; the full list is in
159+
CONTRIBUTING.md "Docs IA invariants".
156160
- **`CHANGELOG.md`** for release notes.
157161
- **`README.md`** for ONE LINE in the `## Estimators` flat catalog (or `## Diagnostics & Sensitivity` for diagnostic-class features). Do NOT add usage examples, parameter tables, per-estimator sections, or full bibliographies.
158162

CONTRIBUTING.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,24 @@ If you find yourself adding a usage example, a parameter table, or a multi-parag
8181

8282
9. **`docs/doc-deps.yaml`** - Add source-to-doc mappings for the new module.
8383

84+
### Docs IA invariants (CI-enforced by `tests/test_docs_ia.py`)
85+
86+
The documentation site's information architecture is machine-enforced; a red
87+
`docs-tests` check means one of these was violated:
88+
89+
1. The root `docs/index.rst` toctree lists ONLY the 5 section landing pages
90+
(Getting Started / Practitioner Guide / Tutorials / User Guide / API
91+
Reference). New top-level pages join a section landing page, never the root -
92+
every root entry becomes a navbar item and past 5 the theme regrows an
93+
unusable "More" dropdown.
94+
2. Every tutorial notebook has BOTH a short-labeled toctree entry (<= 40 chars)
95+
and a `grid-item-card`, in the SAME group of `docs/tutorials/index.rst`.
96+
3. The homepage "Supported Estimators" table stays 1:1 with the
97+
`docs/api/index.rst` Estimators autosummary - new estimators need both.
98+
4. A class documented with `:no-index:` on a module page must keep a canonical
99+
autosummary entry in `docs/api/index.rst`, else `:class:` cross-references
100+
to it render as dead text.
101+
84102
### For Bug Fixes or Minor Enhancements
85103

86104
- Update relevant docstrings

0 commit comments

Comments
 (0)