Skip to content

fix(webui): make the webui baseline's own gates pass again - #266

Merged
stevenjj33 merged 6 commits into
webuifrom
fix/webui-baseline-ci-gates
Oct 27, 2026
Merged

stevenjj33 merged 6 commits into
webuifrom
fix/webui-baseline-ci-gates

Conversation

@stevenjj33

@stevenjj33 stevenjj33 commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

What this fixes

The webui baseline's own CI is red, and every pull request against it inherits the failure — this branch and the other four open PRs all fail at the same gate. This PR makes the baseline's gates pass again, so the pull requests that follow can be green.

Three things are broken on the untouched webui branch (e2de9a1):

Gate What it reports
check:webui-dependency WorkspacePanels.tsx:528 and :573 — the workspace panel reaches for document directly to wait for the fonts before it measures the terminal's grid. The dependency rules confine that global to the platform layer.
test:webui Seven stale expectations in six files, left behind by the terminal and browser work: the panel mounts the browser host for a different tab than the test read; the launcher hands the browser a normalised address; the terminal's create button is gone; the browser control lost its title; the shell's stylesheet list grew by the terminal's stylesheet.
test:webui-browser Nine stale expectations in four spec files, plus the launcher placeholder in the recorded Linux screenshot: the terminal became a workspace tab, the browser control names itself with aria-label, and the address bar is an input rather than a text node.

The fix

The dependency gate. The browser platform owns the wait now:

readonly whenFontsReady: () => Promise<void>;

and the panel asks for it the way it asks for every other browser capability:

void dom.whenFontsReady().then(() => { … });

The stale expectations. Each one now names the behaviour that replaced it.

The unit rows:

  • browser-web-tab-toolbar.test.tsx — the panel mounts the host for the tab it kept mounted, so the navigation state comes from that tab rather than from the selected one.
  • workspace-panel-state.test.ts — the terminal's create button became an automatic create once the roster lands, and the limit is the process half's rule, so the panel states what the service says instead of keeping a copy of the limit.
  • workspace-tab-strip.test.tsx — the launcher hands the browser the browser's own address form, which is what gives a bare host its trailing slash.
  • webui-shell.test.ts — the browser control is an icon button: its accessible name is an aria-label, and a title would only add a hover affordance the glyph already carries.
  • webui-w0-css-structure.test.ts — the shell's stylesheet list now includes the terminal's own stylesheet, which is a package stylesheet (@xterm/xterm/css/xterm.css) and so is not counted among the shell's rules; the list of imports keeps it, in its documented position.
  • workspace-browser-tab-acceptance.test.ts — the same launcher address, seen from the acceptance row that types a URL into the launcher.

The browser rows:

  • browser-workspace.spec.mjs — the browser control's name is an aria-label, and the address bar is an <input>, so the row reads its value rather than its text.
  • architecture-acceptance.spec.mjs — the terminal is a workspace tab now: the client asks the runtime for a terminal when the tab opens, and the runtime records the tab it belongs to. The row therefore asserts what the panel can still say — the terminal is absent, the panel says so, nothing is opened, the rest of the client keeps working — and that the readiness refreshes when the service comes back, which is what the reconnect did for the old button's disabled state.
  • terminal-cross-page.spec.mjs — the roster of #1 entries inside the panel is gone; the terminal belongs to a workspace tab, and the tab id is what binds the two. Two pages that open the same terminal tab meet the same process, so the row keeps its shape: the second page adopts the PTY the first page opened, closing its panel releases its watch without ending the process, and the write still lands.
  • native-runtime.spec.mjs — the same automatic create, against a real PTY.

The fixture learns the one thing the client now needs from the runtime: the workspace tab a terminal belongs to (createTerminal carries it, listTerminals answers it). Without it the panel could never find the terminal its own tab owns.

The recorded screenshot. The launcher's placeholder changed from 输入网址 to 搜索 Google 或输入网址, so the recorded Linux baseline of the launcher panel no longer matches the client. It is re-recorded on Linux — the platform the baselines belong to — and only that one file changes.

The leak scanner. The release audit scans the history of every branch, so a key name that another pull request introduces is read by this one too. The shortcut settings page's storage key name (webui-shortcuts.v1) is high-entropy enough for gitleaks' generic-api-key rule to read it as a credential, so the baseline has to know it is not one — the same kind of documented entry the file already holds for the other non-credentials:

[[rules.allowlists]]
description = "WebUI shortcut storage key name, not a credential"
condition = "AND"
paths = ['''(^|/)packages/webui/src/client/projection/common/shortcuts\.ts$''']
regexTarget = "match"
regexes = ['''^SHORTCUT_STORAGE_KEY = "webui-shortcuts\.v1"$''']

Evidence

Check Result
pnpm check:webui-dependency pass — 0 direction, 0 cycle, 0 role, 0 publication violations
pnpm --filter @mavis/webui typecheck:client pass
pnpm check:source pass — 5450 files
pnpm test:webui (Linux, CI) pass — 218 files, 3354 tests
pnpm exec playwright test packages/webui/test/browser (Linux, CI) pass — 184 tests, after the one stale screenshot was re-recorded
the browser suite on macOS 19 failed / 158 passed — every failure is environmental: browser-bridge-real-* needs a real Chrome installation, native-runtime needs a PTY this machine's node-pty cannot spawn, and the recorded baselines are Linux's, so the macOS ones do not exist. No assertion fails.

Scope

  • Two source files, eleven test files, one recorded screenshot and the leak scanner's configuration, all inside packages/webui except .gitleaks.toml. No new dependency, no server or runtime change, no public surface change.
  • The document access is not removed — the capability moves behind the platform seam that already owns the other browser capabilities, which is what the dependency rules ask for.

Not verified here

  • The browser suite was run locally on macOS as well as on the CI's Linux runner. The browser-bridge-real-* specs need a real Chrome installation and the visual baselines are recorded on Linux, so those fail here for environmental reasons; the CI runner has both.

The workspace panel reached for `document` directly to wait for the fonts
before it measured the terminal's grid. The dependency rules confine that
global to the platform layer, and the platform is where the wait belongs:
a component that reaches for `document` itself is a component that can
only be placed against a browser.

The browser platform now owns the wait (`whenFontsReady`), and the panel
asks for it the way it asks for every other browser capability.

This is the baseline's own `check:webui-dependency` failure — the gate
reported these two accesses on the untouched `webui` branch.
…work left behind

The terminal and browser work changed what these suites read. The panel
mounts the browser host for the tab it kept mounted rather than for the
selected one; the launcher hands the browser its own normalised address,
which is what gives a bare host its trailing slash; the terminal's create
button became an automatic create once the roster lands, so the panel
states what the service says instead of keeping a copy of the limit; the
browser control is an icon button whose accessible name is an `aria-label`
rather than a title; and the shell's stylesheet list now includes the
terminal's own stylesheet, which is a package stylesheet and so is not
counted among the shell's rules.

Each expectation now names the behaviour that replaced it rather than the
shape it used to have.
The release audit scans the history of every branch, so a key name another
pull request introduces is read by this one too. The shortcut settings
page's storage key name is high-entropy enough for gitleaks' generic rule
to read it as a credential, and the baseline has to know it is not one.
…tance

The launcher routes a typed address through the browser's own address
normaliser, so a bare host arrives with the root path the URL parser
gives it. The expectation still carried the pre-normalisation form.
The terminal became a workspace tab: the client asks the runtime for a
terminal when the tab opens, the runtime records the tab it belongs to,
and the panel watches the terminal its own tab owns. The rows still
spoke the old language — a roster of '#1' entries in the panel, a
'新建终端' button and a '关闭' button beside it — and three of them
had nothing left to drive.

The browser control also names itself with aria-label now, and the
address bar is an input rather than a text node, so the assertions
follow those two facts.
The launcher's address box now names itself 'search Google or type an
address', and the panel puts the browser's own toolbar above it. The
recorded Linux baseline is the old frame, so it is re-recorded on Linux
— the platform these baselines belong to.
@stevenjj33
stevenjj33 merged commit b456b9e into webui Oct 27, 2026
12 of 14 checks passed
stevenjj33 added a commit that referenced this pull request Oct 27, 2026
The webui baseline's own gates are green again after #266, so this branch
is brought up to it before its own checks run.
stevenjj33 added a commit that referenced this pull request Oct 27, 2026
The baseline's own gates are green again after #266 and #267, so this
branch is brought up to it before its own checks run.
@stevenjj33
stevenjj33 deleted the fix/webui-baseline-ci-gates branch October 27, 2026 02:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant