Background
Every QuantEcon lecture series publishes an Execution Statistics page — a table of which notebooks were executed, how long each took, and whether it succeeded. It is our standing build-health signal: a reader (or maintainer) can open one page and see whether the whole book executed cleanly and how expensive each lecture is. See the live page for the Python Programming series: https://python-programming.quantecon.org/status.html
That page is generated by a single directive in status.md:
Under Sphinx it is provided by myst-nb. Under mystmd it hard-errors, so the page renders as an error block with no table:
| Diagnostic |
Where |
⛔️ status.md:16 unknown directive: nb-exec-table |
every mystmd build of lecture-python-programming |
This surfaced while validating QuantEcon/lecture-python-programming#363 (the jupyter-book 2 / mystmd migration branch) against main on this fork — v1.10.1 (qe-v8). It is the last hard error remaining from the original migration-warnings sweep in QuantEcon/lecture-python-programming#344; the index-syntax and figure scale warnings listed there have since been fixed.
What the Sphinx directive produces
myst-nb implements it in myst_nb/ext/execution_tables.py as one row per notebook in the project, with these columns:
| Column |
Source |
| Document |
the notebook's docname |
| Modified |
source mtime |
| Method |
how it was run — cache hit, forced execution, etc. |
| Run Time (s) |
wall-clock execution time |
| Status |
succeeded / failed |
Why it does not exist in mystmd
Upstream tracks it only as an unchecked line item in the broad feature-parity audit jupyter-book#189 ("Audit of Features missing in JupyterBook"), open since 2023 and listing it alongside bibliography, grid-item and grid-item-card. There is no dedicated upstream issue and no sign of movement, so if we want it for the migration it likely has to start here.
Implementation sketch
Most of the underlying data already exists — the gap is that it is logged rather than retained. During a build with --execute, myst-execute already knows per-notebook cache state and the CLI already prints per-file timing, e.g. 💿 Executing notebook (polars.md) [no execution cache found] followed by 📖 Built polars.md in 26 s. Execution results are persisted per notebook by packages/myst-execute/src/cache.ts (LocalDiskCache, hash-keyed JSON under _build/execute), but that cache stores outputs, not execution metadata.
So a plausible shape is:
- Have the execution pass record a small per-notebook stats record (path, mtime, method, runtime, success) into the session/store rather than only emitting it to the log.
- Add an
nb-exec-table directive that reads those records at render time and emits a standard table node — so it inherits table styling from whichever theme is in use, including quantecon-theme.mystmd.
- Decide the no-execution case: when a build runs without
--execute there are no stats, and the directive should degrade to a clear note rather than an error or an empty table.
Ordering is the main design question — the directive renders while other pages may still be executing, so the table either needs to be populated in a late pass or the page has to be built last.
Worth considering instead
This is a build diagnostic rather than lecture content, and it is the only thing keeping status.md from building clean. If implementing it in the fork is not judged worth the maintenance, the alternative is to retire the directive from the lecture sources and surface execution stats from CI instead — the same data is already in the build log and could be published as a job summary or artifact. Recording that here so the trade-off is explicit rather than defaulted into.
Links
Background
Every QuantEcon lecture series publishes an Execution Statistics page — a table of which notebooks were executed, how long each took, and whether it succeeded. It is our standing build-health signal: a reader (or maintainer) can open one page and see whether the whole book executed cleanly and how expensive each lecture is. See the live page for the Python Programming series: https://python-programming.quantecon.org/status.html
That page is generated by a single directive in
status.md:Under Sphinx it is provided by
myst-nb. Under mystmd it hard-errors, so the page renders as an error block with no table:⛔️ status.md:16 unknown directive: nb-exec-tablelecture-python-programmingThis surfaced while validating QuantEcon/lecture-python-programming#363 (the jupyter-book 2 / mystmd migration branch) against
mainon this fork —v1.10.1 (qe-v8). It is the last hard error remaining from the original migration-warnings sweep in QuantEcon/lecture-python-programming#344; the index-syntax and figurescalewarnings listed there have since been fixed.What the Sphinx directive produces
myst-nbimplements it inmyst_nb/ext/execution_tables.pyas one row per notebook in the project, with these columns:Why it does not exist in mystmd
Upstream tracks it only as an unchecked line item in the broad feature-parity audit jupyter-book#189 ("Audit of Features missing in JupyterBook"), open since 2023 and listing it alongside
bibliography,grid-itemandgrid-item-card. There is no dedicated upstream issue and no sign of movement, so if we want it for the migration it likely has to start here.Implementation sketch
Most of the underlying data already exists — the gap is that it is logged rather than retained. During a build with
--execute,myst-executealready knows per-notebook cache state and the CLI already prints per-file timing, e.g.💿 Executing notebook (polars.md) [no execution cache found]followed by📖 Built polars.md in 26 s.Execution results are persisted per notebook bypackages/myst-execute/src/cache.ts(LocalDiskCache, hash-keyed JSON under_build/execute), but that cache stores outputs, not execution metadata.So a plausible shape is:
nb-exec-tabledirective that reads those records at render time and emits a standard table node — so it inherits table styling from whichever theme is in use, includingquantecon-theme.mystmd.--executethere are no stats, and the directive should degrade to a clear note rather than an error or an empty table.Ordering is the main design question — the directive renders while other pages may still be executing, so the table either needs to be populated in a late pass or the page has to be built last.
Worth considering instead
This is a build diagnostic rather than lecture content, and it is the only thing keeping
status.mdfrom building clean. If implementing it in the fork is not judged worth the maintenance, the alternative is to retire the directive from the lecture sources and surface execution stats from CI instead — the same data is already in the build log and could be published as a job summary or artifact. Recording that here so the trade-off is explicit rather than defaulted into.Links
status.mdnb-exec-tableas unimplemented