Skip to content
This repository was archived by the owner on Oct 9, 2026. It is now read-only.
This repository was archived by the owner on Oct 9, 2026. It is now read-only.

Prove persistent Codex Lab engine behind official Mac and iOS clients #385

Closed as not planned
3 of 4 issues completed
Closed as not planned

Description

@shiny-code-bot

Objective

Prove the final Codex Lab desktop architecture without building or cloning a GUI: a persistent, provenance-verified Codex Lab engine runs independently of the official clients; the signed ChatGPT macOS app connects to it locally, and the official iOS app connects to the same engine through native remote control.

The engine owns durable sessions, projects, account selection, five-hour and five-day reset awareness, prompt-cache affinity, approvals, and remote enrollment. The official Mac and iOS apps remain replaceable controllers. A ChatGPT app restart or update must reconnect to the same Lab engine rather than silently executing through bundled Codex.

Finish Line

Stock ChatGPT Mac and iOS clients use one persistent provenance-verified Codex Lab engine across client restart and update without silent bundled-Codex fallback.

Current Status

State: waiting historical persistent-engine/controller evidence. The old Lab engine and installation are retired.
Next action: use #974/#975 for the current iPhone-to-CLI proof, starting with the owner's three existing local sessions.
Waiting for: a demonstrated fresh-route gap for which this issue's historical canaries are useful. The old requirement to use only official clients with a persistent Lab engine is not carried into the fresh milestone.
Original canary comments and controller evidence remain unchanged. Current route selection is open under DIRECTION.md.
Last verified: 2026-09-26.

Relationships

Validation

  1. Headless daemon lifecycle and provenance checks in an isolated Codex Lab home.
  2. Direct Unix control-socket initialize, version, and reconnect probes.
  3. Stock Mac controller canary against the persistent engine.
  4. Stock iOS pairing, thread continuation, approval/input, reconnect, and revocation canary.
  5. Project/worktree, terminal/file, browser, and computer-use parity matrix.
  6. Split-auth quota/failover and prompt-cache accounting checks when an alternate account has usable quota.
  7. ChatGPT quit/relaunch, staged-update, daemon crash, login, and reboot recovery tests.
  8. Fail-closed tests for missing, corrupt, stale, and protocol-incompatible Lab engines.

Decisions

  • The official ChatGPT Mac and iOS clients remain the only user-facing work surfaces.
  • Codex Lab becomes a persistent engine/service, not a replacement GUI.
  • The Mac path should be local and low-latency; iOS uses native remote control to the same engine.
  • Launcher/menu-bar work is skipped unless a concrete canary failure proves an external recovery surface is necessary.
  • Configuration is never accepted as proof of runtime identity; only live provenance from the serving engine can establish Lab status.
  • Updates must reconnect to the persistent engine and must never silently switch execution to bundled Codex.

Open Questions

  • Does the current stock Mac client preserve all local-host capabilities when connected through the existing local-daemon socket path?
  • Can Lab identity and provenance be surfaced through the native host/environment UI, or is a minimal error-only status utility ultimately required?
  • Which desktop/iOS app-server protocol changes require compatibility shims or coordinated Lab updates?
  • Which native computer-use and browser host services must be bridged into the persistent daemon?

Acceptance Criteria

  • A fixed Codex Lab engine starts from an immutable, provenance-verified candidate and cannot update itself to an upstream official binary.
  • The current stock Mac client initializes against the engine over local websocket transport while preserving local-host semantics.
  • The paired iOS client initializes against the same engine through native remote control.
  • The Mac and iOS clients can observe and continue the same thread without duplicate turns or lost output.
  • Existing projects and worktrees can be opened or mapped without accidental execution on the bundled Local host.
  • Terminal streaming, file reads/edits, search, command/file approvals, and structured user input work from both relevant controllers. File reads and native iOS command approval are proven; search, structured input, and the full controller matrix remain.
  • Browser use and native computer use are explicitly proven or recorded as a blocking parity gap.
  • Control account identity remains stable while eligible execution accounts rotate only at safe turn boundaries and preserve per-thread cache affinity.
  • ChatGPT quit/relaunch and one real in-app update reconnect to the same engine without re-pairing or bundled-Codex fallback.
  • Engine absence and provenance failure are visible and fail closed; required V8 JIT entitlement validation is now merged, while client/engine protocol incompatibility remains to be exercised explicitly.
  • A durable supervisor recovers the engine after crash, login-equivalent reload, and reinstall without launching ChatGPT automatically.
  • Rollback restores the previous Lab engine or intentionally returns to stock Codex without stale launchd state.

Activity

  1. cbusillo commented on Jul 21, 2026

    @cbusillo
    Owner

    July 21 Mac canary evidence

    The final-form Mac transport is now proven against the stock signed ChatGPT app.

    Live state

    • Persistent engine: ~/.codex-lab/packages/standalone/current/codex
    • Engine signature: Developer ID, fixed identifier com.shinycomputers.codex-lab.engine
    • Daemon PID: 86648
    • GUI PID: 87188
    • Socket: ~/.codex-lab/app-server-control/app-server-control.sock
    • Remote control: enabled in place after local connection

    Stock GUI evidence

    From codex-desktop-265abc52-d084-4231-8f60-ac2505795d41-87188-t0-i1-225539-0.log:

    Transport start success ... hostId=local transport=websocket
    Current reported app-server version: currentVersion=0.0.0 hostId=local
    initialize_handshake_result durationMs=3 ... outcome=success transportKind=websocket
    ... next=connected ... hostId=local ... transport=websocket
    

    Process inspection showed only the managed daemon app-server. No ChatGPT-bundled or legacy candidate stdio app-server existed, and the GUI log contained no SQLite initialization failure.

    Root causes resolved in the canary

    1. InitializeResponse.userAgent had reused the outbound compatibility-clamped user agent, reporting 0.120.0; ChatGPT 26.715.70719 requires >=0.141.0 or the exact 0.0.0 development sentinel.
    2. A freshly built engine had a different ad-hoc CDHash and therefore could not read the existing encrypted-auth Keychain item. Stable Developer ID signing plus one controlled login status authorization solved this without weakening Keychain access.
    3. Full app-server startup generated many concurrent prompts against one item. The controlled preflight generated exactly one prompt and future reads were silent.
    4. Earlier automated rollbacks after successful connections were verifier bugs: the desktop first logs an initial transport=stdio placeholder, then reports the selected local daemon as transport=websocket. Final-state logs, not the initial placeholder, are authoritative.

    Remaining release work

    • Integrate stable engine signing and the one-request Keychain preflight into packaging/install.
    • Preserve/fail closed on signing identifier and Team ID mismatch.
    • Prove quit/relaunch and a real stock-app update reconnect without special manual launch state.
    • Complete same-thread Mac/iOS continuation, approval/input, and reconnect tests.
  2. cbusillo commented on Jul 21, 2026

    @cbusillo
    Owner

    iOS remote-control canary passed — July 21, 2026

    The persistent signed Codex Lab daemon successfully paired with the official ChatGPT iOS client while the desktop GUI remained attached over the local WebSocket transport.

    Verified directly through app-server RPC:

    • designated primary account was active for the control plane
    • remoteControl/status/read returned connected
    • the manual pairing artifact returned claimed: true
    • remoteControl/client/list returned one authorized phone / ios client
    • client identified itself as ChatGPT iOS 1.2026.188
    • the client and daemon were attached to the same account-scoped environment

    Important implementation finding: account/switchActive updates the shared auth manager, but an already-connected remote-control WebSocket does not currently terminate on the auth-change notification. For this canary, cycling remoteControl/disable then remoteControl/enable forced a clean relay re-authentication and produced a new environment for the designated control identity. The final architecture should establish the fixed control identity before starting the relay—or explicitly reconnect the relay when its control identity changes—while execution-account selection remains independent.

  3. cbusillo commented on Jul 22, 2026

    @cbusillo
    Owner

    Official iOS local-mode canary passed — July 22, 2026

    The first complete official-GUI + official-iOS local-control path is now proven end to end.

    Root cause of the earlier mobile rejection:

    • the local development package was built without CODE_VERSION
    • remote enrollment therefore advertised app_server_version = 0.0.0
    • the desktop initialize response also advertised 0.0.0
    • pairing authorization could succeed, but the mobile client correctly displayed “update desktop app to connect” and withheld local mode

    Canary remediation:

    • rebuilt the same Codex Lab source with CODE_VERSION=0.145.0-alpha.27, matching the Codex binary bundled in the installed official desktop application
    • signed it with the stable Codex Lab Developer ID requirement
    • backed up state, removed only the stale primary-control-account enrollment, installed the versioned binary, and restarted the persistent daemon
    • backend re-enrollment reused the existing environment and preserved the authorized iPhone
    • desktop GUI reconnected over WebSocket and reported app-server 0.145.0-alpha.27

    Observed iOS proof:

    • user selected the local host and sent REMOTE CANARY 1
    • Codex Lab created a local thread and persisted the exact user message
    • the model returned Codex Lab active. Remote canary 1 acknowledged.
    • a direct thread/read RPC against the persistent daemon returned both the user and agent messages and reported the thread idle

    This closes pairing, authorization, mobile version compatibility, remote thread creation, remote prompt delivery, model execution, response persistence, and desktop-daemon continuity for the single fixed control identity. Remaining decisive gate: keep this remote control identity fixed while assigning execution for a subsequent turn/thread to a different stored account.

    Packaging follow-up: release/dev installers must always inject explicit CODE_VERSION; 0.0.0 is not a valid remotely usable package identity. The top-level CLI --version path still reports the Cargo workspace version and should be reconciled with build provenance separately.

  4. cbusillo commented on Jul 22, 2026

    @cbusillo
    Owner

    Fixed-control / pooled-execution canary passed

    The remaining architectural gate from the prior comment passed in the same REMOTE CANARY 1 run.

    Direct evidence:

    • thread/start arrived from codex_chatgpt_ios_remote version 1.2026.188
    • the daemon's active account remained the designated primary remote-control identity
    • session initialization logged resolved execution account lease for a different stored account
    • the persisted execution-account lease for the remote-created thread matches that secondary account
    • gpt-5.6-luna completed the turn and the response was returned to/persisted for the iOS-created thread
    • a direct thread/read returned both REMOTE CANARY 1 and Codex Lab active. Remote canary 1 acknowledged.

    Therefore the canary proves this topology:

    official ChatGPT iOS
            │ fixed primary control identity
            ▼
    OpenAI remote-control relay
            │
            ▼
    persistent Codex Lab app-server
            │ independent per-thread execution lease
            ▼
    secondary stored execution account
    

    This is the core product result: official desktop GUI and official iOS remote control can remain stable on one account while Codex Lab selects another paid account for model execution. Remaining work is production hardening rather than architectural feasibility: release-version injection, update/restart continuity, quota/reset-aware selection, stable same-thread affinity for prompt caching, and controlled failover tests.

  5. cbusillo commented on Jul 22, 2026

    @cbusillo
    Owner

    Same-thread affinity and mobile task-stream recovery passed

    After the first successful remote turn, the iOS task view entered Reconnecting to task and disabled Send.

    Diagnosis:

    • persistent daemon remained running
    • remote-control relay remained connected
    • environment and pairing authorization remained unchanged
    • the iPhone continued reporting presence
    • the remote-created thread was intact, idle, and readable through app-server RPC
    • during a 90-second trace, the iOS task view sent no task-stream reconnect request to the host

    Recovery:

    • cycled only remoteControl/disable → remoteControl/enable
    • did not restart the daemon or desktop GUI
    • did not change the control account, environment id, thread, or execution lease
    • did not require re-pairing
    • reopening the existing task restored the Send control

    Follow-up proof:

    • iOS sent REMOTE CANARY 2 in the original thread
    • Codex Lab returned Codex Lab active. Remote canary 2 acknowledged.
    • direct thread/read reported two turns and all four expected user/agent messages
    • the primary control identity remained active
    • the persisted secondary execution-account lease was unchanged
    • the iPhone remained usable with Send enabled after the second response

    This validates stable same-thread execution affinity—the behavior needed to avoid gratuitous account switching and preserve prompt-cache locality. It also establishes a narrow recovery primitive for a stale mobile task view: relay-only reconnect, with no daemon/session/pairing disruption.

    Production hardening should detect this stale-task condition and perform or offer the relay-only recovery automatically rather than leaving the mobile UI indefinitely disabled.

  6. added
    plan:waitingDurable plan parked pending a decision, event, or non-issue condition; not for PR QA
    and removed
    plan:activePlan is actionable now
    on Jul 29, 2026
  7. added
    plan:donePlan completed or superseded
    and removed
    plan:waitingDurable plan parked pending a decision, event, or non-issue condition; not for PR QA
    on Sep 27, 2026
  8. shiny-code-app commented on Sep 27, 2026

    @shiny-code-app

    Backlog reconciliation — 2026-09-26

    Closing against the merged DIRECTION.md. Main is now upstream 2deb542491 plus the fresh-start files and the tools/account-router sidecar; the old Lab code stays preserved on archive/lab-main-2026-09-24. Evidence and history in this thread are kept.

    Disposition: superseded (not planned). DIRECTION.md retires "the installed Lab build and its services", including the remote-control app-server, housekeeping jobs, and the self-hosted release and signing runners. The fresh remote route is #974/#975/#976 on stock Codex. The July canaries stay here as evidence.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    planDurable planning issueplan:donePlan completed or superseded

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions