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
3 changes: 3 additions & 0 deletions CHANGE_LOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ This file records completed project work in chronological order.

## 2026-06-22

- Activated Phase 31 on `feature/p31-literate-notebook-examples`, created GitHub parent issue #183 and child issues #187, #185, #186, #184, #188, and #189, and scoped the next `0.1.0a6` alpha around actual known-valid literate `.ipynb` notebook files for the synthetic and generated 2020 FABLE examples, plus matching Sphinx Examples Gallery documentation and validation.
- Completed P31.1 through P31.5 by adding real literate Jupyter notebooks under `examples/notebooks/` for the synthetic and generated 2020 FABLE notebook-interface workflows; each notebook includes headings, explanatory markdown, code cells, and stored outputs; Sphinx Examples Gallery pages now link to downloadable `.ipynb` files; and default tests validate notebook JSON, Python kernel metadata, markdown-before-code structure, stored outputs, synthetic notebook execution, and static FABLE notebook validation-boundary output without running the expensive generated FABLE model in default pytest.
- Prepared the `0.1.0a6` release candidate by bumping package/import metadata and release docs, passing repo-local bootstrap, Ruff, default `pytest -vv` with `167` passed and `1` benchmark skip, Sphinx warning-as-error docs with notebook downloads copied, Read the Docs theme verification, and `scripts/check_release_artifacts.sh`; the artifact checker built a roughly `56K` wheel and `2.2M` sdist, included the tracked literate notebooks in the sdist, installed the wheel into a clean ignored environment, imported `modelwright 0.1.0a6`, and smoke-tested the CLI.
- Activated Phase 30 on `feature/p30-notebook-dataframe-interface`, created GitHub parent issue #174 and child issues #175, #178, #176, #177, #179, and #180, and scoped the next `0.1.0a5` alpha around an optional pandas-backed notebook/DataFrame layer over `modelwright.wrappers` for live-kernel inspection, scenario mutation, table rendering, and baseline-vs-scenario comparison workflows.
- Completed P30.1 through P30.5 by adding `modelwright.notebooks` with lazy pandas-backed DataFrame helpers for declared inputs, outputs, scenarios, tables, reports, and baseline-vs-scenario comparisons; added a `notebook` optional extra with `pandas>=2` while keeping pandas out of core dependencies; documented the notebook workflow in Sphinx; added always-on synthetic notebook tests plus real generated synthetic model coverage; and extended the opt-in FABLE wrapper benchmark so `MODELWRIGHT_RUN_FABLE_BENCHMARKS=1 .venv/bin/python -m pytest -vv tests/test_fable_wrapper_benchmark.py` passed in 149.67 seconds against ignored local 2020 FABLE artifacts while preserving the existing `281,741` matches and `0` mismatches evidence boundary.
- Added P30.6 release examples scope with a tracked `examples/` directory, a tiny synthetic notebook-interface example, a production-size 2020 FABLE notebook-interface example backed by compressed generated Python output rather than the original workbook, Sphinx Examples Gallery pages linked from the docs index, and lightweight tests that verify example integrity without running the expensive FABLE generated-model calculation in default pytest.
Expand Down
2 changes: 1 addition & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1 +1 @@
recursive-include examples *.md *.py *.xz
recursive-include examples *.ipynb *.md *.py *.xz
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ Restore the public external FABLE benchmark workbooks into ignored local paths:
scripts/bootstrap_dev_env.sh --benchmarks
```

`modelwright` is pre-release. The current alpha line is `0.1.0a5`; alpha releases must not be described as full-workbook conversion guarantees.
`modelwright` is pre-release. The current alpha line is `0.1.0a6`; alpha releases must not be described as full-workbook conversion guarantees.

Check release artifacts locally:

Expand Down
101 changes: 98 additions & 3 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -863,7 +863,7 @@ Release target: `modelwright==0.1.0a5`.
- [x] Add Sphinx Examples Gallery pages linked from the docs index.
- [x] Add lightweight tests for example integrity without running expensive production-size FABLE
calculation in default pytest.
- [ ] P30.7 Publish `modelwright==0.1.0a5`. Child issue: #180.
- [x] P30.7 Publish `modelwright==0.1.0a5`. Child issue: #180.
- Status: complete.
- [x] Confirm P30 notebook/DataFrame scope and evidence are complete.
- [x] Bump package/import version and release docs to `0.1.0a5`.
Expand Down Expand Up @@ -929,5 +929,100 @@ Release result:

## Current Next Steps

1. Keep Phase 30 closed unless a release defect is discovered.
2. Plan the next roadmap phase before opening a new feature branch.
## Phase 31: Literate Notebook Examples Gallery

GitHub parent issue: #183

Active branch: `feature/p31-literate-notebook-examples`

Status: active.

Goal: substantially enhance the examples seed from Phase 30 with actual known-valid Jupyter
notebook files and matching Sphinx gallery documentation. The notebooks should follow a literate
programming style: headings and subheadings, explanatory markdown before code, code cells, stored
outputs, and enough context that motivated new users can understand the workflow without reading
package internals first.

Release target: `modelwright==0.1.0a6`.

- [x] P31.1 Define literate notebook example contract. Child issue: #187.
- Status: complete.
- [x] Decide notebook file placement and naming.
- [x] Define required markdown/code/output structure.
- [x] Define how notebooks import repo examples from source checkouts and installed packages.
- [x] Define validation strategy for notebook JSON, markdown/code alternation, expected outputs, and
expensive FABLE execution boundaries.
- [x] Record non-goals and release boundary in roadmap/planning docs.
- [x] P31.2 Add synthetic `.ipynb` notebook example. Child issue: #185.
- Status: complete.
- [x] Add a real `.ipynb` file with headings, explanatory markdown, code cells, and stored outputs.
- [x] Show import setup, facade construction, scenario creation, input/output frames, table frame,
and scenario comparison.
- [x] Keep the notebook fast enough for default validation.
- [x] Add tests that verify the notebook is valid and its expected outputs stay synchronized.
- [x] P31.3 Add 2020 FABLE `.ipynb` notebook example. Child issue: #186.
- Status: complete.
- [x] Add a real `.ipynb` file with headings, explanatory markdown, code cells, and stored outputs.
- [x] Explain the compressed generated-model artifact and why the original workbook is not tracked.
- [x] Show facade construction, calculation, output frames, table frame, report frames, and
validation-boundary context.
- [x] Avoid running the expensive FABLE generated-model calculation in default pytest; keep full
execution opt-in.
- [x] Keep raw workbooks and generated decompressed models ignored under `tmp/`.
- [x] P31.4 Integrate notebooks into examples gallery docs. Child issue: #184.
- Status: complete.
- [x] Add notebook download/open links to the examples gallery pages.
- [x] Explain the intended workflow for opening notebooks from a source checkout.
- [x] Keep generated workbook binaries and raw validation reports out of docs.
- [x] Verify Sphinx docs build warning-free.
- [x] P31.5 Validate notebook examples and docs. Child issue: #188.
- Status: complete.
- [x] Validate notebook JSON structure and metadata.
- [x] Validate literate structure: headings, explanatory markdown before code, code cells, and stored
outputs.
- [x] Execute or otherwise verify the synthetic notebook in default tests.
- [x] Keep production-size FABLE execution opt-in but verify static stored outputs and provenance in
default tests.
- [x] Run Ruff, pytest, Sphinx docs, and docs theme verification.
- [x] Record evidence in roadmap, changelog, and issue comments.
- [ ] P31.6 Publish `modelwright==0.1.0a6`. Child issue: #189.
- Status: active.
- [x] Confirm P31 notebook example scope and evidence are complete.
- [x] Bump package/import version and release docs to `0.1.0a6`.
- [x] Run local release checks, including Ruff, pytest, Sphinx docs, docs theme verification, and
release artifact checks.
- [ ] Open and merge the P31 PR to `main`.
- [ ] Create annotated tag `v0.1.0a6`.
- [ ] Publish through the gated release workflow after maintainer approval.
- [ ] Verify PyPI JSON, clean PyPI install, import version, CLI help, GitHub release, and docs deployment.

Acceptance boundary:

- May claim tracked, known-valid literate notebook examples for synthetic and generated 2020 FABLE
notebook/DataFrame workflows.
- May claim Sphinx Examples Gallery pages that link to actual `.ipynb` notebooks.
- Must not claim a full spreadsheet UI, automatic workbook semantic recovery, stable public API
compatibility, or Excel-backed recalculation equivalence.

Implementation evidence:

- Added `examples/notebooks/synthetic-notebook-interface.ipynb` with literate markdown, code cells,
and stored outputs for the synthetic notebook/DataFrame workflow.
- Added `examples/notebooks/fable-2020-notebook-interface.ipynb` with literate markdown, code cells,
and stored outputs for the generated 2020 FABLE wrapper workflow.
- Added notebook download links to the Sphinx Examples Gallery pages.
- Added default tests that parse notebook JSON, verify Python 3 kernel metadata, validate markdown
before code, require stored outputs, execute the synthetic notebook code cells, and verify the FABLE
notebook's stored validation-boundary output without running the expensive generated model.

Verification evidence:

- `scripts/bootstrap_dev_env.sh` passed and installed the `0.1.0a6` editable package.
- `.venv/bin/python -m ruff check .` passed.
- `.venv/bin/python -m pytest -vv` passed with `167` passed and `1` skipped benchmark.
- `.venv/bin/sphinx-build -b html docs _build/html -W` passed and copied the notebook downloads.
- `.venv/bin/python scripts/verify_docs_theme.py _build/html` passed.
- `scripts/check_release_artifacts.sh` passed for `0.1.0a6`; the clean wheel install imported
`modelwright 0.1.0a6` and the artifact inspection included the tracked notebook files in the sdist
without including source workbooks, ignored `tmp/`, or private validation material.
- Local release artifacts were about `56K` for the wheel and `2.2M` for the sdist.
3 changes: 3 additions & 0 deletions docs/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ Examples Gallery
These examples show the path from generated Python models to analyst-facing wrapper facades and
notebook-friendly DataFrame displays.

The gallery includes both plain Python source examples and real Jupyter notebook files. The notebooks
are written in a literate style: markdown context, code cells, and stored outputs.

.. toctree::
:maxdepth: 1

Expand Down
9 changes: 8 additions & 1 deletion docs/examples/fable-2020-notebook-interface.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ The example wraps three validated ``SCENARIOS selection`` outputs, renders them
keeps the validation boundary explicit: the source Phase 26 full-validation report recorded 281,741
comparable cached outputs, 281,741 matches, and 0 mismatches.

Open the literate notebook:

- :download:`fable-2020-notebook-interface.ipynb <../../examples/notebooks/fable-2020-notebook-interface.ipynb>`

Run it from the repository root:

.. code-block:: bash
Expand All @@ -24,9 +28,12 @@ Use it from a notebook stored under ``tmp/notebooks/``:
import sys

repo_root = Path.cwd().resolve()
while repo_root.name != "sheetforge":
while repo_root != repo_root.parent and not (repo_root / "pyproject.toml").exists():
repo_root = repo_root.parent

if not (repo_root / "pyproject.toml").exists():
raise RuntimeError("Could not find the Modelwright repository root.")

sys.path.insert(0, str(repo_root))

from examples.fable_2020.notebook_interface import build_facade
Expand Down
9 changes: 8 additions & 1 deletion docs/examples/synthetic-notebook-interface.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ This tiny example uses a small generated-model-shaped ``calculate(inputs=None)``
with ``ModelFacade``, and renders outputs, a declared table, and a baseline-vs-scenario comparison as
DataFrames.

Open the literate notebook:

- :download:`synthetic-notebook-interface.ipynb <../../examples/notebooks/synthetic-notebook-interface.ipynb>`

Run it from the repository root:

.. code-block:: bash
Expand All @@ -19,9 +23,12 @@ Use it from a notebook stored under ``tmp/notebooks/``:
import sys

repo_root = Path.cwd().resolve()
while repo_root.name != "sheetforge":
while repo_root != repo_root.parent and not (repo_root / "pyproject.toml").exists():
repo_root = repo_root.parent

if not (repo_root / "pyproject.toml").exists():
raise RuntimeError("Could not find the Modelwright repository root.")

sys.path.insert(0, str(repo_root))

from examples.synthetic.notebook_interface import build_facade
Expand Down
9 changes: 8 additions & 1 deletion docs/guides/notebook-interface.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ Install the optional notebook dependency when using these helpers:

The core package and ``modelwright.wrappers`` do not require pandas.

The tracked examples also include real notebook files under ``examples/notebooks/``. They are the
best starting point for users who want a literate, open-and-run walkthrough rather than copying code
from this guide.

When using the tracked source-tree examples from a notebook stored under ``tmp/notebooks/``, add the
repository root to ``sys.path`` before importing from ``examples``:

Expand All @@ -22,9 +26,12 @@ repository root to ``sys.path`` before importing from ``examples``:
import sys

repo_root = Path.cwd().resolve()
while repo_root.name != "sheetforge":
while repo_root != repo_root.parent and not (repo_root / "pyproject.toml").exists():
repo_root = repo_root.parent

if not (repo_root / "pyproject.toml").exists():
raise RuntimeError("Could not find the Modelwright repository root.")

sys.path.insert(0, str(repo_root))

Boundary
Expand Down
18 changes: 9 additions & 9 deletions docs/guides/release-deployment.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ all been checked.
Current Alpha Target
--------------------

The current alpha target is ``0.1.0a5`` with Git tag ``v0.1.0a5``.
The current alpha target is ``0.1.0a6`` with Git tag ``v0.1.0a6``.

The alpha may claim full comparable-output validation for the 2020 FABLE Calculator benchmark:
281,741 comparable cached workbook outputs, 281,741 matches, and zero mismatches. It may also claim
the measured Phase 27 generated-runtime and generated-source-size improvements recorded in
``planning/phase-27-performance-memory-hardening.md`` and the initial ``modelwright.wrappers``
facade helpers for building analyst-facing wrappers around generated models. The ``0.1.0a5`` alpha
may additionally claim optional pandas-backed notebook helpers and a tracked Examples Gallery with
synthetic and compressed generated 2020 FABLE model examples. It must not claim full-workbook
conversion, a full spreadsheet UI, Excel-backed recalculation equivalence, compact runtime IR
production readiness, or stable public API compatibility.
facade helpers for building analyst-facing wrappers around generated models. The ``0.1.0a6`` alpha
may additionally claim optional pandas-backed notebook helpers, a tracked Examples Gallery with
synthetic and compressed generated 2020 FABLE model examples, and real literate `.ipynb` notebooks
with stored outputs. It must not claim full-workbook conversion, a full spreadsheet UI, Excel-backed
recalculation equivalence, compact runtime IR production readiness, or stable public API compatibility.

Local Release Checks
--------------------
Expand Down Expand Up @@ -75,7 +75,7 @@ After TestPyPI publication, install the package from TestPyPI in a clean environ

.. code-block:: bash

python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ modelwright==0.1.0a5
python -m pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ modelwright==0.1.0a6
python -c "import modelwright; print(modelwright.__version__)"
modelwright --help

Expand All @@ -89,7 +89,7 @@ Expected sequence:
1. Confirm ``CHANGE_LOG.md`` and release notes describe the actual alpha boundary.
2. Confirm local and CI release artifact checks pass.
3. Confirm TestPyPI rehearsal passes or document the exact blocker.
4. Create the annotated tag, for example ``v0.1.0a5``.
4. Create the annotated tag, for example ``v0.1.0a6``.
5. Run the ``Release`` workflow or push the tag, then approve the protected PyPI environment.
6. Verify the package page, wheel install, import, CLI help, docs deployment, and GitHub release notes.

Expand All @@ -102,7 +102,7 @@ Use one of these responses:

- yank the broken release on PyPI if installation should be discouraged but historical availability is
still useful;
- publish a new alpha such as ``0.1.0a6`` after fixing the issue;
- publish a new alpha such as ``0.1.0a7`` after fixing the issue;
- update release notes and roadmap entries with the failure mode and mitigation.

Private Data Rules
Expand Down
7 changes: 6 additions & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ facades and notebook-friendly DataFrame helpers.
- `synthetic/`: a tiny generated-model example based on the tracked synthetic fixture shape.
- `fable_2020/`: a production-size example using a compressed generated Python model converted from
the public 2020 FABLE Calculator benchmark workbook.
- `notebooks/`: real Jupyter notebooks with markdown explanation, code cells, and stored outputs for
the synthetic and FABLE examples.

The original FABLE workbook is not tracked here. The tracked FABLE example contains Modelwright's
generated Python output, compressed as `generated_fable_2020_model.py.xz` because the uncompressed
Expand All @@ -21,9 +23,12 @@ from pathlib import Path
import sys

repo_root = Path.cwd().resolve()
while repo_root.name != "sheetforge":
while repo_root != repo_root.parent and not (repo_root / "pyproject.toml").exists():
repo_root = repo_root.parent

if not (repo_root / "pyproject.toml").exists():
raise RuntimeError("Could not find the Modelwright repository root.")

sys.path.insert(0, str(repo_root))
```

Expand Down
11 changes: 11 additions & 0 deletions examples/notebooks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Literate Notebook Examples

These notebooks are tracked examples for the Sphinx Examples Gallery.

- `synthetic-notebook-interface.ipynb` is a tiny, fast notebook that can be checked in default tests.
- `fable-2020-notebook-interface.ipynb` documents the production-size generated 2020 FABLE model
workflow. The notebook contains known-valid stored outputs, while full execution remains opt-in
because the generated model import and calculation are intentionally large.

Open them from a source checkout with JupyterLab or Jupyter Notebook. The first code cell adds the
repository root to `sys.path` so imports from the local `examples/` directory resolve.
Loading
Loading