Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions AGENTS.md

Large diffs are not rendered by default.

21 changes: 15 additions & 6 deletions README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ Other available commands:
| `npm run check:bundle` | Size budgets, and the cloud client staying in a chunk of its own (needs a build) |
| `npm run check:mutants` | Breaks the engine on purpose and checks the suite notices — 32/32 (no build needed) |
| `npm run check:a11y` | axe on both pages at 390px and 1280px, plus sideways-scroll checks (needs a build) · `A11Y_WIDTH=390` runs one half, which is how CI runs it |
| `npm run check:e2e` | Drives the real app through 57 flows: opening Ask AI putting what is typed in the question box rather than in the cell it covers, and Escape closing it with focus back on that cell, at 1280 and 390 (#203), on a phone, a second tap on a formula cell opening its editor with the formula whole, what is typed going into that formula and the cell two rows down left alone (#201), and a tap on another cell with nothing typed selecting that cell alone rather than a range (#210), on a phone, typing after Enter into a filled cell replacing its value rather than going on the end (#202), on a phone, a tap after Enter in the formula bar selecting the cell rather than breaking the next cell's formula, and a formula only opened to look at left alone (#201), typing into a dropdown cell saving what was typed in full, text off the list refused and a pick from the list still saving, at 1280 and 390 (#198), a file with a picture and a chart saying what it will lose as it opens, a plain one saying nothing, and range names that could not come in in the same report (#83), a live source that answers after the picker opens never blanking the cell (#126), one tap on a phone only selecting and saying to tap again, with nothing typed lost in silence (#171), Enter or ↓ on the last row adding a row with nothing typed over and one undo taking the value and its row back with typing still landing after it (#170), on a phone an undo with an editor open on a row Enter grew closing the editor, saying what it dropped, and the next value landing (#191), a formula page's try-it button landing the page's own numbers in the sheet, and asking first over work (#149), numbers pasted through the real clipboard as Excel copies them adding up while codes stay text (#52), the AI assistant putting a column's total under it and sending a condition to the SUMIF form (#62–#64), a view-only tab editing by itself, with all the work, once the editing tab closes (#146), a crash bringing up the rescue screen, whose file holds the work and whose Try again comes back (#145), a Buddhist-Era date that counts and Convert to dates from the cell menu (#82), duplicate or invalid sheet names fixed on load, refused when typed, and exported with the right names and formulas (#54), a second tab asking first, and taking over turning the first view-only with no edit lost (#47), dates in Excel's default column width showing as dates rather than `###` (1280 and 390), a Thai sheet name downloading as a Thai file name, the sample sorted in both languages with every row still multiplying its own numbers and a risky sort asking first, a percent saved before #53 reading the same, opening blank with a sample left in the browser not coming back, New file asking first and undoing, formulas, `.xlsx` round trip, an import on top of work that asks first, Tab then Enter and the cell menu, dragging a column's width, Enter on a phone going into the next cell, a range dragged on a phone staying in its column and a tap during `=` saving nothing, tapped cells going into a formula that Done saves with its bracket closed, ⌖ on a phone picking from the grid, a file opened on a phone leaving one message at a time, twelve rows or more and a sideways swipe that works, with "saved in this browser" moved to the save status, a phone on its side folding the bars into two rows with six rows of grid and a long press opening the cell menu, keyboard only, undo, editing after undoing a new sheet, a cut across sheets, a formula bar that never writes a stale value, announcements, the AI assistant, the CSP, an API connected from the browser (nothing reaching `/api/*`), an API without CORS getting the IT checklist, no page calling itself a demo, every page in the sitemap naming its own canonical with the landing page carrying the Search Console tag, the phone tab bar, cross-sheet values on screen after a PDF export, a sort and undo (needs a build · `E2E_ONLY=<part of a name>` runs just the matching flows while editing) |
| `npm run check:e2e` | Drives the real app through 58 flows: `999` and Enter on a live-data cell getting a note under the cell saying why, Enter putting the note away with the cursor and the value where they were, and Delete and a double-click saying so too (#207), opening Ask AI putting what is typed in the question box rather than in the cell it covers, and Escape closing it with focus back on that cell, at 1280 and 390 (#203), on a phone, a second tap on a formula cell opening its editor with the formula whole, what is typed going into that formula and the cell two rows down left alone (#201), and a tap on another cell with nothing typed selecting that cell alone rather than a range (#210), on a phone, typing after Enter into a filled cell replacing its value rather than going on the end (#202), on a phone, a tap after Enter in the formula bar selecting the cell rather than breaking the next cell's formula, and a formula only opened to look at left alone (#201), typing into a dropdown cell saving what was typed in full, text off the list refused and a pick from the list still saving, at 1280 and 390 (#198), a file with a picture and a chart saying what it will lose as it opens, a plain one saying nothing, and range names that could not come in in the same report (#83), a live source that answers after the picker opens never blanking the cell (#126), one tap on a phone only selecting and saying to tap again, with nothing typed lost in silence (#171), Enter or ↓ on the last row adding a row with nothing typed over and one undo taking the value and its row back with typing still landing after it (#170), on a phone an undo with an editor open on a row Enter grew closing the editor, saying what it dropped, and the next value landing (#191), a formula page's try-it button landing the page's own numbers in the sheet, and asking first over work (#149), numbers pasted through the real clipboard as Excel copies them adding up while codes stay text (#52), the AI assistant putting a column's total under it and sending a condition to the SUMIF form (#62–#64), a view-only tab editing by itself, with all the work, once the editing tab closes (#146), a crash bringing up the rescue screen, whose file holds the work and whose Try again comes back (#145), a Buddhist-Era date that counts and Convert to dates from the cell menu (#82), duplicate or invalid sheet names fixed on load, refused when typed, and exported with the right names and formulas (#54), a second tab asking first, and taking over turning the first view-only with no edit lost (#47), dates in Excel's default column width showing as dates rather than `###` (1280 and 390), a Thai sheet name downloading as a Thai file name, the sample sorted in both languages with every row still multiplying its own numbers and a risky sort asking first, a percent saved before #53 reading the same, opening blank with a sample left in the browser not coming back, New file asking first and undoing, formulas, `.xlsx` round trip, an import on top of work that asks first, Tab then Enter and the cell menu, dragging a column's width, Enter on a phone going into the next cell, a range dragged on a phone staying in its column and a tap during `=` saving nothing, tapped cells going into a formula that Done saves with its bracket closed, ⌖ on a phone picking from the grid, a file opened on a phone leaving one message at a time, twelve rows or more and a sideways swipe that works, with "saved in this browser" moved to the save status, a phone on its side folding the bars into two rows with six rows of grid and a long press opening the cell menu, keyboard only, undo, editing after undoing a new sheet, a cut across sheets, a formula bar that never writes a stale value, announcements, the AI assistant, the CSP, an API connected from the browser (nothing reaching `/api/*`), an API without CORS getting the IT checklist, no page calling itself a demo, every page in the sitemap naming its own canonical with the landing page carrying the Search Console tag, the phone tab bar, cross-sheet values on screen after a PDF export, a sort and undo (needs a build · `E2E_ONLY=<part of a name>` runs just the matching flows while editing) |
| `npm run check:ai` | Asks the real Claude with your own key and checks the formulas against what this engine can evaluate — not in `verify`, because it needs a key and costs money |
| `npm run verify` | Everything, before a push: lint → check:readme → check:screens → check:deps → test → check:mutants → build → check:bundle → check:a11y → check:e2e (~5 min) |
| `npm run verify:quick` | The same gates minus `check:mutants`, `check:a11y`, `check:e2e` and `check:deps` — **37 seconds**, for the loop while writing. Not a substitute for `verify` before a push |
Expand Down Expand Up @@ -933,6 +933,12 @@ Behind the scenes:
- Linked cells are tinted green with a border around the block and a bold header row, are read-only, and
**refresh themselves on the source's schedule** (polling). Regular formulas (`=A10*2`, `SUM`, `VLOOKUP`) and
Excel/PDF export work on live data immediately, because the app writes real values into the cells.
- **Typing over a live cell is answered** (#207): a note under the cell says "B2 is live data and can't
be typed over — press "Remove" first to edit it yourself", and a screen reader hears it once, whether the
cell was typed into, cleared with Delete, double-clicked or tapped twice on a phone. Enter or Esc while
the note is up puts it away and leaves the cursor on the cell, as Excel's protected-cell message does,
because typing `999` and Enter in one go was how the value vanished in the blind test: the note came
with the first key and Enter took the cursor, and the note, away before anyone could read it.
- Refreshes **never enter the undo history** (zundo is paused during the write) — one Ctrl+Z undoes the whole
placed block, and "Change" (clear the old block + place the new one) counts as a single step too.
- **Drag and drop still works** for people who prefer it, it's just no longer the primary path.
Expand Down Expand Up @@ -2743,7 +2749,10 @@ up again**.

**Every route in is guarded**, not just typing: Delete, paste, sorting, and adding or removing
rows and columns are all refused *with a reason* — silently doing nothing reads as the app being
broken rather than the template doing its job.
broken rather than the template doing its job. Typing into the structure, a double-click or a second tap
on a phone says so under the cell too, with what to press (#207); it used to be silent, the typed value
gone with only a hover tooltip to explain it. Enter or Esc while the note is up puts it away and leaves
the cursor where it is.

**But you're not trapped in it** — "Unlock the sheet" makes every cell editable like an ordinary
sheet, and Ctrl+Z brings the template back (the template state lives inside `sheets`, so it sits
Expand Down Expand Up @@ -4067,7 +4076,7 @@ assistant sent a range including its text header, because the context builder re
instead of computed values (both tested) · one new button pushed the language toggle 42px off the screen.

```bash
npm run check:e2e # 57 flows in a real browser (needs a build)
npm run check:e2e # 58 flows in a real browser (needs a build)
```

Flows are picked by one rule: **would a unit test already catch it?** If yes it does not belong there. What
Expand Down Expand Up @@ -4434,8 +4443,8 @@ What's not done yet, and why — to show this is a known gap, not something forg
(2.85:1), and two `<select>` elements in the conditional-formatting panel with **no accessible name at
all**, which axe rates critical. A `<label>` sat above them without an `htmlFor`, which looks
associated and is not. Both fixed. Still open: the cloud panel (no button unless a backend is
configured) and the live-data picker, which needs a source first. Now 119 checks — most recently the
report of what an opened file can't keep (#83), before it the "Tap again to type" label on a phone (#171), then the formula pages (#149) and the sheet-name editor saying why Excel would refuse a name (#54), and before them the notice on a tab that edits again because the other closed (#146), the rescue screen after a crash (#145),
configured) and the live-data picker, which needs a source first. Now 121 checks — most recently the
note under a live-data cell that was typed over (#207), before it the report of what an opened file can't keep (#83), then the "Tap again to type" label on a phone (#171), then the formula pages (#149) and the sheet-name editor saying why Excel would refuse a name (#54), and before them the notice on a tab that edits again because the other closed (#146), the rescue screen after a crash (#145),
the Convert to dates dialog (#82), the question asked before a paste over rows a filter hides (#50) and
the 404 page (#148), and before them the AI assistant's answer card, both the one with a formula and the one that points at a form (#62–#64).
- [x] **Property-based testing for the engine** — done: `property.test.ts` names no formula at all,
Expand Down Expand Up @@ -4495,7 +4504,7 @@ What's not done yet, and why — to show this is a known gap, not something forg
prerendering, measured at +10–15 ms of TTFB · an API a user connects from the browser enters that one
user's `connect-src`, through a cookie validated entry by entry. Still open: CSP cannot stop a top-level navigation.
- [x] **Tests that actually open the app (E2E) in CI** — done: `npm run check:e2e` drives Chromium
through 57 flows as its own CI job — a formula recalculating on screen, an `.xlsx` round trip through
through 58 flows as its own CI job — a formula recalculating on screen, an `.xlsx` round trip through
the real buttons, keyboard-only navigation, undo, and whether anything is announced. Three bugs this
project previously found by hand are now inside the gate's reach, and each gate was proved by breaking
it. **The AI assistant is now covered too**, with `/api/ai/formula` stubbed: the range the panel
Expand Down
Loading
Loading