Skip to content

browser: never pinned; the image takes the newest release and the engine reads the server it finds - #1454

Merged
feder-cr merged 2 commits into
mainfrom
libs-latest
Oct 15, 2026
Merged

feder-cr merged 2 commits into
mainfrom
libs-latest

Conversation

@feder-cr

Copy link
Copy Markdown
Owner

The Dot's browser is never pinned: each image build takes the newest invisible-playwright-mcp, and the engine reads the interface of the server installed in each Dot.

Why

A Dot keeps the golden image it was made from but boots every new runtime disk. The engine read the server's tools from a copy pinned in its own source, so it could already disagree with the server a Dot actually had, and every release needed a relock.

What changes

  • Engine (nanobot/dots/server_interface.py, server_capture.py)
    • At start the engine reads the tools, instructions and the OPENED/NOT_OPEN/GONE sentences from the installed server. server_capture.py does this, run as dot by the server's own python.
    • A page tool the server does not serve is not offered; GET /tools says so.
    • When the server cannot be read, no page tool is offered and a launch says why.
    • The pinned copy is now a test fixture.
  • Image (guest/image-builder/src/browser-release.ts)
    • image build asks PyPI for the newest invisible-playwright-mcp, the newest invisible-playwright it accepts, and the invisible-core that version pins.
    • The three versions go into the inputs digest, pins.env and the manifest. The manifest records the versions actually installed.
    • mcp-requirements.lock and capture-mcp-interface.py are removed.
    • The rule against any other browser is now checked at build time, on what was actually installed (builder/other-browsers.txt).
  • CI: golden-image.yml runs every 6 hours, so a new release is published as a prebuilt image.
  • Smokes: the engine smoke's stand-in is installed the way the real server is; the browser smoke installs the newest release.

Verified

  • Engine pytest: full suite.
  • vitest: 2209 tests, via the pre-push gate.
  • Go: 70 tests.
  • Engine smoke: 257/0. Browser smoke: 74/0, with invisible-playwright-mcp 0.72.2, invisible-playwright 0.35.8 and invisible-core 47.39.0 resolved without pins.
  • Real-VM e2e: 16/16 on a golden image built by this branch.
  • server_capture.py reads installed 0.72.1 and 0.72.2 correctly.
  • 0.70.2 predates the OPENED export (added in 0.71.2). A Dot on a golden image that old gets no browser and is told why; recreate it on a current image.

…ine reads the server it finds

A Dot keeps the golden image it was made from and boots every new runtime disk, so the engine already talked to
servers other than the one its pinned copy of the interface described. The engine now reads the interface from the
installed server when it starts (nanobot/dots/server_interface.py, server_capture.py run as dot by the server's own
python): the page tools are what that server serves, a page tool it does not serve is not offered (GET /tools says
so), and a Dot whose server cannot be read offers no page tool and its launches say why.

With nothing in the engine tied to a version, the image no longer pins one: each build asks PyPI for the newest
invisible-playwright-mcp, the newest invisible-playwright it accepts and the invisible-core that one pins
(browser-release.ts). The three enter the inputs digest, pins.env and the manifest, which records what was installed.
mcp-requirements.lock and capture-mcp-interface.py go; the copy of the interface becomes a test fixture. The owner's
no-other-browser rule is checked at build on what was actually installed (builder/other-browsers.txt), and the golden
image workflow runs every six hours so a new release is published as a prebuilt image.
…ture runs on the server's python

The engine smoke found its stand-in by fake_mcp_server.py on the command line; installed the way the real server is,
it runs as `python -I -B -m invisible_playwright_mcp`, and that command line is what the checks look for.
test_dependencies names server_capture.py as a module another interpreter runs: its invisible_playwright_mcp import
is the installed server's, not a dependency of the engine.
@feder-cr
feder-cr merged commit ef69f5e into main Oct 15, 2026
13 checks passed
@feder-cr
feder-cr deleted the libs-latest branch October 15, 2026 01:38
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