Skip to content

feat(chatgpt-ui): profile pool hardening — slot health, safe Chromium cleanup, telemetry#679

Merged
Th0rgal merged 3 commits into
masterfrom
feat/chatgpt-ui-profile-pool-hardening-A
Jul 25, 2026
Merged

feat(chatgpt-ui): profile pool hardening — slot health, safe Chromium cleanup, telemetry#679
Th0rgal merged 3 commits into
masterfrom
feat/chatgpt-ui-profile-pool-hardening-A

Conversation

@Th0rgal

@Th0rgal Th0rgal commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Summary

  • Per-slot health/quarantine (src/api/runners/chatgpt_ui/profile_pool.rs): auth failures quarantine a slot 30 min, launch failures 5 min, compatibility failures 10 min after 3 consecutive strikes; success resets. A fully quarantined pool fails open so missions never deadlock. Existing lease/wait/cancel semantics preserved.
  • Safe Chromium Singleton cleanup (src/api/runners/chatgpt_ui/chromium_cleanup.rs): SingletonLock/SingletonCookie/SingletonSocket are removed only when provably safe — same-host + dead pid, or pool-owned via an ownership marker (.{name}.sandboxed-chatgpt-ui.owner, stored outside the profile) that survives container hostname churn. Live-process locks, foreign unowned locks, and regular files are never touched; unlaunchable profiles fail fast with a structured error instead of a browser crash loop.
  • Failure classes: driver error codes map to TerminalReason/FailureClass (auth_required→AuthError, rate_limited→RateLimited, browser_launch→TransportError, compatibility→ProviderError) and feed slot health.
  • Selector hardening (scripts/chatgpt_ui_driver.py): send/stop controls resolve via stable data-testids first, falling back to composer-form-scoped anchored accessible-name regexes; fallback use emits one fixed-string diagnostic.
  • Privacy-safe telemetry: GET /api/backends/chatgpt_ui/profile-pool returns slot state (available/in_use/quarantined), failure counts, and quarantine countdown — profile basenames only, never full paths or contents. Diagnostics remain on the fixed-string allowlist.
  • Dashboard: read-only "Profile pool status" panel in the ChatGPT UI backend tab (SWR, 15 s refresh, shown only when runtime paths are configured).

Baseline: 17bbf178 (current origin/master, includes #677 — no overlap: #677 covered watchdog/liveness, this covers pool health/cleanup/telemetry).

Verification

  • cargo fmt --all / cargo fmt --all --check — clean
  • cargo check --all-targets — clean
  • cargo clippy --all-targets -- -D warnings — clean
  • cargo test — 1513 passed / 1 ignored / 1 failed: api::remote_build::tests::wrapper_resumes_an_interrupted_async_job_without_resubmitting, pre-existing (reproduced identically on pristine 17bbf178), unrelated to this change
  • cargo test --lib chatgpt_ui — 27/27 (pool quarantine, fail-open, concurrency lease exclusivity, Singleton judgment, ownership marker, error-code classification, diagnostics allowlist)
  • Python unittest in scripts/ — 17/17 (selector fallback matrix, anchored names, download safety)
  • Dashboard: vitest 254/254 (incl. new pool-panel test), eslint 0 errors (no findings in touched files), next build production build passes

Test plan

  • Review quarantine durations and fail-open policy
  • Verify Singleton cleanup rules against a real multi-profile deployment (hostname churn case)
  • Confirm telemetry endpoint exposes no sensitive paths
  • Smoke-test dashboard panel against a live pool

Note

Medium Risk
Changes the ChatGPT UI mission path (profile selection, on-disk browser profile cleanup, and failure classification); cleanup is conservative but incorrect judgment could affect live browser processes or profile locks.

Overview
Hardens the ChatGPT UI browser profile pool so missions skip bad slots, recover from crashed Chromium state, and expose operator-friendly status.

Runner / pool: Profile leasing moves into profile_pool with per-slot health: auth and launch failures quarantine slots for timed cooldowns; compatibility failures quarantine after repeated strikes; successes reset health. Acquisition prefers cleaner slots over ones with recent failures. Driver error codes map to terminal reasons and, where appropriate, slot-local failure records (browser_launch deliberately does not quarantine a slot).

Chromium: Before/after each Chromium turn, conservative cleanup of SingletonLock / cookie / socket entries runs only under the profile lock, with pool ownership markers so container hostname changes do not strand profiles. Unlaunchable singleton states fail fast with structured errors instead of looping launches.

Driver: Send/stop controls resolve via data-testid first, then composer-scoped anchored button names, with one-shot fallback diagnostics.

API & dashboard: GET /api/backends/chatgpt_ui/profile-pool returns basename-only slot telemetry (state, failures, quarantine countdown). The ChatGPT UI backends tab polls this when runtime paths are configured and shows a read-only pool status panel.

Reviewed by Cursor Bugbot for commit cb22bdd. Bugbot is set up for automated code reviews on this repo. Configure here.

… cleanup, and telemetry

Per-slot health/quarantine keeps a single broken login or crashed browser
from stalling every GPT Pro mission: auth and launch failures quarantine a
slot immediately, repeated compatibility failures quarantine after three
strikes, and a fully quarantined pool fails open so missions never deadlock.

Leftover Chromium Singleton files are now removed only when provably safe
(same-host dead pid, or pool-owned via an ownership marker that survives
container hostname churn); regular files and live-process locks are never
touched. Driver error codes map to structured failure classes, composer
selectors prefer stable data-testids with anchored role fallbacks, and
diagnostics stay on a fixed-string allowlist. Slot state is exposed at
GET /api/backends/chatgpt_ui/profile-pool (basenames only) with a
read-only dashboard panel.
@vercel

vercel Bot commented Jul 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
sandboxed-dashboard Ready Ready Preview, Comment Jul 25, 2026 6:32pm
sandboxed-sh Ready Ready Preview, Comment Jul 25, 2026 6:32pm

Request Review

@Th0rgal
Th0rgal marked this pull request as ready for review July 25, 2026 18:26
@Th0rgal

Th0rgal commented Jul 25, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@cursor

cursor Bot commented Jul 25, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_e5682541-c6b4-4751-ac93-752731a94ef6)

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2d0ee1b9bc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/api/runners/chatgpt_ui/mod.rs
@cursor

cursor Bot commented Jul 25, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_faedec25-a199-49f0-996f-6a694dc16ff6)

@Th0rgal

Th0rgal commented Jul 25, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@Th0rgal
Th0rgal merged commit 71d7d2e into master Jul 25, 2026
10 checks passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cb22bddcc5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +565 to 569
if let Some(kind) = slot_failure {
profile_pool::record_slot_failure(&profile_dir, kind);
}
terminate_child_tree(&mut child).await;
return AgentResult::failure(format!("chatgpt_ui: {message}"), 0)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Retry another slot after a slot-local driver failure

When the selected profile emits auth_required or compatibility while another configured profile is healthy, this records the bad slot but immediately returns the failed turn instead of reacquiring from the pool. The main and parallel mission controllers only auto-resume failures classified as TransportError, whereas these codes are classified as AuthError and ProviderError, so the advertised different-slot retry never occurs and the mission fails until the user manually resumes it. Retry once through acquire_profile after recording these slot-local failures so the healthy profile can serve the current mission.

Useful? React with 👍 / 👎.

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