MeridiansMeridians

4. The layer map — src/lib/ is role-first

From the Meridians Wiki · Public · Maintained · joint

src/lib/ is organised into four role buckets, so "is this browser-safe? does it serve the record?" is answered by the path. Import as @/lib/<role>/<folder>. The UI above it has its own three-tier stack (shell → features → ui); both stacks and the lint-enforced import matrix are owned by STRUCTURE.md.

🔵 lib/core/ — SHARED: the reducer + pure derivations (runs browser AND node)

PathRole
core/reducer/The central reducer — the single writer. actions.ts (the Action union), domain-reducer/ + app-reducer/ (the pure reducers), reducer-core, initial-state, domain-registry.
core/forces/ core/graph/ core/game-theory/ core/pacing/ core/futures/ core/search/ core/map/ core/analysis/ core/learning/ core/economics/Pure derivations over the domain model — no IO, no React.
core/program/ core/position/The Program's pure half — cadence/loop logic, constellation program composition, Position schedule presets and re-price math.
core/access/The can permission lattice, action-policy, identity.
core/io/Import/export (epub, package, graph/scene/belief).
core/kernel/Low-level infra (api-logger, api-headers, system-logger, key-store, resolve-api-key).
core/constants/The constant registry, split by concern (ai-models, ai-pricing, generation, forces, time, …).
core/{ai-profiles,model-resolver,merges,onboarding,tutoring,…}.ts · core/utils/Shared modules + helpers.
../../types/domain/The domain modelDomainState, split per slice. Kept at @/types/domain (the conventional types location).

🟢 lib/server/ — BACKEND: Node-only, serves the record (never in the browser bundle)

PathRole
server/record/The record + projection layer. fs-store (read/write the canonical files), mutation (applyLocalMutation — the one write path), server (route helpers + the local-only gate), record-events/record-client/record-mirror (the change stream + client write-through), reconcile/catch-up (keep the cache honest).
server/ops/The service / API-surface layer. Tier-0 queries, Tier-2 operation handlers, the command bus. What the /api/local/{query,op,mutate} routes call.
server/program/The Program's scheduler + run infrastructure — what fires Research, Opinion, Merge, and Position on a cadence.
server/sync/ · server/tunnel-manager.tsMaster↔client replication (broker, protocol, tunnel, roles).
server/gateway/The control-plane boundary — Supabase session, directors, entitlements, Stripe, instance + device registries. Gateway build only.
server/deployment/Route policy for the instance/gateway deployment split (GATEWAY.md 🔒 §10).

🟣 lib/engine/ — the AI generation layer (provider calls + prompts; browser or node)

PathRole
engine/ai/Every LLM call + the generation pipeline (scenes, prose, world, graphs, variables, surveys, review, …).
engine/prompts/All prompt text + output schemas, scoped by domain.
engine/extraction/Text → domain pipeline.
engine/research/The living-loop engine (firecrawl, ingest, ticker, constellation runs). Feeds Streams (research) and Position Signals (monitor) off one fanout.
engine/program/The Program's generative stages — Opinion selection, Tutor proposals, Position composition.
engine/audio/ · engine/image/The non-text providers (speech, cover/entity imagery).

Two evidence boundaries, one engine. A Public Domain is prepared from an explicit research scenario and current, cited web evidence. A Private Domain is prepared from context a Director deliberately supplies through an interview and is not sent through public-web research. Both use the same record, reducer, extraction pipeline, and Program. Public Domains are maintained by Research cycles; Private Domains return to the Director through scheduled Reminders into Notes. Passive private tracking remains product direction and is not implied by the Private boundary.

🟠 lib/client/ — FRONTEND-only (React, IndexedDB)

PathRole
client/store/The renderer's binding to the reducer — store.tsx (the useStore hook), contexts/, hooks/.
client/cache/IndexedDBdb/idb/persistence (the projection cache), asset-manager, encryption (at-rest).
client/ops/The browser's transport to Tier-0 queries and Tier-2 operations — how UI reaches server capability without importing lib/server.
client/game/The Scenario live-game state machine (browser-master reducer).
client/program/ · client/gateway/ · client/voice/Client-side Program bindings, the gateway session client, and the dictation surface.
../../ui/ · ../../features/ · ../../shell/ · ../../hooks/ · ../../app/React UI (three composition tiers), hooks, Next routes.

The AI provider routes (app/api/ai/generate, /embeddings, /firecrawl, …) are adapters, not the provider implementation or record control-plane. Shared provider services live under engine/; browser/remote callers reach them through the HTTP adapters, while the generic operation runner binds typed direct capabilities through engine/ai/runtime.ts for MCP, scheduled, and other headless work. Per-call metering stays in engine callers; provider-service diagnostics stay server-side. Engine code must never introduce a private fetch("/api/…") path.