Skip to content

Fix silent wake: never suppress the first utterance after wake - #12

Draft
jayzuccarelli wants to merge 2 commits into
mainfrom
turn1-always-addressed
Draft

Fix silent wake: never suppress the first utterance after wake#12
jayzuccarelli wants to merge 2 commits into
mainfrom
turn1-always-addressed

Conversation

@jayzuccarelli

@jayzuccarelli jayzuccarelli commented Aug 9, 2026

Copy link
Copy Markdown
Owner

Problem

Sometimes Mycroft wakes, hears the question, and answers with nothing: the model classifies the user's first post-wake utterance as background speech and calls wait_for_user, which intentionally suppresses the response. The session then strands silent until broker hygiene closes it (~16s of spinning LED). Live incident: 2026-07-27 01:22 UTC, the only wait_for_user call in 72h of logs, fired on a real question.

The wake word is proof the first speech is addressed: nobody says "hey Mycroft" for the TV.

Fix (broker only)

  • agent.py: BACKGROUND_GUIDANCE now states the first speech after a session starts is always addressed; never wait_for_user it.
  • server.py: enforcement guard: if the model still calls wait_for_user on the first committed turn (_TurnHygiene.is_first_turn(), counter resets per device connect), the broker answers instead of suppressing, with a warning log. Needed: with the instruction alone the model still misfired 4/5.
  • harness.py: new first_turn_addressed scenario, deliberately the same TV line as tv_line_after_answer: the pair encodes the tradeoff (answer on turn 1, ignore on turn 2).

Bench (5 reps each, fresh sessions, isolated brokers on 8766/8767, real OpenAI + live HA MCP)

scenario main fix
first_turn_addressed 0/5 5/5
background_rejection 5/5 5/5
tv_line_after_answer 4/5 4/5

No regression; the single tv_line failure is symmetric and pre-known flaky, and the override fired 0 times during both counter-metric soaks (correctly scoped to turn 1). Overridden turn-1 answers cost ~880ms p50 first-audio (extra tool round trip) vs 0-420ms direct. Turn-2 rejection with an override in context: 4/4 silent. make check GREEN 2/2.

Known tradeoff (accepted)

On a TV false wake (~0.567/h at current sensitivity), the first TV line now gets answered aloud instead of ignored silently. Previously those sessions died silent after 16s. New exposure this creates: command-like TV speech on a false wake ("turn it up") can now drive real HA tool calls — the bench observed spurious attempts (pause show, find TV, volume) on overridden TV-line answers; all failed, no state changed, but the surface exists. Bounded by turn hygiene in production.

Not fixed here

VAD misses of the first utterance (root cause 2 of the silent-wake report) and the firmware no-answer timeout. Separate levers.

Deploy is gated separately; live container untouched.

🤖 Generated with Claude Code

The model sometimes classified the user's first post-wake utterance as
background and called wait_for_user, stranding the session silent until
hygiene timeout (live incident 2026-07-27 01:22 UTC). The wake word is
proof that first speech is addressed.

- instructions: turn 1 is always addressed, never wait_for_user it
- server: if wait_for_user still fires on the first committed turn,
  answer instead of suppressing (instruction alone fixed only 1/5)
- harness: new first_turn_addressed scenario, turn-1 twin of
  tv_line_after_answer (same TV line: answer on turn 1, ignore on turn 2)

Bench (5 reps, fresh sessions): first_turn_addressed 0/5 on main -> 5/5
with fix; background_rejection 5/5 both; tv_line_after_answer 4/5 both
(pre-known flake, no override fired). make check GREEN 2/2.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: fdf2f4a6-9de4-40e7-9960-4ff91ea54561

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

# Conflicts:
#	broker/realtime_broker/agent.py
@jayzuccarelli

Copy link
Copy Markdown
Owner Author

Deployed to the live container 2026-08-12 as image voicepe-realtime:turn1-2026-08-12 (branch merged with current origin/main first — the branch was cut from a pre-barge-in main; merge commit f53bb69). Pre-deploy verification: make check 2/2 GREEN + first_turn_addressed 2/2 PASS against an isolated broker running the merged build. Instant rollback: stopped container voicepe-pre-turn1 (image wake-2026-08-01).

@jayzuccarelli
jayzuccarelli force-pushed the turn1-always-addressed branch from f53bb69 to e0b8b80 Compare August 14, 2026 21:15
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