Skip to content

fix(codex): restore Desktop discovery and lifecycle tracking#280

Open
hyiiiii wants to merge 1 commit into
wxtsky:mainfrom
hyiiiii:agent/fix-codex-desktop-lifecycle
Open

fix(codex): restore Desktop discovery and lifecycle tracking#280
hyiiiii wants to merge 1 commit into
wxtsky:mainfrom
hyiiiii:agent/fix-codex-desktop-lifecycle

Conversation

@hyiiiii

@hyiiiii hyiiiii commented Jul 23, 2026

Copy link
Copy Markdown

Summary

  • Rebase onto current main after fix: support Codex Desktop hosted by ChatGPT #267 and keep its canonical turnStatus / hasActivity JSONL parsing, Cursor question handling, and CodeIsland's resource usage became significantly higher. #278 tail-offset fix.
  • Detect Codex Desktop by the stable com.openai.codex bundle identifier, including the renamed ChatGPT.app.
  • Keep Desktop app-server, rollout, hook, and SQLite discovery on one codexapp:<thread-id> identity while leaving Codex CLI on the raw provider ID.
  • Recover multiple active Desktop threads from ~/.codex/state_5.sqlite as a best-effort enhancement when the shared app-server reports / as its CWD.
  • Add a single-flight, 6-second Desktop-only polling fallback with a 50-row DB limit and bounded reverse lifecycle scans.
  • Clean up completed subagents, app-server questions, transcript watchers, and closed threads without letting stale scans or delayed callbacks recreate or overwrite a newer session.

Relationship to #267

#267 is the foundation for this change and remains authoritative wherever the two branches overlapped. This PR retains #267's event parsing and layers only the additional recovery and lifecycle behavior on top.

The SQLite reader is never the only discovery path: missing, locked, corrupt, incompatible, or future-schema databases fail closed to rollout/app-server discovery. Reads are READONLY | NOMUTEX, schema-inspected, batched, and tolerate both updated_at and updated_at_ms.

Reliability details

  • Desktop and CLI sessions may share a raw provider UUID without collapsing; parent/subagent lookup is mode-aware.
  • DB-only subagent rows require positive Desktop transcript provenance, preventing CLI subagents from being re-keyed as Desktop cards.
  • Older asynchronous discoveries cannot rewind status, CWD, transcript path, model, terminal bundle, or recent messages.
  • thread/closed records a generation tombstone: late idle DB flushes and terminal hooks cannot revive the card; a real thread/started, SessionStart, UserPromptSubmit, or newer processing observation can start a new generation.
  • App-server helper exit preserves cards, drops questions tied to the dead channel, refreshes from the best-effort DB path, and reconnects with capped exponential backoff. Actual host exit still removes Desktop sessions.
  • Codex Desktop cards do not bind their lifetime to a shared helper or same-CWD CLI PID.
  • JSONL watcher generations prevent delayed rename reattach and queued deltas from an old attachment from mutating a same-ID session that was closed and recreated.
  • Lifecycle recovery scans at most 64 MiB and skips lines over 4 MiB without unbounded fragment growth.

Verification

  • Rebased onto main at 9e3a1eb (includes fix: support Codex Desktop hosted by ChatGPT #267, CodeIsland's resource usage became significantly higher. #278, and v1.0.31).
  • Swift frontend parse for all changed Swift files.
  • swift build -c release --product CodeIsland.
  • swift build -c release --product codeisland-bridge.
  • git diff --check origin/main..HEAD.
  • Standalone production JSONLTailer harness, repeated five times: attachment-token propagation, same-ID generation isolation, replacement reattach, and detach cancellation.
  • Added regression coverage for missing/incompatible/corrupt DBs, timestamp schema variants, NULL/missing rollout paths, root fallback, Desktop/CLI identity collisions, mode-aware parent/subagent routing, stale metadata, close tombstones, app-server reconnect cleanup, bounded reverse scans, completed subagents, and watcher generations.
  • swift test --filter 'AppStateCodex|JSONLTailerTests' — this machine only has CommandLineTools; the test target cannot import XCTest (and debug previews also lack PreviewsMacros). CI or a full Xcode installation is required to execute the XCTest suite.

The release build emits the pre-existing Swift 6 warning for the captured cache variable in AppState.refreshClaudeUsageIfStale(); this PR does not introduce that warning.

@wxtsky

wxtsky commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Heads-up: #267 is now merged (ed6f1bb), since it was ready first and covered the core 'Desktop sessions show live status' value. This PR's additional scope is still very much wanted — the state_5.sqlite-backed multi-thread discovery, the bounded polling fallback, and the completed-subagent/watcher cleanup are all things #267 doesn't do. Both branches touch the same functions in JSONLTailer/AppState+TranscriptTailer with mutually exclusive field names (turnStatus/hasActivity vs turnLifecycle/hadActivity), so a rebase will conflict — recommend keeping #267's event parsing where equivalent and re-basing your increments on top. One design note from review: the _5 schema suffix suggests OpenAI has already bumped that SQLite layout five times, so treating DB reads as a best-effort enhancement layer (never the only discovery path) will keep this resilient. Looking forward to it when it's ready.

@hyiiiii
hyiiiii force-pushed the agent/fix-codex-desktop-lifecycle branch from 29c7fb3 to e63ef06 Compare July 23, 2026 06:28
@hyiiiii
hyiiiii marked this pull request as ready for review July 23, 2026 07:22
@hyiiiii

hyiiiii commented Jul 23, 2026

Copy link
Copy Markdown
Author

The requested rebase and follow-ups are now complete:

  • Rebased onto current main and kept fix: support Codex Desktop hosted by ChatGPT #267's canonical turnStatus / hasActivity parsing wherever the branches overlapped. The CodeIsland's resource usage became significantly higher. #278 appended.count tail-offset fix is preserved as well.
  • Kept SQLite strictly best-effort: reads are read-only, schema-inspected, and batched; missing, corrupt, locked, or incompatible state DBs fall back to rollout/app-server discovery rather than becoming a required path.
  • Added state-DB-backed multi-thread discovery and a single-flight 6-second Desktop-only polling fallback. The query is limited to 50 rows, and reverse lifecycle recovery is capped at 64 MiB total / 4 MiB per line.
  • Added completed-subagent cleanup and watcher generation guards, including protection against delayed reattach and an already-queued old transcript delta mutating a same-ID session after close/recreate.

The release builds for both CodeIsland and codeisland-bridge, changed-file frontend parsing, diff checks, and the standalone watcher lifecycle harness pass. The new XCTest coverage is committed, but this machine only has CommandLineTools and cannot import XCTest, so that suite still needs CI or a full Xcode installation.

The PR is ready for the full review pass.

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.

2 participants