Skip to content

skills(browser): overlapping commands on one session must use SESSION_BUSY, not an in-page lock #385

Description

@ankitranjan7

Why this issue exists

This came from the local:session-concurrency eval. The eval is trying to prove two separate things:

  1. Two different sessions can run browser work in parallel.
  2. Two overlapping CLI invocations against the same session produce structured SESSION_BUSY, followed by a safe retry.

Source reports:

  • /Users/ankitranjan/Work/agentrhq/evals/results/run-20260820T085734Z/report.md
  • /Users/ankitranjan/Work/agentrhq/evals/results/run-20260820T103952Z/report.md

Current Webcmd state

As of origin/main 22974697bb3fe784bad5ef5a208f2d6ee5a272a8 (webcmd-v0.7.4-2-g2297469):

  • SESSION_BUSY exists as a structured CLI error.
  • The error message says the session is busy because another holder is already driving it.
  • The hint says: wait, then run the same command again.
  • If the holder pid is live, the hint says not to force-close; if the holder is not live, webcmd session close --force <session-id> is presented as a last resort.
  • The local runtime queues browser work by profile/session/site before execution, so session occupancy is a Webcmd runtime concern.
  • Current skill/help text names SESSION_BUSY, but it does not make the two-CLI-invocation shape impossible to miss.

Observed agent behavior

The successful run eventually did the right thing:

  • Created two explicit sessions.
  • Backgrounded two webcmd --session <id> browser run commands and proved the 3s waits overlapped.
  • Started one long command on the Alpha session.
  • Issued a second webcmd --session <same-alpha-id> browser run while the first was still holding the session.
  • Received SESSION_BUSY naming the holder pid.
  • Waited, retried the same second command without --force, and verified final count 2.

The failed run shows the agent confusion:

  • It created sessions, but did not create CLI-level contention.
  • It tried to overlap work inside one browser run with two page.evaluate(applyUpdate) calls.
  • Both in-page calls completed, so no SESSION_BUSY envelope appeared.
  • The agent concluded the structured busy response did not exist in page code.
  • The final count became 3, because the retry happened after in-page writes rather than after a CLI busy/retry sequence.

What went wrong

The agent modeled session occupancy as a page-level lock. It looked for busy state inside the browser page instead of in the Webcmd session runtime.

SESSION_BUSY is not produced by two promises inside one browser run. It is produced when a second Webcmd CLI invocation tries to drive the same session while another invocation still owns it.

The recurring failure pattern is:

  1. The agent sees a concurrency task.
  2. It creates two sessions correctly.
  3. For same-session contention, it stays inside one browser program.
  4. It invents an in-page lock or in-page overlap.
  5. It never asks the CLI to arbitrate the session.

Why this matters

This is a product affordance issue more than an eval-specific skill issue. Agents should not need deep skill text to understand where the lock lives. The CLI/runtime should make it hard to miss that session contention is between Webcmd invocations, not page scripts.

Related product concern: SESSION_BUSY must be returned before browser work starts when a session is already held.

Solution directions

The preferred solution should put the durable behavior in the CLI/runtime first.

Possible directions:

  1. Product/runtime: ensure every mutating browser command checks session ownership before doing browser work and returns structured SESSION_BUSY with holder details.
  2. CLI help/error text: make the error say that the caller should wait for the listed holder, then retry the same command. --force is only for a dead holder.
  3. session list: make active holders visible enough that an agent can inspect the session state without inventing page locks.
  4. Minimal skill text, if needed: one troubleshooting line saying SESSION_BUSY comes from a second webcmd --session <id> ... process, not from page.evaluate.

Open questions for senior review

  • Is the runtime/error surface already strong enough after the product fix, making the skill PR unnecessary?
  • Should there be a CLI-visible way to show the current holder command/pid in session list?
  • Should the docs include a two-terminal recipe, or is that too much eval-specific instruction?

Acceptance criteria

  • A second CLI invocation on a held session returns structured SESSION_BUSY before browser work starts.
  • The error tells the agent to wait for the holder and retry the same command.
  • The agent does not implement an in-page mutex or use page.evaluate as the safety signal.
  • The safe retry path completes without --force and without an extra write.

Non-goals

  • No fixture-specific wording.
  • No data: localStorage policy changes here.
  • No encouragement to force-close a live holder.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions