Skip to content

fix(computer): install only the Chromium build the computer launches - #829

Merged
dustywusty merged 2 commits into
CopilotKit:mainfrom
dustywusty:dustywusty/computer-image-no-headless-shell
Oct 27, 2026
Merged

dustywusty merged 2 commits into
CopilotKit:mainfrom
dustywusty:dustywusty/computer-image-no-headless-shell

Conversation

@dustywusty

@dustywusty dustywusty commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

What this changes

playwright install chromium on Playwright 1.62 installs two browsers: the full Chromium and the separate chromium-headless-shell. The computer never starts the shell. This PR stops installing it, and removes the bunx package cache that is left in the same layer.

What it saves

openbot-agent-computer Download before Download after Saved On disk saved
arm64 (Apple silicon) 537 MB 423 MB −114 MB (−21%) −375 MB (1.38 GB → 1.00 GB)
amd64 (Windows, Intel, servers) 520 MB 411 MB −109 MB (−21%) −296 MB (1.05 GB → 0.75 GB)

agent-computer is the biggest image a desktop install downloads. On Apple silicon a first install downloads about 1.24 GB of OpenBot images, and this takes that to about 1.13 GB (−9%). Each upgrade that changes this layer downloads 114 MB less too. The all-in-one openbot image gets the same change.

How this was measured. I took the browser layer of the published v0.2.0 image and unpacked it. I packed it again unchanged, and again without the files this PR removes (ms-playwright/chromium_headless_shell-1234, /usr/local/install/cache, /root/.bun). Both were compressed with zstd level 3, the same as BuildKit's default. To check the method, I compared the unchanged repack with the real layer: arm64 gave 426.0 MB against the published 426.6 MB, and amd64 gave 401.1 MB against 408.0 MB. "Saved" is the difference between the two repacks. The release build will give the exact sizes.

What the arm64 layer held (1.38 GB unpacked):

Contents Unpacked
ms-playwright/chromium-1234 639 MB kept, the browser the computer runs
ms-playwright/chromium_headless_shell-1234 340 MB removed
system libraries (--with-deps) 254 MB kept
fonts 90 MB kept
bunx package caches 35 MB removed

Why the shell is never used. The only launch site, agent-computer/src/profiles.ts:476, always passes channel: BROWSER_RUNTIME.channel, which is "chromium" or "chrome" (browser-runtime.ts:45). In playwright-core 1.62.1, getExecutableName returns "chromium" (the full build) for any Chromium-alias channel, headless or headed. It returns chromium-headless-shell only when no channel is given. The one other launch in shipped code, scripts/self-hosted-learning.ts, is headed and passes a channel.

Changes:

  • agent-computer/Dockerfile and the all-in-one Dockerfile: install --with-deps --no-shell chromium, and rm -rf /root/.bun /usr/local/install/cache in the same RUN.
  • .github/workflows/ci.yml (computer-browser): installs with --no-shell as well. That job says it uses "the one the computer image installs", and now it does, so its headless run fails if anything needs the shell.
  • agent-computer/tests/sign-in.test.ts: this was the only bare chromium.launch(). It now passes channel: "chromium", the way the computer launches. Without that it fails against a browser install that has no shell, which is how I found it.
  • tests/compose.test.ts and docs/deployment.md: updated for the new install line.

Verification

  • With PLAYWRIGHT_BROWSERS_PATH set to an empty directory, bunx playwright install --no-shell chromium installs only chromium-1234 and ffmpeg-1011.
  • Against that install, the full headless set from the CI job (sign-in, session-cookies, follows-popup, demonstration-live, webrtc-proxy, web-bot-auth-browser, handoff-page-restore, with COMPUTER_BROWSER_MODE=headless) gives 21 pass, 0 fail. Before the test fix, sign-in.test.ts failed with Executable doesn't exist at …/chromium_headless_shell-1234/….
  • web-bot-auth-browser.test.ts headed: 1 pass.
  • bun test tests/compose.test.ts: 17 pass.
  • Not run locally: the image build itself and the Linux-only headed-browser.test.ts. CI runs both.

Where it runs

  • New state that outlives a request? None.
  • What happens on the second replica? Nothing different. Every replica's image has the same full Chromium as before.
  • Anything serialised? No.
  • Anything fanned out to a browser? No.
  • New listener, port, or schedule? No.

Boundary and audit

  • No acting path, refusal or trust boundary changes. This is a build change only.

Changelog

  • "The computer image is about a fifth smaller to download", under Unreleased.

`playwright install chromium` on 1.62 installs two browsers: the full
Chromium and the separate chromium-headless-shell. The computer only
ever launches with a named channel ("chromium", or "chrome" for a local
browser), and Playwright's getExecutableName returns the full build for
any Chromium-alias channel, headless or not. The shell is used only by a
bare chromium.launch(), which shipped code never does.

The shell was 340 MB unpacked and about 106 MB of the agent-computer
image's 426 MB browser layer. The bunx package cache Bun leaves under
/usr/local/install/cache and /root/.bun is another 35 MB unpacked.

Install with --no-shell and remove both caches, in the agent-computer
image and the all-in-one image. The real-browser CI job now installs
the same way, so its headless run fails if anything needs the shell.
The one test that launched bare (sign-in.test.ts) now names the channel,
as the computer does.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ⚠️ Failed 2026-10-23T10:27:38.452036Z
We couldn’t complete this review. Comment @codex review to try again.
c3a30c0 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@guidovizoso guidovizoso left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Smaller first download and smaller upgrades, with nothing for the person to do. Good one.

@dustywusty
dustywusty merged commit e5694c7 into CopilotKit:main Oct 27, 2026
20 checks passed
davidmckayv added a commit that referenced this pull request Oct 28, 2026
CI installs Chromium with --no-shell since #829, and enter-text launched
Playwright's default, the separate headless shell, so it failed to start.
It now launches channel "chromium", the build the computer itself launches.

(cherry picked from commit f220198)
davidmckayv added a commit that referenced this pull request Oct 28, 2026
CI installs Chromium with --no-shell since #829, and enter-text launched
Playwright's default, the separate headless shell, so it failed to start.
It now launches channel "chromium", the build the computer itself launches.

(cherry picked from commit f220198)
davidmckayv added a commit that referenced this pull request Oct 28, 2026
CI installs Chromium with --no-shell since #829, and enter-text launched
Playwright's default, the separate headless shell, so it failed to start.
It now launches channel "chromium", the build the computer itself launches.

(cherry picked from commit f220198)
davidmckayv added a commit that referenced this pull request Oct 28, 2026
* Let each person pick a skin for OpenBot in Settings

Adds app/src/skins: a registry of skins, a per-browser choice stored like
the dark theme and applied before first paint as data-skin, a Skin row in
Preferences, and /s/$screen for screens only a skin has. A skin may replace
the frame around the app's pages and scope its tokens to its own data-skin;
tests hold every skin's stylesheet to its own scope and to defining dark for
every light token. OpenDuet, OpenDots and OpenMuse are registered as stubs.

* Give OpenDots a real skin: its rail, Dots sidebar, top bar and computer pane around OpenBot's pages

The OpenDots stub becomes OpenDots' own frame drawn over OpenBot's data. A 48px rail
(home, sidebar toggle, new chat, Bots, activity, skills, connections, admin, settings,
account) sits beside a 220px sidebar whose DOTS are the Bots from the agent list, each
wearing one of OpenDots' four plush avatars chosen by its id, and whose RECENT CHATS are
OpenBot's conversations with search, pin and delete. A Dot reopens its latest chat or starts
one; its "..." opens the Bot's page. The top bar carries OpenDots' breadcrumbs, a pause and
resume for the Bot on screen, and the computer toggle: on a conversation it drives the
conversation's own computer pane, elsewhere it opens OpenBot's computer panel in OpenDots'
right pane. At phone width the sidebar becomes OpenDots' hamburger drawer.

Every page inside is OpenBot's own, chat included, in OpenDots' tokens for light and dark
(the dark set derived with OpenDots' own lightness flip). Scheduled & activity and Memories
are skin screens that put OpenBot's routines and memory lists under OpenDots' page heading.
Spaces, pages, the Brief and the pause-everything switch are left out: OpenBot has nothing
behind them.

Tests draw the frame against OpenBot's own agent routes and hold it to: every OpenBot
surface reachable, Settings reachable on every page even when nothing loads, DOTS listing
the agent list, a Dot opening a chat with its Bot, the computer toggle driving the
conversation's pane, and per-Bot pause reaching the server.

* Show OpenDots' coworker home on a new conversation with a chosen Bot

OpenDots opens a Dot on its persona: the plush, the name, what it does and a way to
edit it, above an empty conversation. OpenBot's new-conversation page leaves that space
empty, so the frame draws the persona there from the Bot's profile and hides it as soon
as the page shows a message. Also keeps the composer and its notices off the pane's edges
where the column is no wider than the composer, drops the rule under a conversation's
header so it reads as one band with the top bar, and gives the disabled send button
OpenDots' pale disc.

* Dress a conversation's own computer pane as OpenDots' right pane

The top bar's computer toggle opens the conversation's own Computer pane, so it now wears
the same grey ground, ruled header and selected-tab title as the frame's pane elsewhere.

* Add the OpenDuet skin: a phone-width frame and a Tasks screen on OpenBot's data

OpenDuet's look, rebuilt from OpenBot's primitives, Tabler icons and
OpenDuet's tokens, so a person can pick it in Settings and keep everything
OpenBot does.

The frame is one column at most 430px wide. On Chat and Tasks a header
floats at the top with the menu disc, OpenDuet's mic orb and the person's
initial (their Settings), and a frosted tab bar floats at the foot. The orb
presses the composer's own dictation rather than running a second one, so
recording, transcription and where the words land stay OpenBot's; on a
screen with no composer it opens Chat and starts there. Every other page
opens over the app with a back disc and its own heading in a title pill.
The side menu lists Chat, every conversation and group (pinned first, pin
and delete on right-click), New conversation, and under Manage: Bots,
Connections, Skills, Memory, Routines, Responsibilities, Approvals,
Notifications and, for administrators, Admin. Settings is never folded
away. The frame keeps OpenBot's channel socket and the browser notification
the sidebar's Bots badge sent.

Tasks, at /s/tasks, shows only what OpenBot keeps: pending approvals and
Bots' questions, decided and answered on their cards with OpenBot's own
mutations; active responsibilities and switched-on routines; and, under Up
next, background research's suggestions with Start and Hide.

Left out because OpenBot has no backend for them: Make, the morning brief,
triage, the setup checklist, first-day onboarding, reply chips, channel
icons and colours, Archived, the "Match phone" theme and adding tasks.

* Let the OpenDuet orb wake only when the composer starts or stops recording

The orb watched the whole conversation for the composer's recording
controls and set its state on every change to the page, which during a
streamed reply is every word. It now sets state only when recording
actually starts or stops.

* Set OpenDots' composer on the canvas colour, as OpenDots draws it in dark

OpenBot's composer sits on the card colour, which in this skin's dark set is a step above
the canvas; OpenDots' composer is the canvas with a hairline around it.

* Fix what OpenDuet's live pass found: the orb, the approval card's glyph, the composer's edge

Driving the skin against a real OpenBot found three things.

The orb rested while a Bot browsed with its computer: it read only the
roster's busy flag, which arrives over the socket and missed the person's
own run. It now also reads the composer's Stop control, which OpenBot
draws for exactly as long as a turn runs, and waits 700ms before thinking
so the moment Stop shows while a conversation opens is not a flash of
"Thinking" on every open.

A waiting computer_run_command was drawn with the browser's globe,
because the card asked whether the tool was the computer's before asking
whether it was a command. The kind is now worked out once, commands and
files first.

A conversation's composer ran flush to the 430px column's edges with its
focus ring on the screen's edge. The skin insets OpenBot's composer
wrapper by 12px, as OpenDuet floats its own.

* Build the OpenMuse skin: one agent, a phone-shaped column, five tabs

OpenMuse is a personal agent shaped like a phone. This rebuilds it on
OpenBot's own components, Tabler icons and tokens so a person can pick it
in Settings and keep everything OpenBot does.

The frame is a single 760px column: a menu button, the centre Bot as
OpenMuse's capybara with its name and a live status line, a bell for the
approvals and questions waiting on the person, and a floating pill of
Chat, Activity, Ideas, Goals and Apps. The centre Bot follows the
conversation on screen, then the person's choice, then OpenBot's default
Bot; a sheet behind the name switches it.

Chat is OpenBot's own chat route under the frame, restyled through the
skin's tokens and scoped CSS, so the computer, approval and component
tools keep working. Activity, Ideas, Goals and Apps read OpenBot's Bot
activity, approval inbox, suggestions, routines, responsibilities,
connections and memory through the existing query and mutation
factories. The menu reaches every OpenBot surface, Settings and Admin
included. Mail, calendar, page watches, PDF filling and task plans have
no OpenBot backend and are left out.

Light is OpenMuse's palette; dark is a night version in its spirit. The
tests render the frame against OpenBot's API shapes and check that every
surface is reachable and each tab reads and writes the right data.

* Clear a skin this build no longer ships from the page on load

index.html applies the stored skin before first paint without knowing which
skins exist, so a removed skin's name stayed on <html> for the whole visit
while the app drew the default. The store now settles the attribute when it
loads.

* Note the skins in the changelog

* Give the OpenDuet skin OpenBot's identity: the deployment's name, OpenBot's orb and avatars

A skin keeps OpenDuet's look and takes its identity from the OpenBot
deployment. The menu header and the orb's "Talk to …" now read the
product name from brand.yaml (appConfig.brand.productName), as OpenBot's
own sidebar does, and nothing a person reads says OpenDuet; the skin's
picker name stays OpenDuet, since that names the look.

The orb's face is OpenBot's AgentOrb, as sign-in and onboarding draw it,
in place of OpenDuet's mic-orb robot, which is removed. Its behaviour is
unchanged: it presses the composer's dictation, listens while recording
or typing, and thinks while the Bot works.

Conversation avatars are each Bot's own, drawn from its avatarSeed in
OpenBot's ChannelAvatar, and Tasks uses OpenBot's words for decisions:
Allow once, Always allow here, Deny, Start as task, Dismiss.

* Wear the deployment's brand in the OpenDots skin, keeping only OpenDots' look

A skin changes how OpenBot looks, never whose product it is. The wordmark and the home
links now name the product from brand.yaml (appConfig.brand.productName), the rail's
monogram is OpenBot's AgentOrb, and every Bot row and the coworker home draw OpenBot's own
avatar from the Bot's avatarSeed. The plush avatars and their images are gone. The words
follow OpenBot: BOTS, "Bots" in the breadcrumb, "Edit Bot". The rail, sidebar layout, top
bar, computer pane, density, type and palette stay OpenDots'. The skin's own name in the
picker is still OpenDots, since that names the look.

New tests render the frame and hold it to the product name, to never showing "OpenDots" or
"Dots", and to drawing each Bot with OpenBot's avatar from its seed; both fail on the
previous skin.

* Wear the deployment's brand in the OpenMuse skin

Skins keep their look but take their identity from the OpenBot deployment.
The OpenMuse skin now names itself with the brand.yaml product name, the
same one OpenBot's sidebar shows, and never says "OpenMuse" to a person;
only the picker still calls the look OpenMuse.

The capybara is gone. The top bar, the Bot switcher, the Your Bot card,
approval cards and conversation rows draw each Bot with its own OpenBot
avatar, and the deployment's AgentOrb stands in when there is no Bot yet.
Copy uses OpenBot's words: Bots, Connections, Approvals.

A regression test renders the frame on every tab and checks that it shows
the product name, never shows "OpenMuse" in text, labels or alt text, and
draws no capybara.

* Read the Anthropic key from either header in the AG2 test

Anthropic's SDK 2.3.0, which CI now installs for the AG2 harness, sends the
key as Authorization: Bearer instead of x-api-key. The agent's key still
reaches Anthropic; the test only looked for the old header, so it failed on
every pull request. It now accepts either, and passes with Anthropic's SDK
1.17.0 and 2.3.0 alike.

(cherry picked from commit a1391e7)

* Build OpenDuet's Tasks from OpenBot's own lists, and give pages OpenBot's width

From Guido's review of the skins.

Tasks re-implemented OpenBot's approvals, suggestions and routines, and
its copies had drifted: its own tool-name formatter, its own decision
buttons, approval cards that were all regions with the same name. Tasks
now draws OpenBot's components unchanged (WaitingForYou for approvals
and questions, BotResponsibilities, RoutinesList and SuggestionsInbox)
under OpenDuet's Active and Up next switch and section headings. What an
action will send, every choice and every confirmation are OpenBot's. The
skin keeps only the badge's count, and a test renders WaitingForYou and
holds the badge to the rows it draws.

The frame no longer writes an attribute onto a page's own heading. A
page opened over the app has a back disc and keeps its heading as drawn.

Only Chat and Tasks are phone-shaped now. Every other page keeps
OpenBot's width on a wide screen, and a conversation with its computer
or its Bot's details open grows by OpenBot's 400px pane, so the computer
sits beside the conversation as it does in OpenBot.

Every animated control in the frame says what reduced motion does, and a
test holds new ones to it; the orb is AgentOrb, which reads the same
preference. The skin's description no longer calls a Bot an agent.

* Make the OpenDots skin pass AA contrast, still for reduced motion, and reuse OpenBot's parts

Review on #856 found the skin's page label and description below WCAG AA, house-style copy
problems, no reduced-motion handling, and pieces rebuilt that OpenBot already has.

- Contrast: every text colour now reaches 4.5:1 and every icon 3:1 on the surface it sits
  on, in light and dark. Greys that fell short are darkened along their own hue; the
  YOUR WORKSPACE label grows from 8px to 10px.
- Copy: the picker description no longer says "coworkers"; the schedule screen is
  Routines, as OpenBot names it, at /s/routines, without "run on the server"; empty states
  and errors say what will appear and what to do next.
- Reduced motion: the frame's chrome and the menus, tooltips, sheets and dialogs it opens
  stop transitioning and animating under prefers-reduced-motion.
- Reuse: the phone drawer is OpenBot's Sheet (focus trap, Escape, scrim) at OpenBot's own
  768px breakpoint, and older conversations load through OpenBot's ChannelPagination.

New tests measure every colour pair against WCAG in both themes, hold the reduced-motion
rule and the chrome markers in place, and open the phone drawer to reach every surface.

* Save the skin on the account, share one navigation list, and give skins data-slot hooks

The skin was a per-browser choice, so the next person on a shared machine
inherited it. It is now a user preference (`skin`, default "openbot") that
the server validates against SKIN_IDS, which move to shared/. The picker
draws a skin at once and saves it through an optimistic preferences
mutation that puts the skin back and says so when the save fails.
SkinAccountSync, mounted in _authed, applies the account's skin whenever
the preferences load or change, so the account wins over the browser's
cache. localStorage stays only as the pre-paint cache, and the central
sign-out clears it.

The picker names the default skin after brand.yaml's product name and
shows each skin's description.

OpenBot's destinations (Bots, Capabilities, Connections, Admin for admins,
Settings) live in lib/navigation.ts. The sidebar renders its footer and
user menu from that list, so skins can read the same one.

Skins styled OpenBot through Tailwind classes and ARIA copy. The composer,
its input and buttons, the conversation header, the composer column, the
detail pane and the page title now carry data-slot hooks for them to use.

The Connections listing rules move from the route file to
lib/plugins/listed.ts, so OpenMuse's Apps screen stops importing a route.

* Build the OpenMuse skin's tabs from OpenBot's own components

The OpenMuse skin rebuilt approvals, routines, responsibilities,
suggestions, memory and connections, and its copies had already drifted
from OpenBot: a different tool-name formatter, "What it will send" hidden
behind a toggle, and its own routine delete flow. A new approval choice or
routine field would have been missing from the skin with nothing failing.

Each tab now puts OpenBot's own sections for the centre Bot under
OpenMuse's titles. The bell and Activity use WaitingForYou and BotNeedsYou;
Activity adds the Bot's activity sections; Ideas uses SuggestionsInbox and
ProactiveResearchSettings; Goals uses RoutinesList and BotResponsibilities,
with OpenBot's Delete dialog. Apps is OpenBot's Connections page. The
skin's copies and its formatter are gone.

A tab is lit only on its own screen, not on every other page. Pages that
are not a tab, and a conversation with its computer or settings open, take
OpenBot's own width on wide screens; the top bar and tab bar stay centred.
The chosen Bot is remembered per signed-in person, so the next person on a
shared browser starts from OpenBot's default Bot. Buttons, tabs and sheets
respect reduced motion, and copy follows OpenBot's style.

* Draw OpenDuet's menu from OpenBot's navigation list and dress pages by their hooks

The menu's destinations are OpenBot's one navigation list now
(useNavigationItems: Bots, Capabilities, Connections, Admin for admins,
Settings), so a destination added to OpenBot reaches this menu too. Chat,
the conversations and Tasks stay the skin's own. The skin's copy of the
list is gone, and the avatar disc takes Settings from the same list.

Every selector that reached OpenBot's markup by its classes or its words
now uses the data-slot hooks: the composer column for the inset, the
composer's stop control for "working", its input for the caret. Only
the three dictation controls, which have no hook, are still found by the
names OpenBot gives them, and a test holds those to the real composer.

A page opened over the app has its title back in the pill, read from its
page-title hook and never written to; the title stays for screen readers.
Where the page draws its own back link, the chrome's back disc goes where
that link goes and the page's own bar is hidden, so there is one way back.

* Give the composer's dictation buttons their own hooks

A skin that restyles or drives dictation found the three buttons by their
aria-labels, so rewording one would break it without a test failing. They
carry composer-dictate, composer-dictate-cancel and composer-dictate-stop.

* Build OpenDots' destinations from OpenBot's navigation list and style pages through their hooks

The rail and sidebar now draw OpenBot's destinations from useNavigationItems(), the same list
OpenBot's own sidebar renders, so a destination added there reaches this skin too. The skin
keeps only what is its own: BOTS, RECENT CHATS, and its Routines and Memories screens. Bots
sits under the list of Bots; Capabilities and Connections are in the rail and the phone
drawer; Admin and Settings close the sidebar. OpenBot's Bots badge, which also sends the
browser notification, is mounted once: on the rail's Bots button, or on the menu button on a
phone.

skin.css no longer names OpenBot's Tailwind classes. The composer, send button, conversation
header, composer column and detail pane are styled through the data-slot hooks those pages
publish for skins.

Tests hold the rail and sidebar to navigationFor() for a member and an admin, and fail any
selector in skin.css that names a class other than .dark.

* Find the composer's dictation controls by their hooks in the OpenDuet orb

The orb found the composer's dictate, cancel and stop controls by their
accessible names, so rewording one for a screen reader would have broken
it silently. It uses the composer-dictate, composer-dictate-cancel and
composer-dictate-stop hooks now, and a test fails if any selector in the
skin, in its stylesheet or its code, targets an aria-label.

* Hook the OpenMuse skin onto OpenBot's navigation list and data-slots

The menu sheet kept its own list of OpenBot destinations, which would miss
any page OpenBot adds. Its destinations now come from the shared
navigation list OpenBot's sidebar draws, filtered for the signed-in
person; conversations and the skin's tabs stay as they were.

The stylesheet reached OpenBot's components through Tailwind classes and
ARIA labels, so restyling the composer or the conversation header in
OpenBot would have broken the skin without a test failing. It now uses
only the data-slot hooks those components publish: composer,
composer-input, composer-attach/send/stop, conversation-header and
page-title. The system font is set through the font-sans token rather
than by overriding OpenBot's font classes.

* Say in the changelog that the skin follows the account

* Read the Anthropic key and API version the 2.x SDK sends in the LangGraph AG-UI test

anthropic 2.x sends the key as Authorization: Bearer instead of x-api-key and
dates its Messages API version later than 2023-06-01. The provider-boundary
test asserted both by their 1.x values, so it failed once the unpinned
requirements resolved 2.x. It now reads the key from either header and checks
the version is a date; the endpoint, key, model and body it asserts are
unchanged.

(cherry picked from commit 99685ee)

* Launch the Chromium build CI installs in the enter-text test

CI installs Chromium with --no-shell since #829, and enter-text launched
Playwright's default, the separate headless shell, so it failed to start.
It now launches channel "chromium", the build the computer itself launches.

(cherry picked from commit f220198)

* Record isBrokered's new home in the duplicate-definition guard

The Connections page's helpers moved from the route file into
lib/plugins/listed.ts, and the guard's list of known brokered-provenance
sites still named the route file.

* Wait for home's composer, not its greeting, when a skin switch lands home

Home's heading became a personal greeting in #861, so the test that a skin
switch on a skin-only screen lands on a drawn home waited for wording that no
longer exists. It now waits for the home composer.
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.

2 participants