oficina / docs Public

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>
Paul Campbell pushed by paul@keymail.dev 368e86e577f627f2527f0f6588f5de94fe927b63 parent 1776123
20 files changed, +451 −66
  • .amadan/ci.d/10-gate +12 −0
  • core/src/fragment.rs +34 −7
  • core/tests/fragment.rs +22 −1
  • fixtures/autoformat.mjs +13 −5
  • fixtures/editor-entry.js +16 −0
  • fixtures/generate-fragment.mjs +9 −0
  • fixtures/indent.mjs +15 −0
  • fixtures/menu.mjs +43 −4
  • fixtures/menu.test.mjs +135 −0
  • fixtures/pages.mjs +24 −12
  • fixtures/toolbar-roving.mjs +21 −2
  • fixtures/toolbar.mjs +44 −1
  • fixtures/vectors/fragment/indented.bin binary
  • internal/core/testdata/docs_core.wasm binary
  • internal/docs/handlers.go +1 −0
  • internal/docs/menu.go +2 −8
  • internal/docs/menu_test.go +0 −2
  • internal/docs/render.go +13 −8
  • internal/docs/static/{editor.32d42be3a13c49bf.js => editor.51ada8c82c1866c8.js} +13 −13
  • internal/docs/views/show.html +34 −3

CI passed — run details

.amadan/ci.d/10-gate

Loading diff…

core/src/fragment.rs

Loading diff…

core/tests/fragment.rs

Loading diff…

fixtures/autoformat.mjs

Loading diff…

fixtures/editor-entry.js

Loading diff…

fixtures/generate-fragment.mjs

Loading diff…

fixtures/indent.mjs

Loading diff…

fixtures/menu.mjs

Loading diff…

fixtures/menu.test.mjs

Loading diff…

fixtures/pages.mjs

Loading diff…

fixtures/toolbar-roving.mjs

Loading diff…

fixtures/toolbar.mjs

Loading diff…

fixtures/vectors/fragment/indented.bin

Loading diff…

internal/core/testdata/docs_core.wasm

Loading diff…

internal/docs/handlers.go

Loading diff…

internal/docs/menu.go

Loading diff…

internal/docs/menu_test.go

Loading diff…

internal/docs/render.go

Loading diff…

internal/docs/static/{editor.32d42be3a13c49bf.js => editor.51ada8c82c1866c8.js}

Loading diff…

internal/docs/views/show.html

Loading diff…