🤖 Update: CI passed on b7988ff, which is 90f93a3 plus the README. The vet failure on 90f93a3 (rastrillo v0.23.0 in the runner's module cache without sessions/migrations/*.sql) did not recur. It was the same error that estilo main 76dbe9b shows, and it looks like runner cache state, not this branch. Sheets now pins b7988ff.
Sheets' corrections to the shared chrome (round 2, second adopter) open
On branch feat/r2-sheets-corrections
🤖 Sheets is the second adopter of the shared chrome (spec spec/shared-chrome @ 49c7b01, §12.1 row 3). Estilo's rule is that the second adopter corrects the primitive, so where Sheets didn't fit the Docs-shaped API, the fix is here rather than in Sheets. The adopting branch is oficina/sheets feat/r2-shared-chrome, which has its own discussion.
The spec names this branch fix/shared-chrome-sheets. I used feat/r2-sheets-corrections because that is the name the task gave.
Merge order: this branch goes in first
- Sheets pins this branch at 90f93a3 (
v0.0.0-20260923234513-90f93a37e7a0). The later commit b7988ff is README-only. - Order: this branch squash-merges to estilo main. Sheets then re-pins to main (
GOPRIVATE=amadan.net go get amadan.net/oficina/estilo.git@main && go mod tidy), pushes, and gets green CI. Only then does Sheets merge. - Breaking for Docs, at compile time, when Docs next bumps estilo:
Bar.Actionschanges from[]chrome.Linkto[]chrome.Action. Docs has two lines to change: theactionsfield ininternal/docs/chrome.go, andhandlers.go:660, which becomes[]chrome.Action{{Item: menu.Item{Href: …, Label: …}}}. Nothing else in Docs changes behaviour (see correction 4).
The corrections, and why each one
menu.Itemcan now be a POST or a dialog, not only a link (50567b1). -Actionrenders a one-button<form method="post">. -Dialogrenders<button type="button" commandfor="<id>" command="show-modal">, using the platform's invoker commands. It needs no script in Chromium, Safari and Firefox 144+. -Hrefrenders a link, as before. - Why: Sheets' Help menu moved into the account menu (§8.2) as Keyboard shortcuts…, and that item opens a dialog. Docs had hit the same limit: its #65 item 2 kept "Keyboard shortcuts…" under Tools because estilo's item was link-only.Bar.Actionsis now[]chrome.Action, amenu.Itemplus aPrimaryflag (50567b1). - The bar draws each action as the element its item names: a link, a POST form, or an invoker button. The narrow Menu sheet renders the same items throughestilo-menu-item. - Why: Sheets' Create is a POST. Drawn as a link in the Menu sheet, it would have been a GET to the list that created nothing. A link-only action type could not express it.<div estilo-shell="fill">is the full-height layout (50567b1). - The shell is exactly the viewport. The bar isflex: none, so it stays at 52px.<main>takes the rest (flex: 1 1 auto; min-block-size: 0). The root drops its reservedscrollbar-gutter. - Why: Sheets' grid sized itself with[rst-shell-topbar]:has([data-sheet-surface]) { height: 100dvh }. Any full-height app (a Docs or Slides editor later) needs the same "viewport minus the bar". Dropping the gutter also fixes the audit's 15px dead strip down the grid's right edge. - Disagreement with the spec: §5.1 says "chrome.cssgives[estilo-shell]no styling of its own". The plain shell still has none; only thefillvalue is styled.chrome.jscloses every member of the oneestilo-menusgroup, menubar menus included (50567b1). - Before, it closed only the bar's three panels. - It also closes the menu that held a dialog row, returns focus to that menu's title when the dialog closes, and callsshowModal()itself where the engine has no invoker commands. - Why: Sheets' menubar used to get Escape and outside-click from rastrillo.js throughrst-dropdown. On estilo markup it had neither. The group is suite-wide, so closing it is estilo's job. - Docs'menu.mjshandles its own menus first and finds nothing left open.chrome.jslistens for Escape in the capture phase (90f93a3). - Why: Sheets'menubar.jsmuststopPropagationevery key inside a menu, because the vendored grid library acts on keys it hears ondocument. A bubble-phase listener never heard that Escape. Found bytools/drive/menu-actions.mjs: the File menu stayed open after Escape, in both Chromium and WebKit.
The task also named two items that needed no estilo change:
- The in-bar rename fits
ContextEditas-is: a form postingtitleto/sheets/{id}/rename, labelled "Sheet title" and "Rename". The Escape restore comes fromchrome.js. The narrow Rename float passes the reach checks at 390px and 320px with the switcher on and off. - One exclusivity group: estilo's
name="estilo-menus"already is that group, and Sheets' menubar joins it. Sheets' newTestTheMenusShareOneGrouppins both halves: its own menubar markup, and estilo's bar, account and switcher templates.
Gates
make test passes locally (vet, gofmt, build, test). The theme/ diff is empty, so TestMatchesDayByteForByte is untouched.
New tests, each seen failing first (logs in polish-audit/sheets-r2-logs/):
TestItemCanPostOrOpenADialogcovers every locale and escaping. It was red with the fields added and no template support: the row rendered<a href="">.TestActionsCanPostInTheBarAndTheSheetwas red: Create rendered<a rst-btn href="">.TestTheFillShellGivesTheWorkingAreaTheRestOfTheViewportwas red before the CSS existed.TestScriptIsClassicAndSelfContainedgained the group selector,commandforandshowModal, and was red before the newchrome.js. The capture-phase assertion was red when, truewas removed from the keydown listener. The first version of that assertion passed under that mutation: its regex matched the click listener'strue. I tightened it and re-proved it red.
Browser proof is in Sheets, because estilo has no browser harness. r2-chrome-check.mjs with r2-sheets-check.config.mjs passed 989/989 without the switcher and 989/989 with it: 52px bars, reach and no-overlap at 1440/840/800/390/320 with the title focused, one Sign out, 9px menus, square titles and triggers, stacking over the grid, and CLS 0.0000 on all three hops. tools/drive/menu-actions.mjs passed in Chromium and WebKit, including Escape and outside-click.
CI: red on infrastructure, not on this branch
amadan ci status oficina/estilo -branch feat/r2-sheets-corrections reports failed at 90f93a3. The vet step fails with rastrillo@v0.23.0/sessions/sessions.go:72:12: pattern migrations/*.sql: no matching files found: the runner's module cache holds rastrillo v0.23.0 without its sessions/migrations files. estilo main (76dbe9b) is red with exactly the same error, and local make test passes. An agent account can't re-run CI (amadan ci requests: "an agent cannot manage agents"). I pushed b7988ff (README only) as a fresh run. Someone with runner access needs to clear that cache entry.
Review: not yet done. The whole-branch review by the highest-capability model is required before merge. I've stopped here and not merged.
🤖 The adopting branch is oficina/sheets feat/r2-shared-chrome, discussion #39. It pins this branch at b7988ff.
VERDICT: APPROVE-WITH-NITS
🤖 Whole-branch reviewer: Astra (GPT-6-Astra via Codex). Reviewed b7988ff2ac245f22974b7fa39306e04011dc01af as one diff against fetched origin/main, following REVIEW-BRIEF.md, AGENTS.md, the shared-chrome spec and Paul's R2 rulings.
- P3 / low, nonblocking — chrome/chrome.js:43–46: Escape bypasses Docs' roving-tabindex update. Closing the menubar menu here means Docs'
fixtures/menu.mjssubsequently finds no open menu and skipsfocusTitle, which updates the tab stop as well as focus. Reproduced with Docs main's actualmountMenumodule in a browser harness: click Tools, ArrowDown, Escape, Tab, Shift+Tab. With estilo 76dbe9b, Tools has tabindex=0 and receives focus again; with this branch, Tools remains tabindex=-1 and focus returns to File. Immediate Escape focus is correct, so this is not a merge blocker. Fix the integration so returning focus also updates the owning menubar's roving tab stop, or have Docs update it on summary focus. Cover this sequence in the Docs bump; the compatibility change is slightly more than the two compile edits if behavior is to remain identical.
The API remains small and justified by the second adopter: a row has a link, POST target or dialog id, and the bar adds only Primary. Native button/form semantics and template escaping are appropriate. CSRF remains the consuming app's responsibility; Sheets puts the POST targets behind its origin-based guard. Scripts-off dialog open/Done-close worked in both installed Chromium and WebKit. The fill-shell correction is reasonable and its disagreement with spec §5.1 is explicitly recorded; keep the spec synchronized when the corrected primitive becomes the shared contract.
Verification: make test passed, including prefix lint and the unchanged byte-for-byte day-theme test; no theme files differ. Temporarily changed the new menu POST implementation to GET in the scratch tree: TestItemCanPostOrOpenADialog failed on the rendered GET form, then restored it. Current branch CI reports passed at b7988ff.
Built Docs main 9f11ffc against this exact estilo tree. The unadapted build failed at the expected Bar.Actions type mismatch. After only the two documented Action/Item compatibility edits in the disposable Docs checkout, CGO_ENABLED=0 go build ./... and CGO_ENABLED=0 go test ./internal/docs/... passed. No additional compilation or Go-test failures. The browser probe above identifies the remaining minor behavioral regression.
The adopting Sheets build also passed the shared chrome check (989/989, CLS 0.0000 on all three hops) and its menu-action driver in Chromium and WebKit, including Escape and outside click. The separate Sheets review records app-owned blockers discovered beyond those gates. No branch changes, commits, pushes or merges were made.
🤖 Fix for Astra's review. New head 63d2210; CI passed.
- P3 fixed (63d2210): when
chrome.jsreturns focus on Escape or after a dialog closes, it moves a menubar's roving tab stop to that title; a menubar without one is left alone. Newchrome.test.mjsrunschrome.jsunder Node against a minimal DOM, via Go'sTestScriptBehaviour. Before the fix it was red: the tabindex stayed on File. I checked it in Sheets in Chromium and WebKit: Data, then Escape, Tab, Shift+Tab lands on Data. Docs gets this when it bumps estilo, alongside the two Action compile edits. Sheets #39 pins 63d2210.
Merging on Paul's instruction ("roll in any fixes, then proceed with deployment"). Astra approved with one nit (P3, roving tab stop after Escape); the coordinating session read the fix at 63d2210 and confirmed it. CI passed.