Closes#156749
## What Problem This Solves
Fixes: a Chrome Web Store tab makes browser tabs, snapshot, and evaluate fail for every tab after the native-identity recovery in #139275.
## User Impact
Ordinary tabs remain usable while Chrome-protected pages are open. The Gateway logs the excluded tab ID and Chrome's refusal; browser tab output lists only usable targets. Transient failures still reject the complete inventory. This is a Gateway-side fix: the existing Store extension forwards Chrome's errors unchanged, so no new Store release is required. CDP response fields and configuration are unchanged.
## Why This Change Was Made
Classify exact Chrome attach refusals, not URL lists or arbitrary errors. The observed Web Store error is `The extensions gallery cannot be scripted.`; Chromium also defines exact restrictions for chrome:// and other extensions' pages. Classification happens for every newly visited tab, including arrivals during enumeration, and is not cached across requests. A changed URL cannot inherit an earlier exclusion. Diagnostics use the existing warning logger rather than adding a protocol field that tab-list consumers discard.
## Evidence
Real Chrome 153, unpacked extension 2.3.0, an isolated Gateway, and a fresh browser profile with https://example.com/ and https://chromewebstore.google.com/:
- Baseline main `932572acb2` relay: browser tabs fails with `Protocol error (Target.getTargets): Target identities are unavailable`.
- Candidate: tabs lists Example Domain with native target ID `<target-id>`. Snapshot returns the Example Domain heading and Learn more link; evaluate returns `"Example Domain"`. The Store tab remains open.
- Gateway warning: `Skipping tab 2017597585 during target enumeration: The extensions gallery cannot be scripted.`
- The first listing immediately after Gateway restart returned no tabs; the later connected listing and snapshot/evaluate succeeded. This does not claim startup behavior changed.
- CLI proof used the normal built `node openclaw.mjs browser --browser-profile chrome ...` entry after the supported wrapper built the runtime; the development wrapper attempts to rebuild a dirty tree and correctly refuses while a Gateway is running.
- Both new regressions fail on baseline with -32002; candidate enumeration passes 15/15. Existing controls still reject transient native acquisition/retirement failures and preserve fresh native identities. New cases cover late-arriving protected tabs and retry after a refusal clears. Initial focused invocation: 23.59 seconds wall including cold worker generation; the new cases took 3–4 ms each.
- Final focused enumeration, cleanup, and Fetch suites: 34/34 passed in 19.68 seconds wall. Extension production/test typechecks and scoped typed lint passed.
Chromium contracts: [debugger attach](https://github.com/chromium/chromium/blob/main/chrome/browser/extensions/api/debugger/debugger_api.cc), [Web Store restriction](https://github.com/chromium/chromium/blob/main/chrome/common/extensions/chrome_extensions_client.cc), [exact error constants](https://github.com/chromium/chromium/blob/main/extensions/common/manifest_constants.h).
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
* refactor(plugins): deslop browser and memory-core second pass
Share browser registration, route orchestration, and documented SDK owners.
Consolidate memory queue state, search preparation, and ingestion checkpoints.
Preserve browser safety and tool definitions, memory schema and ordering,
and existing dreaming and compaction output. Remove 1,344 net production lines.
* fix(browser): break headless source type import cycle
Move the unchanged headless-source union to the existing profile contract
and migrate config, Chrome, and client types directly to that leaf owner.
This removes the type-only cycle caught by the architecture gate.
* chore(deps): refresh dependencies with a seven-day cutoff
* fix(deps): preserve Teams and jsdom integration contracts
Use the Teams SDK public token and processing APIs while keeping SSO sender
checks ahead of native token operations. Remove obsolete ambient declarations
and route workarounds, and cover the SDK routing with real processing tests.
Adapt the test environment to jsdom private-field bindings, preserve file bytes
and registry cleanup, and preload it through native Node and Bun workers.
* fix(test): preserve jsdom window and fixture contracts
* fix(ci): keep typecheck cache reuse within matching inputs
* improve(agents): stop prompt-side refusals for requested work
Drop the system prompt Safety section, the blanket credential ban, the external-content IGNORE list, and template ask-first/when-in-doubt rules. Runtime tool policy, sandboxing, and exec approvals already gate risk; the prompt now says requested actions with available tools are authorized.
* improve(agents): drop refusal prose from tools, skills, and SOUL template
Soften screen/app-UI and subagent-output notes, drop confirm-before and --yolo avoidance lines from skills, and let SOUL.md stop saying 'when in doubt, ask'. Bootstrap completion recognizes the previously shipped AGENTS.md/SOUL.md bytes so the template edit does not end a pending onboarding.
* test(agents): drop prompt wording pins
Delete tests that only asserted literal prompt/tool-description phrases; keep one discriminating assertion per input-dependent branch, cache/ordering invariants, boundary markers, and the refusal-trigger guard.
* fix(agents): keep legacy credential prompt result and align docs
Legacy string and unknown-availability callers of buildCredentialSafetyPrompt keep the documented handoff-only result; the credential-use line needs known control-tool availability. Update system-prompt and SDK migration docs for the Care section, and keep xurl auth checks on auth status.
* fix(agents): align remaining care guidance with requested work
Resolve contradictory workspace-template wording for requested representation and sharing, correct the bootstrap step count, and describe sandbox host access in terms of available tools and permissions.
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
* fix(agents): acknowledge supplied credentials after requested work
Complete requested credential use or storage, then give a brief factual acknowledgment without repeating the value. Preserve the action-oriented execution guidance and restore focused Workshop ownership and scoped cron lookup regression checks.
Validation: 372 targeted tests passed remotely; formatting, diff checks, and uncommitted autoreview passed.
* test(agents): align prompt snapshots and verify fetch spill recovery
Regenerate the Codex prompt fixtures for the current credential acknowledgment and cron guidance. Preserve the 800-character web-fetch budget while checking complete spill recovery and a single matching sanitized boundary pair.
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
* fix(agents): preserve source content in bounded fetch previews
---------
Co-authored-by: roboclaw-bot <309084314+roboclaw-bot@users.noreply.github.com>
Co-authored-by: jalehman <550978+jalehman@users.noreply.github.com>
Co-authored-by: joshavant <830519+joshavant@users.noreply.github.com>
* improve: reuse live placement authority for worker checks
* fix(gateway): narrow placement authority read facts
* test(state): retain real cache lifecycle exports in reader fixture
* test(browser): retain relay fixture port through cleanup
* test(gateway): revoke the actual claim before transcript writes
* fix(plugins): correct vendor logos and remove generic blue icon tiles
Use official square artwork where available, match fallback dark plates to the
OpenClaw lobster, and remove Slack’s inset app-tile padding. Record all source
assets and the complete 159-icon audit.
Co-authored-by: Patrick-Erichsen <20157849+Patrick-Erichsen@users.noreply.github.com>
* improve(plugins): use white tiles and consistent logo insets
Normalize all 159 bundled identity icons against main 208132c299. Use standalone colored or dark artwork on opaque white, including the native mascot family. Record per-icon provenance and adaptations.
Co-authored-by: Patrick-Erichsen <20157849+Patrick-Erichsen@users.noreply.github.com>
* fix(plugins): correct requested product marks and colors
Use verified first-party assets for the requested eight branding groups, keeping the Bedrock Mantle sibling consistent. Preserve white tiles and all unrelated icon bytes. Reef shares the native lobster by request.
Co-authored-by: Patrick-Erichsen <20157849+Patrick-Erichsen@users.noreply.github.com>
---------
Co-authored-by: Patrick-Erichsen <20157849+Patrick-Erichsen@users.noreply.github.com>
Preserve the exact reviewed source tree and layer delta while refreshing CI merge context.
Previous signed head: 84007d6f3e
The failed CI merge predates the canonical cross-peer Vitest type repair landed in ee558121d1. No source, test, dependency, or workflow bytes change in this refresh. Existing runtime proofs retain their original source identities; fresh required CI must verify the repaired main context.
Co-authored-by: Vincent Koc <vincentkoc@ieee.org>
* docs(browser): audit engine licenses and non-AGPL alternatives
Preserve the reviewed browser-stack change while incorporating the landed prerequisites.
Original revision: 8f41f08a1e92c079ad19ab9f3b849be26cf1559b
* feat(browser): verify Chromium headless shell across platforms
Preserve the reviewed browser-stack change while incorporating the landed prerequisites.
Original revision: b11dd7173db731e026b7abae9d3b4064ac30d300
* test(gateway): complete prepared placement read fixture
Supply the required empty policyConfig in the placement lifecycle read fixture. This repairs the inherited check-test-types-core-4 failure while keeping the production browser-stack changes unchanged.
* feat(browser): add opt-in Lightpanda semantic profiles
* fix(browser): reject direct selectors for Lightpanda profiles
* feat(browser): add portable Lightpanda deployment and benchmarks
* docs(browser): translate lightweight browser page title
* fix(browser): verify stale targets with a valid navigation control
* feat(browser): unify local Chrome setup across desktop and terminal
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
* feat(browser): unify local Chrome setup across desktop and terminal
OpenClaw-Publication: d19e865e-b5a0-4c70-8876-c1662f6e7ef2
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
* chore(linux): format Chrome setup fixture
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
* feat(browser): keep desktop Chrome setup local and preserve pairing
Delegate Windows registration to the shared native management owner, preserve
released native bridge compatibility and saved launcher profiles, and integrate
serialized desktop setup through isolated local runtimes.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(browser): repair native setup CI contracts
Keep Windows installer dependencies acyclic, validate Unicode within the
package library target, and remove unused private exports. Require all
eight packaged native-host proof cases and update lazy CLI inventory.
Apply native Swift formatter diagnostics without changing behavior.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* test(cli): account for plugin-owned browser extension catalog
Keep the core-only registration invariant aligned with the Browser plugin
owner already exercised by its lazy registration tests.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* test(macos): retain released Chrome bridge request expectation
Align the native bridge test with the shipped contract1 request retained
by the canonical setup owner, and reject extra legacy payload fields.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* test(tui): give command handler harness a unique export
Rename the shared TUI test helper and both consumers to avoid the
Gateway placement harness export collision. No alias or guard waiver.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* chore(sdk): allow canonical browser config path resolver
Apply the approved single public-export and callable allowance for
resolveConfigPath. Preserve canonical pre-config path ownership and
all other SDK surface checks.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(browser): preserve desktop setup selection and supported actions
Keep native automatic setup selector-free and resolve saved local browser
selection through the canonical setup owner before installation. Respect
Mac action advertisements and the released legacy install projection in
the Apps card, and document the public config-path resolver contract.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(auth): retry model selection after concurrent credential refresh
Adopt upstream PR #152426, commit 32298b10f6, without changing its five source files.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* test: preserve native setup selection and await dashboard document
Match the selector-free native CLI arguments exactly and preserve a saved work-profile result. Wait through the existing document-readiness owner only at the quota test browser-proof boundary, after auth assertions.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(ui): avoid preloading already imported modules
Remove exact direct static JavaScript imports from lazy preload tables using the emitted build graph. Preserve HTML, lazy-only JavaScript, CSS, and locale hints. Source-exact CI merge reproduction drops startup gzip from 363283 to 362968 bytes without changing budgets. Add a real emitted-bundle regression.
Apply rustfmt layout to the native Chrome selector-free expected arguments.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix: preserve Chrome profiles and attachment follow-up branch binding
Let the TUI canonical setup controller retain its saved browser profile and project only a bounded returned name. Align both native first-run fixture expectations with selector-free setup.
Join pending chat history before the composer task handoff can expose an admitted attachment to restored-outbox delivery. Preserve idempotency, attachment custody, restored delivery semantics, and all existing assertions and timeouts. Add a deterministic regression reproduced on the exact failed CI merge and its main parent.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* test(state): adopt canonical worker-custody fixture repair
Adopt src/plugin-state/plugin-state-worker.test.ts byte-for-byte from upstream bfec65a2a0 (#152456).
The former fixture held its late competing owner until after awaiting off-thread acquisition. Preserve that overlap, assert continued host authority checks and noncompletion, release custody, then assert the original result and persisted state. No production locking, guard, deadline or outcome assertion is relaxed.
Both prior failures reproduced on the exact CI main parent with independently installed frozen dependencies and Node 24.19.0. All 12 repaired file tests, selected state-logging types, scoped typed lint and fresh P0-P2 review passed.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(browser): retain saved Windows setup profiles
Recover configured extension profiles through bounded serial read-only C# inspection. Select only independently validated current matching descriptors, confirm the selected generation before effects, and leave the single mutation under the existing C# owner. Preserve POSIX behavior, existing manual relay verification and explicit same-profile repair.
Missing descriptors, runtime/origin drift and unknown or changing observations fail closed without automatic mutation. Keep raw management facts private and populate the existing browserProfile field only from validated binding metadata. No ABI, schema, SDK, configuration flag or registry/activation owner change.
29 actual CLI/controller/Windows-adapter boundary cases plus sibling coverage: 94 tests pass. Canonical changed checks, full production build and fresh independent P0-P2 review passed. Actual C# native proof remains separately coordinated.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(browser): preserve saved profiles after POSIX bundle relocation
Separate validated native registration ownership from supported origin-migration readiness. Recover the profile only after full private manifest and exact launcher validation; preserve the existing one-slot migration rule and all unsupported-origin, ACL and foreign-host refusals. Fail closed before selector-free installation when the saved selection cannot be proved.
Extract the unchanged shared origin helpers into a cohesive sibling to satisfy the existing line-cap guard without waivers. Windows admission, ABI and selector behavior remain unchanged.
Actual Linux/Darwin CLI-to-filesystem relocation regressions: 18 failures on original production, all 22 cases repaired. Preserve the private relay key and inode, config, Chrome preferences, work relay19444 and explicit-profile intent. 137 focused tests, eight real POSIX native-host E2E cases, canonical changed checks, full production build and fresh P0-P2 review passed.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(ui): retain input handoff through the shared outbox owner
Remove the superseded pending-history no-yield workaround after main introduced foreground submission custody in the shared outbox owner. Restore chat-submit-guard.ts exactly to pinned main cc7 rather than retaining competing timing policies. Keep passive drains fenced while the input task yields.
Preserve the retained history regression with explicit MessageChannel admission, no passive send before resume, and the same terminal leaf, idempotency key, attachment bytes and exactly-once assertions after completion. Original composed source fails all five focused cases; the repair passes 67 handoff/attachment cases and 20 real Chromium cases in the canonical secretless network-none runner. Canonical checks, UI build/performance and fresh P0-P2 review pass. No assertion, timeout, origin or proxy-policy weakening.
Browser POSIX/Windows repairs remain byte-identical to accepted255f. The failed e40e CI receipts remain preserved; fresh exact-head CI and parent handoff are still required.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(tasks): preserve reads across native event finalization
Hand joined event publication to its exact native successor after the native
flow and observer publication frame completes. Keep worker settlement and
cleanup, reversible claim transfer, current-authority and ABA checks, and
post-commit delivery in their existing owners without replaying writes.
Cover pre-result and readback finalization, native and reentrant successor
chains, rollback, failed publication, delivery, and terminal activity cleanup.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* test(ui): retain rail baseline geometry on readiness failure
Keep the exact existing readiness predicate, fixtures, case inventory, assertion and timeout. When the predicate is false, retain synthetic marker identity and numeric geometry so hosted CI can distinguish scroll, visibility and viewport failures.
This is diagnostic evidence, not a repair or waiver of the unresolved rail failure. Local rootless browser infrastructure is unavailable; the existing hosted CI lane will verify the reviewed task-publication repair and collect meaningful rail evidence. Canonical changed checks and P0-P2 diagnostic review pass.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* docs(linux): describe saved-profile Chrome setup selection
Match the selector-free adapter argument vector and its regression test. Address the fresh P3 review finding without changing runtime behavior. Markdown syntax and diff checks pass; the generic formatter excludes this subtree.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* test(transcripts): join configured startup before cleanup faults
Observe and await the real startTranscripts promise through a narrow call-through spy while retaining the configured service entry point and real SQLite/provider work. Bind the await to the existing test lifetime instead of charging startup to the subsequent short active-map poll.
Gate provider return after persisted utterance to prove readiness does not settle early; retain both missing/unreadable row injections and all cleanup, private-source, lifecycle-token and summary assertions. Cover real startup rejection explicitly. No production change, timeout increase, retries or broad module/storage mocks.
The deterministic ordering boundary fails with the old fire-and-forget readiness and passes with the real promise join. Final 39 tests across 3 files, canonical changed checks and full-owner P0-P2 review pass. This does not recover whether the historical CI startup was late or rejected.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* fix(browser): preserve automatic desktop status inspection
Restore read-only Device-page inspection for current and released Mac bridges while keeping installation and verification explicit. Preserve the native filesystem prerequisite proof, split installer repair tests within the existing line cap, and remove the superseded constant export.
* fix(browser): preserve registered setup configuration
Require canonical setup to match an owned launcher's effective state and
config selection before installation or relay access. Preserve equivalent
implicit/explicit default selections and the saved launch context. Recheck
automatic profile selection before effects and the current manifest before
publication through the existing registration owner. Keep manual install
and relocation repair contracts unchanged.
Cover mismatched configs, legacy selectors, equivalent defaults, selection
drift, and actual bootstrap after refused setup. Restore the missing Command
import in the existing Unix-only companion CLI test.
Focused tests, types, lint, fresh review, clean package build and sealed Mac
ARM64 runtime proof pass. The separate historical clock-jump CI failure has
bounded replay evidence and remains documented without a speculative fix.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
* fix(browser): keep setup registration types acyclic
Move the private registration status contract beside its context policy and
point both consumers at that owner. Remove the publication-module back-edge
without keeping an unused compatibility export.
The full architecture gate, extension production/test types, typed lint and
fresh independent review pass. Node's transformed JavaScript is byte-identical
for all three affected modules, so the existing runtime proof remains valid.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
* test(linux): handle Chrome setup in desktop sharing fixture
Recognize the exact automatic Chrome setup invocation and require its native
no-respawn flag. Keep unknown-command rejection, selected-auth validation,
process-group ownership and joined teardown assertions unchanged.
The original fixture reproduces the CI rejection against the real Linux app.
The repaired fixture passes all nine checks against that same binary, with
five Chrome setup calls and five node starts and joined stops. Fresh review
is clean; production app behavior is unchanged.
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
---------
Co-authored-by: fuller-stack-dev <263060202+fuller-stack-dev@users.noreply.github.com>
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Carry the current subagent cleanup owner through Browser activation, dashboard reconciliation, and tab claims. Let already admitted closes settle against their captured tab ownership without removing later registrations.
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* chore(deps): refresh dependencies with seven-day cutoff
Advance eligible runtime, native, release, and development dependencies published by 2026-09-14T07:00:00Z. Preserve compatibility holds and existing reviewed newer pins. Synchronize release integrity checks and scoped overrides; remove the superseded mailparser override.
Preserve Clack cancellation inference with its precise sentinel type and isolate the Vertex proxy fixture from ambient credentials. Timestamp and checksum audits, targeted consumers, native builds/tests, and independent review validate the refresh; required hosted CI remains the landing gate.
* fix(deps): preserve Clack cancellation types in exported prompts
Give styled configure prompts the exact upstream return types so plugin SDK declaration emission can name the new cancellation sentinel. Runtime behavior and generic option values are unchanged.
* fix(deps): preserve release tooling and Android test contracts
Regenerate Ruby lock metadata with pinned Bundler 2.6.9, grant Robolectric 4.17 its documented module access only in Android test JVMs, and keep the precise cancellation type without growing an over-cap source file.
Both previously failing Ruby lock guards, the line-cap and core type checks, all three configured Android test-task JVM arguments, and the actual Robolectric interceptor before/after probe pass. Independent review found no actionable P0/P1 issues.
* fix(deps): close Rustls advisory and align mock session clocks
Rustls 0.23.45 has now completed the seven-day cooldown; update only the shared crate pin and lock to the existing security-fixed desktop version.
Advance accepted mock Gateway writes on the synthetic fixture timeline and correlate permission tests with the actual mutation and refresh. This repairs a reproduced CI fixture race without changing production behavior or weakening assertions.
Validation: 36 Rust gateway-client tests including four TLS handshakes, 50 fixture tests, nine browser cases, scoped changed checks, and independent P0/P1 review passed.
* test(ui): keep external session updates on the committed timeline
* test: stabilize approval and desktop CI fixtures
* build(workboard): refresh assets after dependency rebase
* fix(gateway): apply settings without unnecessary restarts
Apply operation settings through their existing runtime owners, retire stale request authority, and retain accepted work through cleanup. Preserve current visitor grants and cancellation while consolidating desktop, secrets, transcript, and UI ownership.
* refactor(gateway): consolidate history and audit test wiring
* test(gateway): observe plugin approval response completion
Replace the plugin approval fixture's one-second polling deadline with
observation of the existing response callback. Keep acceptance, payload,
visibility, decision, and handler-settlement assertions intact. Worker-backed
registration can legitimately finish after the unrelated polling deadline.
The unchanged full file reproduced nine acceptance-wait failures out of 35
cases (341.72s). All nine affected cases passed with the repair. The repaired
full file passed 34/35 (462.81s); an untouched resolve case reported a SQLite
lock error without an operation stack. A bounded replay of that case and its
immediate predecessor passed 2/2 with 33 cases filtered (77.50s), so the lock
cause remains unestablished and is not claimed fixed.
The owning gateway-methods type graph (44.54s), typed lint (89.54s), formatting,
and diff checks passed. Independent review found no actionable P0-P2 findings.
No production code, retries, or timeout values changed.
Co-authored-by: Peter Steinberger <steipete@gmail.com>
Related: #153023, #152938, #153923
## What Problem This Solves
Fixes browser proxy staging producing nonportable filenames when the 180-byte limit cuts an otherwise sanitized name at a dot, space, or reserved-name boundary.
## User Impact
Long upload names retain the existing portable-name rules after truncation. File contents, private permissions, upload limits, per-file isolation, and cleanup behavior stay unchanged. Existing staged files are not renamed; no configuration or migration is required.
## Why This Change Was Made
Truncation runs after the initial sanitation and can undo its result. The existing browser owner now trims the truncated suffix and rechecks reserved names, retaining the empty-name fallback. This matches the already-fixed terminal-upload behavior without adding a new SDK surface.
## Evidence
The shipped CLI drove a real authenticated Gateway, a separately paired foreground node, and Chromium in a credential-free local Linux/arm64 container. Command-surface approval used `openclaw nodes approve`. Upload requests explicitly targeted that node, so they could not fall back to the Gateway host.
- On current-main baseline `2cb001d2e8`, an actual source name of 179 `a` characters plus `.b` became a staged name ending in `.`. The same name appeared in the real browser file input and the receiving website's multipart request.
- On exact PR head `ae4a099c42a12a605d98fd1881bab79b0eeb5c11`, the upload completed with the expected 179-character name. An `ordinary.txt` control completed alongside it in both phases. Physical staging, browser File objects, and website-received bytes agreed with each phase's original fixture bytes.
- Both phases stopped the browser, node process group, and Gateway, with no remaining process referencing the task's node home. Only their own staged files were removed after shutdown.
- Seven additional registered-command groups cover suffixes, reserved names, UTF-8 boundaries, empty fallback/collisions, portable controls, and invalid envelopes. Mode 0600, distinct file paths, unchanged bytes, and failed-request cleanup were preserved.
- The retained regression fails on baseline production code; all 17 upload-owner tests pass on the candidate. Exact-head runtime build, scoped type-aware lint, and formatting passed.
The full user-path proof replaces the earlier staging-only evidence. Fixture setup failures were retained and corrected without changing product code or rebuilding for driver-only edits. Native Windows behavior was not exercised; the earlier blanket Windows `EINVAL` claim and incorrect introduction attribution are not retained.
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Related: #154066
## What Problem This Solves
Gateway startup can activate the browser plugin in memory while preserving the authored configuration. Cold browser-control startup then incorrectly checks the authored allowlist again and reports the activated plugin disabled.
This repairs that runtime/control mismatch. It does not claim to fix external rewriting or ordering of `plugins.allow`; the diagnostics from #154091 remain intact.
## User Impact
A browser that the Gateway has activated can initialize its in-process control service and eager HTTP control server without requiring an extra source-allowlist edit. Effective plugin disablement, deny rules, disabled plugin entries, and a fresh `browser.enabled=false` still prevent cold startup. Browser options continue to use the existing source-backed refresh owner, and startup does not rewrite the authored allowlist.
## Why This Change Was Made
Both existing cold-start owners now evaluate plugin enablement using the activated runtime config. Their browser-option resolver, authentication, shared control state, and shutdown owners are unchanged. No new configuration, dependency, schema, permission policy, or public SDK surface is introduced.
## Evidence
- **Actual supported Gateway startup:** on main `894fb140a2`, both the registered `browser.request` path and eager HTTP startup reproduce the false allowlist refusal. The Gateway records browser auto-activation, the source allowlist remains unchanged, and explicitly allowlisting browser restores the baseline positive control.
- **Candidate runtime:** the same real CLI/Gateway, authenticated WebSocket client, and HTTP routes pass **28 scenarios**. These cover both cold entrypoints, source-option refresh, all four disable/restart/recovery paths, unchanged authored config during reads/startup, and absent/bad HTTP-token rejection. Only the downstream CDP-discovery endpoint is synthetic and returns 503; no Chrome process is launched.
- **Discriminating regressions:** six newly added assertions fail against the original startup owners; the fresh-source browser-disable preservation case passes. Four focused browser suites pass **86 tests**. After removing the fixture's retired color field, its 11 tests and scoped lint pass again; unchanged sibling results are retained.
- **Source and checks:** baseline and candidate runtime builds pass; scoped type-aware lint, formatting, whitespace, and both structural ratchets pass. The prepared contributor-preserving branch has the exact same complete tracked tree as the runtime-tested candidate.
- **Settlement:** the normal Gateway lifecycle closes owned servers and process groups without forced retirement. Source-helper compiler services are observed separately after their driver exits; all **256 observed child processes** are gone before synthetic state is removed. The Node fence admits no external request and records two blocked catalog-prewarm attempts separately.
The baseline's explicit-allowlist rescue setup also exposed an eager hot-disable counterexample; that failed observation is retained, not presented as a passing baseline suite. The candidate's auto-activated configuration passes its complete live disable/restart/recovery sequence. Earlier fixture setup failures are also retained rather than counted as product failures or successful runs.
Limits: this is real Gateway/control-startup and configuration-lifecycle proof on Node 24.21/macOS, not Chrome navigation, native-app, visual UI, Windows, packet-capture, or full update-migration proof. No live provider, paid model call, operator state, or operator Gateway was used. Hosted exact-head CI and final review remain required before landing.
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
Browser control failures could suggest restarting the Gateway when plugin policy still blocked browser control. Preserve the existing policy refusal reason and request-scoped runtime failure details in one browser-owned diagnostic, shared by local dispatch, Gateway requests, node proxies, and the extension relay.
Give cause-specific recovery for allowlist exclusions, global/plugin/browser disablement, denylist refusal, and plugin failures. Unknown availability and generic local transport errors point to browser diagnostics or Doctor instead of an unconditional restart. This changes no enablement policy or stored configuration.
Related: #154066. Thanks @mmkerrigan for reporting the restart loop. The reported allowlist rewrite remains unidentified and outside this diagnostic fix.
Evidence: seven assertions failed on the original code; 188 focused browser tests passed across six files. Changed-file checks and the canary-proven extension-lint substitute passed; exact-head CI was green. Codex autoreview was scoped-clean and ClawSweeper found no actionable findings.
* fix(browser): preserve snapshot identity through canceled captures
Keep native DOM bindings tied to their captured controls, fence canceled
snapshot writes, and preserve visible descendants under ignored AX roots.
Consolidate snapshot capture under the existing role snapshot owner.
Keep MCP labels scoped to their documents, finish cleanup before publishing,
and discard ambiguous cross-document IDs. Retire refs before every snapshot
refresh, including hidden and failed captures.
Preserve healthy sibling connections during tab closure, ignore superseded
extension bootstrap timeouts, deliver node timeout diagnostics through the
CLI, and recheck node access before browser actions.
* test(browser): preserve request budgets in CLI timeout assertions
Refresh 13 direct dependency packages and 15 resolved versions published by September 13, 2026 at 14:50 UTC.
Preserve compatibility-constrained versions, patches, overrides and the existing strict cooldown. Retain YAML 2.9.0 for the verified release producer and frozen security-review runtime. Regenerate Workboard's content-addressed browser asset pointers.
Validated by exact-head CI run 35520400755 and security/merge-gate reconciliation 35521175227, plus local consumer, release-producer, publication-admission and unchanged UI-budget checks.
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
Closes#151301
## What Problem This Solves
Fixes browser storage commands silently trimming keys, so reading or setting `" account "` targets the distinct `account` entry instead.
## User Impact
Quoted keys retain their exact contents in both local and session storage. Setting a padded key no longer overwrites its unpadded neighbor. Ordinary keys, primitive-key coercion, value whitespace, omitted-key reads, and rejection of blank SET keys remain unchanged.
## Why This Change Was Made
The CLI lookup and the shared storage GET/SET routes now reuse the existing whitespace-preserving string helpers. Browser authorization, URL guards, storage formats and the Playwright storage owner are unchanged. Existing regression tests assert returned values and resulting storage state instead of forwarded call shapes.
## Evidence
- Ran 24 independently reset before/after cells through the actual built browser CLI and direct authenticated Gateway requests, using a task-owned real Chromium page. Raw CDP independently inspected both storage buckets.
- Baseline padded reads selected the unpadded entry; padded writes overwrote it while leaving the requested entry unchanged. Candidate reads and writes use the exact padded key and preserve its neighbor.
- Both storage kinds passed ordinary-key, padded-value, omitted-key listing, rejected blank SET/no-mutation, and numeric/boolean key controls. No egress attempts occurred, and all task-owned Gateway/client/browser resources settled.
- 57 focused CLI/route tests passed. Reintroducing trimming at the two owners caused five distinct regression failures while the two clear-storage controls still passed. Runtime build, scoped lint, formatting, whitespace and line-cap checks passed.
Proof used main `d0192ed506` with byte-identical contributor production files. The isolated Gateway used its shipped canary startup profile to suppress unrelated autonomous sidecars while preserving real plugin loading and method admission; this is not a full normal-startup or upgrade claim. The disposable Chromium proof replaces the proposal's optional direct-route-only fixture; retained tests cover the regression at both parsing boundaries without requiring a browser installation.
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
* fix(browser): preserve snapshot targets and automation deadlines
Bind scoped role references to native DOM identities and keep capture cleanup
alive through timeout settlement. Preserve shared CDP connections when one
reader cancels and reject captures spanning replaced child documents.
Use native Chrome MCP coordinate input, preserve actual action errors, and
align extension and node request budgets. Repair aborted pairing, tab adoption,
and lifecycle cleanup; remove the retired plain-ARIA reference builder.
* test(browser): preserve endpoint redaction coverage and fix snapshot lint
Probe tab identities concurrently and evict only the browser connection that failed selection. Preserve blocked-target state across recovery and cover slow sibling tabs, overlapping reconnects, and quarantine behavior.
* chore(deps): refresh dependencies with seven-day release cutoff
Update 20 compatible package versions published by September 11, 2026 at 17:55 UTC; preserve patches, overrides, and incompatible pins.
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* chore(deps): refresh dependencies with seven-day release cutoff
Worked on by:
- @steipete
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
OpenClaw-Publication: 56ff74cb-22b8-4962-ab53-39496522a822
* fix(deps): preserve docs publishing and align ACP version checks
Retain slugify 2.2.1 and transliterate 1.6.0 so the independent publisher graph and existing documentation anchors remain compatible. Align exact Claude ACP assertions and skill documentation with the updated 0.76.0 manifest pin.
Validation: docs-sync CLI failed before the hold and passed afterward; 11 publisher tests, 26 Markdown/anchor tests, and 326 ACPX tests passed. No production logic, timing budgets, or assertions weakened.
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
---------
Co-authored-by: steipete <58493+steipete@users.noreply.github.com>
* perf(browser): move dashboard event discovery to SQLite worker
Keep board-change and deleted-session discovery off the Gateway thread through the existing keyed-store worker. Drain accepted discovery and reconciliation before service stop or restart, and discard late results from replaced runtimes. Preserve the canonical namespace and final browser-close authority.
* test(browser): align worker batch expectations
* feat(node): update headless runtimes automatically when idle
Stage private packaged node runtimes and activate only after all owned work
and cleanup settle. Preserve pairing and launch options, keep automatic
activations at least 12 hours apart, and leave shared-state migration and
Gateway installation ownership with the normal updater.
Document defaults, opt-outs, runtime version discovery, and recovery.
Support recoverable Windows selector replacement across service restarts.
Refs #151462
* fix(node): complete auto-update integration and settings defaults
Capture the launcher in compiled test runtimes and trusted wrapper inventories, register the package update proof, and use the canonical Kysely read path. Preserve the inherited enabled state in the config UI and align caller tests with the node shutdown lifecycle.
* fix(node): preserve retained plugin work during automatic updates
Require an explicit idle result from plugin commands, preserve older-plugin work, and connect bundled lifetime owners to automatic node updates. Join canceled inference and failed terminal cleanup before command settlement; keep historical state repair with Doctor. Document compatibility and extend installed-package proof for retained legacy plugin work.
* test(browser): align idle-work fixtures with runtime exports
* test(browser): extract proxy request fixtures
* test(node): retain idle assertions across native cleanup
Use the existing guarded store operations to retire process state after successful deletion or native identity replacement. Preserve observations for sibling generations and retained dashboards, and inspect remaining canonical owners only when a cold observation exists.
Reserve per-tab Input dispatch order before asynchronous tab policy checks.
Release the turn at native invocation so unrelated commands and replies
remain concurrent while original authority and attachment checks stay intact.
Prove release-before-press and keyboard ordering through authenticated relay
socket frames, including queue retirement and failed-lookup recovery.