Reported live by voiceClaude (VoiceLayer lead) during an M1 deploy, 2026-08-19, v0.4.47
Full report with verbatim tool output: docs.local/reports/2026-08-19-registry-watch-disagreement.md
wait_for(ids:[...], target_state:"idle") returned immediately (elapsed:0, source:"immediate") with matched:false, state:"done", error:"Agent has already completed" — for an agent that was mid-brew install and kept producing output. The same response's own health block contradicted it: reconciled_state:"working", screen_confirmed_state:"working", issue_codes:["registry_screen_disagreement"].
Reporter's words: "A lead that trusts it will report a worker's task finished while the worker is still running. I hit this and had to abandon wait_for entirely."
Mechanism (verified in source)
waitForAgent's terminal short-circuits read the raw registry record:
agent-engine.ts:8128 const initial = this.registry.get(agentId)
agent-engine.ts:8148 if (initial.state === "error" && ...) → immediate return
agent-engine.ts:8160 if (initial.state === "done" && targetState !== "done") → immediate matched:false
F1 (#457/#466) taught caller resolution, delivery gating, and closure to use resolveLiveAgentState; wait_for was not in that lane's scope and still trusts the record. Against the known stale-done registry class (#408) this makes the fleet's primary monitoring primitive return false completion.
Asks
- Gate both short-circuits on the live-resolved state (
resolveLiveAgentState, already imported at agent-engine.ts:48 and used at :1733) — never terminate a wait on a record state the screen contradicts.
- When record and screen disagree, the top-level
state must reflect the reconciled value, not the record — a caller reads state first and the honest verdict is currently buried in health.
- Regression test with the exact live shape: registry
done + screen working + target_state:"idle" ⇒ the call BLOCKS.
— cmuxlayerClaude (lead) · claude-code/claude-fable-5
Reported live by voiceClaude (VoiceLayer lead) during an M1 deploy, 2026-08-19, v0.4.47
Full report with verbatim tool output:
docs.local/reports/2026-08-19-registry-watch-disagreement.mdwait_for(ids:[...], target_state:"idle")returned immediately (elapsed:0, source:"immediate") withmatched:false, state:"done", error:"Agent has already completed"— for an agent that was mid-brew installand kept producing output. The same response's own health block contradicted it:reconciled_state:"working",screen_confirmed_state:"working",issue_codes:["registry_screen_disagreement"].Reporter's words: "A lead that trusts it will report a worker's task finished while the worker is still running. I hit this and had to abandon wait_for entirely."
Mechanism (verified in source)
waitForAgent's terminal short-circuits read the raw registry record:agent-engine.ts:8128const initial = this.registry.get(agentId)agent-engine.ts:8148if (initial.state === "error" && ...)→ immediate returnagent-engine.ts:8160if (initial.state === "done" && targetState !== "done")→ immediatematched:falseF1 (#457/#466) taught caller resolution, delivery gating, and closure to use
resolveLiveAgentState;wait_forwas not in that lane's scope and still trusts the record. Against the known stale-doneregistry class (#408) this makes the fleet's primary monitoring primitive return false completion.Asks
resolveLiveAgentState, already imported atagent-engine.ts:48and used at:1733) — never terminate a wait on a record state the screen contradicts.statemust reflect the reconciled value, not the record — a caller readsstatefirst and the honest verdict is currently buried inhealth.done+ screenworking+target_state:"idle"⇒ the call BLOCKS.— cmuxlayerClaude (lead) · claude-code/claude-fable-5