Skip to content

feat(computer): gate 3 checks a browser computer's input and page tools on an HTML Fixture Desk - #475

Merged
earakely-scale merged 4 commits into
mainfrom
edgararakelyan/page-desk
Nov 4, 2026
Merged

earakely-scale merged 4 commits into
mainfrom
edgararakelyan/page-desk

Conversation

@earakely-scale

@earakely-scale earakely-scale commented Nov 4, 2026 •

Copy link
Copy Markdown
Collaborator

What and why

Gate 3 now checks a browser computer's input and its page tools the way it checks a desktop's input. Before this, a browser computer's build was marked ready with six input checks unverified (P3–P7 and P9), because the probe's Fixture Desk is a Tk window and a browser computer has no display. So a page driver whose clicks landed off target, or whose typing dropped characters, still passed gate 3.

This is PR 3 of 3 for the browser as a computer, part of FD-5116. Its five decisions are in the design note, under "PR 3, the probe on a page".

The HTML Fixture Desk (conformance/page_fixture.py). It's a web page with the Tk desk's widgets at the same places:

  • the name field, Save, the Subscribe checkbox and the notes;
  • the 100-item list, the 8×8 grid, the drawing pad and the wheel box;
  • the pixel markers.

Its script sends what it records to a small server on loopback. That server writes the same layout.json and state.json the Tk desk writes and reads inbox.txt back to the page. So P3–P7 and P9 are unchanged; only the desk changes. The page adds an Ask button that opens a prompt() and a file input, for the page-tool checks.

The probe picks the desk by the card's screen (decision 1):

  • On screen: "page", it stages the server with data/add, starts it with computer-exec and opens the desk with computer_tabs in a tab of its own.
  • It then runs P3–P7, P9 and the full X checks: pointer input, data/add and recording.
  • Desktop drivers keep the Tk desk, unchanged.
  • A page driver without computer-page/v1 leaves the full checks unverified and says why.

The page tools are checked too, as X checks under computer-page/v1, each confirmed on the desk or in the page a new frame names (decision 3):

  • dialog: a click on Ask opens a prompt, which the frame's page shows. A click meanwhile is refused dialog_open, and computer_dialog's text reaches the page. When the browser answers dialogs itself, this check is not applicable and says so.
  • upload: the probe puts a file in ~/Uploads, and a click on the file input opens a chooser shown in page. A path outside ~/Uploads is refused, and computer_upload delivers the file's name and content to the page.
  • reload: the desk counts the load.
  • navigate: the desk's second page, named by the next frame's page.
  • back and forward, through the tab's pages.
  • tabs: open one, switch back, close it. The list and the frame's page follow the active tab.

The clipboard check on a page (decision 2). "Typing leaves the clipboard as it was" fails when typing arrives as a paste. The desk watches its fields for paste events, which checks the risk itself without needing headless Chrome's clipboard or a permission the probe can't grant.

What the probe leaves (decision 4). It closes its own tab, then removes the desk and its file in ~/Uploads. The tab that was open before keeps its page and history.

The page driver sends one wheel event per notch (decision 5), in one page/input call, as a real mouse wheel does in Chrome. Before, a scroll of 3 was one 300 px event, so pages that count wheel events, and P7, saw 1.

Two fixes to the browser's control, found by the desk on the VMs:

  • A tab opened headless loads its page at the window's size. Target.createTarget with a URL starts loading before the tab is attached and held to the window, so a page opened with computer_tabs ran its scripts at 1280×713 and then resized to 1280×800. Headless, the tab now opens blank and navigates once it's held.
  • The active tab is the visible one with focus. A hidden tab whose page had input still says document.hasFocus(). So after an agent typed in one tab and opened another, the hidden first tab stayed the active one, and screenshots and input went to it.

Size: 732 lines added, about 270 of them tests, and the fake page driver.

How it was tested

  • ruff check: clean.

  • The desk in a real browser: a local headless Chrome, driven over CDP with the page driver's events:

    • the markers read back exactly;
    • typing, the select-all chord, tab and Enter in the notes, and the inbox arrived;
    • each wheel event was counted per direction;
    • the drag started and ended where it was sent;
    • the prompt's answer and the uploaded file reached the desk, and a reload kept the state.
  • Protocol tests: 1021 passed. The new ones, against a fake page driver:

    • every check passes on the HTML desk, page tools included, and the probe closes its tab and removes its file;
    • a tab the probe opened is closed though the check that opened it failed;
    • a page driver without the page tools leaves the input checks unverified with why;
    • a browser that answers dialogs itself makes the dialog check not applicable;
    • typing that arrives as a paste fails the clipboard check.

    And in the browser's control: a tab it opens loads its page once held to the window, and a hidden tab that still says it has focus isn't the active one.

  • Unit tests: 11,793 passed. The page driver's new test checks a scroll is one wheel event per notch, sent together. test_a_token_signs_the_clone was left out, because it waits on git credential fill on this laptop, on main too.

  • Integration, slow tier, on agent-environments-admin VMs (amd64 c6i.2xlarge, arm64 c7g.2xlarge): 13 passed on each, at 1a94a58. That's browser_computer_test.py (4), chromium_app_test.py (7) and website_browser_test.py (2).

    • Gate 3's test on chromium alone now requires no unverified checks and computer-page/v1 verified. Its probe: 60 passed, 0 failed, 0 unverified, and P8 not applicable.
    • The probe takes about 30 s on a page; each section is under 3 s except the dialog check, at 6.5 s.
    • The earlier runs found the two control fixes above. At 223f13a the desk saw 1280×713 and its checks were unverified; at 6862f4f the start tab stayed active, so P3, P4 and P6 failed.
  • Greptile: 4/5 on the first commit, with two findings, both fixed in 223f13a with tests:

    • P9 checked the owner of fixture.py, which the page desk doesn't stage, so it would have failed every browser computer;
    • a failed tabs check left its tab open.

    Then 5/5 on 223f13a and on 1a94a58.

🤖 Generated with Claude Code

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; no new blocking issue was found.

Summary

Adds an HTML Fixture Desk so gate 3 can check browser input and page tools.

  • Gate 3 checks browser input and page tools on an HTML desk.
  • Headless browser tabs load requested pages after sizing.
  • The browser picks a visible, focused tab as active.
  • Page scrolling sends one wheel event for each notch.

No new actionable issues were found. Tests were inspected, not run.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Probe[Full probe] --> Screen{Screen kind}
  Screen -->|Desktop| Tk[Tk Fixture Desk]
  Screen -->|Page| Server[Loopback fixture server]
  Server --> Tab[Probe-owned browser tab]
  Tk --> Input[Input checks]
  Tab --> Input
  Tab --> Tools[Page-tool checks]
  Tools --> Cleanup[Close probe tabs and remove fixture files]
Loading

Reviews (4) · Last reviewed commit: "fix(computer): the active tab is the vis..." · Reviewed by Greptile

…ls on an HTML Fixture Desk

On a driver whose screen is a page, the probe stages an HTML desk with the Tk desk's widgets,
serves it on loopback, opens it in a tab of its own and runs P3-P7, P9 and the full X checks on it,
then checks the page tools against it. The page driver sends one wheel event per notch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@earakely-scale
earakely-scale requested a review from a team as a code owner November 4, 2026 03:31
earakely-scale and others added 3 commits November 3, 2026 19:37
…es every tab it opened

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Target.createTarget with a URL starts loading before the tab is attached and held to the window, so
its page loaded at 1280x713 and then resized. Headless, the tab now opens blank and navigates once held.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A hidden tab whose page had input still says document.hasFocus(), so after an agent typed in one tab
and opened another, the hidden first tab stayed the active one and got its input.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@earakely-scale
earakely-scale merged commit 9217e2e into main Nov 4, 2026
26 checks passed
@earakely-scale
earakely-scale deleted the edgararakelyan/page-desk branch November 4, 2026 04:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant