Repository navigation
Refresh the docs notebooks and fail CI when they drift from the library - #170
Merged
Merged
Conversation
## Summary - **What:** a script, `scripts/refresh_notebooks.py`, that re-executes the docs notebooks; CI runs it with `--check` in place of nbmake; the notebooks are refreshed. - **Why:** the docs site shows each notebook's saved outputs without running them, and nbmake only checked that they execute. Eight tutorials had drifted (limits from before 0.4.0 in the Design-State-1 analysis; flat Xbar limits where they now vary with n in the reference validation; older process means, lane charts and signal counts), and Derived Variables had never been executed, so the site showed its code with no output. - **Scope:** the script and its tests; ci.yml (one step); the `[test]` extra; nine refreshed notebooks with three prose fixes; CONTRIBUTING.md; CHANGELOG. Stacked on #168, whose signal-rule fixes the refreshed outputs show. ## Contract / Invariants (must remain true) - [x] **Default behavior unchanged:** nothing under `processbehavior/` changes; Bishop gate 1547/0/4 - [x] **Residuals unaffected:** no library change - [x] **Row/index alignment preserved:** no library change - [x] **Lane boundaries preserved:** no library change - [x] **Output schema compatible:** no library change; notebook code cells and metadata unchanged ## Behavior Changes (explicit) - **New API:** `python scripts/refresh_notebooks.py [PATH ...] [--check]` - **New semantics:** - CI executes every docs notebook (globbed, no hand-kept list) and fails if what a reader sees differs from what is saved: printed text, errors, tables, and each figure's data, title, axis titles, annotations and shape positions - Ignored as noise: the temporary path in a warning's location, a derived variable's random id, how the kernel chunks printed text, plotly templates, typed-array encoding, NaN vs null, and float digits past 10 significant figures - A refresh keeps the saved bytes of every cell whose visible content is unchanged, so float noise does not churn the diff ## Key Design Decisions - **Compare what a reader sees, not bytes:** CI resolves plotly 7.x while local venvs may have 6.x; figures are compared on decoded data and labels - **Refresh the whole set from one command;** CONTRIBUTING says when to run it and to reread the prose around changed outputs - **Prose:** only text a refreshed output contradicted was changed - signal-detection: Rules 4 and 5 read "Suggests a sustained shift" and "Suggests drift" - sds-validation: the Slide 19 and 32 reference values now quote the VAS rerun of 13 October 2026 used by the gate (PP 1.58, PPL 1.84 on Slide 32); the current process mean is explained as the mean of the cell means (237.83) beside the plain average (237.81) - stratified-analysis: Lane D's one signal is a chance six-point trend in a lane with no special cause ## Risks & Mitigations - **P0 risks:** a false drift report in CI from an environment difference - **Mitigations:** the check passed three runs in a row locally; normalisation covers the differences found (stream chunking, NaN, random ids, temp paths); if CI finds another, normalise that field rather than fall back to text only ## Tests ### Added / Updated - [x] `tests/test_refresh_notebooks.py` (8 tests): docs notebooks found; warning paths, random ids, stream chunking, plotly template and bdata-vs-list ignored; a changed number in text, a changed figure value and a changed figure label all count as drift ### Regression Focus (must fail if broken) - [x] a stale saved output passes CI (negative check: one saved digit changed in a scratch copy fails with the cell named and the difference shown) - [x] noise fails CI (three consecutive clean runs) ## Manual Verification - [x] `python scripts/refresh_notebooks.py --check`: all 14 current - [x] `pytest tests/`: 2704 passed, 7 skipped - [x] `python validation/e2e_bishop_report.py`: 1547 passed, 0 failed - [x] `ruff check .` clean; mypy shows the same 15 advisory errors - [x] `mystmd@1.10.1 build --html` succeeds; only the three existing changelog citation warnings ## Notes - **Docs:** CONTRIBUTING.md "Docs notebooks"; CHANGELOG [Unreleased] Fixed and CI / Infrastructure - **sds-validation diff** is large (about 100k lines) because two R2/X charts now plot 1599 points where 1565 were saved, which shifts whole arrays; the encoding is unchanged and the file grew by 12 KB - **Follow-ups (not in this PR):** none
…to a tolerance CI's first run of the notebook check found two differences between Linux CI and macOS, neither a stale saved output: - **Factor x time interaction chart:** it sorted its points by time with pandas' default (unstable) sort, so the order of factor combinations within a time, and with it the legend order and each line's colour, depended on the numpy version (CI 2.4.6/2.5.4, local 2.4.0). It now sorts stably, keeping the groupby's factor order. Test: `test_lines_are_in_factor_order`. The one notebook cell showing this chart is refreshed. - **Float noise:** one value differed in its 11th significant figure, on the boundary of the 10-figure rounding the check used. Figure numbers are now compared to a relative 1e-9 (`same()`), with tests for noise ignored and for real changes, including a reordered legend, still caught. Checks: `refresh_notebooks.py --check` passes twice in a row; pytest 2707 passed, 7 skipped; Bishop gate 1547/0; ruff clean.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
scripts/refresh_notebooks.py, that re-executes the docs notebooks; CI runs it with--checkin place of nbmake; the notebooks are refreshed.[test]extra; nine refreshed notebooks with three prose fixes; one plotting fix the check exposed (below); CONTRIBUTING.md; CHANGELOG. Stacked on Make signal rules 2, 5 and 6 match their definitions; correct the WECO rates #168, whose signal-rule fixes the refreshed outputs show.Contract / Invariants (must remain true)
Behavior Changes (explicit)
python scripts/refresh_notebooks.py [PATH ...] [--check]Key Design Decisions
Compare what a reader sees, not bytes: CI resolves plotly 7.x while local venvs may have 6.x; figures are compared on decoded data and labels
Refresh the whole set from one command; CONTRIBUTING says when to run it and to reread the prose around changed outputs
Prose: only text a refreshed output contradicted was changed
Interaction chart order (found by this check on its first CI run):
create_time_interaction_chartsorted by time with an unstable sort, so the order of factor combinations within a time depended on the numpy version (Linux CI 2.4.6/2.5.4 vs macOS 2.4.0). It now useskind='stable', keeping the groupby's factor order;test_lines_are_in_factor_orderpins itRisks & Mitigations
Tests
Added / Updated
tests/test_refresh_notebooks.py(10 tests): docs notebooks found; warning paths, random ids, stream chunking, plotly template, bdata-vs-list and last-digit float noise ignored; a changed number in text, a changed figure value, a changed figure label and a reordered legend all count as drifttest_lines_are_in_factor_order(interaction chart legend order)Regression Focus (must fail if broken)
Manual Verification
python scripts/refresh_notebooks.py --check: all 14 currentpytest tests/: 2707 passed, 7 skippedpython validation/e2e_bishop_report.py: 1547 passed, 0 failedruff check .clean; mypy shows the same 15 advisory errorsmystmd@1.10.1 build --htmlsucceeds; only the three existing changelog citation warningsNotes