Act on the whole-branch review: four blocking, four should-fix
Fable read the branch as one diff and found four things the gate cannot see, because all four only fail in a browser — which is the hole this branch's own §1.5 warned about and then fell into. THREE FEATURES WERE UNREACHABLE. menu.mjs's sync read the LOCAL_COMMANDS module constant where it should have read the merged localCommands table. That constant holds only `print`, so paged, infinite, word count and the shortcuts sheet fell through to the toolbar's table, found nothing, and were set disabled on every editor update — shipping disabled from the server and staying that way for the life of the page. The comment eight lines above the merge says the two tables were merged "so run and sync cannot disagree". They then disagreed, because only one of them was changed to read the merged table. Writing an invariant down is not holding it. That bug had no test because menu.mjs had no test. It has one now: fixtures/menu.test.mjs, five cases against a forty-line fake DOM, and the first of them fails against the exact edit that caused this — verified by making it again and watching it go red. [docs-chrome] WAS STYLED AND NEVER RENDERED. Both rules were right and neither had an element: the formatting bar stopped being sticky (a regression against main, under a thirty-line comment describing the sticky fix that replaced it) and File → Print printed the menu bar and the toolbar across the top of page one. THE SELECTS LIED AND WERE UNNAMED. select.js writes its input's value at enhancement, on a pick, and on blur — never again — so every programmatic select.value left the combobox displaying whatever was last chosen by hand while the document said otherwise. That is the exact failure the spec's own argument for keeping Font and Size out of the Format menu was written to avoid. And with no id on any select, all three comboboxes got id="-combo", every aria-controls resolved to the first listbox in the document, and each announced as "Type to filter" because select.js transfers a <label for> and not an aria-label. PAGED MODE OVERFLOWED 320px. The page gap pulls itself out by -1in to reach the sheet's edge; below 36rem the page's padding is 1rem, so each gap overhung by ~80px with nothing clipping it. SC 1.4.10, in the one check this branch promised to keep green. Also: the indent clamp disagreed across the wire — Rust parsed u8, so "400" overflowed to flush left where the editor rendered 8, and Number() accepted " 3", "3.0" and "0x3" where Rust rejected all three. Both sides are digits-only-then-clamp now, and indented.bin carries all four. Escape leaves the editor for the toolbar, which makes render.go's claim that it does true and gives the repurposed Tab the exit WCAG 2.1.2 wants told. autoformat.mjs no longer claims a y-undo interaction test that does not exist. Local menu commands focus the menu title before running, so focus no longer falls to <body> and showModal has a return target. The "both size marks" assertion checks the nesting its comment claimed to pin rather than only that the words survived. The dead Collapsed field and its catalog key are gone with the design they served. And one Fable did not find, from my own re-read: breakPositions summed getBoundingClientRect().height, which excludes margins, so pages ran about 15% long and the error compounded down the document. It measures from the page's top now. Rebased onto main's triage work at the same time.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
20 files changed,
+451
−66
.amadan/ci.d/10-gate+12 −0core/src/fragment.rs+34 −7core/tests/fragment.rs+22 −1fixtures/autoformat.mjs+13 −5fixtures/editor-entry.js+16 −0fixtures/generate-fragment.mjs+9 −0fixtures/indent.mjs+15 −0fixtures/menu.mjs+43 −4fixtures/menu.test.mjs+135 −0fixtures/pages.mjs+24 −12fixtures/toolbar-roving.mjs+21 −2fixtures/toolbar.mjs+44 −1fixtures/vectors/fragment/indented.binbinaryinternal/core/testdata/docs_core.wasmbinaryinternal/docs/handlers.go+1 −0internal/docs/menu.go+2 −8internal/docs/menu_test.go+0 −2internal/docs/render.go+13 −8internal/docs/static/{editor.32d42be3a13c49bf.js => editor.51ada8c82c1866c8.js}+13 −13internal/docs/views/show.html+34 −3
CI passed — run details
.amadan/ci.d/10-gateLoading diff…
core/src/fragment.rsLoading diff…
core/tests/fragment.rsLoading diff…
fixtures/autoformat.mjsLoading diff…
fixtures/editor-entry.jsLoading diff…
fixtures/generate-fragment.mjsLoading diff…
fixtures/indent.mjsLoading diff…
fixtures/menu.mjsLoading diff…
fixtures/menu.test.mjsLoading diff…
fixtures/pages.mjsLoading diff…
fixtures/toolbar-roving.mjsLoading diff…
fixtures/toolbar.mjsLoading diff…
fixtures/vectors/fragment/indented.binLoading diff…
internal/core/testdata/docs_core.wasmLoading diff…
internal/docs/handlers.goLoading diff…
internal/docs/menu.goLoading diff…
internal/docs/menu_test.goLoading diff…
internal/docs/render.goLoading diff…
internal/docs/static/{editor.32d42be3a13c49bf.js => editor.51ada8c82c1866c8.js}Loading diff…
internal/docs/views/show.htmlLoading diff…