Skip to content

[bug] "Stop-stop." doesn't match the "stop stop" keyword — normalizeTranscript strips punctuation but not hyphens #334

Description

@serge-ivo

Supersedes the diagnosis in #331 for users who have configured a stop-word. The owner does have
"stop stop" configured, and reports it works sometimes — "seems like it works now, weird".

That intermittency is fully explained.

Cause: the stop-word normaliser does not strip hyphens

packages/sdk/src/voice/convo.ts:243:

function normalizeTranscript(text: string): string {
	return text
		.toLowerCase()
		.replace(/[.,!?¿¡]/g, "")   // ← no hyphen
		.replace(/\s+/g, " ")
		.trim();
}

stripStopWord compares the normalised transcript against the normalised stop-word. Measured:

Whisper output normalised matches "stop stop"
"Stop stop." stop stop yes
"Stop, stop." stop stop yes
"Stop-stop." stop-stop no

Whisper renders a repeated word as a hyphenated compound sometimes — it is a formatting choice,
not a transcription difference. So the same spoken phrase silently succeeds or fails depending on
punctuation the user cannot control or even see.

That is exactly the reported behaviour: it works, then it does not, then it works again.

Observed failing case, Coder Lead 2026-08-06 23:51:37 — transcript "Stop-stop." was sent as a
chat message instead of ending the turn, and the agent replied "Got it. Stopped." while the mic
stayed live. The silence that followed produced two phantom turns (#332).

The same file already has the answer

isNoiseTranscript in audio.ts:90 strips a much wider punctuation set, hyphens included:

.replace(/[.,!?"'·:;()-]|\[|\]/g, " ")

So there are two normalisers in the voice package with different ideas of what punctuation is, and
the stricter one is used for the noise filter while the looser one guards the commands. That is
backwards — the command path is where a near-miss is user-visible.

Fix

Normalise hyphens (and en/em dashes) to a space in normalizeTranscript, then collapse whitespace
— which the function already does, so "stop-stop" becomes "stop stop" and matches.

Better still: have both paths share one normaliser. Two functions that must agree about punctuation
and do not is the underlying defect; the hyphen is just the instance that surfaced.

This affects every command path, not only stop-words — matchVoiceCommand and
splitTrailingCommand both run on normalizeTranscript, so any hyphenated rendering of a
multi-word command ("mute-mute", "text-mode") fails the same way.

Verification

  • "Stop-stop.", "Stop stop." and "Stop, stop." all end the turn identically.
  • A hyphenated rendering of any configured multi-word command matches.
  • Ordinary hyphenated speech is unaffected: "well-known" does not become a command, because
    matching is still whole-utterance or trailing-phrase.
  • A unit test pinning the three renderings above, since the failing one depends on Whisper
    formatting and will not reproduce reliably by hand.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions