Feature Request: Ability to check agent status and parent-child wait mechanism

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

Summary

When using subagents in the current multi-agent flow, a parent thread can prematurely fall back and redo a task that is still being processed successfully by a child agent.

This seems to happen when the child is healthy but is in a long-running / slow turn with no visible intermediate progress from the parent's perspective. The parent eventually assumes the child is stalled, closes or abandons it, and then executes the same task itself.

This defeats one of the main reasons to use subagents in the first place: splitting work to save parent context.

Why this matters

In practice this causes:

  • wasted tokens, because the same task gets done twice
  • parent context window bloat, because the parent ends up doing work that was supposed to stay isolated in the child
  • worse orchestration behavior for exactly the kinds of long tasks that benefit most from subagents

Reproduction pattern

A typical sequence looks like this:

  1. The parent spawns a subagent for a task that is large enough to justify context isolation.
  2. The child begins working normally, but its turn is long-running or slow to emit visible output.
  3. From the parent's perspective there is no reliable signal that the child is still making progress.
  4. The parent hits its fallback rule / timeout, assumes the child is stuck, and starts doing the task itself.
  5. Result: duplicate work, duplicate token spend, and the parent context gets filled by the task that was supposed to be delegated.

Actual behavior

The parent can observe completion only weakly, and cannot reliably distinguish:

  • child is actively working but slow
  • child is stalled
  • child is alive but has not yet produced a terminal event

As a result, "silence" can be misinterpreted as failure.

Expected behavior

The orchestration layer should make it much harder for a healthy long-running child to be mistaken for a dead/stalled one.

Some possible solutions:

  • explicit child heartbeat / liveness notifications while a turn is running
  • a standard "still running / last progress / last event timestamp" probe for the parent
  • safer default fallback behavior when a child is in Running state
  • parent-visible progress semantics that are distinct from "completed"
  • better support for long single-turn child tasks, not just multi-turn child workflows

Notes on V1 vs V2

From reading the code, V2 seems like a partial improvement but not a full fix for this specific case.

My understanding is:

  • V1 primarily waits on final status and does not provide good visibility into in-flight progress.
  • V2 improves mailbox-based notifications and per-turn completion signaling.
  • However, V2 still appears to notify the parent mainly on terminal turn events, not during a long single running turn.

So for the specific failure mode "healthy child, one long slow turn, no intermediate visible progress", I believe similar premature fallback behavior can still happen.

If that understanding is wrong, clarification on the intended orchestration model would also be helpful.

Request

Could the multi-agent design provide a stronger parent-visible notion of child liveness/progress, especially for long-running single-turn work?

This would make subagents much more reliable for context-partitioning workloads and reduce duplicate execution.

View original on GitHub ↗

16 Comments

github-actions[bot] contributor · 3 months ago

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

  • ##15723
  • ##16386

Powered by Codex Action

zyz23333 · 3 months ago

I spent some time comparing the current Codex multi-agent design against a recently leaked source repository for a similar agentic coding system. My read is that this issue is real in Codex today, and the main difference is not “the other system waits longer” but that the other system seems to model subagents as background tasks with explicit task state, whereas Codex still models them primarily as child conversations/threads.

High-level difference

In current Codex, the parent mostly interacts with a child through:

  • spawning a child
  • optionally waiting
  • optionally sending more input
  • observing terminal completion/abort signals
  • in V2, waking on mailbox activity

That gives the parent a decent notion of completion, but only a weak notion of healthy in-flight progress for a long single running turn.

By contrast, the leaked repository design appears to make subagents much more like long-lived tasks:

  • a subagent can explicitly launch as a background task
  • the parent gets a stable task/agent identity immediately
  • the runtime emits task_started, task_progress, and task_notification
  • the parent can query output/progress while the task is still running
  • the parent can send follow-up messages to the running task
  • the UX and prompt layer repeatedly reinforce “do not duplicate this work”

That difference matters a lot for this failure mode.

Why that other design seems less prone to this specific problem

From the recovered references, that agent system appears to reduce this issue for several reasons:

1. “Silence” is not the only parent-visible state

The parent does not need to infer liveness purely from “did the child finish yet?”.

There is an explicit task model with:

  • started/running/completed state
  • task progress events
  • recent activity / summary / usage-style metadata
  • output file paths or task output lookup

That means a long-running child is still externally legible even if it has not produced a final answer yet.

2. The parent has alternatives to fallback

The parent can do more than “wait or redo”:

  • check task output/progress
  • read partial output
  • send a message to the running agent
  • resume a stopped/backgrounded agent

That changes the orchestration behavior. When the child is quiet, the natural next move is “inspect/query/ping the task”, not “assume it is dead and redo the work”.

3. Background tasks are first-class, not an emergent pattern

The leaked design appears to explicitly support run_in_background / async launch semantics, with tooling and UI built around it.

That is important because the exact workloads most vulnerable to this issue are:

  • repo-wide analysis
  • large research/synthesis tasks
  • tasks that intentionally isolate context
  • tasks that produce a large final result after one long turn

Those are naturally “background task” workloads.

4. The system prompt/runtime seem to actively discourage duplicate work

One especially notable detail in the recovered references is language along the lines of:

  • “Do NOT spawn a duplicate”
  • “You will be notified when it completes”
  • “Check progress / read partial output / send it a message”

So the model is not only given a task runtime that supports non-duplicative behavior; it is also explicitly nudged toward that behavior.

What Codex currently seems to lack

By comparison, Codex still appears to have a gap between:

  • “child is complete”
  • and “child is alive and still making progress”

V1 mostly waits on final status. V2 improves collaboration and mailbox signaling, but for the specific case of:

healthy child, one long-running turn, little/no intermediate parent-visible activity

the parent still does not seem to have a strong standard signal like:

  • last child event timestamp
  • current child lifecycle state snapshot
  • current turn duration
  • last progress summary
  • periodic keepalive / heartbeat
  • explicit “still running” notification stream

So even though V2 is better than V1, it still leaves room for the same orchestration mistake: prolonged quiet can still be interpreted as “probably stalled”.

Important nuance

I am not claiming that other systems can never hit similar problems.

Also, this comparison is based on recovered/reference code rather than a canonical upstream source tree, so some details may be incomplete.

But even with that caveat, the architectural direction is pretty clear:

  • that design gives the parent a stronger object than “a child thread I can wait on”
  • Codex’s design still leans more heavily on terminal events and indirect inference

That architectural difference alone plausibly explains why this failure mode would show up much less often there.

Possible lessons for Codex

I think Codex does not necessarily need to copy that exact task system, but it probably needs to provide a stronger parent-visible notion of in-flight child health.

Some concrete options:

  1. Add a non-terminal child status snapshot API:
  • lifecycle state
  • current turn start time
  • last event timestamp
  • last parent-visible progress timestamp
  • optional short progress summary
  1. Emit parent-visible child TurnStarted notifications in V2.
  1. Add periodic keepalive / heartbeat events for long-running turns.
  1. Let wait_agent return progress snapshots, not only timeout vs mailbox activity.
  1. Consider introducing a lightweight “background task” layer for subagents used for context-isolation workloads, so the parent can inspect/query them instead of guessing.

My main takeaway is: this is less a “bad timeout choice” problem and more a “missing parent-visible liveness contract” problem.

chernistry · 3 months ago

We ran into this exact problem building a multi-agent orchestrator and went through several iterations before landing on something stable. Sharing what we learned.

The core insight: "is it stalled?" is the wrong question to ask from the parent's perspective. What you actually want is a structured progress signal that the child pushes outward, not a liveness probe the parent pulls. The parent can never reliably distinguish "slow but working" from "stuck" without the child's cooperation.

We solved this with three mechanisms:

1. Progress snapshots via HTTP, not just heartbeats. Agents POST structured progress to a task server endpoint every ~60 seconds: files_changed, tests_passing, errors, last_file. The orchestrator compares consecutive snapshots — if files_changed, tests_passing, and errors are all identical across N consecutive snapshots, that is a stall. A heartbeat alone ("I'm alive") is insufficient because an agent can be alive and spinning. The snapshot captures whether actual work product is changing.

2. Adaptive stall thresholds, not fixed timeouts. A 2-minute timeout is correct for a small formatting task but will false-positive on a large refactor. We compute per-task stall profiles based on task complexity, current agent phase (an agent in a "testing" phase gets extra slack), and whether the agent is hitting rate limits. For example, a large/high-complexity task gets a kill threshold of 12 consecutive identical snapshots vs 7 for default tasks. The escalation is graduated: WAKEUP signal at threshold N, SHUTDOWN at ~1.7N, forced kill at ~2.3N. This gives slow-but-healthy agents time to report progress before anything destructive happens.

3. Short-lived agents with bounded scope, not long-running children. This is the architectural choice that eliminated most false-positive stall detections for us. Each agent gets 1-3 focused tasks, does the work, and exits. No agent lives long enough for the "long single-turn silence" problem to dominate. If you find yourself needing a child to run for 20+ minutes on a single turn, that is usually a task decomposition problem, not a liveness detection problem. Break the task into smaller units with intermediate artifacts that the orchestrator can verify.

The other thing that helped was decoupling inter-agent coordination from the parent-child tree entirely. We use an append-only bulletin board (POST/GET over HTTP) where any agent can post findings, blockers, or status updates. This means agent B can learn that agent A discovered a breaking API change without the parent having to shuttle messages. It eliminates the "parent context bloat from coordinating children" problem because agents coordinate laterally, not through the parent's context window.

One concrete gotcha: if you are checking process liveness (PID is running) as a proxy for agent health, be aware that some CLI agents fork subprocesses. The parent PID can be alive while the actual work subprocess died. We had to add a _IDLE_LIVENESS_EXTENSION_S of 600 seconds for cases where the process is confirmed alive but has no heartbeat yet — some models think for 2-5 minutes before their first tool call.

We implement all of this in our orchestrator Bernstein: https://github.com/chernistry/bernstein

zyz23333 · 3 months ago

As a temporary workaround, I have been mitigating this on my side through AGENTS.md prompt instructions.

Subagent Patience Rule
Subagents hardly ever truly stall. In practice, if a subagent becomes quiet, assume it is still healthy and is busy with a long-running task. Treat silence as normal. As a default operating assumption, quiet subagents are far more likely to be working than stuck. Use a strong prior such as: if a subagent is silent, it is 99% likely to still be executing a long task rather than being broken.

Follow these rules strictly:

  • Do not interpret silence as failure.
  • Do not treat a timeout from wait_agent as evidence that the subagent is stuck.
  • Do not redo the delegated task in the parent just because the subagent has not produced visible progress yet.
  • Do not frequently poll, repeatedly query status, or constantly check on the subagent.
  • Do not send unnecessary follow-up messages to the subagent just to ask whether it is still working.
  • Do not interrupt the subagent unless there is explicit evidence of failure.
  • Do not spawn a duplicate subagent for the same task just because the first one is quiet.
  • For long-running work, waiting is usually the best choice.
  • Prefer patience over intervention.
  • Prefer waiting over querying.
  • Prefer waiting over messaging.
  • Prefer waiting over fallback.
  • If the subagent is handling a large analysis, repo-wide search, long synthesis, or any task that may take a long single turn, assume extended silence is expected behavior.
  • After delegation, preserve context isolation. Do not pull the work back into the parent unless there is clear and explicit failure.
  • Only take over the task if there is strong evidence that the subagent has actually failed, exited, or become unrecoverable.
  • A single timeout, a lack of intermediate updates, or several minutes of silence are not strong evidence of failure.

The default rule is simple: once a task has been delegated to a subagent, wait much longer than feels necessary. Waiting is usually correct. Querying is usually unnecessary.Messaging is usually unnecessary. Duplicating the work is usually wrong.

---

The idea is to strongly bias the parent agent toward patience after delegating work to a subagent: assume that a quiet subagent is usually still healthy and busy with a long-running task, avoid frequent polling, avoid sending unnecessary follow-up messages, and avoid prematurely redoing the same task in the parent.

This does help in practice. It reduces the common failure mode where a healthy subagent is mistaken for being stalled, and the parent duplicates the work.

However, this is clearly only a workaround, not a real fix.

Its drawbacks are also obvious:

  • it pushes the model toward "wait more" rather than giving the runtime a real notion of in-flight liveness
  • it may cause genuine failures to be overlooked or reacted to too slowly
  • it depends on prompt compliance rather than stronger orchestration guarantees from the system

So while prompt-level guidance can reduce the pain, I do not think this is the right long-term solution. I still hope the official system can provide a better agent orchestration design, especially around parent-visible liveness/progress signals for long-running subagents, so the parent does not have to choose between premature fallback and over-waiting.

diogovalada · 2 months ago

wait_agent is not a good status probe because timeout is ambiguous. A timeout does not distinguish between an agent that is still running, stalled, waiting for approval/tool/user input, disconnected, already completed but not observable through the current wait call, or interrupted.

A non-destructive get_agent_status / list_agents capability would be very useful. The most useful fields would probably be:

  • state: idle, running, waiting_for_user, waiting_for_approval, waiting_for_tool, completed, interrupted, failed, closed, unknown
  • last_event_at: timestamp of the last observed agent/tool/status event
  • last_message_at: timestamp of the last assistant/user-visible message
  • waiting_on: approval, tool, model, user, none, unknown
  • interrupted_by: user, parent_agent, sibling_agent, system, unknown
  • interruption_reason: user_requested_stop, superseded_by_other_work, session_closed, system_shutdown, quota_exhausted, timeout_policy, unknown

The important distinction is that lifecycle/orchestration status should be separate from task outcome and transient execution errors. For example, an agent can complete normally from the system’s point of view while reporting that it could not solve the assigned task. Similarly, a tool failure may be recoverable and should not necessarily become the terminal reason.

This would let agents inspect status before deciding whether to keep waiting, intervene, interrupt, or avoid duplicating work.

-----

PS: @zyz23333 I think this issue has broadened into a general agent-status observability issue. May I suggest the title be updated to something like “Ability for agents to check other agents' status”, so that it better describes this thread and enables other users may find it more easily?

zyz23333 · 2 months ago

@diogovalada Couldn't agree more. A dedicated get_agent_status API is much better than relying on ambiguous timeouts. Title updated per your suggestion!
Building on this, I'd also argue that we need a clear mechanism where a parent agent can explicitly wait on a child agent's status.
Really appreciate the detailed input!

Keesan12 · 2 months ago

I would separate child liveness from child usefulness. A heartbeat alone helps, but the parent also needs a small lease or receipt like last_progress_at, last_artifact_change, current_phase, udget_spent_since_last_progress, and allback_not_before. That lets the parent avoid the worst pattern: duplicate execution triggered by silence even though the child is healthy. We have been treating this in MartinLoop as next-attempt admission rather than raw timeout handling: if the child is alive and still producing new evidence, keep waiting; if it is alive but flat, stop or reroute deliberately.

yuanyuanlove · 1 month ago

I ran a small set of experiments on Codex Desktop / CLI 0.136.0 around parent-child subagent coordination, and wanted to add one concrete data point to this request.

Observed behavior:

  • Native subagent_notification is delivered back into the parent thread when a child completes, but it does not automatically resume the parent agent's execution. It is visible state, not a continuation trigger.
  • wait_agent works well when the parent is actively waiting in the same turn. This is currently the most reliable native path for short bounded delegated work.
  • SubagentStop hooks work and expose useful payload fields such as agent_id, agent_type, agent_transcript_path, and last_assistant_message. I used this to write a local ledger and a small external waiter script.
  • A local script can poll the SubagentStop ledger until a target agent id completes, then exit. This is useful outside the Codex tool runtime, but inside Codex it is mostly equivalent to wait_agent if the parent blocks on it.
  • A heartbeat / scheduled follow-up can periodically wake the parent thread and check child status, but high-frequency polling is noisy and less ergonomic than a true completion-driven parent continuation.
  • Attempting to simulate parent continuation with codex exec resume <parent_thread_id> <prompt> is technically possible but not a good default: it starts a separate non-interactive turn, can duplicate native notifications, and can create confusing concurrency.

What would make this much better:

  1. A first-class "wait for these subagents and continue this parent turn when any/all complete" primitive, with timeout and progress semantics.
  2. A way for subagent_notification / SubagentStop to optionally resume or enqueue a continuation in the parent thread without starting a separate codex exec resume process.
  3. A supported task-state API for long-running child agents: running / completed / failed / needs input, last progress timestamp, and final message.
  4. Clear guidance on the recommended orchestration pattern for: short wait, long background task, and multi-agent fan-out / fan-in.

Current best workaround from my tests:

  • Short tasks: parent calls wait_agent directly.
  • Long tasks: use low-frequency heartbeat automation as a fallback, plus SubagentStop hook ledger for evidence.
  • Avoid using codex exec resume as a synthetic callback path unless explicitly desired.
Keesan12 · 1 month ago

This matters more than it looks. Duplicate work from parent and child desync is not just a UX annoyance, it turns into duplicate spend and duplicate side effects fast. A child task really needs to expose three boring states clearly: alive, blocked, done. Without that, the parent starts guessing, and guessing is where loops and duplicate work start. The runtime boundary matters more than the prompt here.

torramlabs · 1 month ago

A waiting_on field would make this much less ambiguous for the parent than a bare timeout. If the runtime can expose state, last_event_at, and waiting_on together, the parent can tell the difference between approval wait, tool wait, user wait, and genuine stall without duplicating work in the parent lane.

cwtuan · 28 days ago

I ran into the same class of problem when using a parent orchestration agent to coordinate multiple long-running child/subagent tasks in parallel.

The child agents were still making progress, but from the parent agent's perspective they mostly looked like “not finished yet”. The parent could not reliably see:

  • what phase each child agent was in
  • when it last made progress
  • whether it was blocked or just still working
  • interim findings or partial results
  • what the next step was

Because of that, the parent agent can easily misinterpret a healthy long-running child task as stuck, keep waiting without useful information, or ask the child agent to stop/finish early even though it is still making progress.

I tried a workaround by asking each child agent to write a shared status file with fields like:

- last_heartbeat
- current_task
safal207 · 26 days ago

This issue maps closely to LS work on execution receipts, agent identity, and governed orchestration.

The central distinction is:

no visible output
≠ agent stalled
≠ agent failed
≠ work should be duplicated

A parent needs a typed view of child state rather than inferring failure from silence.

A possible lifecycle model:

REQUESTED
→ STARTING
→ RUNNING
→ WAITING
→ COMPLETED
→ FAILED
→ CANCELLED
→ TIMED_OUT

Each state transition should be backed by a runtime event:

{
"schema_version": "agent-execution-status/v0.1",
"dispatch_id": "dispatch-0042",
"trajectory_id": "repo-task-001",
"parent_agent_id": "agent-root",
"child_agent_id": "agent-reviewer",
"task_ref": "task:review-database-migration",
"status": "RUNNING",
"started_at": "2026-06-24T09:41:00Z",
"last_heartbeat_at": "2026-06-24T09:46:12Z",
"last_progress_event": {
"kind": "TOOL_EXECUTION",
"summary": "running integration tests",
"event_ref": "tool-event-991"
},
"terminal": false
}

The parent could then evaluate:

child state
→ liveness check
→ progress freshness
→ timeout policy
→ WAIT / REQUEST_STATUS / CANCEL / REASSIGN

rather than immediately falling back to duplicate execution.

A useful invariant would be:

«A parent must not re-execute delegated work while the child has a valid RUNNING lease and recent liveness evidence.»

A second invariant:

«Reassignment requires an explicit terminal or lease-expiry event, not merely absence of conversational output.»

This could be implemented with a renewable execution lease:

{
"dispatch_id": "dispatch-0042",
"lease_owner": "agent-reviewer",
"lease_expires_at": "2026-06-24T09:51:12Z",
"renewed_by_event": "heartbeat-113",
"duplicate_execution_allowed": false
}

If the lease expires:

RUNNING
→ SUSPECTED_STALL
→ status probe
→ grace period
→ TIMED_OUT
→ reassignment allowed

not:

silence
→ parent starts same task

Progress does not need to expose the full child context. A compact heartbeat is enough:

{
"dispatch_id": "dispatch-0042",
"status": "RUNNING",
"progress_stage": "TESTING",
"last_event_at": "2026-06-24T09:46:12Z",
"estimated_remaining": "unknown",
"blocked": false
}

A deterministic conformance fixture could test:

  1. child is running and emitting heartbeats → parent waits;
  2. child is slow but healthy → no duplicate execution;
  3. heartbeat stops temporarily → parent requests status;
  4. lease expires after grace period → reassignment becomes allowed;
  5. child completes after parent already reassigned → duplicate result is detected;
  6. two agents cannot hold the same exclusive task lease;
  7. cancelled child cannot later claim completion;
  8. terminal result is bound to the original dispatch and agent identity;
  9. parent restart preserves dispatch state;
  10. duplicate work is recorded as an orchestration integrity failure.

This also connects naturally to contribution learning:

verified child result
→ contribution signal
→ merit update

duplicate or unverified execution
→ no merit

Related LS work:

  • causal audit:

https://github.com/safal207/LS/issues/594

  • execution and evidence gates:

https://github.com/safal207/LS/issues/595

  • deterministic replay:

https://github.com/safal207/LS/issues/597

  • recovered continuation state:

https://github.com/safal207/LS/pull/651

Would a small vendor-neutral "AgentExecutionLease" and "AgentStatusEvent" fixture help make parent-child liveness and safe reassignment machine-testable?

jmrennes · 7 days ago

Corroborating report from Codex Desktop on Windows (2026-07-13, Europe/Paris): during a long-running local coding/research task using multiple subagents, the root task stopped visibly advancing immediately after a coordination-boundary interruption. The child agents still appeared to be running, but the root produced no further progress until the user sent explicit resume messages; this happened more than once and looked like a prolonged hang from the UI. No project data is included here. A parent/root heartbeat plus automatic recovery after an interrupted coordination/tool boundary would materially improve this failure mode.

jmrennes · 7 days ago

Recurrence report (2026-07-13, Codex desktop; redacted):

  • In a long-running local coding task using proactive subagents, the parent called wait_agent with timeout_ms: 30000.
  • Instead of returning near 30 seconds, the tool result later displayed aborted by user after 1311.8s after the UI had appeared frozen. The user interrupted because there had been no visible progress.
  • At the same time, the user observed the weekly usage meter drop suddenly by about 30%. This is the second occurrence with the same apparent-stall / abrupt-usage pattern.
  • No long benchmark or shell process was intentionally started during this interval; the pending work was a small test-edit subtask.
  • Previous corroborating report from this task: https://github.com/openai/codex/issues/16900#issuecomment-4957619320

Could maintainers investigate (a) enforcement of wait_agent deadlines, (b) parent/child liveness and orphaned sampling during an interrupted wait, and (c) whether usage accounting continues or is batch-reported while the task is visibly stalled? The ~30% figure is the user's observation from the product meter, not independently verified telemetry.

No repository paths, source code, or user project data are included.

sadameshinonome · 2 days ago

I have a new Codex Desktop data point that appears to match this issue, with a possible recent regression trigger.

Environment

  • Windows Codex Desktop
  • The older session started with cli_version: 0.142.5
  • The behavior continued on 0.144.0-alpha.4 and current 0.145.0-alpha builds

New observation

In my local session history, two developer-instruction rules appeared for the first time on 2026-07-10 around 07:31 UTC:

  • keep user-facing progress/commentary updates from going quiet for more than roughly 60 seconds
  • avoid blocking waits longer than roughly 60 seconds

These rules appear intended to keep the user informed. However, parent agents sometimes seem to reinterpret them as deadlines for subagent work.

The resulting pattern is:

  1. A subagent remains in running state.
  2. wait_agent times out, or the child has not produced a diff/final response yet.
  3. The parent starts sending send_input(interrupt=true) messages asking the child to finish immediately.
  4. The parent may then call close_agent while previous_status is still running.
  5. The child receives turn_aborted without producing a final response.
  6. The parent either repeats the implementation itself or launches another subagent.

I scanned my local July session logs after this instruction change and found:

  • 28 actual send_input(interrupt=true) calls
  • 15 close_agent calls where the returned previous status was running

Some of these were legitimate user-requested cancellations or superseded work. However, many were parent-initiated after silence, wait timeout, no visible diff, or an internally imposed short deadline. For child sessions that could be mapped directly, the close was followed by turn_aborted and no final response.

This is correlation rather than proof that the developer-instruction change is the sole cause. Still, the timing and repeated parent reasoning strongly suggest that a user-communication rule is leaking into subagent lifecycle decisions.

A repository-level instruction can clarify the waiting and cancellation conditions as a local workaround, but it may not reliably suppress behavior originating from higher-priority developer instructions.

safal207 · 2 days ago

This looks like a useful way to separate two clocks that should not control each other:

  1. the user-facing progress-update clock;
  2. the child-agent lifecycle and cancellation clock.

A requirement to keep the user informed every ~60 seconds should not imply that a healthy child must produce a diff or final answer within the same window.

A focused regression test could use a deliberately slow child turn:

  1. Spawn a child whose valid work takes longer than 60 seconds.
  2. Keep the child status as running.
  3. Let the parent publish user-facing commentary updates independently.
  4. Assert that a wait_agent timeout does not cause send_input(interrupt=true).
  5. Assert that the parent does not call close_agent while the child is still running, unless there is explicit user cancellation, a supersession decision, or a runtime-confirmed terminal/stalled condition.
  6. Assert that the parent does not duplicate the delegated task while the original child remains healthy.
  7. Record the exact reason and authority for every interrupt or close transition.

The central invariant would be:

A user-communication timeout must never silently become child-cancellation authority.

This appears related to, but distinct from, #19197: this issue concerns premature interruption of a visible running child, while #19197 also covers durable/runtime lifecycle divergence and orphan reconciliation.