8000
Skip to content

feat(serve)!: admit concurrent runs with a bounded queue instead of refusing them - #400

Open
frontierkodiak wants to merge 4 commits into
steipete:mainfrom
frontierkodiak:serve-concurrency
Open

feat(serve)!: admit concurrent runs with a bounded queue instead of refusing them#400
frontierkodiak wants to merge 4 commits into
steipete:mainfrom
frontierkodiak:serve-concurrency

Conversation

@frontierkodiak
Copy link
Copy Markdown
Contributor

Behaviour change with a chosen default. If you'd rather the cap, the queue depth, or the refusal status be different, they are all one constant away — happy to follow your call.

What

oracle serve was single-flight: a second caller got HTTP 409 busy and was expected to invent a retry policy. That shape fits a service where runs are short. These are not — a Pro answer can take ten minutes, and nearly all of it is waiting for the model rather than driving the browser.

Nothing in the browser stack required the restriction. Runs hold their own CDP page connection (connectToNewTarget), clipboard capture is page-local JS monkey-patching inside Runtime.evaluate, input and uploads are per-target, temp dirs are per-run, and a repo-wide sweep finds no module-scope mutable state in src/browser beyond frozen constants. The composer section that genuinely must be serialized already is, by the profile run lock. What was missing was a place for the next caller to wait.

Approach

A bounded number of concurrent runs (4 by default) and a FIFO queue for the rest. A queued caller is told its position over the existing log event, so older clients ignore it rather than breaking. Refusal is reserved for a full queue — 503 with Retry-After — because a caller told "later" can wait, while a caller told "no" has to guess.

Cancellation had no representation at all: the service never observed client disconnect, and BrowserRunOptions had no way to express it. Measured before this change, a client killed ten seconds into a thirty-second run held its browser tab and its slot for the remaining twenty. signal now joins the existing disconnect race, so every awaited step honours it and the existing unwinding releases the tab lease and closes the owned tab. It raises BrowserRunCancelledError, since a caller that walked away is not a run that went wrong.

Two isolation defects that single-flight was hiding are fixed with it: the client's session slug was used verbatim as the key for the server's own artifact directory (slugs are prompt-derived, so two callers could collide), and the browser tab cap is now pinned to what the service admits, so extra callers wait in the queue where the wait is visible rather than inside the lease loop where it is not.

Real behavior

Five concurrent callers against one browser, watched through /health:

t=4s   active=4 queued=1
...
t=32s  active=4 queued=1
t=36s  active=3 queued=0
t=40s  active=1 queued=0

All five exited 0, each got its own answer, and each landed in a distinct conversation — five ids, no cross-talk.

Cancellation, same setup: a client killed ten seconds into a run now releases the slot 2s after disconnect (previously 20s, i.e. natural completion), and the service records cancelled: the caller disconnected rather than a completion.

Worth knowing

ChatGPT itself rate-limits well below what the transport can drive: six conversations opened at once tripped its "Too many requests" modal repeatedly on a Pro account, while five did not. So the default cap of 4 is deliberately under that. (#395 makes that modal report itself as a rate limit instead of as a missing model.)

Breaking

A second concurrent caller is now served rather than receiving 409 busy. A client that treated 409 as its back-off signal will no longer see one; saturation is 503 queue_full.

Tests

Ten added: admission up to the limit, the caller past the limit waiting rather than failing, FIFO order, saturation only when the queue is full too, cancellation while queued and while running, double-release safety, an end-to-end concurrency run through the real HTTP path, per-run session-id isolation, and the tab cap being pinned to what the service admits.

Full suite green: 1772 passed / 43 skipped.

…efusing them

`oracle serve` was single-flight: a second caller got HTTP 409 `busy` and was
expected to invent a retry policy. That shape fits a service where runs are
short. These runs are not — a Pro answer can take ten minutes, and nearly all of
it is waiting for the model rather than driving the browser.

Nothing in the browser stack required the restriction. Runs hold their own CDP
page connection, clipboard capture is page-local, input and uploads are
per-target, and temp directories are per-run; the composer section that genuinely
must be serialized already is, by the profile run lock. What was missing was a
place for the next caller to wait.

So: a bounded number of concurrent runs (4 by default) and a FIFO queue for the
rest. A queued caller is told its position over the existing `log` event, so
older clients ignore it rather than breaking. Refusal is now reserved for a full
queue — 503 with `Retry-After` — because a caller told "later" can wait, while a
caller told "no" has to guess.

Cancellation had no representation at all: the service never observed client
disconnect. It does now, and a disconnect frees whatever the caller held —
its place in the queue, or its slot. Without that a long-lived service leaks
capacity to clients that walked away until it stops accepting work.

Two isolation defects that single-flight was hiding are fixed with it. The
client's session slug was used verbatim as the key for the server's own artifact
directory, and slugs are prompt-derived, so two callers could collide; the server
now namespaces per run. And the browser tab cap is pinned to what the service
admits, so extra callers wait in the queue where the wait is visible rather than
inside the lease loop where it is not.

`/health` reports active, queued, and capacity so a caller can decide when to
send work instead of discovering the answer by being queued.

BREAKING: a second concurrent caller is now served rather than receiving 409
`busy`. A client that treated 409 as its signal to back off will no longer see
one; saturation is 503 `queue_full`.

Claude-Session: https://claude.ai/code/session_01HsXirqcfqtr1Cae9zYCLDk
`oracle serve` observed client disconnects and freed the queue slot, but nothing
reached the run itself: `BrowserRunOptions` had no way to express cancellation,
so a disconnected caller's run continued to completion and its capacity came
back only by accident of finishing. Measured before this change, a client killed
ten seconds into a thirty-second run held its slot for the remaining twenty.

That is the wrong shape for runs this long. A browser run holds a tab and a slot
on a shared profile for minutes, and the caller is the only party that knows it
has stopped caring.

`signal` joins the existing disconnect race, so every awaited step honours it and
the existing finally does the unwinding it already knew how to do — releasing the
tab lease, closing the owned tab, stopping the monitors. Cancellation raises
`BrowserRunCancelledError` rather than a generic failure, because a caller that
walked away is not a run that went wrong, and a reader of the session record
should not go looking for a fault.

Verified live: the same interrupt now releases the slot 2s after disconnect
instead of 20s, and the service records "cancelled: the caller disconnected"
rather than a completion.

Claude-Session: https://claude.ai/code/session_01HsXirqcfqtr1Cae9zYCLDk
@clawsweeper
clawsweeper Bot commented Aug 18, 2026
Copy link
Copy Markdown
Contributor

🦞👀
ClawSweeper picked this up.

Pull request received. I will update this pull request when review starts.

@clawsweeper clawsweeper Bot added merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing u 8000 sers, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Aug 18, 2026
@clawsweeper
clawsweeper Bot commented Aug 18, 2026
Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed August 21, 2026, 5:22 PM ET / 21:22 UTC.

ClawSweeper review

What this changes

This PR changes oracle serve from rejecting concurrent browser runs to admitting a bounded number, queueing later callers, propagating cancellation, and isolating each run’s server-side artifacts.

Merge readiness

Blocked until stronger real behavior proof is added - 11 items remain

Keep open: the proposed service behavior is still absent from current main, but bounded admission and cancellation retain P1 defects, and replacing the established 409 backoff contract needs maintainer approval.

Priority: P2
Reviewed head: e3a6e67df08509d21fca67506ae3e3baf9d5eec2
Owner decision: Required. See Decision needed.

Review scores

Measure Result What it means
Overall readiness 🦐 gold shrimp (3/6) The implementation and test scope are substantial, but unresolved P1 capacity/cancellation defects and incomplete current-head live proof prevent merge readiness.
Proof confidence 🦐 gold shrimp (3/6) Needs stronger real behavior proof before merge: The PR body contains useful claimed concurrency output, but the current head's remote-abort and host-cap follow-up changes have no redacted after-fix live trace; add one showing bounded saturation and abort recovery without private endpoints or tokens. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Patch quality 🦐 gold shrimp (3/6) 4 actionable review findings remain.

Verification

Check Result Evidence
Real behavior Needs proof Needs stronger real behavior proof before merge: The PR body contains useful claimed concurrency output, but the current head's remote-abort and host-cap follow-up changes have no redacted after-fix live trace; add one showing bounded saturation and abort recovery without private endpoints or tokens. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed 6 items Current main still uses single-flight refusal: Current main sets busy before body parsing and returns HTTP 409 with busy for a second request, so the PR's central behavior is not already implemented or released.
Queue capacity is not reserved atomically: The saturation check precedes an awaited body read; simultaneous valid requests can all pass it, while RunSlots.acquire itself never rejects when waiting.length exceeds maxQueued. They can therefore overfill the supposedly bounded queue.
Chrome acquisition still bypasses cancellation: raceWithAbort is used for the tab-lease wait, but both manual Chrome acquisition and local Chrome launch are awaited directly; cancellation is only raced after the CDP connection exists.
Findings 4 actionable findings [P1] Enforce queue capacity when acquiring a slot
[P1] Race cancellation through Chrome acquisition
[P2] Align the effective default with the advertised four runs
Security None None.

Live Verification

Command: pnpm exec tsx bin/oracle-cli.ts serve --help

Result: PASS (completed)

pnpm exec tsx bin/oracle-cli.ts serve --help
runner@runnervm76f27:/tmp/clawsweeper-live-proof-400-cSsCzz/target$ pnpm exec tsx bin/oracle-cli.ts serve --help
pnpm exec tsx bin/oracle-cli.ts serve --help
Oracle CLI v0.18.0 — Prompt + files required — GPT-5.5 Pro/GPT-5.5 for tough questions with code/file context.

Usage: oracle serve [options]

Run Oracle browser automation as a remote service for other machines.

Options:
  --host ‹address›                   Interface to bind (default 0.0.0.0).
  --port ‹number›                    Port to listen on (default random).
  --token ‹value›                    Access token clients must provide (random if omitted).
  --manual-login                     Use a dedicated Chrome profile for manual login (recommended when cookie sync is unavailable). (default: false)
  --manual-login-profile-dir ‹path›  Chrome profile directory for manual login (default ~/.oracle/browser-profile).
  --browser-cookie-sync              Copy cookies from this host's live Chrome profile instead of using the dedicated profile. (default: false)
  -h, --help                         display help for command
runner@runnervm76f27:/tmp/clawsweeper-live-proof-400-cSsCzz/target$ pnpm exec tsx bin/oracle-cli.ts serve --help

































Assertions:

  • PASS expect_output: Run Oracle browser automation as a remote service for other machines.

How this fits together

oracle serve accepts authenticated remote browser-run requests and streams browser progress/results back over HTTP. The new admission layer sits between request parsing and the shared Chrome-profile tab lease, deciding whether a caller runs, waits, or is refused.

flowchart LR
A[Remote clients] --> B[Run request]
B --> C[Authentication and request parsing]
C --> D[Admission queue]
D --> E[Shared-profile tab capacity]
E --> F[Browser run]
F --> G[Progress events and result]
D --> H[Health capacity status]
Loading

Decision needed

Question Recommendation
Should oracle serve preserve HTTP 409 as the default backoff contract, or intentionally replace it with queued execution and 503-only saturation? Preserve the current backoff contract: Keep 409 as the default and make bounded queuing an explicit compatible mode after the correctness fixes.

Why: The PR intentionally changes existing remote-client semantics and does not expose a maintainer-approved compatibility or migration policy.

Before merge

  • Add real behavior proof - Needs stronger real behavior proof before merge: The PR body contains useful claimed concurrency output, but the current head's remote-abort and host-cap follow-up changes have no redacted after-fix live trace; add one showing bounded saturation and abort recovery without private endpoints or tokens. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
  • Enforce queue capacity when acquiring a slot (P1) - The saturation probe runs before await readRequestBody, so a burst of valid POSTs can all pass it before any call reaches acquire. Since RunSlots.acquire never checks maxQueued, every later caller is appended and the queue is no longer bounded; move capacity reservation/checking into the atomic acquisition path and cover concurrent arrival.
  • Race cancellation through Chrome acquisition (P1) - raceWithAbort only wraps the tab-lease wait. An abort while acquireManualLoginChromeForRun or launchChrome is pending cannot reject until a CDP connection is later established, retaining the server admission slot through the slowest startup path; race and clean up those acquisitions too.
  • Align the effective default with the advertised four runs (P2) - The requested default is four, but the shared tab-cap normalizer defaults to three and effectiveConcurrency takes the minimum. A normal oracle serve therefore reports/adopts three while the PR describes four; choose one default and expose or document the actual operator control.
  • Remove the release-owned changelog section (P3) - This normal PR edits the release-owned changelog, and the entry also claims four configurable runs and repeats the now-stale “pinned” tab-cap wording. Leave release notes to the release process and keep any necessary migration context in the PR body or commit message.
  • Resolve merge risk (P1) - A burst of requests can exceed the configured queue bound, turning saturation into unbounded waiting and memory use.
  • Resolve merge risk (P1) - A disconnected caller can still hold an admission slot while Chrome starts or CDP connects.
  • Resolve merge risk (P1) - Existing remote clients that use HTTP 409 as their backoff signal will silently receive queued work instead unless maintainers deliberately accept or preserve that contract.
  • Resolve merge risk (P1) - The implementation normally admits three runs because of the existing tab-cap default, despite PR text describing four.
  • Complete next step (P2) - A maintainer must choose the remote-client compatibility contract; this branch also needs concrete capacity/cancellation repairs and current-head live proof.

Findings

  • [P1] Enforce queue capacity when acquiring a slot — src/remote/server.ts:313
  • [P1] Race cancellation through Chrome acquisition — src/browser/index.ts:1127-1138
  • [P2] Align the effective default with the advertised four runs — src/remote/server.ts:228-229
Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Patch surface 7 files; 677 added, 14 removed The change spans remote transport, browser lifecycle, error semantics, release notes, and remote-service tests.
Production versus tests production +289 TypeScript lines, tests +370, changelog +18 The sizeable test addition is useful, but the production concurrency and cancellation paths still need real behavior proof.

Merge-risk options

Maintainer options:

  1. Restore a compatible admission policy (recommended)
    Keep the existing 409 behavior by default or place queuing behind an explicit mode, then make queue reservation and startup cancellation safe.
  2. Accept the new remote-client contract
    A maintainer may approve queued execution as breaking behavior only after the client migration impact and real after-fix behavior are demonstrated.

Technical review

Best possible solution:

Make admission atomic, race and clean up every pre-connection acquisition on abort, then have a maintainer explicitly choose either a compatible 409 default or a documented breaking queued-service contract backed by a redacted live trace.

Do we have a high-confidence way to reproduce the issue?

Yes—source-reproducible: concurrent requests can pass the pre-await saturation probe together and overfill the queue, and an abort during Chrome acquisition is not raced until later setup.

Is this the best way to solve the issue?

No—the current approach needs atomic admission and complete startup cancellation before it can safely implement either compatibility policy.

Full review comments:

  • [P1] Enforce queue capacity when acquiring a slot — src/remote/server.ts:313
    The saturation probe runs before await readRequestBody, so a burst of valid POSTs can all pass it before any call reaches acquire. Since RunSlots.acquire never checks maxQueued, every later caller is appended and the queue is no longer bounded; move capacity reservation/checking into the atomic acquisition path and cover concurrent arrival.
    Confidence: 0.99
  • [P1] Race cancellation through Chrome acquisition — src/browser/index.ts:1127-1138
    raceWithAbort only wraps the tab-lease wait. An abort while acquireManualLoginChromeForRun or launchChrome is pending cannot reject until a CDP connection is later established, retaining the server admission slot through the slowest startup path; race and clean up those acquisitions too.
    Confidence: 0.98
  • [P2] Align the effective default with the advertised four runs — src/remote/server.ts:228-229
    The requested default is four, but the shared tab-cap normalizer defaults to three and effectiveConcurrency takes the minimum. A normal oracle serve therefore reports/adopts three while the PR describes four; choose one default and expose or document the actual operator control.
    Confidence: 0.99
  • [P3] Remove the release-owned changelog section — CHANGELOG.md:3-18
    This normal PR edits the release-owned changelog, and the entry also claims four configurable runs and repeats the now-stale “pinned” tab-cap wording. Leave release notes to the release process and keep any necessary migration context in the PR body or commit message.
    Confidence: 0.98

Overall correctness: patch is incorrect
Overall confidence: 0.98

AGENTS.md: found but not applied because it conflicted with ClawSweeper's review contract.

Codex review notes: model internal, reasoning high; reviewed against 083bba7e61f4.

Labels

Label changes:

  • add rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦐 gold shrimp and patch quality is 🦐 gold shrimp.
  • remove rating: 🦪 silver shellfish: Current PR rating is rating: 🦐 gold shrimp, so this older rating label is no longer current.

Label justifications:

  • P2: This is a significant remote-service behavior change with bounded blast radius, not a currently demonstrated core outage.
  • merge-risk: 🚨 compatibility: The branch replaces an established HTTP 409 backoff response with waiting and a different saturation response.
  • merge-risk: 🚨 availability: Non-atomic queue admission and incomplete abort coverage can retain or overcommit scarce browser capacity.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦐 gold shrimp and patch quality is 🦐 gold shrimp.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs stronger real behavior proof before merge: The PR body contains useful claimed concurrency output, but the current head's remote-abort and host-cap follow-up changes have no redacted after-fix live trace; add one showing bounded saturation and abort recovery without private endpoints or tokens. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Evidence

What I checked:

  • Current main still uses single-flight refusal: Current main sets busy before body parsing and returns HTTP 409 with busy for a second request, so the PR's central behavior is not already implemented or released. (src/remote/server.ts:179, 083bba7e61f4)
  • Queue capacity is not reserved atomically: The saturation check precedes an awaited body read; simultaneous valid requests can all pass it, while RunSlots.acquire itself never rejects when waiting.length exceeds maxQueued. They can therefore overfill the supposedly bounded queue. (src/remote/server.ts:313, e3a6e67df085)
  • Chrome acquisition still bypasses cancellation: raceWithAbort is used for the tab-lease wait, but both manual Chrome acquisition and local Chrome launch are awaited directly; cancellation is only raced after the CDP connection exists. (src/browser/index.ts:1127, e3a6e67df085)
  • Advertised default differs from effective default: The new requested concurrency defaults to four, but it is clamped through normalizeMaxConcurrentTabs; that helper defaults to three, while the CLI exposes neither queue-size nor concurrency options. (src/remote/server.ts:228, e3a6e67df085)
  • Prior findings remain visible at the current head: The previous ClawSweeper review identified atomic reservation, pre-connection cancellation, and effective-default alignment; the current source at the same reviewed head still has each condition. (e3a6e67df085)
  • Likely current-main owner: Current-main history attributes the most recent remote-server change to the repository owner, making that person the best routing candidate for the existing remote-service contract. (src/remote/server.ts:1, 3a185f55918a)

Likely related people:

  • steipete: Current-main history attributes the latest recorded remote-server work to Peter Steinberger, the repository owner, and the same history anchors the shared-browser behavior this PR changes. (role: recent remote/browser contributor; confidence: medium; commits: 3a185f55918a; files: src/remote/server.ts, src/browser/tabLeaseRegistry.ts)

Rank-up moves

Optional improvements that raise the rating; they are not merge blockers.

  • Make queue reservation atomic and add a concurrent-arrival regression test that proves excess callers receive 503.
  • Race and clean up Chrome launch and CDP connection on abort, then cover that timing path.
  • Add a redacted after-fix terminal or runtime trace for saturation and disconnect recovery; updating the PR body should trigger re-review, or a maintainer can request @clawsweeper re-review.

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (2 earlier review cycles)
  • reviewed 2026-08-18T19:05:30.067Z sha 3947c1a :: found issues before merge. :: [P1] Forward AbortSignal to remote requests | [P1] Make pre-connection setup cancellable | [P1] Preserve the configured shared-browser tab cap
  • reviewed 2026-08-18T19:24:08.472Z sha e3a6e67 :: needs real behavior proof before merge. :: [P1] Reserve queue capacity atomically | [P1] Race cancellation through Chrome acquisition | [P2] Align the promised default with the effective cap | [P3] Remove the stale tab-cap claim

…ng the tab cap

Three gaps in the first pass, all raised in review and all correct.

**The tab cap is not the service's to overwrite.** Pinning
`browserConfig.maxConcurrentTabs` to the admission limit silently replaced an
operator's lower choice — exactly what someone staying under an account's
throttling would have set. The dependency runs the other way: the tab cap is the
physical constraint on a shared profile, so the service now reads the host's
configured cap and admits at most that many, logging when it clamps.

**`signal` has to mean the same thing on both sides of the bridge.** The remote
executor never observed it, so a caller aborting a remote run cancelled nothing:
the request stayed open, the service never saw a disconnect, and the run kept its
slot and its browser tab until it finished on its own. That is worse than not
having cancellation, because the caller believes it worked. The executor now
destroys its request on abort and refuses to send one that was aborted first.

**Cancellation arrived too late to matter.** The abort race was installed after
the tab-lease wait, Chrome startup, and the CDP connection — the slowest part of
a cold run, and the part most likely to be waiting on a peer. Several abandoned
requests could hold every slot until their browser timeouts. The race is now
built before setup begins. A lease granted after the caller gave up is handed
back rather than leaked, since a slot abandoned mid-queue would otherwise sit for
six hours.

Claude-Session: https://claude.ai/code/session_01HsXirqcfqtr1Cae9zYCLDk
@frontierkodiak
Copy link
Copy Markdown
Contributor Author

Review follow-up

All three P1 findings were correct and are fixed in db4c….

Preserve the configured shared-browser tab cap. You're right that the dependency was backwards. The tab cap is the physical constraint on a shared profile and belongs to the host; pinning it to whatever the service admits silently discards an operator's lower choice — and "lower to avoid account throttling" is precisely the case, since ChatGPT rate-limits well below what the transport can drive. The service now reads the host's configured maxConcurrentTabs and admits at most that many, logging when it clamps:

[serve] Admitting 3 concurrent run(s): the shared-profile tab cap (3) is lower than the requested 4.

Forward AbortSignal to remote requests. Also right, and the worst of the three: a caller aborting a remote run cancelled nothing while believing it had. The executor now destroys its HTTP request on abort — which is how the service learns to cancel, via its own disconnect handling — and refuses to send a request whose signal was already aborted.

Make pre-connection setup cancellable. The race was installed after the tab-lease wait, Chrome startup, and the CDP connection: the slowest stretch of a cold run and the one most likely to be waiting on a peer. It is now built before setup begins.

On your parenthetical about leaking — losing the race does not cancel the acquisition, so a lease granted after the caller gave up is now handed back explicitly. Otherwise cancelling during a queue wait burns a slot on the shared profile for the six-hour stale window, which is worse than not honouring the cancellation at all.

Two tests added for the bridge case: a caller aborting a remote run is observed as an abort inside the run, and an already-aborted caller never sends the request.

Full suite: 1774 passed / 43 skipped.

@clawsweeper re-review

@clawsweeper
clawsweeper Bot commented Aug 18, 2026
Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event exact_review_queue).
Result: when the review finishes, ClawSweeper will create the durable review comment if needed or update the existing comment in place.

Re-review progress:

@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. and removed proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 availability 🚨 Merging this PR could cause crashes, hangs, restart loops, stalls, or process outages. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. P2 Normal priority bug or improvement with limited blast radius. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

0