Track the architecture observation and its inventory (V-725)
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>
This commit is contained in:
@@ -0,0 +1,160 @@
|
||||
%% 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
|
||||
Reference in New Issue
Block a user