Problem
The README advertises a Playwright spec that covers Pyodide bootstrap, sample loading, training, predictions, export and the scatter-plot render (8 assertions). `CLAUDE.md` confirms the spec file is no longer in the repo.
This means every refactor risks silently breaking the Pyodide bootstrap or model-export paths with zero automated signal. The app is a single static site that lives or dies on the bridge between `frontend/js/pyodide-bridge.js` and `frontend/py/learner.py` — exactly the surface a smoke test should defend.
Proposal
Recreate `tests/e2e.spec.ts` (or similar) with at minimum:
- Page loads, `pyodide-ready` event fires within 30 s.
- Load a built-in sample (e.g., Iris).
- Select two features, set a target, pick 3 models, click Train Selected.
- Wait for the comparison chart to render; assert all 3 metrics rows are non-empty.
- Click Export on one model and assert a `.joblib` download is offered.
- Re-run with a regression sample (Airfoil) and assert residuals and predicted-vs-actual charts render.
Acceptance criteria
Blocker note
This should land before any significant feature work; without it every change is a leap of faith.
Problem
The README advertises a Playwright spec that covers Pyodide bootstrap, sample loading, training, predictions, export and the scatter-plot render (8 assertions). `CLAUDE.md` confirms the spec file is no longer in the repo.
This means every refactor risks silently breaking the Pyodide bootstrap or model-export paths with zero automated signal. The app is a single static site that lives or dies on the bridge between `frontend/js/pyodide-bridge.js` and `frontend/py/learner.py` — exactly the surface a smoke test should defend.
Proposal
Recreate `tests/e2e.spec.ts` (or similar) with at minimum:
Acceptance criteria
Blocker note
This should land before any significant feature work; without it every change is a leap of faith.