Architecture — runtime boundaries, canonical state, and the one-writer model
Source path: knowledge-base/knowledge/architecture/overview/foundations.md
# Architecture — runtime boundaries, canonical state, and the one-writer model
> **Who this is for.** A developer used to a **backend/frontend split** landing in this repo and
> asking "where's the server, where's the client, where's the database, and why is it shaped like
> this?" This is the map. It complements — doesn't replace — the specialized docs:
> [API_PRINCIPLES.md](../API_PRINCIPLES.md) (the reducer + tiers), [PERSISTENCE.md](../PERSISTENCE.md)
> (the store linkage + replication layer), and [FRONTEND_CONVENTION.md](../../conventions/FRONTEND_CONVENTION.md) (UI component names).
---
# 1. The three ideas that explain everything
Meridians looks unusual to a backend/frontend developer because it collapses three things most
apps keep separate. Internalise these and the layout follows.
### Idea 1 — One process is both the frontend AND the backend
There is **one Next.js app**. Its React tree is the **frontend**; its `app/api/*` route handlers are
the **backend**; and a large **shared core** (the domain model + the reducer + pure derivations)
runs in *both* — the same TypeScript executes in the browser and in the Node server. So "frontend"
and "backend" here are **runtime roles of one codebase**, not separate deployables.
```
┌───────────────────────── one Next.js app ─────────────────────────┐
│ FRONTEND (browser) SHARED CORE BACKEND (Node) │
│ React components ◀──────── domain model ────────▶ api/ routes │
│ hooks · view state the REDUCER record + ops │
└────────────────────────────────────────────────────────────────────┘
```
### Idea 2 — The reducer is the single writer of state
State changes **only** by dispatching a reducer `Action` through one deterministic write path.
Not a component, not a service, not an operation — everything is a *caller* of that one door. This
is what makes the system trustworthy: one place to reason about "how did state get here," one place
to gate authority, one deterministic replay. (Full treatment: [API_PRINCIPLES.md](../API_PRINCIPLES.md).)
Because the reducer is **pure and clock-injected**, the *same* action produces a *byte-identical*
result in the browser (optimistic) and on the server (authoritative) — which is what lets the two
stay in lockstep without a merge.
### Idea 3 — Two data stores, one is canon, the other is a rebuildable projection
There is **no per-user database on a server**. Instead:
| Store | What | Role |
|---|---|---|
| **The record** — a folder on disk (`.meridians-local/record/…`), JSON + assets | The **source of truth** (canon). Versioned, inspectable, the thing the daemon owns. | **write here, then read follows** |
| **IndexedDB** — the browser's local DB | A **projection** (cache) rebuilt from the record. Fast reads; never a co-authority. | disposable, reconstructable |
The rule (the *projection model*): **the file advances before the cache.** A write hits the record
first (version bump), then the cache follows via an echo. If the two ever disagree, the record wins
and the cache is re-derived. IndexedDB holding derived indexes (embeddings) that aren't in the
record is fine — those are rebuildable by re-deriving.
### Idea 4 — What the record holds is a *maintained opinion*, in three layers
The mechanics above (one process, one writer, one canon) exist to keep something alive: a domain
artifact's **opinion**, carried across **three time horizons** over the three measured forces
(**System / World / Fate**). This is the belief spine the whole app renders and steers:
| Layer | Horizon | Force | What it holds |
|---|---|---|---|
| **Threads** | long | Fate | settled opinion about broad-world *outcome* questions |
| **Streams** | present (memory) | World | evidence-driven priors that drive **action** + record model changes **now** |
| **Positions** | the live read of where the world is heading (foresight) | Fate | a self-updating, priced Reading grounded in a Reasoning Graph, re-pricing as evidence lands |
Their sum *is* the expert's opinion — *what has settled · what to do now · where the world is heading*.
Keeping them distinct is the point; the record never collapses them into one score.
The **Program** — **Research → Opinion → Merge → Position** — is the daily maintainer that keeps all
three current: it re-reads the world, moves open Streams, surfaces material belief movement, folds
judgment into canon (a Merge), and re-prices active Positions (surfacing where the read moved for the
user's review). It runs on a cadence (manual or autopilot) and emits **Feeds** — editorial, timestamped
records of the expert and how its opinion evolved, consumable by other people. *A Position repositions on
evidence and stays live as long as its question is live; the read itself is never marked true or false and
carries no Brier or resolve-at-close. What **is** graded is the **committed consequence**, and
across many Positions the engine's **Calibration**. That historical verification direction no longer has
an active mechanics specification and does not define the product. Current identity and migration state
live in [PIVOT.md](../../foundations/PIVOT.md). The value that survives is the maintained, inspectable,
versioned model **and the record it accrued**.* (The belief vocabulary is owned by
[LANGUAGE.md](../../vocabulary/index.md).)
---
Open on GitHubRaw Markdown source