Skip to content

fix(input): harden readiness around persistent background leases - #311

Open
lymerin wants to merge 1 commit into
Tencent:mainfrom
lymerin:codex/242-background-input-hardening
Open

lymerin wants to merge 1 commit into
Tencent:mainfrom
lymerin:codex/242-background-input-hardening

Conversation

@lymerin

@lymerin lymerin commented Sep 21, 2026

Copy link
Copy Markdown

Problem

This is follow-up hardening related to #242, not a claim that the original 0.2.1 bug remains unfixed.

BrowserSkill 0.3.0 added withInputReady in 1740a1d. For an unprepared hidden target, it temporarily enables focus emulation, waits for renderer readiness, dispatches the input, and disables the temporary override during cleanup.

Current main also has the persistent background-execution policy introduced later by #249. The dispatcher acquires that lease before invoking controlled page-tool handlers.

The two mechanisms did not have an explicit ownership boundary. withInputReady could not determine whether the current session already owned the persistent policy. If it still observed the page as hidden, it could independently enable and later disable focus emulation. Those direct toggles do not update BackgroundExecution's applied cache, leaving this inconsistent state:

  • the renderer override has been disabled by temporary cleanup;
  • BackgroundExecution still records the persistent policy as enabled;
  • a later synchronize can treat the cached state as current and skip reapplying it.

The existing click browser coverage also invokes the handler directly for its readiness assertions, bypassing the dispatcher's prepareBackgroundExecution step. It therefore covers the compatibility fallback but does not pin the production lease-before-handler ordering.

Change

  • Add an optional read-only CdpRunner.ownsBackgroundExecution(sessionId, tabId) predicate.
  • Implement it in ChromiumCdp using BackgroundExecution.has, so it reports desired session ownership rather than transient attachment state.
  • When the session owns a persistent lease, make that lease authoritative for focus emulation and skip the temporary visibility/screenshot readiness path.
  • Preserve the bounded 0.3.0 fallback when no persistent lease exists, including direct-handler compatibility paths.
  • Add dispatcher-level coverage proving that the persistent lease is acquired before the click handler checks ownership and dispatches input.
  • Keep the direct-handler readiness tests intact and add coverage for ownership across ordinary debugger detach, release, and terminal target_closed.
  • Retain a real-browser invariant check that leased clicks do not issue temporary focus toggles or readiness screenshots.

An ordinary debugger detach invalidates only the applied attachment state and retains desired ownership. The next send performs ensureAttached → synchronize before the requested CDP command, so the persistent override is restored before input dispatch. A terminal target_closed intentionally forgets the owner.

This does not add page-event delivery verification, change click result semantics, or activate the browser window.

Validation

  • Extension suite: 123 test files and 1,898 tests passed; 14 browser-gated files and 103 tests were skipped by the default configuration.
  • Targeted input/dispatcher/driver suite: 169 tests passed.
  • TypeScript --noEmit check passed.
  • Targeted real-browser click and background-execution tests passed on Windows 11 with Chrome 153.
  • Biome and git diff --check passed.

Related to #242.

@lymerin
lymerin force-pushed the codex/242-background-input-hardening branch from b1254da to 32cbfe1 Compare September 21, 2026 16:08

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant