Skip to content

fix(tests): the suite typed on the real keyboard, and the second model is retired - #60

Merged
hannesreinsch merged 1 commit into
mainfrom
chore/burn-the-second-server
Sep 9, 2026
Merged

fix(tests): the suite typed on the real keyboard, and the second model is retired#60
hannesreinsch merged 1 commit into
mainfrom
chore/burn-the-second-server

Conversation

@hannesreinsch

@hannesreinsch hannesreinsch commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

The headline: the test suite typed into his screen, all day

"I keep getting this same random paste everywhere, even tho I'm not using murmurflow"

hello there my friend and also yougokigen you desu ne totemo ii tenki

It was not MurmurFlow. It was MurmurFlow's tests.

Two tests drive _stream_loop with a fixed Heard and monkeypatch dictate._inject, believing the clipboard was the way out to the machine. It is not the only one: dictate.place tries platforms.type_text first, and that is a real CGEventKeyboardSetUnicodeString with nothing in front of it. So every run of the suite typed both fixtures into whatever window had focus, back to back and with no space between them.

The giveaway was that it was byte-identical every time. A hallucination differs every time; a fixture does not.

tests/conftest.py shuts that one door for every test, autouse, and a test asserts it stays shut. Only that door: the clipboard and the recorder have tests that drive them on purpose, and stubbing those would replace the thing under test with the stub — a suite reporting green over a function it never ran is worse than the bug.

And silence is cut before anything transcribes it

Whisper invents words when handed audio with nothing in it. The same 12 seconds of speech, three ways:

clip what came back
speech alone ...but just in this text box,
+ 20s digital silence ...but just in this text box, **Thank you.**
+ 20s faint room noise ...but just in this text box..

A word list cannot catch that — this file already said so, whisper answers silence in a different invented language each time — and neither can whisper's own per-segment no_speech_prob: the invented " Thank you." came back at 0.000, sitting among real speech at -0.05. Both were built and both were measured useless before trim_trailing_quiet, which was measured to work.

This matters more now that a forgotten microphone closes itself after 15 seconds: that clip ends with 15 seconds of exactly the audio whisper invents into.

The bridges, burned

partial_model, PARTIAL_PREFERENCE, DEFAULT_PARTIAL_MODEL, partial_port, start_partial_server, partial_at, livePass, and the whole at/model parameter family — deleted. One model answers the live pass and writes the final, on one server, on one queue.

stop_server still sweeps the port above ours, because a version that no longer starts a small server must still reap the one an older one left.

The language pin went with it. whisper-server reports back whatever language it was told to decode, so pinning made the "is that one of yours" gate blind for the whole clip after its first second — and a partial is pasted.

And whole_clip_read is deleted, four hours after it shipped. It never fired: a big-model pass costs 1.5–2.4s, so several seconds of speech are always unread when the key comes up. Measured on his own log after the change: 4830ms, 8929ms, 5528ms — the shortcut refused every time. It also reused a pinned read as the final transcript, which is the guarantee the pin's own docstring promised never to break.

STREAM_TIMEOUT 10s → 30s: a pass on a two-minute clip costs more than ten.

Docs and website

Both carry the measured numbers now: one model, 1.5s a pass under 30s of speech and 2.4s past it, the punctuation trade with the livePass note removed, and the microphone that closes itself.

Gate

206 passed, ruff clean, mypy clean. 483 lines deleted, 412 added.

🤖 Generated with Claude Code

https://claude.ai/code/session_01P7oJz8M9QzsdJimoM318cj

Summary by CodeRabbit

  • New Features

    • Live and final transcription now use one warm large-v3-turbo model.
    • Trailing silence is trimmed before transcription to reduce unwanted text.
    • Microphone recordings close automatically after 15 seconds of silence.
    • Streaming passes detect language automatically.
  • Improvements

    • Updated performance information reflects current live-pass timing.
    • Setup now downloads and runs a single speech model.
    • Star-field visuals now feature slowly rotating 3D star marks instead of lighting and glow effects.
  • Documentation

    • Updated settings, model, server, privacy, and performance descriptions.

…l is retired

THE SUITE TYPED INTO HIS SCREEN, ALL DAY, AND THAT IS THE HEADLINE. Two tests
drive `_stream_loop` with a fixed `Heard` and monkeypatch `dictate._inject`,
believing the clipboard was the way out to the machine. It is not the only one:
`dictate.place` tries `platforms.type_text` FIRST, and that is a real
`CGEventKeyboardSetUnicodeString` with nothing in front of it. So every run of
the suite typed both fixtures into whatever window had focus, back to back:

    hello there my friend and also yougokigen you desu ne totemo ii tenki

Reported as "I keep getting this same random paste everywhere, even tho I'm not
using murmurflow", which is exactly right — it was not MurmurFlow, it was
MurmurFlow's tests. The giveaway was that it was byte-identical every time: a
hallucination differs every time, a fixture does not. `tests/conftest.py` shuts
that ONE door for every test, autouse, and a test asserts it stays shut. Only
that door: the clipboard and the recorder have tests that drive them on
purpose, and stubbing those would replace the thing under test with the stub.

AND SILENCE IS CUT BEFORE ANYTHING TRANSCRIBES IT. Whisper invents words when
handed audio with nothing in it — the same 12s of speech, three ways:

    speech alone               "...but just in this text box,"
    + 20s digital silence      "...but just in this text box, Thank you."
    + 20s faint room noise     "...but just in this text box.."

A word list cannot catch that (this file already said so) and neither can
whisper's own per-segment `no_speech_prob`: the invented " Thank you." came
back at 0.000 among real speech at -0.05. Both were built and both were
measured useless before `trim_trailing_quiet`, which was measured to work.

THE SECOND MODEL AND ITS SERVER ARE GONE. `partial_model`, `PARTIAL_PREFERENCE`,
`DEFAULT_PARTIAL_MODEL`, `partial_port`, `start_partial_server`, `partial_at`,
`livePass` and the whole `at`/`model` parameter family are deleted; one model
answers the live pass and writes the final, on one server, on one queue.
`stop_server` still sweeps the port above ours, because a version that no
longer starts a small server must still reap the one an older one left.

THE LANGUAGE PIN IS GONE with it: whisper-server reports back whatever language
it was TOLD to decode, so pinning made the "is that one of yours" gate blind
for the whole clip after its first second — and a partial is pasted.

AND `whole_clip_read` IS DELETED, four hours after it shipped. It never fired:
a big-model pass costs 1.5-2.4s, so several seconds of speech are always unread
when the key comes up, and the shortcut refused every time (measured on his own
log: 4830ms, 8929ms, 5528ms, all after the change). It also reused a PINNED
read as the final transcript, which is the guarantee the pin's own docstring
promised never to break.

STREAM_TIMEOUT 10s -> 30s: a pass on a two-minute clip costs more than ten.

README and the website carry the measured numbers now: one model, 1.5s a pass
under 30s of speech and 2.4s past it, and the microphone that closes itself.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P7oJz8M9QzsdJimoM318cj
@coderabbitai

coderabbitai Bot commented Sep 9, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: efa88450-9a15-4b0e-a6b6-211d74f35741

📥 Commits

Reviewing files that changed from the base of the PR and between 8ff06c4 and 1f38a91.

📒 Files selected for processing (8)
  • README.md
  • docs/field.js
  • docs/index.html
  • murmurflow/cli.py
  • murmurflow/dictate.py
  • murmurflow/whisper.py
  • tests/conftest.py
  • tests/test_murmurflow.py

📝 Walkthrough

Walkthrough

Changes

Single-model transcription

Layer / File(s) Summary
Single-model setup and server lifecycle
murmurflow/cli.py, murmurflow/dictate.py, murmurflow/whisper.py
Setup, health checks, server routing, startup, shutdown, and recovery now use one configured model and server.
Shared live-pass transcription
murmurflow/dictate.py
Live passes use the warm server, independent language detection, and no partial-server fallback.
Trimmed final transcription
murmurflow/dictate.py
Trailing quiet audio is trimmed before transcription. Finalization always performs a final transcription.
Behavior tests and safe test input
tests/conftest.py, tests/test_murmurflow.py
Tests cover the single-model flow, silence trimming, server cleanup, language handling, and keyboard-input isolation.
Transcription behavior documentation
README.md, docs/index.html
Documentation describes the one-model flow, live-pass timing, silence handling, language detection, and automatic microphone closing.

3D star-field rendering

Layer / File(s) Summary
3D star turns and lighting removal
docs/field.js
Stars use seeded 3D turning and projected tips. Body lighting, halo glow, and body state are removed.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RecordingLoop
  participant trim_trailing_quiet
  participant WarmServer
  participant Finalizer
  RecordingLoop->>trim_trailing_quiet: trim trailing quiet audio
  RecordingLoop->>WarmServer: request language-gated live pass
  Finalizer->>trim_trailing_quiet: trim recorded audio
  Finalizer->>WarmServer: request final transcription
  WarmServer-->>Finalizer: return final transcript
Loading
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch chore/burn-the-second-server

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@hannesreinsch
hannesreinsch merged commit 3974f41 into main Sep 9, 2026
1 of 2 checks passed
@hannesreinsch
hannesreinsch deleted the chore/burn-the-second-server branch September 9, 2026 14:24
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