Repository navigation
Diagnose Codex Desktop restart and Task disappearance while CodexHub is connected #141
Description
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
- No Codex internal SQLite/session-index edits, synthetic rollout creation, or unsupported stale-card deletion.
- No new Task creation during diagnosis.
- No global proxy/TUN, credential, or shared Desktop profile mutation.
- No inference that every Find and fix Responses disconnects across official and external routes #114 disconnect or the Make native Responses apply_patch tool contracts symmetric for external models #140 GLM tool-shape failure shares this cause.
- No change to Gateway routing, retry, timeout, pool, or SSE policy before the first failing boundary is proven.
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.pyremains report-only.
Relationships
- Related to Restore reliable sidebar Task control and continuation while CodexHub is active #106, but separate from its completed catalog/Task-tool discovery outcome and the Direct-Official stale-card residual.
- Related to Find and fix Responses disconnects across official and external routes #114 only as a consumer of the Debug recorder; the current ordering shows downstream 499 after the Codex process stopped.
- Make native Responses apply_patch tool contracts symmetric for external models #140 remains the current GLM-5.2 shortest-path fix and should complete before the disconnected control leg.
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
NOirBRight commentedon Jul 15, 2026
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:
ChatGPT.exefailures for the Codex package;MoAppCrashwith exception0xc06d007f;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.
NOirBRight commentedon Jul 16, 2026
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:
26.707.9981.0was already running through CodexHub when visible restarts and severe UI lag recurred.WinError 10053/10054, final status 499) while upstream data was current (last_upstream_byte_age_ms0-1 ms). Five of the six closes belonged to one active Task/window.response.custom_tool_call_input.delta, two during reasoning events, and one afterresponse.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.Conversation state not foundandReceived item/... for unknown conversationacross multiple concurrent Tasks. This is consistent with renderer/app-server Task-state divergence and provides a stronger boundary than the later loopback 499.A separate official-app defect was also observed: each Desktop process logs a native DLL initialization failure in the packaged desktop-notifications
serialport.nodeaddon, with Windows WER exception0xc06d007f. 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.
NOirBRight commentedon Jul 20, 2026
Moved to 0.1.7 as P1
ready-for-humanand 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.NOirBRight commentedon Jul 25, 2026
{ "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 }NOirBRight commentedon Jul 26, 2026
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.pyalways callsthread/startand creates a new ephemeral thread.scripts/run_issue_106_task_lifecycle.pycreates, 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.
0/1or1/1; no repeated rate experiment is required.Privacy-safe evidence retained per leg
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
NOirBRight commentedon Jul 27, 2026
0.1.7 takeover preflight — live evidence gate remains blocked
A dedicated isolated Codex profile was inspected through the app-bundled
codex app-serverusing onlyinitialize,account/read, andthread/list.Sanitized result:
26.721.4979.000thread/start: not calledturn/start: not calledThe #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.
NOirBRight commentedon Jul 28, 2026
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
customProvider identity, so connected and Direct configuration changes could preserve one Task without history database/session rewrites.During evidence:
26.721.4979.0, and machine/network state;0/1, Direct0/1;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.NOirBRight commentedon Jul 28, 2026
Final connected-versus-Direct GUI disposition
This supersedes the prior GUI-shell-only limitation. On exact candidate
fad95c869bf3726461d9f9a764020863a5ba0317(treecf79fc8e47ae9b47b9d484a46641e48c8254b049), packaged Desktop build26.721.4979.0used 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:
0/1; one GUI root and one app-server child remained alive; WER/Application Error0; Gateway Official and Gateway Ollama Cloud foreground composer turns each completed once with200and no retry/request-error.0/1; one GUI root and one app-server child remained alive; WER/Application Error0; 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
499atfailure_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.