Skip to content

v10.10.2

@github-actions github-actions tagged this 03 Oct 19:44
  `4.1.31-canary.1791055414.4bbb683a`: `extension_dev`,
  `extension_start` and `extension_build` spawn that build when a project
  has no engine of its own, and the nightly engine-pin check now reads a
  canary pin against the canary dist-tag instead of latest. The canary's
  log query treats level `off` as none (it was a synonym for all), which
  changes nothing for `extension_logs`, whose `off` stays "signals only".
  The canary also adopts a project root only when it owns the manifest
  (same folder, the `src/manifest.json` layout, a dependency on
  Extension.js, or an `extension.config.*` beside it) and otherwise builds
  into the manifest's own folder; the session artifact resolver here
  applies the same four tests, so `extension_wait` and `extension_logs`
  keep reading the ready.json the engine writes.
- Logins to several projects now live side by side in `auth.json`, one
  entry per workspace/project with the latest marked active, instead of
  one slot the next login overwrote. `extension_publish`,
  `extension_release_promote`, `extension_submit`, `extension_shares` and
  `extension_preview_web` take `project` ('<workspace>/<project>', or a
  project slug that matches one login) to pick a stored login, which
  outranks `EXTENSION_DEV_TOKEN`; omitted, the order stays environment
  first, then the active login. `extension_auth` status lists every login
  under `logins`, and logout with `project` removes just that one. A
  version 1 file is read as a store of one and rewritten on the next login
 .
- Four findings from the six-browser sweep: `extension_open` reads new headless off the `User-Agent` field
  of `/json/version` as well (`--headless=new` keeps `Chrome/151` in the
  `Browser` field) and, whatever the launch flags said, falls back to the
  tab route on any window refusal: Chromium's gesture refusal for a popup,
  an options or popup window the engine called opened but no document
  appeared for within 3 s, and Gecko's "Popup is disabled"; a Gecko
  browser that gets Chromium's gesture sentence is answered with
  Gecko wording; and when the background refuses the `runtime.getURL` eval
  the tab route needs (an extension CSP that forbids eval), the
  `moz-extension://` base is read off the profile's
  `extensions.webextensions.uuids` pref through the add-on id the built
  manifest declares, so the fallback still lands (40). `extension_eval` context `background` wakes an idle
  MV3 worker through `ServiceWorker.startWorker` from a page session
  before evaluating, with a warning that it was idle, instead of answering
  `E_NO_TARGET` (41). `extension_open surface: "devtools"` takes `waitMs`
  and `reload` (reload the inspected tab once DevTools is open, for
  extensions that create their panel when the page reports to them) and
  the missing-panel hint names both (42). A page eval the PAGE's CSP
  refuses on a Gecko MV2 build is re-run through `tabs.executeScript`, the
  same wrapper the no-scripting-API case uses (43); an MV3 Gecko build
  keeps the policy explanation, pending.
- `extension_eval` over CDP awaits a promise-valued expression again. The
  CDP routes added for the background and url reads passed `replMode` on every
  `Runtime.evaluate`, and Chrome 151 answers a replMode evaluate with the
  promise object itself, ignoring `awaitPromise`, so `Promise.resolve(42)`,
  an async IIFE or `chrome.tabs.query({}).then(...)` read as `{}` with
  `ok: true` on pages and workers alike. The evaluate now runs without
  replMode, and only an expression Chrome refuses for a top-level `await`
  is re-run in replMode with the promise settled through
  `Runtime.awaitPromise`.
- `extension_open` takes `surface: "devtools"` on Chromium: it opens the
  browser's real DevTools on a tab (the one `url` matches, else the first
  web page) through CDP `Target.openDevTools`, waits for the extension's
  `devtools_page` to register its panel, shows it (`panel` picks a title
  when there are several) and hands back the panel document's url, which
  `extension_eval` reads with context `page` and that url, with
  `chrome.devtools` available. Context `devtools` on `extension_eval` now
  evaluates over CDP on an MV3 session like the other surfaces, and an
  extension document lookup matches the iframe targets a DevTools panel
  and its devtools page are. Works headed or headless (measured Chrome
  151). Gecko gets a refusal that says no protocol opens its developer
  tools.
- `zen` and `floorp` join the browser enum of `extension_dev`,
  `extension_start` and friends, the Gecko family, `extension_browsers`
  detection (app bundles, Linux and Windows paths) and the process match
  `extension_stop` uses, the same way waterfox is listed; the engine has
  launched both since 4.1.26.
- The dependency floors move past every advisory `pnpm audit` reported on
  2026-09-30 (42: 18 high, 22 moderate, 2 low, all transitive): axios,
  brace-expansion, fast-uri, js-yaml, nanoid, devalue, hono, ip-address,
  qs and postcss-selector-parser through `pnpm.overrides`, vitest to 4.1.11
  as a dev dependency. The audit reads zero; nothing the server does
  changes.
- The bundled template catalog moves to the corpus at `2c3a486a`, which
  renamed the `new-*` examples to `newtab-*` and added the `devtools-*`
  family and `sidebar-monorepo-nx`. `extension_add_feature`'s newtab row
  now names `newtab`, `newtab-react`, `newtab-vue`, `newtab-svelte` and
  `newtab-preact`; the catalog-sync PR had failed on the old names every
  day since 2026-09-26.

Nine findings from a session that brought ten third-party extensions under
the server in one day:

- `extension_dev` and `extension_start` spawn the engine in the project
  directory, not where the MCP client started the server, so the engine a
  session drives is the project's own and the started envelope names it
  under `value.engine`.
- Every session artifact path (ready.json, logs, the build summary) now
  resolves from the engine's project root, the nearest package.json,
  deno.json or deno.jsonc at or above the manifest, so a project whose
  manifest sits in a subfolder no longer makes `extension_wait` watch a
  contract the engine never writes.
- A failed `extension_build` carries the compiler errors the engine stamped
  on its contract under `value.errors`, or the bundler's own output under
  `value.output`, and its hint no longer asserts a manifest location the
  engine does not require.
- `extension_wait` on an `extension_start` session answers `launched` at
  once with the production-build guidance instead of spending its budget on
  a "transient" `E_NOT_ATTACHED` that is permanent there; a clamped budget
  is reported in `warnings` on every exit; and a dead-contract note names
  only the browser the call asked about.
- `extension_eval` names the extension's own content security policy when
  the engine refuses with "call to eval() blocked by CSP", instead of
  blaming the expression, and on MV2 Gecko a page or content
  eval goes through `tabs.executeScript` from the background when the
  engine has no scripting API, with the content-world caveat stated
 .
- `extension_open` with a `url` opens a new tab unless `tab` names one, so
  a page under test is never taken over; a path with no scheme resolves
  against the extension's own origin on Chromium and Gecko.
- `extension_manifest_validate` reads `public/` when resolving manifest
  references, warns rather than blocks on a missing web-accessible resource
  and on a Chromium-only side panel, counts `devtools_page` and options
  pages when ranking similar templates and ranks by surface overlap ratio,
  and on Firefox warns on a missing `browser_specific_settings.gecko.id`,
  on Chromium-only keys and on `extension_ids`, and gives an MV2 manifest
  the keys to port for MV3.
- `extension_start` takes `outputPath`, an existing unpacked extension
  directory to launch as it is through the engine's preview verb, so an
  artifact another toolchain produced, or the exact release candidate, can
  be run and watched without an Extension.js build. A directory
  with no manifest.json is refused before anything launches.
- `extension_manifest_validate` warns on Firefox when
  `browser_specific_settings.gecko.data_collection_permissions` is missing,
  which AMO now requires for new add-ons, and shows the minimal form.

Seven more from the same session's functional sweep:

- `extension_eval` reaches the Chromium background over CDP: the MV3 service
  worker or MV2 background page is a target of its own, and evaluating on it
  is the inspector path the extension's content security policy does not
  govern, so state only the worker knows is readable again under
  `script-src 'self'`. An idle worker with no target answers `E_NO_TARGET`
  with how to wake it.
- `extension_eval` with context `page` and a url evaluates on the matching
  tab's CDP target, so a site that enforces Trusted Types (YouTube, Gmail)
  no longer refuses the string; the active-tab refusal names Trusted Types
  and the url route. Every CDP route falls back to the in-bundle
  relay when the session has no debug port.
- `extension_open` asks the browser whether it is headless (HeadlessChrome
  names itself) and renders popup, options and sidebar as a tab at once
  when it is, instead of opening a popup that is gone before the next call
 . A page the browser swapped for its own error page answers
  `navigate-blocked` with the browser's title instead of `navigated`, and
  eval refuses such a tab.
- `extension_browsers` reports the newest managed version when several sit
  in the cache, the one the engine launches.
- `extension_inspect` probes on Gecko return the same shape as on Chromium,
  `{selector, count, samples[]}` with a text snippet per element
 .
- `extension_assert` on Gecko reads `background-worker-booted` off the
  control channel (the bridge executor runs in the background) and
  `surface-rendered` off the surface relay, instead of answering
  inconclusive for want of a CDP target list; a selector clause stays
  inconclusive there and names the tool that probes it.

- `@extension.dev/urls` moves to `^0.8.1`, which reserves `chromium`,
  `firefox`, `mcp` and `skill` as mint slugs.
- `extension_browsers` install hands the canary's installer the server's
  own managed-binary search as `locateInstalledBinary`, which that
  installer now requires to verify an install before it reports success.
- The stored login reader no longer types a missing entry as `undefined`
  where it promises `null`, so consumers that compile the server's source
  under `noUncheckedIndexedAccess` typecheck it.
Assets 2
Loading