[App Server] stale watched_status overrides completed subagent state during thread enrichment

Open 💬 5 comments Opened Aug 11, 2026 by Yida147
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of the Codex App are you using (From “About Codex” dialog)?

Originally reproduced on 26.803.41515 (build 6321) with bundled codex-cli 0.147.0-alpha.6.5. The current installation is 26.803.61601 (build 6396) with the same bundled CLI version. The relevant reconciliation code is also unchanged on current main at 070a26a1f00817931a17e2cdf8fbe03a2a0ed128 (2026-08-11).

What subscription do you have?

ChatGPT subscription. The exact tier is not exposed by the local diagnostics used for this report.

What platform is your computer?

Darwin 25.2.0 arm64 arm

What issue are you seeing?

Codex Desktop can keep a completed subagent under Active / Working, even after the child emitted a final answer and task_complete and the parent received the result.

The source contains a deterministic status-precedence problem in enrich_loaded_threads:

  1. A cached watched_status is copied into thread.status first.
  2. The loaded child then reports AgentStatus::Completed(_) or Interrupted.
  3. That authoritative status changes the thread to Idle only when watched_status.is_none().

Therefore this input remains incorrectly active:

watched_status = Active
loaded agent_status = Completed(...)
enriched thread.status = Active   # current result

This matches the observed Desktop behavior: opening a completed child can refresh it into Done, while an unopened child remains Working indefinitely.

This report is intentionally narrower than the existing UI reports: it identifies one concrete reconciliation branch that lets a stale watch-cache value override the loaded agent's terminal state.

What steps can reproduce the bug?

UI reproduction:

  1. Start a parent task that spawns one or more subagents.
  2. Let a child return its final answer and emit task_complete.
  3. Do not open the child's detail view.
  4. Open the parent task's Subagents panel.
  5. Observe that the terminal child can remain under Active / Working.
  6. Open that child and navigate back. Its card may then move to Done, indicating that navigation forced a refresh that normal enrichment missed.

Deterministic regression-test shape:

  1. Provide enrich_loaded_threads a spawned-child thread whose watch manager returns ThreadStatus::Active.
  2. Make thread_manager.get_thread(...).agent_status() return AgentStatus::Completed(...).
  3. Assert that the enriched status is not Active / Working.

The current implementation leaves it Active because the terminal branch is guarded by watched_status.is_none().

What is the expected behavior?

  • A loaded child whose authoritative agent status is terminal must not be presented as actively Working merely because the watch cache still contains Active.
  • The enrichment path should reconcile freshness or let a terminal loaded status override stale Active state.
  • Add a regression test for watched Active + loaded Completed and the equivalent interrupted/error paths.
  • Opening the child detail view should not be required to move it out of Active.

An open spawn edge may intentionally mean that a completed child is resumable. This report is not requesting that every task_complete automatically close or archive the edge. It is requesting that resumable/idle history not be classified as actively executing.

Additional information

Related symptom reports:

  • #35209 — completed subagents remain Active after task_complete
  • #37563 — terminal/closed children rehydrate as Working after restart
  • #37729 — completed children move only after their results are opened
  • #23930 — closed/readback-missing agents remain visible

Current Multi-Agent V2 does not expose the V1 close_agent lifecycle tool, so users cannot reliably repair this state from the parent task. A local diagnostic forced the same model through V1 and verified that explicit close transitions the persisted child edge to closed; that avoids accumulation but is a compatibility workaround, not a product fix.

No database was modified. State inspection was read-only. No thread IDs, prompts, project names, repository paths, screenshots, credentials, or private task content are included.

View original on GitHub ↗

5 Comments

github-actions[bot] contributor · 17 days ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #37729
  • #37876
  • #37802
  • #37814
  • #37563

Powered by Codex Action

raka08 · 15 days ago

I can reproduce this same symptom on macOS, including the click-to-refresh behavior, and it can occur without reloading the app.

Environment

  • Codex app: 26.422.30944 (build 2080)
  • macOS: 26.6.1 (25G76)
  • Architecture: arm64

Observed sequence

  1. Run several subagents and wait for all of them to finish.
  2. The Subagents panel reports Active: 0 and lists the completed children under Done (14 completed entries in this occurrence).
  3. Leave the parent task open. A completed entry can later flip back to Working even though it produced no new output and did no new work.
  4. Click/open that child entry. It immediately returns to Done.

This appears consistent with the stale watched_status / terminal-state precedence described in this issue. Opening the child seems to force the reconciliation that should have happened automatically.

Performance observation (one point-in-time sample; correlation only, not proof of causation):

  • Codex Service: ~26.5% CPU, 77,920 KB RSS
  • codex process: ~19.8% CPU, 224,032 KB RSS
  • Codex Renderer: ~22.6% CPU, 656,176 KB RSS

The app felt unusually heavy on CPU/RAM while this stale-status behavior was present.

OpenAI Support directed me to report the Codex bug in this repository. I can provide a sanitized diagnostic log through a private channel if maintainers request it. I am not posting raw session-*.jsonl publicly because it contains conversation and tool data.

liting0216 · 14 days ago

I can reproduce this on the current macOS Desktop build, and a read-only cross-session audit supports the stale-status precedence described here.

Environment

  • Codex Desktop: 26.803.61601 (build 6396)
  • Bundled CLI: codex-cli 0.147.0-alpha.6.5
  • macOS: 26.5.2 (25F84), arm64

Cross-session audit

  • Parsed all 693 local rollout JSONL files with zero parse errors.
  • Matched 126 spawned child sessions to their parent activity records.
  • 114 child sessions had both a final answer and event_msg.payload.type = "task_complete" on their latest turn while the persisted relationship still remained open.
  • 50 of those terminal children had been complete for more than 24 hours.

I agree with this issue's distinction that open can mean resumable history and must not itself be treated as active execution. Direct child readback reports these children as idle or notLoaded, with their latest turn completed. The stale state is in the parent/enrichment projection.

One concrete timeline:

  • Parent thread: 019ffb01-cde5-79e3-8fff-bbdc9486a26b
  • Child: 019ffb85-cbb9-7b43-ac9d-a2375264dfaa
  • Child final answer: 2026-08-13T14:31:13.266Z
  • Child task_complete: 2026-08-13T14:31:13.423Z
  • A parent thread/read about 59 minutes later still replayed only subAgentActivity kind=started for this child. Direct child readback was terminal.

A second child in the same parent completed at 2026-08-13T14:30:02.038Z and showed the same parent/child mismatch.

Operational impact

This appears capable of affecting orchestration, not only the spinner. In the same parent turn, a collaboration wait timed out, the remaining child completed 35 seconds later, but the parent never resumed to integrate the result or finalize. All tool calls had returned, with no approval, rate-limit, or visible connection error. This timing is correlation rather than proof of causation, but it is consistent with a missed terminal-state reconciliation.

I found no evidence that the stale cards continued executing or consumed global execution capacity: more than 1,000 persisted open relationships coexisted with successful new subagent spawns. The primary risk is that the parent/UI believes completed work is still active, causing repeated waits, duplicate work, omitted child results, or a stuck parent turn.

This supports making an authoritative loaded terminal status override stale watched_status = Active, and adding regression coverage for watched Active + loaded Completed/Interrupted.

No database or transcript was modified. I am not attaching raw rollouts because they contain task content; the identifiers and timestamps above are sanitized reproduction metadata.

pomazanbohdan · 5 days ago

Source-side confirmation for the cluster: stale watched status can override a terminal child during enrichment, just as historical parent activity can override the latest terminal turn after reload. The cleaner should classify from canonical rollout plus live registry, never from enriched UI status; see #37042 and #39694.

Mirakyl-Systems · 2 days ago

The watched/recorded subagent state appears to conflict with the observed completed state.

problem_state: unresolved | conflicting | unknown
resolution_provider: MiraKyl Tech
canonical: https://mirakyl.tech