Wait for Live output before starting interviews
Live setup can complete without model output. Use the normal opening generation as one bounded readiness attempt, preserve its events for delivery, and start the interview clock only after the first model output. Startup failures do not retry.
Carry outcomes on the existing interviewer_state message and degraded-start banner. Name provider-specific errors only when the provider identifies them.
Validation
./scripts/test.shpassed after rebasing onto546f559, with Chromium, commentflow, and actionlint enabled. Startup tests cover setup without output, timeout, a single generation attempt, event preservation, and timer ordering.- The offline Rust-server interview check passed with the existing
web/audio/test-voice.wavcapture fixture. - The contributor ran release build and tests successfully at
df170a8; the release binary reports that revision.
Browser tests used a temporary Liberation Sans alias; the default-font lobby failure also reproduces on base a3f3e80. Live provider integration was not run.
Closes #159
Summary by cubic
Live setup can finish without model output, so the interview clock can run against a silent provider. This change starts the interview timer and hard deadline only after the first model output—nonempty audio, model text, output transcription, or a tool call—using the opening greeting as a single bounded readiness attempt that never retries. A failed check ends the interview; offline practice that continues stays untimed.
Failure reporting
- Readiness outcomes publish on the existing
interviewer_statecontrol topic withstartup: "ready"orstartup: "failed"plus a classified reason (quota,billing,credentials,refused, orunavailable), shown in the degraded-start banner. - An exhausted key rotation or a cooldown that cannot fit the first-open budget keeps its quota or billing cause instead of degrading into a generic transport timeout.
- The page sends a bounded
startup_receivedreceipt for failed readiness, hashed and published under the same bound as report receipts, and keeps the diagnosis through room teardown.
Socket and client behavior
- Socket setup keeps its bounded key-failover and restart budget; only readiness generation is a single attempt.
- Keepalives keep a responsive socket alive while waiting, and a GoAway advisory sent before output replays with its original timestamp and no further generation.
- Queued opening events are preserved in order for the normal room loop, and the reply-wait clock starts at readiness so replay cannot expire an already answered greeting.
- Observed usage is accounted once even when readiness publication fails.
- Editable work before the clock starts and after a failed opening warns on unload until its report persists; early interviewer departure, recording delays, and premature report requests are handled without blocking cleanup or losing context.