Day one. The PM asks for “a simple spreadsheet — 3x3 grid, cell references, formulas like `=A1*2`. Google Sheets on a page. Thirty minutes?” The junior writes the obvious version: one dictionary {A1: 10, B1: '=A1*2'} and calls eval on every string-valued cell during render. Ship it.
Below is that engine, live. Tap the demo buttons to trigger the three failure classes QA reports within a day. Each demo loads a different sheet into the grid and re-runs the naive resolver; the meters show the failure mode and the cost. Trigger at least two.
Record<string, string>idleEach demo replaces the sheet with a trap input. Watch the grid and the meters change. Feel at least two distinct failures.
These aren't three unrelated bugs — they're three faces of the same structural mismatch. The dictionary holds four things at once: raw values like A1=10, formula sources like "=A1*2", computed outputs like 30, and implied dependency relationships like “C1 reads A1 and B1.” One shape, four invariants, and every mutation has to preserve all four at once. The fix isn't “guard eval”; it's to give each invariant its own table.
Trigger at least two of the three demos. Felt so far: 0 / 3.