Skip to content

Release BetterWright 2.8.9 - #235

Merged
SSHdotCodes merged 4 commits into
mainfrom
maintenance/2.8.9
Oct 13, 2026
Merged

SSHdotCodes merged 4 commits into
mainfrom
maintenance/2.8.9

Conversation

@SSHdotCodes

@SSHdotCodes SSHdotCodes commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

BetterWright now supports cookie sources outside the browser reader registry, lets Pi sessions initialize or change local browser visibility, and reads validated launch defaults from the home config across the SDK, CLI, MCP, and Pi. The package version and changelog are updated to 2.8.9, including the fixes already on main.

  • Cookie Sync accepts a database file or Chromium profile directory through source: { path } and --source-path, retaining domain filtering, quotas, remote consent, source preservation, and target verification. Empty results redact source filenames consistently with imported results.
  • Pi adds browser_visibility and /browser-visibility with visible, headless, and offscreen modes. Results report restarts and lost tabs. Persistent profile cookies and storage survive; operations are serialized and current evidence proofs reset after a restart. Remote and host-supplied browsers remain host-controlled.
  • A closed launch configuration section supplies display, profile, ad-blocking, locale, timezone, and download defaults. Explicit options override environment variables, which override saved defaults. Overridden invalid environment values do not prevent SDK or CLI startup. Effective settings participate in CLI daemon compatibility checks, and one-shot agent browsers receive the same settings.

Validation: native reader regression tests with a synthetic Chromium database; real-browser cookie import and persistence; real Pi transitions through all three display modes with retained cookies and local storage; 23 CLI binary E2E cases passed. bun install --frozen-lockfile --ignore-scripts and bun run release:check passed with 1,354 tests and 3 expected skips, including lint, type, build, and package smoke checks. The review regressions passed all 46 focused tests. Cross-platform CI gates the merge.

Fixes #230
Fixes #231
Fixes #232

@devin-ai-integration

Copy link
Copy Markdown
Contributor

I stopped the review of PR #235 partway through, because the commit that triggered it is no longer the latest. It was e956016; the branch head is now 867468b ("test: release SQLite fixture statements before Windows cleanup", a small change to tests/node/cookie-sync.test.ts only). Your rules say to stop when the triggering commit is superseded, so I didn't post a PR comment, record videos, or open a fix PR. The new push should start a fresh run against 867468b. I deleted the fix branch I had pushed (devin/e2e-fix/235-e956016) because any fix has to be based on the new head.

Checks that ran on e956016 (Linux x64, Bun 1.4.0):

  • Passed: version, lint, typecheck, build, declaration-type and package checks.
  • Unit tests: 1,346 passed and 2 failed. Both failures are in the Chromium archive packaging tests and come from this machine, not the PR: its Python 3.10 lacks a function the packaging script calls (hashlib.file_digest).
  • Real-browser tests: all 9 cookie-sync, launch and Pi visibility tests passed with a display available, including switching between visible, headless and offscreen with the saved login kept.

Two bugs I reproduced, for the next run:

  1. cookies sync --source-path can't read a real, encrypted Chromium profile. It fails with "Cookie Sync could not read the selected local browser profile." The code in src/cookie-sync.ts never tells the cookie reader which browser the file came from, so the reader can only handle unencrypted databases. Calling the reader directly with browserId: "chromium" returned both test cookies. The PR's own test only uses a Firefox-format database, so it doesn't catch this. I didn't fix it: it needs a maintainer to decide how users name the source browser for a path.
  2. A relative --source-path breaks if the background session process started in another directory. I started that process in one folder, then ran --source-path ./cookies.sqlite from a folder that has the file, and got the same "could not read" error. The process resolves the path against its own starting folder. My fix resolves the path in the caller's folder before it's sent. With the fix, the same command synced 1 cookie and the test page showed the user signed in. The new regression test fails without the fix and passes with it; lint and typecheck pass. The change is in the attached patch, ready to re-apply on 867468b.

Not done for this commit: MP4 recordings, launch-default runs through the SDK/MCP/Pi entry points, and the PR comment.

Files are in this session:

  • 235-relative-cookie-path.patch
  • NOTES.md

This response includes attachments — view them in Devin

@devin-ai-integration

devin-ai-integration Bot commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Superseded: this run reviewed 1c468b5, but the branch head is now 867468b. The two new commits (e956016, 867468b) touch only src/agent.ts, types/agent.d.ts and tests. src/cookie-sync.ts, bin/cli-main.ts, src/launch-config.ts and src/pi-extension.ts are unchanged, so both findings below still apply to the current head as far as the code goes, and #236 still merges cleanly into maintenance/2.8.9. I stopped after detecting the new head. A run against the new head should re-verify these findings. The results below cover 1c468b5 only. I could not check from the review VM that the MP4 links open, because its network policy blocks app.devin.ai. The animated previews below are embedded directly.

E2E review: BetterWright 2.8.9 (#235)

Tested head: 1c468b57ae5a0013c31dfac7fadaecf34ae29cb6 (base main @ 5a4590a). This is a same-repo branch, not a fork.
Environment: Ubuntu 22.04 x64 VM under KDE/X11, display 3200x2400. Bun 1.4.0 (official GitHub release zip, SHA-256 verified), playwright-core 1.61.1, BetterChromium 153.0.8010.36-r2 (installed by betterwright setup, checksum OK). doctor printed "BetterWright is ready." Python is 3.10.12. All homes and profiles were disposable, the only site was a local 127.0.0.1 fixture, and no credentials were used.

Verdict

1 confirmed functional defect in the headline Cookie Sync path feature (#230). 1 small confirmed CLI bug, fixed in draft #236. Pi visibility (#231) and launch defaults (#232) behaved as described.

Journey matrix

Journey Result
lint, typecheck, test:types, check:versions, build:harness pass
test:unit (1353 tests) 1351 pass, 2 fail. Both failures are environment-only: the chromium-package win/linux packager tests need Python ≥3.11 hashlib.file_digest
Focused browser.test.ts (Pi visibility ×2, Cookie Sync ×5, including the new source: { path } test) with the real managed browser 7/7 pass
CLI launch defaults: saved locale/timezone/profile → env BETTERWRIGHT_LOCALE/_TIMEZONE → --locale/--timezone pass (precedence correct; profile dir browser/profiles/cfgprof created)
CLI downloadPolicy saved none/ask/deny → canceled, allow → completes; env deny → canceled; saved deny + --approve-downloads → refused pass
CLI daemon after a config.json change pass. The new settings apply through a one-shot browser, with the "daemon with different browser flags" warning (as documented)
Invalid saved launch values (bad locale, timezone, profile ../evil, headless, adBlock) pass (ignored, defaults used)
Invalid BETTERWRIGHT_HEADLESS / BETTERWRIGHT_DOWNLOAD_POLICY fail: wrong error label (see 2, fixed in #236)
SDK new BetterWright({ home }): saved, env, then explicit options (including profile: null, downloadPolicy: "allow") pass
MCP over real stdio (betterwright mcp, MCP SDK client, browser tool): saved locale, then env override pass
Pi browser_visibility + /browser-visibility with a real headed browser on the display: bad mode or extra key rejected; same mode keeps tabs; visible→offscreen→headless→visible restarts with tabsLost; HttpOnly cookie + localStorage persist in the launch-config profile; session_shutdown cleans up pass (see the note on offscreen)
cookies sync --source-path on a real Chromium profile directory or Cookies file fail (see 1)
--source-path argument errors (with <browser>, with --source-profile, empty value, no scope) pass
--source-path + --include-session Rejected, but only through the generic "could not read" error with cookieReaderCode: reader_unavailable, because the TypeError is thrown inside extraction. Optional hardening: validate it in normalizeCookieSyncOptions
Source DB left unmodified after a sync attempt pass (sha256 unchanged)

Confirmed findings

1. --source-path / source: { path } cannot read real (encrypted) Chromium cookie databases.

  • Repro: I created a profile with BetterChromium through playwright-core. The fixture set a persistent HttpOnly cookie with Set-Cookie. Then I ran betterwright cookies sync --source-path <dir>/Default --domain 127.0.0.1 --profile target --json. The result was {"ok":false,"cookieReaderCode":"reader_failed"}, and the target profile never sends the cookie. The Cookies file path fails the same way, with or without the daemon.
  • Root cause: extractCookieSync calls reader.fromPath({ path, timeoutMs, appBound }) with no browserId, localStatePath or plaintextOnly. rookie-cookies 0.6.0 documents that a Chromium DB sniffed with no selector is plaintext-only. Calling it directly gives InvalidArg … chromium_sqlite: missing_chromium_credentials, while the same file with browserId: "chromium" returns e2e_session=src-1.
  • Why tests missed it: The new unit test uses a synthetic plaintext cookies table, and the browser test uses a Firefox moz_cookies DB. Real Chromium-family profiles store encrypted_value (v10/v11 on Linux, Keychain/DPAPI keys on macOS/Windows). The documented Helium example would therefore hit the same failure.
  • Not auto-fixed: Fixing this needs a public-API or security decision about which credential identity a path source may use. Options include an optional browser/browserId hint next to path (today browser?: never), or a localStatePath option. That would change types/public.d.ts, the CLI contract and Keychain prompting, so a maintainer should pick the shape. The docs/CHANGELOG claim ("The reader handles supported decryption") should not ship as-is.

2. Invalid launch-default env vars are reported under the profile label. BETTERWRIGHT_HEADLESS=maybe betterwright run … prints BETTERWRIGHT_PROFILE: BETTERWRIGHT_HEADLESS must be …. With --profile work it prints --profile: …. The cause is that cliProfile() now runs launchOptionsFromEnv(), and the runCli preflight catch labels every error with the profile source. This affects every command, including doctor. Fix + regression test: draft #236 (targets maintenance/2.8.9). The new test fails on 1c468b5 and passes on ce29ba3.

Notes / limitations

  • Offscreen mode under KWin: the window is not off-screen. With offscreen / headedInvisible, the window reported screenX,screenY = 640,669 on the 3200x2400 display and is visible in the recording, because KWin clamps --window-position=32000,32000. The mechanism lives in src/launch-identity.ts, which this PR does not change, so this is not a regression here. But Pi now exposes it as offscreen, so it is worth noting that it depends on the window manager.
  • Not tested: macOS Keychain and Windows App-Bound cookie paths; Electron; cloud/CDP providers (including the "remote browsers are host-controlled" visibility refusal); exec (no model backend configured); interactive console /headed / /headless switching with headedInvisible; Pi inside a real Pi host (I used the extension API directly with the PR build); cross-platform CI. Release artifacts were not checked against this commit, since none are published for 2.8.9 yet.
  • I did not merge or push to maintenance/2.8.9. Merge approval is left to a human.

Recordings (real runs, MP4)

Animated previews of the same recordings:

Pi visibility on 1c468b5
Cookie source-path failure on 1c468b5

Written by Devin

@greptile-apps

greptile-apps Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 4/5

[Medium impact] Release version 2.8.9 with new features and configuration.

Do not merge until the explicit-option precedence failure is fixed. The one-shot display-mode and empty-result metadata findings are non-blocking.

Findings

  1. P1 Overridden settings still block startup ▶
  2. P2 One-shot tasks lose off-screen mode ▶
  3. P2 Empty results expose local filenames ▶

T-Rex evidence

Evidence from the check

  • The executed script imports actual SDK source and records nine constructor cases plus head resolver calls, isolating the claimed precedence failure.

Evidence from the check

  • The executed command script extracts unchanged parent sources and captures both runs with commands, exit codes, and source lines, making the comparison reproducible.

Command output from the check

  • Ran nine actual SDK constructor cases on the parent commit and captured structured results and source lines, showing explicit ad-block and profile settings construct successfully despite invalid overridden environment values.

Command output from the check

  • Ran the same nine constructor cases and direct resolver calls on unchanged PR235 head, showing invalid overridden environment values throw before explicit settings are applied.

Evidence from the check

  • Builds the parent sources and captures the same real CLI harness on parent and PR builds, making the comparison reproducible.

Evidence from the check

  • Runs the actual CLI against a local model and browser fixture, inspects live Chromium arguments, and executes direct-construction controls to measure launch behavior.

Evidence from the check

  • Logs the actual worker configuration while returning it unchanged, exposing the effective launch mode without changing product behavior.

Command output from the check

  • Captures the parent commit identifier and successful compilation before executing the comparison, establishing that the before run used parent sources.

Command output from the check

  • Runs both saved configurations through the parent CLI and real Chromium, showing that prior one-shot execution launched headless for both.

Command output from the check

  • Runs both saved configurations through the PR CLI and real Chromium alongside direct browser controls, confirming that one-shot execution loses the saved invisible mode.

Evidence from the check

  • The executed harness creates a synthetic Chromium database and checks empty and nonempty public SDK responses, demonstrating the metadata discrepancy without personal cookies.

Evidence from the check

  • The executed command script builds both source revisions and captures their SDK requests, responses, and source excerpts, making the comparison reproducible.

Command output from the check

  • The parent build received both synthetic path-source requests and rejected them with the browser-id validation error, showing explicit paths were unsupported before the change.

Command output from the check

  • The PR235 build returned an absolute filename for the empty match but 'selected' for the matching control, confirming inconsistent source metadata redaction.

Evidence from the check

  • The executed script imports actual SDK source and records nine constructor cases plus head resolver calls, isolating the claimed precedence failure.

Evidence from the check

  • The executed command script extracts unchanged parent sources and captures both runs with commands, exit codes, and source lines, making the comparison reproducible.

Command output from the check

  • Ran nine actual SDK constructor cases on the parent commit and captured structured results and source lines, showing explicit ad-block and profile settings construct successfully despite invalid overridden environment values.

Command output from the check

  • Ran the same nine constructor cases and direct resolver calls on unchanged PR235 head, showing invalid overridden environment values throw before explicit settings are applied.

Evidence from the check

  • Builds the parent sources and captures the same real CLI harness on parent and PR builds, making the comparison reproducible.

Evidence from the check

  • Runs the actual CLI against a local model and browser fixture, inspects live Chromium arguments, and executes direct-construction controls to measure launch behavior.

Evidence from the check

  • Logs the actual worker configuration while returning it unchanged, exposing the effective launch mode without changing product behavior.

Command output from the check

  • Captures the parent commit identifier and successful compilation before executing the comparison, establishing that the before run used parent sources.

Command output from the check

  • Runs both saved configurations through the parent CLI and real Chromium, showing that prior one-shot execution launched headless for both.

Command output from the check

  • Runs both saved configurations through the PR CLI and real Chromium alongside direct browser controls, confirming that one-shot execution loses the saved invisible mode.

Evidence from the check

  • The executed harness creates a synthetic Chromium database and checks empty and nonempty public SDK responses, demonstrating the metadata discrepancy without personal cookies.

Evidence from the check

  • The executed command script builds both source revisions and captures their SDK requests, responses, and source excerpts, making the comparison reproducible.

Command output from the check

  • The parent build received both synthetic path-source requests and rejected them with the browser-id validation error, showing explicit paths were unsupported before the change.

Command output from the check

  • The PR235 build returned an absolute filename for the empty match but 'selected' for the matching control, confirming inconsistent source metadata redaction.

View artifacts

Summary

Releases BetterWright 2.8.9 with explicit cookie-file sources, Pi browser visibility controls, and shared saved launch defaults.

  • Cookie Sync can read cookies from a database file or profile folder.
  • Pi can set a local browser to visible, headless, or offscreen mode.
  • All hosts can use the same saved browser launch defaults.
  • Release metadata and notes identify BetterWright 2.8.9.

Fix explicit-option precedence before merging: malformed environment values prevent SDK construction even when valid explicit settings override them. Two non-blocking concerns also remain: one-shot tasks lose saved off-screen mode, and empty Cookie Sync results return local filenames instead of the metadata placeholder.

Reviews (1) · Last reviewed commit: "feat: release 2.8.9 with cookie paths, P..." · Reviewed by Greptile

Comment thread src/launch-config.ts Outdated
Comment thread bin/cli-main.ts
Comment thread src/cookie-sync.ts
@devin-ai-integration

Copy link
Copy Markdown
Contributor

Requested access to app.devin.ai only so I can confirm the uploaded MP4 evidence links work before posting on PR #235. I'm carrying on with the report and the fix PR in the meantime.

@devin-ai-integration

Copy link
Copy Markdown
Contributor

PR #235 is still at 867468b, and no earlier run reviewed this SHA. I confirmed four defects and opened draft fix PR #237. I've handed off to the testing agent to record real MP4s; the #235 report comes after that.

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Starting E2E review of PR #235 (head e040763): verifying PR state/dedup first, then building and running the PR version.

@SSHdotCodes
SSHdotCodes merged commit 4ddb510 into main Oct 13, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant