Skip to content

[bug] quick-router: "turn the oven on" is answered with a status read — the oven never actuates #877

Description

@kai392

home_status_target's oven branch has no question-shape gate:

if (text.contains("oven on") || text.contains("leave the oven"))
    && !text.contains("self cleaning")
    && !text.contains("self clean")
{
    return Some("oven".into());
}

It runs ahead of the looks_like_status_query gate, so any utterance
containing the phrase "oven on" resolves to a status read — including a
command to turn the oven on. The router returns a home_status tool call, the
turn never reaches the LLM, and the oven does not actuate. The user gets a
status report in response to an actuation request.

Reproduced on main @ 9e54db4 through tools::quick::route():

"Turn the oven on"                     -> home_status {"entity":"oven"}
"Switch the oven on"                   -> home_status {"entity":"oven"}
"Please turn the oven on"              -> home_status {"entity":"oven"}
"Can you turn the oven on?"            -> home_status {"entity":"oven"}
"Remind me to turn the oven on at six" -> home_status {"entity":"oven"}
"Don't leave the oven on"              -> home_status {"entity":"oven"}

What makes this specific to the oven is that every other appliance already
abstains on the same word order and lets the LLM ground the write:

"Turn the lights on"                   -> (abstain)
"Turn the fan on"                       -> (abstain)
"Turn the kettle on"                    -> (abstain)

So the oven is the one device where a trailing-particle command silently fails
instead of falling through.

The same predicate also matches "oven" inside pr[oven] / w[oven], which the
cooktop branch further down was already fixed for (#792):

"Is that theory proven on the test bench?" -> home_status {"entity":"oven"}
"Is the basket woven on a loom?"           -> home_status {"entity":"oven"}

Expected: all of the above abstain. The genuine status questions must keep
resolving, including the "did …" form that the gate prefixes do not cover and
that the existing corpus already pins:

"Is the oven on?"                  -> home_status {"entity":"oven"}
"Did I leave the oven on?"         -> home_status {"entity":"oven"}
"Is the self-cleaning oven on?"    -> home_status {"entity":"self-cleaning oven"}
"Set the oven to 400 degrees"      -> home_control {set_temperature, 400}

Fix is the shape the iron block above already uses — looks_like_status_query()
plus the "did " prefix — combined with a whole-word match on oven.

Related but distinct: #861 / #862 cover the bare-appliance noun branches
(water pressure, sump pump, sous vide, baby monitor). This is the "oven on"
phrase branch, which that change does not touch.

Environment: no Jetson available; reproduced by compiling
crates/genie-core/src/tools/{quick,home_action,calc_input,number_words}.rs
unmodified into a standalone harness and calling route() directly, since
genie-core as a whole is Linux-only.

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