%% View 2 — Core internals of mavend.
%% The real path, in the order runTurn actually runs it. The sequence is NOT
%% input → routing → intent → state → tools → response: eleven stateful
%% pre-emptors get first refusal BEFORE routing, and a query intent then enters
%% a second, longer arbitration of its own.
%% Evidence: cmd/mavend/voice.go runTurn, cmd/mavend/turnroute.go,
%% cmd/mavend/actions.go, cmd/mavend/actions_query.go, internal/router/router.go.
flowchart TB
subgraph IN["input — three reaches, one pipeline"]
A1["voice.Server
HandlePushToTalk"]
A2["daemonAPI.Chat
mavweb /api/chat"]
A3["telegram poller
getUpdates"]
STT["stt seam
Remote mavsttd · CW2 · Stub"]
end
A1 --> STT --> RT
A2 --> RT
A3 --> A2
RT["runTurn
cmd/mavend/voice.go"]
RT --> D0["decision.With
one arbitration record per turn"]
D0 --> TR0["turnRoute created
sync.Once, on the context"]
subgraph PRE["pre-route ladder — 11 rungs, order load-bearing"]
direction TB
P1["1 expired-clarify notice"]
P2["2 confirm answer
resolveConfirm"]
P3["3 targeted repair"]
P4["3b untargeted repair"]
P5["3c command prohibition"]
P6["4 clarify answer"]
P7["5 quiet toggle"]
P8["5b snooze"]
P9["5c ack"]
P10["5d reminder cancellation"]
P11["5e ordinal selection"]
P1-->P2-->P3-->P4-->P5-->P6-->P7-->P8-->P9-->P10-->P11
end
TR0 --> PRE
PRE -->|"any rung claims"| OUT
subgraph ROUTE["step 6 — the cascade · internal/router"]
direction TB
CONT["continuationDecision
an elliptical follow-up is answered
from the previous turn, not routed"]
S0["stage 0 grammars
StageZeroGrammars · first match wins at 1.0
the ONLY arm that may set SourceAnchored"]
SH["stage 0b routing heads
ONNX softmax over the label set"]
SL["stage 1a LLM router
resident model, grammar-constrained"]
SC["stage 1 classifier
nearest centroid · THE FLOOR
names no destination"]
SE["stage 2 extractor + stage 3 gate"]
CONT -->|"not a continuation"| S0
S0 -->|"no match"| SH
SH -->|"declines"| SL
SL -->|"error or unparsable"| SC
SH --> SE
SL --> SE
SC --> SE
end
PRE -->|"nobody claimed"| ROUTE
ROUTE --> DLG["step 7 dialogue merge
followUpMerge · rememberTurn"]
DLG --> CLAR{"step 8
dec.Clarify OR a required slot missing?"}
CLAR -->|"yes"| ASK["askClarify
park the request, ask one question"]
ASK --> OUT
CLAR -->|"no"| ACT
subgraph ACT["step 9 — actionHandlers, 7 intents"]
direction TB
HF["fact
actions_fact.go"]
HR["reminder
actions_reminder.go"]
HA["act
actions_act.go"]
HN["note"]
HC["chat"]
HS["system"]
HQ["query → the chain"]
end
subgraph QC["the query chain — a SECOND arbitration, 22 sources"]
direction TB
QW["queryWalk
removes only guesses:true sources
when the cascade named a destination"]
Q1["his data
fact-by-key · day-plan · habits · tasks
attention · list · money · history · feeds
home · network · calendar · weather · self
embed · memory · notes"]
QB["personal boundary
the only source a stage 0 anchor may drop"]
Q2["the world
search → kiwix → web → general-knowledge"]
QW --> Q1 --> QB --> Q2
end
HQ --> QC
HF -->|"question-shaped ⇒ re-route"| QC
HF -->|"complaint ⇒ re-route"| HC
subgraph STATE["state and memory"]
direction TB
DB[("store · sqlite
facts · reminders · notes · tools
tasks · lists · nudges")]
VEC[("memory_vectors
brute-force cosine")]
DLGS[("dialogue_sessions
persisted, TTL 2m")]
CLS["clarifyStore
IN MEMORY ONLY, by design"]
PEND["pending act / routine / hexis
3 single-slot registers, one mutex"]
SURF["surfacedItems
last Praxis read-out order"]
RING["decision.Ring
bounded, in memory"]
end
HF --> DB
HF --> VEC
HR --> DB
HN --> DB
HN --> VEC
Q1 --> DB
Q1 --> VEC
DLG --> DLGS
ASK --> CLS
HA --> PEND
QC --> SURF
D0 --> RING
subgraph TOOLS["act execution"]
direction TB
ALLOW[("tools table
only status='enabled' runs")]
EXEC["tool.Executor
+ MCP + Home Assistant callers"]
CONF["destructive confirm turn
binds capability, entity, args, requester, expiry"]
HEX["Hexis capability
entity id resolved via Nexus first"]
end
HA --> ALLOW --> EXEC
HA --> CONF
HA --> HEX
subgraph RESP["response generation"]
direction TB
REP["replier
only when the handler returned \"\""]
PHR["phraser
parseResponseMood is the one parser"]
TTS["tts seam
Remote mavttsd · Stub"]
end
ACT --> RESP
QC --> RESP
REP --> PHR
OUT["reply text
+ notice + resumed question"]
RESP --> OUT
OUT -->|"voice path only"| TTS
subgraph PROACT["the other half of the process — nothing above touches it"]
direction TB
TICKL["tick loop · 60s
13 jobs in one function"]
GTH["loop.Gatherer
one consistent snapshot"]
RUL["loop rules + restraint gate
pure"]
DISP["delivery.Dispatcher
ChannelsFor severity,presence"]
SNK["sinks: voice · ntfy · telegram"]
TICKL --> GTH --> RUL --> TICKL
TICKL --> DISP --> SNK
end
TICKL --> DB
SNK -->|"PushToMostRecent on the request conn"| A1
classDef stage fill:#1f3a5f,stroke:#7fb3ff,color:#eaf2ff
classDef store fill:#1f4a3a,stroke:#6ed0a8,color:#e8fff5
classDef mem fill:#4a3a1f,stroke:#e0b050,color:#fff6e0
classDef danger fill:#4f2626,stroke:#e08080,color:#ffecec
class S0,SH,SL,SC,SE,CONT stage
class DB,VEC,DLGS,ALLOW store
class CLS,PEND,SURF,RING mem
class QB,CONF danger