Skip to content

fix: make browser session starts recoverable - #290

Merged
iuyo5678 merged 4 commits into
mainfrom
fix/recoverable-session-starts
Sep 20, 2026
Merged

iuyo5678 merged 4 commits into
mainfrom
fix/recoverable-session-starts

Conversation

@iuyo5678

Copy link
Copy Markdown
Collaborator

Problem

Fixes #245.

The DSH plugin previously recorded ownership only after a successful CLI reply. If the CLI was cancelled, timed out, or terminated after window creation, that reply could be lost and the Agent Window became unreachable from the plugin. Initial navigation/emulation failure could also discard ownership even when the compensating close failed.

Change

Represent each managed start as a recoverable request whose identity exists before any browser side effect:

  • Persist the request and conversation ownership before dispatch; prepare, start, then claim only after initialization succeeds.
  • Deduplicate retries by request token. Cancellation is terminal, including cancellation before a delayed start arrives. An unprepared start is rejected after a daemon restart.
  • Keep ownership until window closure is confirmed. Wait for delayed creation to settle, retain failed startup compensation in the extension, and retry failed cleanup.
  • Recover abandoned plugin journals; cancel pending and completed starts on archive/unload. Unclaimed requests expire through the existing daemon reaper.
  • Keep pending cleanup visible and counted against capacity. Verify request ownership when short session IDs are reused, and release transfer resources on confirmed stop.

Ordinary CLI starts keep their existing behavior. Managed starts require matching CLI/daemon support; update the extension too for retryable startup-compensation failures. No new package dependencies.

Lifecycle and recovery contract

Validation completed on macOS

Suite Passed
CLI/daemon Rust unit tests 352
Protocol tests 154
Session IPC, cancellation, queue and user-interrupt integration tests 50
DSH plugin tests 268
Extension session-manager and session-tool tests 59

Rust formatting, Clippy with warnings denied, TypeScript checks, and targeted Biome checks passed. The plugin build also passed.

The integration tests use a real daemon, IPC/WebSocket connections, and a controlled extension peer. One test kills an actual CLI child after dispatch and before its successful reply, then recovers and closes the session through a new CLI process. Additional cases cover delayed creation, duplicate requests, failed close/retry, failed startup compensation, archive/unload, journal recovery, capacity, and foreign-session isolation.

Windows/DSH/Chrome GUI validation is still pending. The results above do not claim that coverage.

Windows verification requested

Use CLI, daemon, extension, and DSH plugin builds from this branch; ensure the DSH profile points to that CLI and the daemon is also running this build. Keep the same working directory and journal location when testing host restart recovery.

  1. Start, navigate, list, and stop normally. Expect one Agent Window and consistent current-session/list state.
  2. Cancel a start around window creation, and separately terminate only that test's CLI process while the start is pending. Expect eventual closure; a temporarily unresolved outcome must remain recoverable instead of disappearing.
  3. Trigger an initialization failure, then retry cleanup if the initial close fails. Expect the owned resource or pendingCleanup to remain visible until closure is confirmed.
  4. Archive the conversation or unload/reload the plugin during a pending start. Expect no late successful start to become usable; cleanup must continue or recover on reload.
  5. Terminate and restart the test DSH host. Expect abandoned requests to be recovered and cancelled. Keep a second live DSH instance/session open to verify it is unaffected.
  6. Repeat interrupted starts and cleanup. Expect no growing window count, no bypass of maxSessions, and no closure of unrelated Agent Windows.

Focused automated checks to run on Windows:

cargo test -p bsk --lib --locked session_requests
cargo test -p bsk --test sessions_ipc --locked recoverable_starts
pnpm --filter @wxg-prc-cpg/browser-skill-dsh-plugin test

Please include Windows/Chrome or Edge/DSH versions, commit SHA, reproduction steps, and the before/after window and session counts with test results. Reviewer attention is especially useful on lifecycle races, journal recovery ownership, and cancellation/cleanup boundaries.

Track prepared starts with stable request handles, durable plugin ownership, monotonic cancellation, and retryable cleanup. Retain delayed and failed startup resources until cleanup is confirmed, without touching other sessions.

Add regression coverage for lost replies, killed CLI processes, delayed creation, failed cleanup, restart recovery, archive and unload, capacity accounting, and reused session IDs.

Fixes #245
Capture initial tab identities when creating an Agent Window and retain them
through failed startup compensation. Retry cleanup through the production
stop handler, preserving later user tabs and keeping ownership if agent tabs
still cannot close.

Separate owned starting and cleanup resources from active sessions. Publish
sessions only after initialization and claim succeed, preserve the working
current session on failure, and reject ordinary operations and captures for
resources awaiting cleanup. Recheck queued operations before execution.

Add regression coverage for production stop retries, mixed windows, delayed
claims, current-session fallback, recovery, capacity, and queued operations.
Update window API fixtures for the creation result's initial tab identities.

Validation: extension 1862 passed (103 skipped), plugin 276 passed; both
TypeScript checks and production builds passed.
Route tool, overlay, archive, unload, and recovery cleanup through one lifecycle
owner and one job per request. Persist explicit stop intent before making a
session unusable; caller cancellation only ends its wait after admission.

Retain durable completion receipts independently of the current session so a
retry cannot stop another working session, even after background cleanup or
restart. Preserve failed default callers' retries across concurrent successful
waiters. Support exact request targeting and reject ambiguous stop targets.

Cover failed normal stops, queued and in-flight cancellation, concurrent entry
points, timer and disk recovery, persistence failures, anonymous starts, reused
IDs, unconfirmed replies, and completion receipt capacity accounting.

Validation: 303 plugin tests passed, including 31 stop recovery tests;
TypeScript checking, production build, and formatting passed.
Package lint was unavailable because publint is not installed in this environment.
Share optional stop target parameters between browser_session and its internal
stop handler. Document exact request targeting, mutual exclusion, and default
stop retry behavior in the model-visible contract.

Add a public schema regression covering requestId, optional targets, and retry
guidance. Lifecycle execution remains unchanged.

Validation: 95 tool and stop recovery tests passed; TypeScript and formatting
checks passed. The new schema test reproduced the omission before the fix.
@iuyo5678
iuyo5678 merged commit d04c752 into main Sep 20, 2026
7 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

2 participants