%% View 3a — Runtime flow: a reminder request. %% Traced through cmd/mavend/voice.go runTurn, internal/router/stagezero.go, %% cmd/mavend/clarify.go, cmd/mavend/actions_reminder.go, cmd/mavend/tick.go, %% internal/loop/loop.go and internal/delivery/dispatcher.go. %% Shows the branch where the hour is missing, the parked clarify, the answer %% turn, the write and the eventual delivery with durable retry. sequenceDiagram autonumber participant K as Owner participant W as mavwaked participant V as voice.Server participant H as reactiveHandler.runTurn participant PRE as pre-route ladder participant R as router cascade participant CL as clarifyStore participant AR as actionReminder participant DB as store participant T as tick loop participant D as dispatcher Note over K,W: "Мэйвен, напомни позвонить маме" K->>W: speech W->>W: silero VAD + keyword head, score ≥ 0.999 W->>V: PushToTalkReq, one utterance V->>H: HandlePushToTalk H->>H: stt seam → text H->>H: decision.With, turnRoute created H->>PRE: 11 rungs PRE-->>H: nobody claims H->>R: rt.resolve R->>R: stage 0 ReminderGrammar matches, Stage=0, conf 1.0 R-->>H: IntentReminder, Slots.Text="позвонить маме", HasTime=false rect rgb(70,40,40) Note over H,CL: BRANCH — missingFor names `time`, whatever the confidence H->>H: dec.Clarify false BUT len missingFor > 0 → step 8 fires H->>CL: Push a PendingQuestion, park the request H-->>V: "во сколько напомнить?" V-->>W: reply audio + text end Note over K,W: "в семь вечера" K->>W: speech W->>V: PushToTalkReq V->>H: runTurn H->>PRE: rung 4, resolveClarifyAnswer PRE->>CL: Pop the parked question PRE->>R: extractor parses the hour with the SAME parsers stage 2 uses PRE->>AR: finishClarified → applyAction Note right of AR: filling in an argument never grants authority AR->>AR: router.ResolvedTheHour guard AR->>DB: CreateReminder fire_ts, payload DB-->>AR: id AR-->>H: reminderConfirm, phrased FROM THE ROW not the utterance H-->>V: "хорошо, напомню сегодня в 19:00." Note over T,D: later — the proactive half, no shared code with the turn path loop every 60s T->>DB: Gatherer.GatherState, due reminders, collapsed by group T->>T: loop.RemindDecisions — reminders BYPASS the restraint gate alt not cached T->>T: phraser.PhraseReminder end T->>D: DispatchReminder D->>DB: BeginDeliveryAttempt BEFORE the external send alt a voice session is live D->>V: voicesink push on the request conn else away D->>D: ntfy is nil (disabled) → telegram end alt success D->>DB: CompleteSuccessfulReminderAttempt + fire the originals, one txn else failure D->>DB: advance the persisted bounded backoff, next_attempt_ts end end Note over T,DB: Recurring is NOT on this path. reminders.cron and next_fire_ts
exist since migration #2 and no spoken path writes them.