The stale-stream detector only bounds the gap BETWEEN chunks and resets on
every chunk, so a drip-fed stream — a gateway trickling keep-alive-shaped
chunks, or a model crawling through one runaway generation for hours —
defeats it indefinitely: the turn never completes and the session sits
silent until an outer timeout (if any) kills it.
Adds a total wall-clock lifetime cap for one streaming response attempt:
- agent.stream_max_lifetime (config.yaml) / HERMES_STREAM_MAX_LIFETIME,
default 1800s, 0 disables. Never fires before the effective stale-stream
timeout, so it cannot preempt reasoning-model patience floors.
- Main OpenAI/Anthropic poll loop: tripping the cap kills the connection
exactly like a stale kill (attempt cancelled, request client closed),
counts in the #58962 cross-turn stale-streak breaker, and lets the
bounded retry loop / partial-stub continuation recover.
- Bedrock poll loop (sibling site): same cap wired into the existing event
watchdog, surfacing a distinct TimeoutError.
Tests: drip-fed stream (events flowing every 50ms so the stale detector can
never fire) is killed at the cap and bumps the streak — verified to hang
without the fix (sabotage run timed out); 0-disable; config/env resolution
precedence. Docs: configuration.md timeout table + env var reference.