869580c913
"напомни в 11:00 позвонить маме" answered "Когда?" about an hour he had just said. ReminderGrammar builds its slots by hand and the router ran no extraction over a stage-0 decision, so HasTime was false however plainly the hour was spoken; missingFor read the silence as absence. The fix runs the stage-2 extractor over every stage-0 decision, filling only the slots the grammar left empty. A matched value always wins: the rule read a literal pattern, the extractor guesses. This is the same hole the LLM path already had, so fillSlots and the new stage-0 call share one fillMatchedSlots. Enabled for all ten grammars rather than a chosen few, because for every intent but reminder it is inert. Extract fills Time for a reminder, Fn for an act and Key for a fact, and nothing at all for query, system, note or chat — which is what the clock, agenda, feed, list, task, Praxis-adjacent and narrative rules emit. The two act rules, wakeword-act and the Praxis ones, already carry an Fn or they do not match, so the matcher has nothing left to fill. Measured rather than asserted: benchmarked at 20000x, a stage-0 query is 3.7µs against 3.9µs before and a clock or act rule is 0.7µs either way, both inside the noise. The reminder rule is the one that gains, and its date parse is not new spend — actionReminder was already running exactly that parse one layer down, and now skips it. Slots.Text is deliberately not filled. Extract sets it to the raw utterance, and a grammar that left it empty meant it: agendaQueryBuild hands the query chain the sentence itself, and narrativeQueryBuild's Text is the topic. Fixture unchanged at 64/91 (70.3%) on TestONNXBaseline, no case regressed, no new false clarify. What moved is the line the fixture calls "slots deferred to daemon": 6 to 0. Verified on homesrv: "напомни в 11:00 позвонить маме" now answers "хорошо, напомню сегодня в 11:00."