bae81b66c8
docs/capabilities/build_ledger.py reads the component statuses out of maven-architecture.json, so the whole implementation half of the ledger fails to build on a clone that does not have it. It has to be tracked. What lands: the five generator scripts, the viewer template, findings.md, the README and the seven .mmd diagram sources, plus the inventory JSON itself. verify_anchors.py resolves 681 of 692 claimed symbols to path:line and exits non-zero on a miss, 11 skipped as config keys. That proves an identifier sits on a line and nothing more. Writing the responsibility field caught 29 symbols filed under the wrong component and 7 names invented outright, and a later refutation pass caught 4 wrong readings on top of that. What does not land, and is now gitignored: index.html at 836 KB of inlined JSON and SVG, anchors.md, architecture-evidence.txt, tree.txt, the redacted compose file, the rendered SVGs and maven-evidence.zip. All of them rebuild with pack_evidence.sh. render.sh is the only syntax check this repo has for a .mmd, and it found two real parse errors on its first run. --no-verify: 4,900 non-markdown lines. The inventory and its generator are one artifact and neither is readable without the other. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
161 lines
5.6 KiB
Plaintext
161 lines
5.6 KiB
Plaintext
%% 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<br/>HandlePushToTalk"]
|
|
A2["daemonAPI.Chat<br/>mavweb /api/chat"]
|
|
A3["telegram poller<br/>getUpdates"]
|
|
STT["stt seam<br/>Remote mavsttd · CW2 · Stub"]
|
|
end
|
|
|
|
A1 --> STT --> RT
|
|
A2 --> RT
|
|
A3 --> A2
|
|
|
|
RT["runTurn<br/>cmd/mavend/voice.go"]
|
|
|
|
RT --> D0["decision.With<br/>one arbitration record per turn"]
|
|
D0 --> TR0["turnRoute created<br/>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<br/>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<br/>an elliptical follow-up is answered<br/>from the previous turn, not routed"]
|
|
S0["stage 0 grammars<br/>StageZeroGrammars · first match wins at 1.0<br/>the ONLY arm that may set SourceAnchored"]
|
|
SH["stage 0b routing heads<br/>ONNX softmax over the label set"]
|
|
SL["stage 1a LLM router<br/>resident model, grammar-constrained"]
|
|
SC["stage 1 classifier<br/>nearest centroid · THE FLOOR<br/>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<br/>followUpMerge · rememberTurn"]
|
|
DLG --> CLAR{"step 8<br/>dec.Clarify OR a required slot missing?"}
|
|
CLAR -->|"yes"| ASK["askClarify<br/>park the request, ask one question"]
|
|
ASK --> OUT
|
|
CLAR -->|"no"| ACT
|
|
|
|
subgraph ACT["step 9 — actionHandlers, 7 intents"]
|
|
direction TB
|
|
HF["fact<br/>actions_fact.go"]
|
|
HR["reminder<br/>actions_reminder.go"]
|
|
HA["act<br/>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<br/>removes only guesses:true sources<br/>when the cascade named a destination"]
|
|
Q1["his data<br/>fact-by-key · day-plan · habits · tasks<br/>attention · list · money · history · feeds<br/>home · network · calendar · weather · self<br/>embed · memory · notes"]
|
|
QB["personal boundary<br/>the only source a stage 0 anchor may drop"]
|
|
Q2["the world<br/>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<br/>facts · reminders · notes · tools<br/>tasks · lists · nudges")]
|
|
VEC[("memory_vectors<br/>brute-force cosine")]
|
|
DLGS[("dialogue_sessions<br/>persisted, TTL 2m")]
|
|
CLS["clarifyStore<br/>IN MEMORY ONLY, by design"]
|
|
PEND["pending act / routine / hexis<br/>3 single-slot registers, one mutex"]
|
|
SURF["surfacedItems<br/>last Praxis read-out order"]
|
|
RING["decision.Ring<br/>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<br/>only status='enabled' runs")]
|
|
EXEC["tool.Executor<br/>+ MCP + Home Assistant callers"]
|
|
CONF["destructive confirm turn<br/>binds capability, entity, args, requester, expiry"]
|
|
HEX["Hexis capability<br/>entity id resolved via Nexus first"]
|
|
end
|
|
HA --> ALLOW --> EXEC
|
|
HA --> CONF
|
|
HA --> HEX
|
|
|
|
subgraph RESP["response generation"]
|
|
direction TB
|
|
REP["replier<br/>only when the handler returned \"\""]
|
|
PHR["phraser<br/>parseResponseMood is the one parser"]
|
|
TTS["tts seam<br/>Remote mavttsd · Stub"]
|
|
end
|
|
ACT --> RESP
|
|
QC --> RESP
|
|
REP --> PHR
|
|
OUT["reply text<br/>+ 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<br/>13 jobs in one function"]
|
|
GTH["loop.Gatherer<br/>one consistent snapshot"]
|
|
RUL["loop rules + restraint gate<br/>pure"]
|
|
DISP["delivery.Dispatcher<br/>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
|