Skip to content

Fix flaky voice spec: take the silence meter's first reading synchronously - #194

Merged
HamptonMakes merged 1 commit into
mainfrom
hampton/awesome-rubin-2706b1
Aug 23, 2026
Merged

Fix flaky voice spec: take the silence meter's first reading synchronously#194
HamptonMakes merged 1 commit into
mainfrom
hampton/awesome-rubin-2706b1

Conversation

@HamptonMakes

Copy link
Copy Markdown
Collaborator

What

One change in voice_controller.js: the silence meter takes its first reading synchronously when metering is set up, instead of waiting for the first requestAnimationFrame callback.

Why

The system spec "recording for the server to transcribe doesn't send a recording it heard nothing in" was flaky in CI (example failure: CoPlan::Ai.transcribe called 1 time, expected 0).

The spec clicks start/stop back-to-back. The meter's meterLive latch was only set inside a rAF callback, so on a loaded CI box where no frame rendered between the two clicks, the take ended with a meter that "never ran". The controller deliberately treats that as "when in doubt, send it" (the suspended-AudioContext safeguard), so the silent recording went to the transcriber anyway. Any slow frame reproduced it — the failing commit's diff was unrelated.

Sampling once at setup removes frame timing from the verdict entirely. In production the only behavioral change is that a take shorter than one frame is now judged by a real (silent) reading rather than sent on the benefit of the doubt — a sub-frame take contains no speech, so "didn't hear anything" is the right answer for it. The suspended-context path is untouched: a context that never ran still gets no vote, and the take is still sent (its own regression spec confirms).

How this was verified

  • Reproduced the flake deterministically first: with requestAnimationFrame stubbed to never fire in the spec's recorder stub, the old code fails with the exact CI message (raised from dictations_controller.rb:109); the fixed code passes under the same condition.
  • With the temporary rAF stub removed: full voice_commenting_spec.rb (20 examples) and voice_hotkey_setting_spec.rb (3 examples) green on an isolated Postgres DB mirroring the test-postgres job's db:migrate path; the formerly flaky example green 5 consecutive runs.

🤖 Generated with Claude Code

The "doesn't send a recording it heard nothing in" system spec was flaky
in CI: the meter's first reading happened inside a requestAnimationFrame
callback, so a take that ended before the browser painted a frame was
judged by a meter that "never ran" — and the when-in-doubt fallback sent
the silent recording to the transcriber, tripping the spec's
expectation that Ai.transcribe is never called.

Sampling once at setup makes the verdict independent of frame timing:
reproduced deterministically by stubbing rAF to never fire (old code
fails exactly like CI, fixed code passes). The suspended-AudioContext
path is unchanged — a suspended context still gets no vote and the take
is still sent.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@HamptonMakes
HamptonMakes merged commit 2737c75 into main Aug 23, 2026
4 checks passed
@HamptonMakes
HamptonMakes deleted the hampton/awesome-rubin-2706b1 branch August 23, 2026 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant