wait_notice_text and WaitNoticeState.should_emit now both derive near-deadline
from the watchdog tuple, so the two call sites stop recomputing it and passing
it as a kwarg. Two docstrings still described the removed copy as the 60s notice.
Both wait-status builders — the Codex Responses request poller
(chat_completion_nonstream) and the chat-completions stream monitor — rewrote
the status line on every 30s heartbeat once a request had been silent for 60s,
always with "provider may be slow or overloaded" and an unlabeled
"auto-reconnect at Ns". Successful long calls (p95 ~53s on large contexts)
therefore looked unhealthy, and a genuine zero-event stall produced the same
text, so the two states were indistinguishable.
The 30s heartbeat stays (it is gateway liveness) but the visible notice now
comes from one shared, presentation-only module (chat_completion_wait_notice):
- emitted once when the silence crosses the threshold, then only when the wait
phase changes or the applicable watchdog is within 15s of firing;
- neutral phase wording: "waiting for the first provider event" (also
"...after reconnect") vs "provider stream active; Ns without stream events";
stream path: "waiting for the first stream chunk" vs "stream open; Ns
without stream output";
- the reconnect hint names the watchdog (TTFB / stream idle / wall-clock stale
/ stream stale) and the seconds left before it fires, which is unambiguous
across the elapsed-vs-silence timelines the old "at Ns total elapsed" mixed.
No watchdog thresholds or retry behaviour change. The old
_codex_wait_notice_recovery helper (deadline as a bare string) is replaced by
codex_watchdog_deadline (label + seconds remaining). Design ported from the
candidate fix in #92657 (phase-keyed dedupe, labeled deadlines, imminent
window), which targeted a pre-refactor call site that no longer exists.
Fixes#92550
Co-authored-by: chelsealong <chelsealong@126.com>