Skip to content

DIAGNOSTIC (do not merge): which code cells does thebe-lite actually execute? - #65

Draft
mmcky wants to merge 4 commits into
mainfrom
probe/thebe-cell-nesting
Draft

DIAGNOSTIC (do not merge): which code cells does thebe-lite actually execute?#65
mmcky wants to merge 4 commits into
mainfrom
probe/thebe-cell-nesting

Conversation

@mmcky

@mmcky mmcky commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Draft, never for merge. This exists to give #64 a Netlify preview you can click, and to delete afterwards.

Why a probe rather than reasoning

When a cell fails to execute under thebe-lite there is no error and no output — and for an assignment cell, "no output" is also the correct result. Those two states are indistinguishable by eye, which is exactly why this bug took several wrong turns: a %%file cell producing nothing was read as "the magic is broken" when the cell had simply never run.

So this page makes non-execution observable. Every cell appends a marker to a list; a final top-level REPORT cell prints which markers are present and which are MISSING. One click on that cell names every cell that silently did nothing.

What it probes

Position Question
A top level control — must work
B top level, %%file magic does the magic work at all, independent of nesting?
C top level, reads B's file back did %%file actually write to the FS?
D inside gated {exercise-start} the position that fails in short_path
E inside gated {solution-start} the position that works in short_path — but only because a malformed directive spills it to root
F inside a plain {note} is this specific to exercises, or nesting generally?

How to run it

Open the preview's probe_nesting page, run the cells top to bottom, then run the REPORT cell. Expected output shape:

EXECUTED: ['A_toplevel_setup', 'C_toplevel_after_magic', ...]
MISSING : ['D_in_gated_exercise', ...]
%%file worked at top level: True

What each result would mean

If D is MISSING and A/C/E/F present — nesting inside {exercise} is the cause, confirming #64, and the fix is to move the data cell out of the exercise block.

If D and F are both MISSING — it is nesting generally, not exercises, which is a broader and more interesting upstream report for mystmd/thebe.

If B/C show %%file worked at top level: True — this is the one that changes the design. %%file under thebe-lite has never actually been tested; it was assumed broken on evidence that turned out to be about the cell not running. If it works at top level, lecture-wasm can converge with lecture-python-intro, lecture-dp, lecture-jax, lecture-intro.zh-cn and test-actions-lecture-intro — same %%file graph.txt cell, same canonical open(in_file) helper — instead of carrying a divergent string-based variant indefinitely.

If B/C show False%%file is genuinely unavailable here and the inline literal is the only option, which is worth knowing definitively rather than by assumption.

Relates to #63 and #64.

… executes

Temporary page to settle #64 by measurement rather than
inference. It exists to make a silent failure visible.

The problem it solves: when a cell does not execute under thebe-lite there is no
error and no output — and for an assignment cell, "no output" is also the
CORRECT result. Those two states are indistinguishable by eye, which is what
made this bug take several wrong turns to pin down.

So every cell here appends a marker to a list, and a final top-level REPORT cell
prints which markers are present and which are MISSING. One click on that cell
names every cell that silently did nothing.

Positions probed, all in the same document:

  A  top level                          - control, must work
  B  top level, `%%file` magic          - tests the MAGIC independently of nesting
  C  top level, reads B's file back     - did %%file actually write?
  D  inside a gated {exercise-start}    - the position that fails in short_path
  E  inside a gated {solution-start}    - the position that WORKS in short_path,
                                          but only because a malformed directive
                                          spills it to root level
  F  inside a plain {note} admonition   - is it exercises, or nesting generally?

B and C are the ones that matter for the fix: `%%file` under thebe-lite has never
actually been tested. It was assumed broken, and that assumption was wrong — the
cell it was tried in was nested and never ran at all. If B/C pass at top level,
`%%file` is viable and lecture-wasm can converge with the five sibling repos
instead of carrying a divergent string-based helper forever.

Not for merge. Delete the branch once #64 has its answer.
@netlify

netlify Bot commented Aug 12, 2026

Copy link
Copy Markdown

Deploy Preview for beautiful-dodol-cb9543 failed.

Name Link
🔨 Latest commit 6d934fc
🔍 Latest deploy log https://app.netlify.com/projects/beautiful-dodol-cb9543/deploys/6a7bebb204eca2000837eac9

mmcky added a commit that referenced this pull request Aug 12, 2026
BLOCKED on #64 — do not merge yet. See that issue and the
diagnostic in #65. This PR is the intended END STATE; what
is unproven is whether this runtime can run it.

This lecture executes in the reader's browser (`lite: true`) and was the only
repo in the family fetching this graph across repos on every page view:

    import requests
    file_url = "https://raw.githubusercontent.com/QuantEcon/lecture-python-intro/main/lectures/graph.txt"
    graph_file_response = requests.get(file_url)

Every sibling — lecture-python-intro, lecture-dp, lecture-jax,
lecture-intro.zh-cn and test-actions-lecture-intro — writes the data with a
`%%file graph.txt` cell and reads it back with `open(in_file)`. This repo now
does the same, so all six are identical on this exercise, and the divergent
string-splitting helper `map_graph_to_distance_matrix(in_file_data)` returns to
the canonical filename form.

It also retires a cross-repo dependency: that `requests.get` was the only thing
reading lecture-python-intro's committed `lectures/graph.txt` anywhere in the
organisation, so intro could not delete its copy while this line stood. This
repo's own byte-identical `lectures/graph.txt`, which nothing read, is deleted
here too.

WHY THIS IS BLOCKED, and what is NOT known. `short_path` cannot be completed
in-browser today, and this PR does not change that. `myst-ext-exercise` nests a
gated `{exercise-start}` body as children of the `exercise` node — `exercise-start`
is an ALIAS for `exercise`, not a hoist — and thebe only wires up cells at the
top-level block layer. So the data cell sits at
['root','block','exercise','block'] and never executes, whichever form it takes.
On `main` two cells are stranded there; with this change it is one.

A second bug currently masks a worse version of that one. `short_path.md:480` is
a bare ```{solution}``` closer that mystmd rejects, so the solution node is empty
and its five cells spill to root level — which is the ONLY reason they are
runnable. Correcting it to the gated pair was tried and rebuilt: the error
clears, the cells correctly re-nest, and the page would go from one dead cell to
six. So that fix is deliberately NOT included here.

RETRACTED, and recorded so it is not repeated: an earlier revision of this PR
asserted that `%%file` does not fire under thebe-lite. That was wrong. The
evidence was a cell producing no output and a later FileNotFoundError, both of
which are equally explained by the cell never having executed — which is what
was happening. `%%file` under thebe-lite has never been tested. #65 tests it at
top level, where nesting cannot confound the result.

Equivalence of the data itself is measured, not assumed: intro's canonical
filename-based helper over the file written by this cell gives 286 finite
entries, Q[99,99]=0.0 and J[0]=160.5500, identical to the network path this
replaces, and the written file is byte-identical at 4,691 bytes,
sha256 046759fb...

graph.txt is not migrating to QuantEcon/data-lectures: it is synthetic teaching
data with null provenance, the exercise prose depends on it being visible, and
that repo is a cache for upstream sources rather than a host for our examples.
@github-actions

Copy link
Copy Markdown

📖 Netlify Preview Ready!

Preview URL: https://pr-65--beautiful-dodol-cb9543.netlify.app (1e857e3)

✨ Browse the preview at the URL above.

The probe page was committed but never reached the toc, so mystmd did not build
it and the preview 404s — 42 pages published, none of them the probe.

Cause: the edit that was supposed to add it matched on the wrong indentation
(`    toc:` / `      - file:` where this file has `  toc:` / `    - file:`), and
the script printed a success message unconditionally instead of asserting the
replacement had happened. A silent no-op reported as done — the same failure
mode this probe exists to expose, which is a fair thing to have walked into.

This version asserts the anchor matches exactly once and re-reads the file to
confirm the entry is present before exiting.

Also drops the `.md` extension to match every other toc entry in this file.
@github-actions

Copy link
Copy Markdown

📖 Netlify Preview Ready!

Preview URL: https://pr-65--beautiful-dodol-cb9543.netlify.app (fdd0b9d)

✨ Browse the preview at the URL above.

mmcky added 2 commits August 12, 2026 13:42
The `{note}` container used three backticks around a three-backtick code-cell,
so the inner fence closed the outer directive. Everything after it was absorbed:
the REPORT cell's value began with the literal markdown

    ## REPORT (top level)

    ```{code-cell} ipython3

and would have raised SyntaxError rather than reporting anything — the probe
would have failed in a way that says nothing about what it is probing.

A container directive wrapping a code-cell needs MORE backticks than the cell.
The gated `{exercise-start}` / `{solution-start}` forms are unaffected: they are
standalone directives rather than containers, which is why D and E nested
correctly while F's block leaked.

Now asserts its own structure after writing: exactly 7 code cells, none
containing markdown, and the REPORT cell starting where it should.
The page rendered but showed no JupyterLite power button, so nothing on it could
be run — the probe was unrunnable for a reason unrelated to what it probes.

Cause: its frontmatter carried only `title`. Every real lecture here carries
`jupytext` + `kernelspec`, and without a kernelspec mystmd does not treat the
page as a notebook, so thebe never attaches a kernel.

Frontmatter is now copied from short_path.md, the page this probe is modelling.

This is worth recording rather than just fixing, because it is a third distinct
way a cell can fail to execute here, each silent in its own way:

  1. no kernelspec        -> whole page has no kernel, no run controls
  2. nested in a directive -> cell renders with controls but is never wired up
  3. cell simply not run   -> indistinguishable from a cell that ran and printed
                              nothing, which is the normal case for an assignment

All three look like "nothing happened". Only the third is the reader's fault,
and the probe's REPORT cell is designed to separate it from the other two.
@github-actions

Copy link
Copy Markdown

📖 Netlify Preview Ready!

Preview URL: https://pr-65--beautiful-dodol-cb9543.netlify.app (6d934fc)

✨ Browse the preview at the URL above.

mmcky added a commit that referenced this pull request Aug 12, 2026
…run (#63)

* short_path: write the graph with %%file, as every other repo does

BLOCKED on #64 — do not merge yet. See that issue and the
diagnostic in #65. This PR is the intended END STATE; what
is unproven is whether this runtime can run it.

This lecture executes in the reader's browser (`lite: true`) and was the only
repo in the family fetching this graph across repos on every page view:

    import requests
    file_url = "https://raw.githubusercontent.com/QuantEcon/lecture-python-intro/main/lectures/graph.txt"
    graph_file_response = requests.get(file_url)

Every sibling — lecture-python-intro, lecture-dp, lecture-jax,
lecture-intro.zh-cn and test-actions-lecture-intro — writes the data with a
`%%file graph.txt` cell and reads it back with `open(in_file)`. This repo now
does the same, so all six are identical on this exercise, and the divergent
string-splitting helper `map_graph_to_distance_matrix(in_file_data)` returns to
the canonical filename form.

It also retires a cross-repo dependency: that `requests.get` was the only thing
reading lecture-python-intro's committed `lectures/graph.txt` anywhere in the
organisation, so intro could not delete its copy while this line stood. This
repo's own byte-identical `lectures/graph.txt`, which nothing read, is deleted
here too.

WHY THIS IS BLOCKED, and what is NOT known. `short_path` cannot be completed
in-browser today, and this PR does not change that. `myst-ext-exercise` nests a
gated `{exercise-start}` body as children of the `exercise` node — `exercise-start`
is an ALIAS for `exercise`, not a hoist — and thebe only wires up cells at the
top-level block layer. So the data cell sits at
['root','block','exercise','block'] and never executes, whichever form it takes.
On `main` two cells are stranded there; with this change it is one.

A second bug currently masks a worse version of that one. `short_path.md:480` is
a bare ```{solution}``` closer that mystmd rejects, so the solution node is empty
and its five cells spill to root level — which is the ONLY reason they are
runnable. Correcting it to the gated pair was tried and rebuilt: the error
clears, the cells correctly re-nest, and the page would go from one dead cell to
six. So that fix is deliberately NOT included here.

RETRACTED, and recorded so it is not repeated: an earlier revision of this PR
asserted that `%%file` does not fire under thebe-lite. That was wrong. The
evidence was a cell producing no output and a later FileNotFoundError, both of
which are equally explained by the cell never having executed — which is what
was happening. `%%file` under thebe-lite has never been tested. #65 tests it at
top level, where nesting cannot confound the result.

Equivalence of the data itself is measured, not assumed: intro's canonical
filename-based helper over the file written by this cell gives 286 finite
entries, Q[99,99]=0.0 and J[0]=160.5500, identical to the network path this
replaces, and the written file is byte-identical at 4,691 bytes,
sha256 046759fb...

graph.txt is not migrating to QuantEcon/data-lectures: it is synthetic teaching
data with null provenance, the exercise prose depends on it being visible, and
that repo is a cache for upstream sources rather than a host for our examples.

* short_path: move the graph data cell out of the exercise so it can run

A code cell nested in any directive is never registered with the kernel by
@myst-theme/jupyter, so inside `{exercise-start}` this cell renders a run button
that does nothing, and the solution then fails with FileNotFoundError. It is the
only cell on the page in that position — every other cell is already top level
and runs.

Moving it below `{exercise-end}` makes the whole lecture runnable in the
browser for the first time. Reading order is unchanged: the prose still says
"The text below describes a weighted directed graph" and the data still appears
directly beneath it, just outside the exercise's box. The solution's "reads in
the graph data above" is likewise still accurate.

A comment records why it sits there, so nobody tidies it back in — that would
silently break the page again, with no error and no CI signal.

Root cause and the general fix: #64 and
QuantEcon/quantecon-theme.mystmd#117.

Verified the move did not touch the data: 9 cells, 100 data lines,
reconstitutes to 4,691 bytes / sha256 046759fb..., and the cell now sits
strictly between `{exercise-end}` and the solution.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant