Skip to content

Diagnose Codex Desktop restart and Task disappearance while CodexHub is connected #141

Closed

Description

@NOirBRight

Problem

Codex Desktop can exit/restart while CodexHub is connected, after which an existing sidebar Task no longer appears in the restored view even though the native Task record still exists and is idle.

This is distinct from #106's completed catalog/Task-tool discovery work and from its Direct-Official stale-card residual. The current observation is a whole Codex Desktop process restart, not a failed Task-creation placeholder.

Reporter evidence

One natural occurrence on Codex Desktop build 26.707.9981.0 with CodexHub 0.1.4 Debug connected to the local Gateway produced this sanitized ordering:

  • the affected existing Orchestrator Task started a read-only turn to inspect GitHub/repository state;
  • no create_thread, fork, replacement Task, automation, Issue write, Worker dispatch, or repository mutation was issued in that turn;
  • the old Codex app-server process recorded normal streaming/tool activity through 23:14:36, then its logging stopped without a recorded panic/fatal/shutdown event;
  • the Codex Desktop GUI process restarted at 23:15:04 and its new app-server child started at 23:15:27;
  • Windows Application/WER had no matching crash record and no recent Crashpad dump was found;
  • CodexHub and the single Gateway process remained alive continuously from 20:15, with the same PID and the same sole 9099 listener;
  • the Gateway recorded two in-flight Official streams closing with status 499 at 23:14:38 and 23:14:43, no response terminal, and a downstream/client-close disposition. These closes followed the old Codex process log stop; they do not establish a Gateway-initiated failure;
  • the missing Task was still returned by the supported native Task list, was not archived, read back as idle with its last turn marked interrupted, and became visible again through supported native navigation.

The reporter states that this repeated Desktop restart pattern was not observed while CodexHub was disconnected and appeared after recent CodexHub fixes. That association is important but is not yet a root-cause proof.

Outcome

Build a bounded connected-versus-disconnected differential that determines why Codex Desktop restarts and fails to restore the sidebar Task view, then fix only the proven CodexHub-owned trigger. If the trigger is in the official Desktop/client, produce an upstream-ready sanitized report and retain a supported recovery path without editing Codex internal databases.

Scope

  • Capture one ordered timeline across Codex GUI/app-server process identity, Task/turn state, Gateway request/stream state, and supported Task list/read/navigation.
  • Run the same existing-Task read-only operation with CodexHub connected and disconnected, holding Desktop build, Task, model/effort, workload, proxy/TUN state, and concurrency constant.
  • Distinguish GUI process restart, app-server child restart, renderer crash, explicit shutdown, OS termination, and process exit without WER/Crashpad evidence.
  • Determine whether the Gateway sees only a downstream consequence (499 after client exit) or emits an earlier malformed/duplicate/unterminated protocol sequence that can trigger the client exit.
  • Preserve the existing rolling Debug recorder and add only privacy-safe process/request correlation needed for the differential.
  • Restore affected Tasks only through supported native list/read/navigation/archive actions.

Non-goals

Acceptance criteria

  • A bounded harness records the exact process and Task state before, during, and after the operation and can detect the reported whole-Desktop restart rather than merely a request disconnect.
  • A connected/disconnected A/B holds all named variables constant and records the observed reproduction count for each leg.
  • The first observed failing boundary is classified from ordered evidence; a later Gateway 499 cannot be reported as the initiating cause when the client process exited first.
  • If CodexHub emits an earlier invalid/duplicate/unterminated sequence, a red regression reproduces that exact sequence and the fix removes it without changing unrelated routes.
  • If no CodexHub-owned trigger is proven, an upstream-ready sanitized report contains build identity, process ordering, Task survival, and Gateway consequence without prompts, responses, credentials, paths, or Task IDs.
  • After a reproduced restart, the real Task remains uniquely discoverable and can be restored through supported navigation without duplicate Task creation or internal-state repair.
  • Existing Official/third-party routing, diagnostic-recorder, Task-control, and GLM native-Responses regressions remain green for every touched boundary.

Verification

  • New bounded process/Task/Gateway timeline harness with connected and disconnected modes.
  • Focused recorder/Gateway tests for any new correlation fields.
  • Affected Python, Rust, and frontend gates only when their boundaries change, plus repository CI.
  • One same-build human A/B after Make native Responses apply_patch tool contracts symmetric for external models #140 is complete: connected leg first, then disconnected leg, with no new Task creation.
  • python scripts/report_quality_gates.py remains report-only.

Relationships

Expected hotset

  • Debug diagnostic recorder and sanitized Gateway event correlation.
  • A dedicated bounded Desktop process/Task lifecycle harness.
  • CodexHub transport/protocol code only if ordered evidence proves it emitted the initiating trigger.

Execution contract

Execution-Contract: v2
Verification-Class: strict
Verification-Commands: bounded connected/disconnected process-Task-Gateway harness; focused tests for every touched recorder/Gateway/client-projection boundary; relevant repository full gate; python scripts/report_quality_gates.py report-only
Manual-Evidence: After #140, run the same existing-Task read-only operation once with CodexHub connected and once disconnected, preserving Desktop build/profile/model/proxy state and creating no new Task.
Architecture-Decision: resolved
Review-Owner: orchestrator

Activity

  1. NOirBRight commented on Jul 15, 2026

    @NOirBRight
    OwnerAuthor

    2026-07-16 WER-backed connected occurrence

    A later connected occurrence on Codex Desktop build 26.707.9981.0 differs from the earlier no-WER report:

    • Windows Application Error recorded ChatGPT.exe failures for the Codex package;
    • Windows Error Reporting classified them as MoAppCrash with exception 0xc06d007f;
    • the Codex GUI crash evidence precedes the later intentional Gateway cleanup and the resulting stream retries.

    This is now a positive GUI-crash classification for the connected leg. It still does not establish that Gateway traffic initiated the crash; the connected/disconnected A/B and first-failing-boundary requirement remain necessary.

  2. NOirBRight commented on Jul 16, 2026

    @NOirBRight
    OwnerAuthor

    2026-07-16 same-process route-switch differential

    A later same-process observation strengthens the CodexHub association while keeping the first-failure classification fail-closed:

    • Codex Desktop build 26.707.9981.0 was already running through CodexHub when visible restarts and severe UI lag recurred.
    • In the final six Gateway failures before the route switch, every Responses stream had already started downstream. Gateway saw the Desktop client close/reset the loopback connection during a downstream write (WinError 10053/10054, final status 499) while upstream data was current (last_upstream_byte_age_ms 0-1 ms). Five of the six closes belonged to one active Task/window.
    • Three closes occurred during response.custom_tool_call_input.delta, two during reasoning events, and one after response.output_item.done; none contained an upstream terminal event. This classifies the 499 records as consequences of the client-side interruption rather than an initiating OpenAI/upstream reset.
    • During the same interval, Codex Desktop repeatedly logged Conversation state not found and Received item/... for unknown conversation across multiple concurrent Tasks. This is consistent with renderer/app-server Task-state divergence and provides a stronger boundary than the later loopback 499.
    • The reporter switched the already-running Desktop process from CodexHub to Direct Official. Gateway traffic and established loopback connections stopped immediately. The Desktop root process remained the same, and the reporter observed no further visible restart plus materially improved responsiveness.
    • This is a strong same-process association, not the required clean-start control: the current process began under CodexHub before the switch. The Issue must still run a fresh Direct-Official-start control and a bounded connected leg with the same build/workload.

    A separate official-app defect was also observed: each Desktop process logs a native DLL initialization failure in the packaged desktop-notifications serialport.node addon, with Windows WER exception 0xc06d007f. Because WER reports can continue without a visible whole-App exit, treat this as a possible upstream performance/crash contributor, not proof that it initiates the CodexHub-only restart pattern.

    Release note: v0.1.5 may carry the completed Task/tool compatibility fixes, but this Issue remains a known high-priority blocker for long-term CodexHub-connected Desktop use.

  3. added
    P1Priority 1: current iteration goal
    on Jul 20, 2026
  4. NOirBRight commented on Jul 20, 2026

    @NOirBRight
    OwnerAuthor

    Moved to 0.1.7 as P1 ready-for-human and now natively blocked by #114. The Desktop/Gateway first-failure differential must consume the transport fault-injection evidence rather than infer causality from later 499 closes.

  5. NOirBRight commented on Jul 25, 2026

    @NOirBRight
    OwnerAuthor
    {
      "contract": {
        "acceptance": [
          "The connected and disconnected legs use the same exact Debug candidate, Desktop build/profile, existing Task, model/effort, workload, proxy state, and concurrency, with a recorded reproduction count for each.",
          "The timeline distinguishes whole GUI restart, app-server restart, renderer/native-addon crash, explicit shutdown, OS termination, and exit without WER/Crashpad evidence.",
          "Every Gateway request and terminal event is ordered against process exit, so a later 499 or connection reset cannot be misreported as the initiating cause.",
          "Before and after each leg, supported Task list/read/navigation proves whether the one existing Task remains uniquely discoverable and recoverable without duplicate creation or internal-state repair.",
          "A CodexHub-owned first failure produces a separate scoped child Issue with exact red evidence and blocks #227; no speculative transport or protocol patch is made in #141.",
          "An upstream-owned or non-reproduced outcome produces a sanitized report containing build/process ordering, reproduction counts, Task survival, and recovery result without prompts, responses, credentials, paths, or Task IDs.",
          "The final disposition explicitly states whether #141 blocks #227, is closed as current-candidate non-reproduction/upstream, or is deferred with the exact missing evidence."
        ],
        "change_claims": {
          "paths": [],
          "resources": [
            "codex-desktop-persistent-profile",
            "existing-codex-task",
            "codexhub-connected-desktop-leg",
            "direct-official-desktop-leg",
            "windows-wer-crashpad-evidence",
            "desktop-task-recovery-evidence"
          ]
        },
        "dependencies": {
          "dispatch_after": [
            114
          ],
          "merge_after": [
            114
          ]
        },
        "design": [
          "Keep this as a bounded human differential after #114 and its transport children are complete. Do not change Gateway, Desktop integration, Task state, or recorder behavior before ordered evidence identifies the first failing boundary.",
          "Use one exact Debug candidate, one Codex Desktop build and persistent profile, one existing Task, one model and reasoning level, one read-only workload, and identical proxy, concurrency, and machine state. Cold-start a CodexHub-connected leg and a disconnected Direct-Official leg; create no new Task.",
          "Record only privacy-safe timestamps and identities for Codex GUI and app-server start/exit, renderer or native-addon failure classification, WER/Crashpad classification, Gateway request and terminal ordering, and supported Task list/read/navigation before and after each leg.",
          "Classify causality from the earliest observed boundary. A Gateway 499 after the Desktop or app-server exits is a downstream consequence and cannot establish a CodexHub trigger.",
          "If the connected leg exposes an earlier CodexHub-generated invalid, duplicate, or unterminated sequence, stop the release gate and create a narrowly scoped child bug with a deterministic red fixture before any fix. If the same failure occurs disconnected or begins in Desktop/WER without an earlier Gateway violation, retain an upstream-ready report and supported recovery path.",
          "Restore a disappeared Task only through supported native list/read/navigation. Never edit Codex databases, create replacement Tasks, expose Task IDs/content, mutate shared profiles, or fabricate a non-reproduction."
        ],
        "difficulty": "heavy",
        "done_when": [
          "Issue #114 and its required transport children are complete on the exact Debug candidate used for the differential.",
          "One bounded cold-start connected leg and one bounded cold-start Direct-Official leg complete with all named variables held constant and no new Task creation.",
          "Privacy-safe process, WER/Crashpad, Gateway ordering, and supported Task list/read/navigation evidence is retained for both legs.",
          "The first failing boundary and reproduction counts yield one explicit keep-child-fix, close-upstream/non-reproduction, or defer-needs-info disposition.",
          "Any CodexHub-owned trigger is moved into a separately admitted strict child ticket with a deterministic regression before code changes.",
          "python scripts/report_quality_gates.py remains report-only if and only if a later child touches repository files; #141 itself performs no speculative code change."
        ],
        "priority": "P1",
        "risk": "strict",
        "sha256": "ec37e8ac801ee24f0d27b27ddb5afe52148e2d4220966491044363a21da28ad5",
        "unresolved_decisions": []
      },
      "dispatch": null
    }
  6. added
    orch:readyOrchestrator V6: valid hashed contract is complete and dispatchable
    on Jul 25, 2026
  7. NOirBRight commented on Jul 26, 2026

    @NOirBRight
    OwnerAuthor

    Pre-execution bounded A/B runbook

    This is preparatory guidance only. It does not start the connected/direct legs or claim a disposition before #114 closes.

    Existing tools that must not be used as the #141 harness

    • scripts/e2e_codex_app_transport.py always calls thread/start and creates a new ephemeral thread.
    • scripts/run_issue_106_task_lifecycle.py creates, resumes, renames, and deletes lifecycle threads.

    Both violate this Issue's requirement to use one already-existing Task and create no replacement Task during diagnosis.

    Exact two-leg boundary

    Use one dedicated persistent E2E Desktop profile and one uniquely discoverable existing Task. Do not use the reporter's shared Desktop profile.

    1. Record the exact candidate SHA, Desktop build, profile fingerprint, model/effort, read-only input fingerprint, proxy mode, and concurrency.
    2. Cold-start the CodexHub-connected leg, navigate to the existing Task through supported Desktop navigation, perform the one read-only operation, then close the App normally after the bounded observation window.
    3. Restore Direct Official through the supported routing UI/config seam while the App is closed. Do not edit SQLite, session JSONL, or Task state.
    4. Cold-start the Direct Official leg with every named variable unchanged, navigate to the same existing Task, and perform the same one read-only operation.
    5. Each leg is one bounded occurrence, so its reproduction count is explicitly 0/1 or 1/1; no repeated rate experiment is required.

    Privacy-safe evidence retained per leg

    • GUI root and app-server start/exit timestamps, parent relationship, and restart count; no command line or host path.
    • WER/Application Error event time, provider/event ID, exception code, and fault-module basename only; no dump or user path.
    • Gateway request start/terminal ordering, status, first closing side, close phase, bytes/events exposed, and completion count; no prompts or response content.
    • Debug-recorder segment hash and bounded summary only.
    • Supported Task list/read/navigation results as counts and booleans: unique before, unique after, interrupted/idle classification, visible after navigation, and duplicate count. Do not retain the Task ID or title.

    Perform Task list/read verification only through supported native APIs and only when it does not contend with the running Desktop process. A second app-server must not be started against the same profile while Desktop owns it.

    Disposition

  8. NOirBRight commented on Jul 27, 2026

    @NOirBRight
    OwnerAuthor

    0.1.7 takeover preflight — live evidence gate remains blocked

    A dedicated isolated Codex profile was inspected through the app-bundled codex app-server using only initialize, account/read, and thread/list.

    Sanitized result:

    • isolated profile: yes
    • app build: 26.721.4979.0
    • total existing Tasks: 0
    • unarchived existing Tasks: 0
    • thread/start: not called
    • turn/start: not called
    • shared Desktop state: not read or mutated

    The #141 contract requires one already-existing unarchived Task in the dedicated profile for the connected/disconnected cold-start and native recovery A/B. Creating a Task as part of the diagnosis is prohibited, so no Desktop session was launched and no Task ID or content was collected.

    #141 remains open and blocks the 0.1.7 release candidate until a dedicated profile with exactly one existing unarchived Task is provisioned externally and the bounded A/B can be completed.

  9. removed
    orch:readyOrchestrator V6: valid hashed contract is complete and dispatchable
    on Jul 27, 2026
  10. NOirBRight commented on Jul 28, 2026

    @NOirBRight
    OwnerAuthor

    Provisioned single-Task profile and bounded GUI-shell A/B

    The prior zero-Task preflight is superseded. With explicit maintainer authorization, setup provisioned exactly one persistent Task before diagnosis. A first Direct/openai setup Task was removed through the supported native API and replaced before evidence under the unified custom Provider identity, so connected and Direct configuration changes could preserve one Task without history database/session rewrites.

    During evidence:

    • exactly one persistent Task existed; no replacement or additional Task was created;
    • connected and Direct legs used the same dedicated GUI user-data profile, Codex profile, Task, build 26.721.4979.0, and machine/network state;
    • each leg cold-started one real packaged GUI root with one app-server child and supplied the supported Task deep link;
    • no whole-GUI restart occurred: connected 0/1, Direct 0/1;
    • no matching WER/Application Error event occurred in either bounded window;
    • after each leg, supported native list/read/resume returned exactly one active Task with unchanged identity and turn count;
    • shared Desktop state, global proxy/TUN state, Codex databases, session JSONL, Task IDs/content, credentials, and host paths were not used or retained.

    Fail-closed limit: renderer DOM was not safely automatable without the prohibited Computer Use path, so the GUI composer did not submit the read-only workload. The separate transport A/B completed all Direct/Gateway Official/Gateway Ollama Cloud app-server and CLI legs, but it cannot be represented as a whole-GUI turn.

    Accordingly this supplies real GUI cold-start/process/WER/recovery evidence but not the Issue's complete same-workload GUI differential. full_issue_141_disposition_available=false; #141 remains open and continues to block #227.

  11. NOirBRight commented on Jul 28, 2026

    @NOirBRight
    OwnerAuthor

    Final connected-versus-Direct GUI disposition

    This supersedes the prior GUI-shell-only limitation. On exact candidate fad95c869bf3726461d9f9a764020863a5ba0317 (tree cf79fc8e47ae9b47b9d484a46641e48c8254b049), packaged Desktop build 26.721.4979.0 used one isolated Codex profile, one isolated GUI profile, and the same single persistent native Task across all legs. The user supplied the GUI composer input; Computer Use was not used.

    Observed bounded reproduction counts:

    • CodexHub connected: whole-GUI restart 0/1; one GUI root and one app-server child remained alive; WER/Application Error 0; Gateway Official and Gateway Ollama Cloud foreground composer turns each completed once with 200 and no retry/request-error.
    • Direct Official: whole-GUI restart 0/1; one GUI root and one app-server child remained alive; WER/Application Error 0; no Gateway listener or Gateway base URL was present; the Direct foreground composer turn completed natively.

    Supported native readback proved exactly one Task throughout. Completed turn count advanced 4 → 6 → 7; the Task remained list/read/resume recoverable without replacement creation, duplicate Task, database edit, or session rewrite.

    During connected startup, a separate background-resume follow-up was cancelled by the client before output and recorded one 499 at failure_side=downstream_write. The GUI root remained alive, no WER event occurred, no retry or opaque reconnect followed, and the two foreground turns completed afterward. This ordered boundary is not a CodexHub-generated invalid/duplicate/unterminated sequence and did not cause a root restart.

    Disposition: current-candidate non-reproduction/upstream boundary. No CodexHub-owned whole-Desktop restart trigger is proven, no speculative Gateway patch or child bug is warranted, and the native navigation/recovery path remains verified. #141 no longer blocks #227.

    Sanitized evidence schema: codexhub.issue-114-141-gui-composer-ab.v1; it retains no Task/window/request IDs, prompts, responses, credentials, or host paths.

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

    P1Priority 1: current iteration goalbugSomething isn't workingwayfinder:researchWayfinder evidence or research ticket

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions