You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A worker's escalate_to_supervisor call with expectsReply: true blocks the worker polling for a reply keyed to the escalation id. When the wait times out with no reply, the worker session exits. Nothing relaunches it: the lane-runner does not respawn the worker, and the runtime registry and lane state stay running with frozen timestamps. Supervisor steers then fail (send_agent_message has no live process to deliver to), and the supervisor has no tool that re-engages the lane short of orch_resume — which, in the observed run, was itself blocked (see the companion issue on replacement-supervisor resume).
Observed in penster batch henrylach-20260905T210935 (TP-2047, single wave, single lane), 2026-09-06.
Sequence
The worker hit a plan-gate REVISE at the round-2 cap and, per the operator's standing hold rule, entered a hard hold and escalated to the supervisor for a ruling: escalation id 1788657826267-4ee58, expectsReply: true.
The supervisor session that should have replied was itself wedged on a provider-side 400 (thinking-block mismatch) and was being replaced; no reply arrived inside the worker's wait window.
The worker's poll timed out and the process (pid 59452) exited. Get-Process returned nothing.
.pi/runtime/<batch>/registry.json and lanes/lane-1.json remained status: running, updatedAt 1788657826268 (the moment after the escalation call), for the next 17+ minutes. batch-state.json stayed phase: executing.
The replacement supervisor's send_agent_message refused (no live consumer); a manual inbox file drop was inert (no process to drain it; an escalation-wait expects a replyTo-keyed reply, not a fresh steer). orch_pause was accepted but inert (nothing running to honor it).
Recovery required a manual batch-state.json phase edit plus a fresh supervisor session plus orch_resume (precedence-4 re-execute in the existing worktree). Committed work survived; the hold-time commits (hold(TP-2047):) were intact.
Why this matters
The hard hold is the operator-sanctioned posture for a cap escalation (#627). A worker that holds correctly and then dies because the ruling took longer than its poll timeout converts a governance pause into a dead lane with stale running state — the worst of both: no work, no signal, and a registry that lies about it.
If the worker process does exit for any reason while the task is non-terminal, the lane-runner (or the engine monitor) must reconcile the registry/lane state to exited within one poll interval and surface a supervisor alert (worker-exited-while-held or similar), instead of leaving running frozen.
send_agent_message to a dead worker should return a distinct, actionable error naming the dead pid and last-seen timestamp, not a generic refusal.
Summary
A worker's
escalate_to_supervisorcall withexpectsReply: trueblocks the worker polling for a reply keyed to the escalation id. When the wait times out with no reply, the worker session exits. Nothing relaunches it: the lane-runner does not respawn the worker, and the runtime registry and lane state stayrunningwith frozen timestamps. Supervisor steers then fail (send_agent_messagehas no live process to deliver to), and the supervisor has no tool that re-engages the lane short oforch_resume— which, in the observed run, was itself blocked (see the companion issue on replacement-supervisor resume).Observed in penster batch
henrylach-20260905T210935(TP-2047, single wave, single lane), 2026-09-06.Sequence
1788657826267-4ee58,expectsReply: true.Get-Processreturned nothing..pi/runtime/<batch>/registry.jsonandlanes/lane-1.jsonremainedstatus: running,updatedAt 1788657826268(the moment after the escalation call), for the next 17+ minutes.batch-state.jsonstayedphase: executing.send_agent_messagerefused (no live consumer); a manual inbox file drop was inert (no process to drain it; an escalation-wait expects areplyTo-keyed reply, not a fresh steer).orch_pausewas accepted but inert (nothing running to honor it).batch-state.jsonphase edit plus a fresh supervisor session plusorch_resume(precedence-4re-executein the existing worktree). Committed work survived; the hold-time commits (hold(TP-2047):) were intact.Why this matters
The hard hold is the operator-sanctioned posture for a cap escalation (#627). A worker that holds correctly and then dies because the ruling took longer than its poll timeout converts a governance pause into a dead lane with stale
runningstate — the worst of both: no work, no signal, and a registry that lies about it.Expected
expectsReplyescalation must not terminate the worker. Options: the worker re-enters its hold loop and re-polls (bounded by the stall limit, which the hold should suspend per Cap-ruling hold: runtime must block .DONE and merge while an operator ruling is pending (.PENDING-RULING) #627); or the lane-runner treats the exit as a hold-safe exit and preserves aheldmarker rather than nothing.exitedwithin one poll interval and surface a supervisor alert (worker-exited-while-heldor similar), instead of leavingrunningfrozen.send_agent_messageto a dead worker should return a distinct, actionable error naming the dead pid and last-seen timestamp, not a generic refusal.Relation to other issues
heldstate): a first-class held state with no iteration/stall progression would make the wait indefinite by design and remove the timeout-exit path entirely.supervisor_takeover,orch_retry_task;orch_resumewas the correct primitive once reachable.