temperature=0 removed Whisper's repetition/truncation mitigation — clauses the user spoke are missing from the transcript
The owner reports voice sometimes not transcribing. Two recorded messages show a different failure from a dropped clip: the clip transcribed, and a whole trailing clause he spoke inside the recorded window is absent.
The evidence
dictation is persisted only when the live capture and the final transcript diverge (packages/sdk/src/voice/machine.ts:599-604), and heard is stamped at end-of-turn (machine.ts:410) — so anything in heard was spoken inside the clip. Two messages on Chess coder 2 (bd43f4de-ef35-4051-bdec-43f8571414a1), 2026-08-11:
| UTC |
sent |
heard (live capture) |
| 23:04:28 |
…and file issues that come out of it. |
…file issues that come out of it **don't wait for the night rebuild we have to run** |
| 23:00:49 |
…Headless, headless browser, but they should run. |
…**also run Browser** but they should run **are they running an HP** |
And a repetition loop that was sent as a real user turn at 21:44:05: "apps chess academy, chess academy, chess academy, …" ×6. A second, longer loop was caught and ignored at 01:33:37 ("chess-academy" ×14, client:voice "result ignored").
Mechanism — INFERRED, and the experiment that settles it
1449ee1 (#490) added form.append("temperature", "0") to all requests, including the streaming default model — packages/sdk/src/voice/stt.ts:401.
OpenAI's reference Whisper decoder uses a temperature fallback ladder (0 → 0.2 → 0.4 → … → 1.0), triggered on compression-ratio and average-logprob thresholds, and it exists specifically because pure greedy decoding produces repetition loops and premature truncation. Pinning temperature to 0 with no fallback removes that mitigation.
I cannot claim it introduced the repetitions. A drifting (not looping) repetition appears pre-#490 at Aug 10 02:11:24. What is established is that the documented mitigation is now gone, and pure loops appear after.
Settled by: unset temperature for a day and count repetition/truncation rows against the same window. That is a one-line change and a query, not a design argument.
Why it matters beyond tidiness
A dropped clip is visible — the user says it again. A silently truncated clip is not: the agent receives a grammatical, plausible instruction that is missing its operative clause. In the 23:04:28 case the lost words were "don't wait for the night rebuild we have to run" — an instruction with real consequences, spoken and never delivered.
Acceptance criteria
- Decide, with reasons written down, whether
temperature=0 should apply to the streaming model at all — it was added for the phantom-turn problem, which no_speech_prob was also meant to address (and does not, on this model — see the gate-calibration issue).
- If greedy decoding is kept, add the repetition/compression-ratio check the ladder provided, or detect a repetition loop client-side before it is sent as a user turn (one was, at 21:44:05).
- Where the live capture and the final transcript diverge by more than a threshold, that divergence is surfaced rather than silently resolved in favour of the transcript — the data is already persisted (
machine.ts:599-604).
- A test with a known repetition-loop transcript asserting it is not sent as a user turn.
temperature=0removed Whisper's repetition/truncation mitigation — clauses the user spoke are missing from the transcriptThe owner reports voice sometimes not transcribing. Two recorded messages show a different failure from a dropped clip: the clip transcribed, and a whole trailing clause he spoke inside the recorded window is absent.
The evidence
dictationis persisted only when the live capture and the final transcript diverge (packages/sdk/src/voice/machine.ts:599-604), andheardis stamped at end-of-turn (machine.ts:410) — so anything inheardwas spoken inside the clip. Two messages on Chess coder 2 (bd43f4de-ef35-4051-bdec-43f8571414a1), 2026-08-11:…and file issues that come out of it.…file issues that come out of it **don't wait for the night rebuild we have to run**…Headless, headless browser, but they should run.…**also run Browser** but they should run **are they running an HP**And a repetition loop that was sent as a real user turn at 21:44:05:
"apps chess academy, chess academy, chess academy, …"×6. A second, longer loop was caught and ignored at 01:33:37 ("chess-academy"×14,client:voice"result ignored").Mechanism — INFERRED, and the experiment that settles it
1449ee1(#490) addedform.append("temperature", "0")to all requests, including the streaming default model —packages/sdk/src/voice/stt.ts:401.OpenAI's reference Whisper decoder uses a temperature fallback ladder (0 → 0.2 → 0.4 → … → 1.0), triggered on compression-ratio and average-logprob thresholds, and it exists specifically because pure greedy decoding produces repetition loops and premature truncation. Pinning temperature to 0 with no fallback removes that mitigation.
I cannot claim it introduced the repetitions. A drifting (not looping) repetition appears pre-#490 at Aug 10 02:11:24. What is established is that the documented mitigation is now gone, and pure loops appear after.
Settled by: unset
temperaturefor a day and count repetition/truncation rows against the same window. That is a one-line change and a query, not a design argument.Why it matters beyond tidiness
A dropped clip is visible — the user says it again. A silently truncated clip is not: the agent receives a grammatical, plausible instruction that is missing its operative clause. In the 23:04:28 case the lost words were "don't wait for the night rebuild we have to run" — an instruction with real consequences, spoken and never delivered.
Acceptance criteria
temperature=0should apply to the streaming model at all — it was added for the phantom-turn problem, whichno_speech_probwas also meant to address (and does not, on this model — see the gate-calibration issue).machine.ts:599-604).