You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[bug] "Stop-stop." doesn't match the "stop stop" keyword — normalizeTranscript strips punctuation but not hyphens #334
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:
functionnormalizeTranscript(text: string): string{returntext.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:
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.
There is now ONE normaliser for spoken text (packages/sdk/src/voice/normalize.ts), shared by the command matcher, the stop-word splitter and the noise filter — the two-normalisers-that-must-agree defect the ticket identifies, not just the hyphen.
It works in Unicode categories rather than a longer ASCII class: \p{P} → space (a hyphen JOINS two words spoken separately, so spacing is what makes the three renderings one utterance), apostrophes and \p{Cf} deleted (they join letters, or are invisible), NFC first. That covers en/em dashes, the non-breaking hyphen, the soft hyphen and CJK/inverted punctuation in one rule.
One follow-on defect found while fixing it: stripStopWord dropped the last N whitespace tokens for an N-word stop-word. Once hyphens space out, "run the tests, stop-stop" is four tokens and six words, so that arithmetic ate "tests,". It now cuts at a real whitespace boundary.
Pinned by test: "Stop-stop.", "Stop stop.", "Stop, stop.", "stop—stop" and "STOP-STOP!" all end the turn identically.
Activity
fix(sdk): one normaliser for spoken text, so "Stop-stop." stops (#334, …
serge-ivo commentedon Aug 7, 2026
Fixed in 3d7e28b.
There is now ONE normaliser for spoken text (
packages/sdk/src/voice/normalize.ts), shared by the command matcher, the stop-word splitter and the noise filter — the two-normalisers-that-must-agree defect the ticket identifies, not just the hyphen.It works in Unicode categories rather than a longer ASCII class:
\p{P}→ space (a hyphen JOINS two words spoken separately, so spacing is what makes the three renderings one utterance), apostrophes and\p{Cf}deleted (they join letters, or are invisible), NFC first. That covers en/em dashes, the non-breaking hyphen, the soft hyphen and CJK/inverted punctuation in one rule.One follow-on defect found while fixing it:
stripStopWorddropped the last N whitespace tokens for an N-word stop-word. Once hyphens space out,"run the tests, stop-stop"is four tokens and six words, so that arithmetic ate"tests,". It now cuts at a real whitespace boundary.Pinned by test:
"Stop-stop.","Stop stop.","Stop, stop.","stop—stop"and"STOP-STOP!"all end the turn identically.fix(supervision): the resolver normalises a spoken agent name with th…