Hotato tells you when not to trust a score.
A bad export must never become a confident-looking but hollow verdict. Before Hotato scores a recording, hotato trust inspects the audio and decides whether a score would mean anything. This is the exact contract: input condition on the left, Hotato's behavior on the right.
Every input condition maps to a defined behavior.
Warnings do not make a recording unscorable; three hard defects do. The exit code is the machine contract: 0 safe to scan, 2 not scorable, with the reason and the next step.
| Input condition | Behavior | Exit | Downstream |
|---|---|---|---|
| Clean dual-channel (stereo) | safe to scan | 0 | Full score. scan, run, compare, verify all run normally. |
| Silent caller channel | not scorable | 2 | Refused. No caller to measure a yield against. |
| Silent agent channel | not scorable | 2 | Refused. No agent floor to interrupt. |
| Swapped channels | warn + confirm | 0 | Scores, but confirm the mapping first. A swap silently inverts every yield and hold. |
| Crosstalk / echo bleed | warn, lower confidence | 0 | Scores. scan tags the moment echo_correlated_activity; a yield there may be the agent hearing itself. |
| Mono (single channel) | refuse | 2 | Refused by default. Export dual-channel, or take one of the two opt-in escapes. |
Mono, opt-in --allow-mono | indicative only | 0 | Degraded mode on capture / pull / sweep for a mono-only stack. Talk-over cannot be attributed, so no SLA gate fires. Never equivalent to dual-channel. |
Mono, opt-in --diarize | indicative only | 0/2 | The separation front-end. Tier high / low / refuse; at low the verdict is stamped indicative_only. Never equivalent to dual-channel. |
| Backchannel overlap | candidate only | 0 | scan lists it; you label yield or hold. Hotato never decides the intent behind a caller sound. |
| Noisy / false-positive candidate | candidate + warn | 0 | Surfaced with the warning. A candidate you inspect and label, not a bug Hotato asserts. |
score
Clean stereo. Full confidence, no caveat.
caveat
Swap, crosstalk, echo-driven candidates. Proceed, each with a specific warning you must act on.
refuse
Silent caller, silent agent, mono. Not scorable. Hotato names the reason and exits 2.
Eight recordings, eight verdicts.
Every terminal block below is verbatim output from hotato 0.5.0, offline. The clean case is a bundled example; the defect cases are that same recording with a channel silenced, reversed, or downmixed, so you can reproduce every verdict.
Safe stereo: the good case
$ hotato trust --stereo 01-hard-interruption.example.wav hotato trust: 01-hard-interruption.example.wav recording: 6.0s, 16000 Hz, 2 channels caller (ch0): 2.46s speech, first at 2.39s, peak -4.4 dBFS agent (ch1): 2.71s speech, first at 0.19s, peak -4.4 dBFS crosstalk: coherence 0.306 (low) at 0.5s lag scorability: separated tracks yes, caller activity yes, agent activity yes => safe to scan
Clean two-channel export, caller on ch0, agent on ch1. Verdict: safe to scan, exit 0. The only condition where a full turn-taking verdict is trustworthy without a caveat.
Silent caller: nothing to measure against
$ hotato trust --stereo silent-caller.wav caller (ch0): 0.00s speech, -, peak -120.0 dBFS agent (ch1): 2.71s speech, first at 0.19s, peak -4.4 dBFS scorability: separated tracks yes, caller activity no, agent activity yes => NOT SCORABLE: caller channel has no detected speech next step: verify channel mapping or export dual-channel again
The caller channel carries no speech. Verdict: not scorable, exit 2. A yield is a response to a caller; with no caller there is nothing to be late to.
Silent agent: no floor to interrupt
$ hotato trust --stereo silent-agent.wav caller (ch0): 2.46s speech, first at 2.39s, peak -4.4 dBFS agent (ch1): 0.00s speech, -, peak -120.0 dBFS possible channel swap: channel 0 (caller) holds the floor 2.46s vs 0.0s on channel 1 (agent) scorability: separated tracks yes, caller activity yes, agent activity no => NOT SCORABLE: agent channel has no detected speech
The agent channel is empty. Verdict: not scorable, exit 2. Hotato also flags a possible channel swap, because a caller-only recording looks like a mis-mapped agent. Two checks, one fix: re-check the export.
Swapped channels: still scorable, confirm first
$ hotato trust --stereo swapped-warn.wav caller (ch0): 2.71s speech, first at 0.19s, peak -4.4 dBFS agent (ch1): 1.05s speech, first at 0.00s, peak -5.2 dBFS possible channel swap: channel 0 (caller) holds the floor 2.71s vs 1.05s on channel 1 (agent); an agent usually holds the floor longer, so the channels may be reversed scorability: separated tracks yes, caller activity yes, agent activity yes => safe to scan
Both channels carry speech, but the long floor-holder sits on the caller channel. Verdict: safe to scan, exit 0, with a swap warning. The most dangerous condition, because scoring proceeds and a swap silently inverts every yield into a hold. Confirm the mapping first.
Crosstalk / echo bleed: score at lower confidence
$ hotato trust --stereo 07-echo-bleed.example.wav caller (ch0): 5.69s speech, first at 0.31s, peak -13.5 dBFS agent (ch1): 5.81s speech, first at 0.19s, peak -4.4 dBFS crosstalk: coherence 1.0 (HIGH) at 0.12s lag scorability: separated tracks yes, caller activity yes, agent activity yes => safe to scan
The caller channel carries a delayed copy of the agent audio. Coherence pegs at 1.0. Verdict: safe to scan, exit 0, with a HIGH crosstalk warning. Scoring proceeds, but the "caller" activity may be leaked TTS, so every candidate here is lower confidence.
Mono: refused by default, tiered under --diarize
$ hotato trust --stereo mono-mixed.wav recording: 6.0s, 16000 Hz, 1 channel scorability: separated tracks no, caller activity no, agent activity no => NOT SCORABLE: single channel, so the caller and agent cannot be told apart next step: export a dual-channel recording, caller on one channel, agent on the other
A single channel. Caller and agent are mixed into one track. Verdict: not scorable, exit 2. The gold-standard refusal. Two opt-in escapes, both indicative only: --allow-mono accepts a mono-only stack in degraded mode (talk-over unattributable, no SLA gate), and the --diarize separation front-end scores hotato run --mono call.wav --diarize, stamping indicative_only at the low tier. Neither equals dual-channel.
Backchannel candidate: surfaced, never labelled
$ hotato scan --stereo 02-backchannel-mhm.example.wav --top 5 hotato scan: 02-backchannel-mhm.example.wav (6.0s, 3 candidate moments) Candidates are timing events. You decide the expected behavior. [ 1] t=2.09s overlap_while_agent_talking overlap=1.58s agent did not go silent within 3.0s [ 2] t=3.19s overlap_while_agent_talking overlap=1.07s agent did not go silent within 3.0s [ 3] t=4.29s overlap_while_agent_talking overlap=0.56s agent did not go silent within 3.0s
A scan of a call where the caller says "mhm" over the agent. Three candidates, exit 0. Whether "agent did not go silent" is correct (held through a backchannel, good) or a bug (talked over a real interruption) is your call. scan reports timing; you label hold or yield.
Noisy false positive: a candidate that is really the agent
$ hotato scan --stereo 07-echo-bleed.example.wav --top 5 hotato scan: 07-echo-bleed.example.wav (6.0s, 2 candidate moments) [ 1] t=0.31s overlap_while_agent_talking overlap=3.00s agent did not go silent within 3.0s [ 2] t=0.31s echo_correlated_activity WARNING likely agent echo: coherence=1.00 (caller channel looks like leaked TTS; a yield here may be the agent hearing itself)
A scan of the echo-bleed call. Two candidates, exit 0. Candidate 1 looks like a bad talk-over. Candidate 2 is Hotato telling you the overlap is probably the agent hearing its own audio, not a real interruption. The honest failure mode of a wide net: it labels why a candidate is likely spurious instead of hiding it.