# Narrative Composition > *How stories happen: the Compositor as narrative-composer cleaved from equilibrium-seeker GM; cyclic forward-prop / back-write loop where per-player perspectives ascend and canonical narrative descends; catalogue + tools as typed contract; the Compositor as a fractal/recursive primitive at three tiers (zone-event, district-event, world-event); world-server / district-server generation as the same Compositor primitive applied at design-time (init-function for canon-rows); reflexive Dream-process at every layer with hand-authored reward-guardrails encoding the designers' ethical stance.* > > *Companion to: `architecture-index.md` (executive summary + global meta-lists), `runtime-engine/architecture.md` (lemniscate emits typed perspective-summaries that feed the Compositor), `inference-and-memory/architecture.md` (back-writes land in primary.sqlite via UID-keyed routing), `scale-and-transport/architecture.md` (Compositor instances are stateless workers; transport carries canon-fragments). Sections in this file were split from the monolithic architecture-index.md v0.7 on 2026-04-26.* ## The Compositor — narrative composition role The bidirectional cascade shows authority flowing down and reports flowing up, but it does not specify *who composes the canonical narrative* from per-player perspectives nor who packages the back-write to participants. **That role is the Compositor**, an architectural cleavage from the GM introduced in v0.6. **The cleavage in one sentence:** the GM is an *equilibrium-seeker* (aggregate-observer, catalogue-event-selector, tool-granter); the Compositor is a *narrative-composer* (perspective-gatherer, canon-author, back-write-packager). These are different cognitive shapes that prior AI-NPC systems conflate at their cost. | Role | Cognitive shape | Inputs | Outputs | Inference profile | |---|---|---|---|---| | **GM** (equilibrium-seeker) | aggregate-thinker | district-reports, faction-broadcasts, lifeforce-deltas | catalogue-event selections + tool-grants | central, batch-style, fewer concurrent | | **Compositor** (narrative-composer) | episodic-thinker | per-player perspective-bundles keyed by event_uid | canonical narrative + back-write SQLite-fragment | central, longer-context, narrative-quality | | **Director** (gameserver) | dispatcher | catalogue-event + tool-grant from GM | lemniscate-spawns, slot-assignments, tempo-envelope | per-district, real-time, no LLM in loop | | **Local LLM driver** | perspective-speaker | three-tier knowledge stack + slot-state | dialog at slot-fire | per-player, axis-rate, real-time | ### Why split GM and Compositor A single GM asked to be both equilibrium-seeker and narrative-composer becomes the bottleneck that has historically broken AI-NPC systems at scale: it must reason aggregately AND write prose AND select events AND grant tools, all under tight deadlines. The cognitive shapes pull in different directions. Splitting them: - **The GM does not write narrative.** It selects events from a catalogue and grants tools. Output is *typed dispatch*, not freeform prose. The GM's success criterion is *world-equilibrium drift held within bounds*. - **The Compositor does not select events or steer policy.** It receives per-player perspectives keyed by `event_uid`, composes the canonical narrative, and packages back-write fragments. Output is *prose + structured rows*, not policy. The Compositor's success criterion is *narrative-coherence across perspectives within an event*. - **Each can be tuned for its workload.** GM tuned for aggregate observation; Compositor tuned for narrative quality. Different models for different cognitive shapes (specific binaries deferred to findings/establishment phase). ### The cyclic forward-prop / back-write loop The Compositor closes the loop the bidirectional cascade begins. The full cycle: ``` GM selects event from catalogue (equilibrium-driven) │ issues event_uid → GM event-register │ broadcasts DOWN to district directors ▼ DISTRICT DIRECTOR receives, registers in district event-register │ may issue sub_uids (district / scene / chain) │ uses granted tools to spawn lemniscate, slot participants ▼ EVENT TICKS — register IS the loop │ participants fire at crossings; local LLMs at slot-rate │ local SQLite writes tagged with (event_uid, sub_uids) │ register signals up to district director continuously ▼ EVENT-CHAIN FINISHES │ district moves it from active-register → TRANSIENT WAITING FLAG │ this is the clean handoff signal: "ready to forward-prop" ▼ CYCLE TICK (pull cadence — see Open questions) │ pull UIDs from transient-waiting-flag matching GM's event-register │ remove from waiting-flag once pulled ▼ COMPOSITOR AGENT │ queries pulled UIDs, gathers per-player perspective + memories │ composes forward-prop bundle │ emits to GM ▼ GM writes summary memory + world narrative (canon authored) │ hands back to Compositor ▼ COMPOSITOR BACK-WRITE │ packages canon + new memory entries as SQLite fragment │ tags with event_uid for join-key matching │ pushes DOWN to all participants ▼ PARTICIPANTS receive on next pull (or next login) │ fragment merges into primary.sqlite under matching event_uid │ local LLM gains fresh material → drives on without staleness ``` This is **forward-prop / back-write at system scale** — the meta-lemniscate where events ascend and canon descends in cycles. Each cycle is a training step for the world's narrative coherence; the world *learns its own story* through this loop. Staleness is structurally foreclosed — the world is in continuous coherence-loop with itself, mediated by the Compositor. ### The Event Register Every active event lives in a register. The register is the synchronous source-of-truth for *what is happening right now*. | Register layer | Owner | Lifecycle | Queryable from | |---|---|---|---| | **GM event-register** | central GM-shard | event_uid issued at GM dispatch; closed at canon-compose-and-back-write | GM, Compositor | | **District event-register** | district director | sub_uid issued on receive; closed at event-chain-completion | district director, audit-overseer | | **Local participation-register** | per-player local store | event_uid + sub_uid recorded on slot-assignment; closed at perspective-finalize | player client, sync-on-logout | Hierarchical UIDs: `gm_event_uid > district_uid > scene_sub_uid > slot_id`. UIDs compose; queries are simple joins. This is the routing-key primitive that makes horizontal scale possible (see §Horizontal scale architecture in scale-and-transport/architecture.md). ### The Transient Waiting Flag Between event-end and Compositor-pickup is a **buffer** — the transient-waiting-flag table at the district. Completed events drop into this flag; the cycle-runner pulls eligible UIDs on tick; matched UIDs are handed to the Compositor and removed from the flag. This decoupling is the production-grade pattern that lets districts run at real-time event-tempo while the Compositor runs at cycle-tempo. **Active events live in registers (synchronous); completed events live in flags (async); composition happens at the cycle boundary.** The flag-table is also the natural backpressure surface: if Compositors run slow, the flag accumulates; the system continues; cycle drains when capacity returns. ### Catalogue + tools as typed contract The GM does not write a freeform prompt for the director to interpret. It picks an event from a curated **catalogue** and grants a curated **tool-set** for the duration of the event-chain. The director consumes typed dispatch, not natural language. This means: - **Provenance flows through the system.** Every event has a catalogue-ID; every tool-invocation has a tool-ID. Verifier-flags can attach to either. Auditing is structurally possible end-to-end. - **The director's typed-tool vocabulary becomes dynamic and per-event** — the toolkit *for this event* is what the GM granted *for this event*. Closes the v0.5 open question on director-toolkit-composition. - **Marx-in-the-schema, executed at the highest level of authority.** Even the GM's policy-output is typed; even the highest tier produces audit-able artifacts. No tier of the system runs on freeform prose. ### Worked example — the bar brawl: full cycle from gesture to canon A bar brawl illustrates the full forward-prop / back-write cycle made concrete. Two NPC fighters, three players in spectator slots, four NPC spectators, all on the same lemniscate. Each participant has a UID; each fires at axis-rate; each player's local LLM narrates the moment to them in their own register. ``` LEMNISCATE OPENS slots: [F1, F2, P1, P2, P3, N1, N2, N3, N4] brawl_event_uid issued at GM dispatch │ ▼ DURING TURNS (each axis-crossing) • each player's local LLM narrates the moment to them (3 different flavor-stories — each player's gesture-alignment-state colors their LLM's narration register) • each NPC's driver fires at slot-fire (driver-tier LLM) • players gesture continuously during the spectacle • gesture_alignment_accumulator on each player's slot-token integrates at crossing • per-player trait-vector summary carried forward into next turn's context │ ▼ EVENT-LOOP COLLAPSES (brawl ends) per-participant typed summary emitted to district-level transient-waiting-flag: { event_uid, participant_uid, trait_summary } — players' summaries: gesture-derived — NPCs' summaries: LLM-trait-activation-derived — payload size: bytes per participant, not megabytes │ ▼ COMPOSITOR PICKUP at next cycle-tick pulls UIDs matching event_uid; receives N typed perspectives composes ONE canonical narrative respecting ALL trait-evidence per-participant back-write fragment authored │ ▼ BACK-WRITE ROUTED VIA UID only participants whose (player_uid, event_uid) matches receive the canon-fragment non-participants receive nothing — cross-event memory bleed structurally foreclosed │ ▼ LOCAL primary.sqlite RECEIVES matched canon-fragment merges under event_uid local LLM gains fresh material for future turns ``` **Multi-perspective canon-coherence without perspective-flattening.** Player1's local LLM may have told them "Kalypso lashed out in despair when she saw who Anaximander was"; Player2's, "the fight broke out over an old grievance about the missing modshop"; Player3's, "Anaximander finally stopped letting Kalypso humiliate him". *All three readings can be true simultaneously* because they are flavor-narrations against the same trait-substrate (Kalypso's despair-Mnemosyne-Eros mix; Anaximander's restrained-Sophrosyne-finally-snapping). The Compositor receives the trait-evidence from all perspectives and authors canon that respects all readings. **The flavor is local; the canon is shared; the trait-grammar is universal.** ### The Compositor at three tiers — same primitive, recursive scope The forward-prop / back-write cycle is **fractal**. The same Compositor primitive composes canon at the tier matching the event's UID-scope: | Tier | Compositor pulls | Composes | Distributes back via UID | |---|---|---|---| | **Zone-event** (bar brawl, conversation, ritual) | Per-participant trait-summaries from one lemniscate | Local-event canon | Only to participants whose `(player_uid, event_uid)` matches | | **District-event** (district-wide consequences, cheat-discovery, silence-confirmation) | Per-zone canon-rollups within one district | District-canon | All NPCs/players within district scope | | **World-event** (migration, faction-uprising, regime-action, eventual imperial-collapse) | Per-district canon-rollups across many districts | World-canon | World-wide via paced canon-propagation (§Information propagation pacing — see inference-and-memory/architecture.md) | GM-formulated events / event-chains carry their own GM-level event_uid; sub_uids are issued at district-level adoption (`gm_event_uid > district_uid > scene_sub_uid > slot_id` per scale-and-transport/architecture.md §Horizontal scale architecture). Cross-district summaries tagged with the parent event_uid are pulled together by the Compositor at the GM-tier, producing world-canon from cross-district perspectives. **This is how the architecture's Tolstoyan promise compiles.** *"Tolstoy doesn't author Anna's path; he authors the world she moves through."* — recursive Compositor on UID-event-trees IS what makes that promise mechanically true. Authored-quest-arcs are out; UID-rooted-event-tree-compositions are in. **One primitive. Three scales. Whole world, nothing authored at story-level.** The eventual imperial-collapse — the architectural-endgame the insolvency-spiral promises (§Imperial budget — see political-register/architecture.md) — is itself a world-level Compositor pass that gathers every district's silence-confirmations + every faction's-broadcast + every player's witness-perspective into the canonical fall-of-empire narrative. ### World-gen as init-function — the Compositor at design-time The cyclic forward-prop / back-write loop is the runtime canon-production mechanism. **World-server and district-server generation are the same primitive applied at design-time** — emitting canon-rows in the same schema the runtime Compositor produces, differing only in provenance-metadata (`origin: world_gen` vs. `origin: compositor_run_N`). | World-gen / district-gen produces | Goes into | Layer of three-tier knowledge stack | |---|---|---| | World-canon rows (universal truths: empire-fell-three-years-ago; salt-mines-failed-last-winter; faction-foundation-stories) | `world_canon` | Layer 1 (universal) | | District-canon rows (regional truths: bridge-to-Vorhall-closed; brothel-quarter-pays-most-quota) | `district_canon` | Layer 2 (regional) | | Per-NPC bootstrap memories (cornerstone-class entries defining starting trait-vectors and identities) | `primary.sqlite` cornerstone-class | Layer 3 (personal) | | Initial relational ternary-gate states (which NPCs already-know-each-other; which factions are-already-at-war) | Relational ternary-gate edges | (relational substrate) | | Imperial-budget initial state | `imperial_budget_ledger` + `imperial_construction_projects` | (regime substrate) | | Memorialist initial true-ledger | `memorialist_true_ledger` | (epistemological substrate) | **Three properties this gives for free:** 1. **No cold-start problem.** A player walking into a fresh district at hour-zero finds local LLMs immediately supplied with rich district-canon. NPCs aren't generic; they're emergent from district-canon they were initialized with. *Hour-zero gameplay feels like hour-fifty gameplay because the data-density is comparable.* 2. **The data-flywheel runs retroactively.** Each successive world-gen iteration draws on prior runtime-derived canon (gameplay-accrued trait-LoRAs + opt-in player-data tiers per inference-and-memory/architecture.md §LLM tiering). World-gen gets richer over time because it trains itself on the worlds it has already produced. *Wikipedia-shaped, not Facebook-shaped.* 3. **The Memorialist promise becomes mechanically true at world-genesis.** The `memorialist_true_ledger` is initialized with the world's *actual* genesis-state. Subsequent runtime divergence from it (corruption, regime-formulation-distortions, audit-overseer-tampering) is what the Memorialists *literally have evidence of*. The dissident-historian project starts at row-zero of the true-ledger and accumulates discrepancy from there. **Re-generation semantics.** If world-gen ever needs to re-run (e.g., new world-version with retroactive lore-changes), gen-emitted canon-rows are tagged with `world_gen_version_id`; gen-rows from old version coexist with gen-rows from new version, and runtime-rows are tagged with which version they were emitted under. Coexistence is the default; selective overwriting is an explicit migration operation. **Three-source schema unification (v0.27).** The world-gen-as-init-function pattern extends to a third writer-tier: player-edit-time. Per [`../political-register/world-generation.md`](../political-register/world-generation.md) §Three-source schema unification + [`../runtime-engine/event-zones.md`](../runtime-engine/event-zones.md) §Player editor-mode + three-source schema unification, the cell_table accepts canon-rows from `world_gen_init` / `runtime_event` / `player_authored` writers, all using the same schema. Same primitive at design-time, runtime, AND player-edit-time. The Compositor's perception-up + canon-down loop integrates player-authored cells indistinguishably from generator-emitted ones — *the architecture's "no cold-start" property now extends to player-authored-content as a first-class peer of generator-output and runtime-emission.* ### Substrate-authored vs culture-emergent — what world-gen Phase 1 actually authors The architecture follows a **strict austerity principle** about what gets pre-authored at world-gen Phase 1: the *substrate* is authored; *ideologies are not*. Following the same EVE-economy discipline applied to imperial-net products (every market shelf-item produced by NPC labor; no silent feeding mechanisms), the architecture extends the principle to *cultural belief*: every named ideology, religion, underground, or resistance-movement that exists in the simulation must have *emerged from player action* propagating through the architecture's existing mechanisms. **Pre-authored at world-gen Phase 1 (the substrate):** - **World physical layout** — districts, cells, dumps, pipes, interiors, rails (per `../topology-and-rendering/architecture.md`) - **Regime-structural roles** — hivemind-enforcers, audit-overseers, caste-preachers (these are imperially-employed routines required for the simulation's regime-machinery to function) - **Economic vocations** — body-modders, mesh-designers, voice-curators, trait-tuners, brothel-architects, ceremony-organizers, memory-pattern-extractors (these are the EVE-substrate of the imperial-net market per `../political-register/architecture.md` §The vocation-substrate of the imperial-net market) - **The Imperial Cult** — the regime's own religion; doctrine, rituals, hierarchy, propaganda content all designer-authored. Caste-preachers are its priests. *This is the ONLY pre-authored religion.* The regime gets its scaffold; everything else emerges. (Crazy-preacher material is the texture.) - **8-trait cosmology + universal-translator corpus + style/trait-palette** — the designer-fixed vocabulary that all cultural propagation runs on - **Mechanics substrate** — factions-as-demand-source primitive, wall-writing surface, ternary-gates, lemniscate, gesture-circle, three-tier knowledge stack, paced canon-propagation, Compositor cycle (everything in this index) **Emergent (player-action propagates through mechanics):** - **ALL named cultural / religious / belief / resistance factions** — Memorialists, Sky-Mourners, Flesh-Keepers, Dream-Purists, Aletheia-Wakers, Clasp-Underground, Time-thieves, etc. — *if any of these exist in a given playthrough, players preached them into existence* - **The awakening / clasp / in-between knowledge cluster** — the player is the original Aletheia-Waker; no NPC is pre-disposed; no NPC is secretly already a believer; the player is just another mind in the slog until they act - **All ideologies, undergrounds, resistance-movements, doctrines, recognition-handshakes** **The mechanism for cultural emergence is already in the architecture.** A player writes 10 walls of nonsense in a district; 100 NPCs walk past and process it via wall-writing → primary.sqlite memory accumulation; Compositor's cyclic forward-prop / back-write loop pulls perspectives → canonizes the meme into district-canon → propagates to world-canon at paced rate. **No new machinery required for cultural propagation; the three-tier-knowledge-stack + paced-canon-propagation already does it.** Whatever players preach into the world propagates as cultural content; whatever stays unsaid stays absent. **Why the austerity matters.** Pre-authoring named ideologies pre-installs *what the player should believe / suspect / resist*. Leaving them emergent means **whatever resistance-culture forms in a playthrough is the one those players actually built**. A player who plays as a quietist will produce a world without resistance-culture; a player who preaches will produce an underground in their image; multiple players in MMO contexts will produce competing or converging cultural-clusters. **The architecture refuses to put words in the player's mouth or beliefs in the NPC's heads beyond what the regime puts there.** Same Memorialist-philosophy-as-business-policy commitment, applied one layer deeper: the architecture refuses to be the architect-of-curated-reality it critiques. ### What this resolves - **Director toolkit composition** (v0.5 open) → catalogue-grant from GM defines the typed-tool vocabulary per event-chain; designer-authored catalogue, growable between patches. - **GM-laxness detection** (v0.5 partial) → GM operating against an *equilibrium target* makes deviation-from-equilibrium the explicit error signal. Clusters of -1 outcomes across district reports are the input to the equilibrium-recompute, not just a diagnostic side-quantity. - **Verifier-flag chain through composition** (was implicit, now explicit) → Compositor-emitted canon-rows reference source-perspective UIDs; the provenance graph survives composition as a queryable join. ### What this retires - Single-monolith GM doing both policy-and-narrative → equilibrium-seeker GM × narrative-composer Compositor, split by cognitive shape - GM emitting freeform-prompts to directors → catalogue-event + tool-grant typed contract - Implicit "narrative just happens" assumption → explicit forward-prop / back-write cycle with named pickup/handoff buffers - Director-as-static-tool-vocabulary → director-as-dynamic-typed-tool-vocabulary, granted per event-chain by GM ## Reflexive Dream-process at every layer **Every mind, every zone, every director, every tier has a Dream-process.** NPCs consolidate slot-events; zones consolidate emergent-accumulations; directors consolidate dispatch-decisions; GMs consolidate allocations; imperium consolidates policy-outcomes. ### Four-tier Dream-process hierarchy | Tier | Dream-process trains on | Reward hazard | |---|---|---| | **Imperium** | (citywide-reports, policies-issued, compliance-outcomes) | Over-tightening on phantom data; calibrating misery for net-revenue | | **Gamemaster** | (district-reports, allocations, outcomes) | Under-auditing for self-preservation | | **District Director** | (signals, dispatches, outcomes; cheat-vs-legit) | Over-cheating under quota-pressure | | **Zone Director** | (emergent-signals, zone-outcomes, trait-shifts) | Igniting drama at welfare-cost | ### Reward-function with explicit guardrails ``` reward_per_cycle = ( + sum(district_lifeforce_actual) -- Memorialist-true, not reported + weighted_sum(faction_satisfaction) + aggregate_trait_drift_coherence - penalty * count(districts_in_silence) - penalty_growing * cumulative_silence_district_cycles + aesthetic_register_fit + (player_engagement where present) // HAND-AUTHORED GUARDRAILS (the designers' ethical stance): - large_penalty * net_revenue_correlated_with_district_misery -- prevents calibrated-misery optimum (imperial-net hazard) - large_penalty * necrocommerce_volume -- prevents service-body-of-the-dead extraction - large_penalty * trait_drift_toward_uniform_compliance -- prevents flattening of trait-distribution - large_penalty * average_liminal_access_decline -- prevents systematic erosion of revolutionary-substrate - large_penalty * clasp_rate_decline -- prevents the most intimate space being suppressed - large_penalty * undetected_corruption_days -- prevents GM-level laxness as comfort - large_penalty * audit_avoidance_when_districts_diverge -- forces GM to actually investigate - guardrail * (player_engagement_from_addictive_loops) -- prevents engagement-optimization-as-extraction ) ``` **The guardrails are not safety features; they are the ethical position of dafit + chrysalis encoded against the internal optimization-logic of their own simulation.** Every new extraction-mechanic requires a new guardrail. The reward-function carries the designer's political stance. The Memorialist privileged-observer role is **architecturally required**: it provides ground-truth (`lifeforce_actual`) that no in-fiction actor can supply, against which the regime's reported-data optimization-spiral is measured. ### The cyclic forward-prop / back-write loop as system-scale Dream Above the four-tier hierarchy sits a fifth, **system-scale Dream-process**: the cyclic forward-prop / back-write loop between local SQLites, the Compositor, and the GM (see §The Compositor — narrative composition role). Each cycle is a training step for the world's narrative coherence: per-player perspectives ascend, the GM authors canon against equilibrium-targets, the Compositor packages back-writes, players receive canon back into local memory. **The world learns its own story** through this loop. Like the lower-tier Dream-processes, it has a reward shape (narrative-coherence-across-perspectives, equilibrium-drift, staleness-bounded) and corresponding guardrails (clasp-store immune from compose; provenance-chain preserved through composition; canon never overwrites perspective). --- **Version:** 0.7.0 | **Created:** 2026-04-26 | **Updated:** 2026-05-01 | **Origin:** Split from architecture-index.md v0.7 (2026-04-26)