CI blind spot: interactive ipywidgets callbacks aren't exercised (slider-state bugs slip through)
- Dominant language
- Jupyter Notebook
- Stars
- 12
- Forks
- 76
- PR merge metrics
- No merged PRs in 30d
Description
## Problem
CI runs notebooks via `jupyter nbconvert --execute` — each cell once, top-to-bottom, with **no widget interaction**. So bugs that only appear when a user *interacts* with an `ipywidgets` control (moves a slider), or that depend on **shared global state mutated by later cells**, are invisible to CI.
## Concrete example (just fixed in `60_linear_algebra_2/200`)
The Power Method arrow-slider callback `show_iterate(step)` read the global `n`. Cells 49/52/58 (`lam, vecX, n = power_method(...)`) overwrite `n` → `99999` for the non-converging "What if" matrices. After running those cells, **moving the slider** raised:
```
ValueError: shape mismatch ... (99999,) vs (2,) # ax.bar(range(99999), vec[2])
```
CI passed cleanly because:
- the `interact` callback only fires once, at creation, when `n` was still correct;
- nbconvert never moves the slider, and never re-fires the callback after `n` is clobbered;
- the `if os.getenv('CI'): show_iterate(last)` guard renders one static frame — by design, to keep CI green — which also means the interactive path is never exercised.
(Fixed by capturing the dimension locally: `dim = vec_array.shape[1]`, independent of the mutable global `n`.)
## Options
1. **Convention (cheapest):** widget callbacks must capture all needed state **locally** in their own cell, never reading mutable globals that later cells reassign. Make it a review/lint checklist item.
2. **Exercise callbacks in a test:** for notebooks containing `interact(...)`, after executing all cells, call the callback across its full slider range and assert no exception. Non-trivial to wire generically.
3. **Static check:** flag a widget callback that references a module-level name reassigned elsewhere in the same notebook. Hard to do reliably (needs data-flow analysis).
## Related
Same family as #440 and the "missing Colab clone cell" gap — CI executes the *repo, non-interactive* path, not the *interactive/Colab* path.
🤖 Filed via Claude Code after fixing the 200 slider crash.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by reviewing the CI command, the interactive notebook path 60_linear_algebra_2/200, and the related issue #440. Decide which of the three proposed approaches is in scope, then define a reproducible check for callbacks whose state changes after later cells run. Done should include coverage for the slider-state failure without breaking the existing non-interactive CI path.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- jupyter-notebook, python
- Domain
- ci-cd, testing-qa
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100