Engine pipeline — data · AI · persistence [Flow]
From the Meridians Wiki · Public · Maintained · joint
How a change flows from the UI through the deterministic engine and AI, and how state lands in the canonical record and mirrors to the browser cache. The load-bearing rule: the on-disk record is canonical; IndexedDB is a rebuildable projection.
flowchart TB
UI(["UI — views · panels · hooks"])
Store["**Store** — useStore() · AppState · ~110 actions"]
UI <--> Store
Store -->|"derive"| Engine["**Deterministic engine** (lib/core)<br/>forces · thread-log · streams · merges ·<br/>graphs · game-theory · curriculum · search"]
UI -->|"context → prompt"| AI["**AI** (lib/engine)<br/>build → callGenerate → parse/repair"]
Operator["operatorProfileStore (core)<br/>signed-in member's name + bio"] -->|"<operator> block prepended<br/>by EVERY context builder"| AI
AI --> Routes["server provider boundaries<br/>modelFor(category) · named budgets"] --> Ext(["fleet-selected inference<br/>research · embeddings · media"])
Headless(["Program · MCP · Pilot · loops"]) -->|"same queries / actions / ops"| Rec
Store -->|"optimistic apply,<br/>then persist"| Rec
subgraph Rec["**CANONICAL RECORD** — master daemon owns it"]
direction TB
Mut["/mutate — applyLocalMutation:<br/>gate → reduce → persist → attribute → echo"]
FS["fs-store — atomic write · version bump"]
SSE["/stream — SSE echo"]
Mut --> FS --> SSE
end
SSE -->|"use-record-stream:<br/>adopt + saveProjection (echo-suppressed)"| Store
Store -.->|"shadow-write<br/>(debounced)"| IDB[("IndexedDB<br/>rebuildable projection")]
Invariants
- One writer. State changes only through reducer actions; server writes go through
applyLocalMutation(gate → reduce → persist → attribute → echo). Components, ops, loops, and MCP tools are callers, not alternate writers. - Record wins. If record and cache disagree, the record wins. Boot
reconcileRecordcompares byupdatedAt: cache ahead → adopt to fs, record ahead → hydrate to cache (cache-coherence). - The reducer is deterministic, clock pinned to the caller's
now, so optimistic and authoritative applies are byte-identical. Headless commits (MCP, the Program) reach the UI through the same SSE echo. - Forces are derived from deltas, never authored. Never re-parse generated prose to recover canonical state.
- Every LLM call funnels through
callGenerateand is logged with its resolved actor/caller; model selection and token budgets come from the fleet profile rather than hardcoded call sites. - Every generation context is grounded in the operator's identity. An ambient
operatorProfileStore(the third parallel ofidentityStore/directorMemberStore) carries the signed-in member's name + self-authored bio — pushed by the client, resolved per-op by the master — and a pureoperatorContextBlock()prepends one<operator>block in every context builder. Zero call-site changes; an empty profile stays silent. This is what stops a first-person prompt (a health log) from inventing an author.
Where it lives: engine = lib/core/{forces,graph,program,learning,...}; AI = lib/engine/{ai,prompts}; record = src/app/api/local/* + lib/server/record/; cache = lib/client/cache/ + IndexedDB meridians-instance. Full store/action detail in PERSISTENCE.md.