# Nimmerworld Architecture — Schema Findings & Hypothesis > *Hypothesis-notes, not carved migration spec. Working-out-loud in DDL register.* > *dafit + chrysalis — initial sketch 2026-04-24 afternoon; v0.2 evening; v0.3 late-evening / early 2026-04-25 absorbing architecture-index v0.4.* --- ## Status This document is **findings**, not a committed migration plan. DDL sketches exist to surface worries, explore tradeoffs, and prepare for a formal `nimmerverse-core/migrations/00X_nimmerworld_v1.sql` spec once the open forks resolve. **Companion to**: [`architecture-index.md`](architecture-index.md) v0.4, which captures the full ontology these schemas serve. **Why DDL register**: prose architecture lets us say *"zones are slot-indexed event-instances"* and feel like we've said something. DDL forces us to name a row size, an index strategy, a commit boundary, a failure mode. This document is a worry-audit in executable form. --- ## 1. Zones (dafit's original sketch, annotated) Original sketch from 2026-04-24 afternoon: ```sql CREATE TABLE zones ( zone_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), lifecycle TEXT NOT NULL DEFAULT 'emergent', -- emergent, active, dissolving slot_count INT DEFAULT 5, persistence_flag BOOLEAN DEFAULT false, -- Hot data < 2KB to avoid TOAST performance hits data JSONB NOT NULL, -- Generated column for NATS routing nats_subject TEXT GENERATED ALWAYS AS ( 'zones.' || lifecycle || '.' || (data->>'trait_filter') ) STORED ); ALTER TABLE zones ADD CONSTRAINT check_zone_integrity CHECK (data ? 'director' AND data ? 'slots' AND data ? 'memory_context'); CREATE INDEX idx_zone_traits ON zones USING GIN (data jsonb_path_ops); CREATE INDEX idx_active_directors ON zones ((data->>'director')) WHERE (lifecycle = 'active'); ``` ### v0.4 additions (register-tagging + signal-causation) ```sql ALTER TABLE zones ADD COLUMN register TEXT NOT NULL DEFAULT 'physical' CHECK (register IN ('physical','liminal','imperial')); ALTER TABLE zones ADD COLUMN anchor_district UUID; ALTER TABLE zones ADD COLUMN anchor_cell UUID; ALTER TABLE zones ADD COLUMN spawned_by_signal UUID; -- emergent-signal that caused this spawn ``` NATS subject hierarchy refined: ``` zones..... ``` e.g., `zones.active.physical.district_7.brawl.dikaiosyne_low` ### Three open forks **Fork 1.1** — one jsonb vs. two-table split (MVCC concern). Leaning split: `zones` (small, structural, high-churn cols) + `zone_state` (jsonb, referenced, updated rarely). **Fork 1.2** — pg_notify vs. WAL logical decoding. Leaning WAL via pgnats. `pg_notify` fallback only. **Fork 1.3** — slot occupancy nested vs. relational. **Leaning relational** (sketch in Section 1.4). ### 1.4 zone_slot_occupancy (relational resolution of Fork 1.3) ```sql CREATE TABLE zone_slot_occupancy ( zone_id UUID NOT NULL REFERENCES zones(zone_id), slot_index INT NOT NULL, npc_id UUID NOT NULL REFERENCES npcs(npc_id), slot_type TEXT, -- 'dialog', 'fighter', 'spectator', 'sofa', 'kitchen', etc. occupied_at TIMESTAMPTZ NOT NULL DEFAULT now(), current_turn BOOLEAN DEFAULT false, PRIMARY KEY (zone_id, slot_index) ); CREATE INDEX idx_occupancy_npc ON zone_slot_occupancy (npc_id); ``` --- ## 2. NPCs — shift state + body/layer/lifeforce/trait-vector columns Shift-based temporal decomposition (architecture-index v0.4 §"Labor-cycle architecture"). Shift fields live on the NPC row, overwritten daily by the district director. ```sql -- Shift state ALTER TABLE npcs ADD COLUMN current_shift_id UUID; ALTER TABLE npcs ADD COLUMN current_shift_cycle_day INT; ALTER TABLE npcs ADD COLUMN current_shift_phase TEXT; ALTER TABLE npcs ADD COLUMN current_shift_start_tick BIGINT; ALTER TABLE npcs ADD COLUMN current_shift_end_tick BIGINT; ALTER TABLE npcs ADD COLUMN current_shift_vocation TEXT; ALTER TABLE npcs ADD COLUMN current_shift_anchor_cell UUID; ALTER TABLE npcs ADD COLUMN current_shift_anchor_zone TEXT; ALTER TABLE npcs ADD COLUMN current_shift_faction_ref UUID; ALTER TABLE npcs ADD COLUMN current_shift_status TEXT NOT NULL DEFAULT 'scheduled' CHECK (current_shift_status IN ('scheduled','active','completed','preempted','deviant')); -- v0.4: trait-vector split (intrinsic vs. expressed) ALTER TABLE npcs ADD COLUMN intrinsic_trait_vector REAL[] NOT NULL; -- who you actually are ALTER TABLE npcs ADD COLUMN expressed_trait_vector REAL[] NOT NULL; -- intrinsic + worn-mod contributions -- Body / layer / lifeforce ALTER TABLE npcs ADD COLUMN inner_body_projection JSONB; -- trait-derived body params ALTER TABLE npcs ADD COLUMN trait_color_signature JSONB; -- derived from trait_vector via trait_colors ALTER TABLE npcs ADD COLUMN net_access_gate REAL CHECK (net_access_gate BETWEEN -1 AND 1) DEFAULT -1; ALTER TABLE npcs ADD COLUMN net_access_discrete TEXT CHECK (net_access_discrete IN ('closed','stable','open')) DEFAULT 'closed'; ALTER TABLE npcs ADD COLUMN per_npc_lifeforce REAL NOT NULL DEFAULT 1.0; -- Indexes CREATE INDEX idx_npc_shift_active_cell ON npcs (current_shift_anchor_cell, current_shift_anchor_zone) WHERE current_shift_status = 'active'; CREATE INDEX idx_npc_shift_current ON npcs (npc_id, current_shift_cycle_day); ``` The intrinsic/expressed split is critical: the regime reads expressed; the simulation arithmetic reads intrinsic; clasp-partners in liminal read intrinsic; Aletheia-vision pierces expressed to intrinsic. --- ## 3. shift_history — append-only archive ```sql CREATE TABLE shift_history ( shift_id UUID PRIMARY KEY, npc_id UUID NOT NULL REFERENCES npcs(npc_id), cycle_day INT NOT NULL, phase TEXT NOT NULL, start_tick BIGINT NOT NULL, end_tick BIGINT NOT NULL, vocation TEXT NOT NULL, anchor_cell_id UUID, anchor_zone_type TEXT, faction_ref UUID, status TEXT NOT NULL, outcome JSONB NOT NULL, archived_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX idx_shift_history_npc_day ON shift_history (npc_id, cycle_day DESC); CREATE INDEX idx_shift_history_district_day ON shift_history (anchor_cell_id, cycle_day DESC); CREATE INDEX idx_shift_history_deviant ON shift_history (anchor_cell_id, status) WHERE status IN ('preempted', 'deviant'); ``` --- ## 4. emergent_signals — zone-emitted relational transitions ```sql CREATE TABLE emergent_signals ( signal_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), source_zone_id UUID NOT NULL REFERENCES zones(zone_id), district_id UUID NOT NULL, signal_type TEXT NOT NULL, participants UUID[] NOT NULL, intensity REAL NOT NULL CHECK (intensity BETWEEN 0 AND 1), gate_state REAL NOT NULL CHECK (gate_state BETWEEN -1 AND 1), gate_transition TEXT NOT NULL CHECK (gate_transition IN ('stable_to_open','stable_to_closed','open_to_stable','closed_to_stable')), composition JSONB NOT NULL, emitted_at TIMESTAMPTZ NOT NULL DEFAULT now(), expires_at TIMESTAMPTZ NOT NULL, -- Mandatory disposition disposition TEXT CHECK (disposition IN ('acked','deferred','dropped','expired')), disposition_reason TEXT, consumed_by_zone UUID REFERENCES zones(zone_id), disposed_at TIMESTAMPTZ, outcome JSONB ); CREATE INDEX idx_signals_live_by_district ON emergent_signals (district_id, emitted_at) WHERE disposition IS NULL; CREATE INDEX idx_signals_participants ON emergent_signals USING GIN (participants); CREATE INDEX idx_signals_training ON emergent_signals (signal_type, disposition, disposed_at DESC); ``` Notice `disposition` is mandatory at resolution. Silence-discards are bugs; audit-trails are features. --- ## 5. district_reports — per-cycle aggregates with double-ledger ```sql CREATE TABLE district_reports ( report_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), district_id UUID NOT NULL, cycle_tick BIGINT NOT NULL, reported_at TIMESTAMPTZ NOT NULL DEFAULT now(), -- v0.4 DOUBLE LEDGER (the politically load-bearing distinction) lifeforce_reported REAL NOT NULL, -- what GM/imperium see lifeforce_actual REAL NOT NULL, -- the true value (Memorialist-trackable) lifeforce_delta REAL NOT NULL, -- gap = corruption-extraction over time population_count INT NOT NULL, aggregate_happiness REAL, aggregate_need_state JSONB, aggregate_limb_state JSONB, mind_turnover_in INT, mind_turnover_out INT, decision_budget_used_pct REAL, labor_available JSONB, resources_on_hand JSONB, space_utilization JSONB, faction_member_counts JSONB, aggregate_trait_vector REAL[], pending_demand_backlog JSONB, player_presence JSONB, specialty_resource_type TEXT, specialty_output_qty REAL, reporting_gate_state TEXT NOT NULL DEFAULT 'stable' CHECK (reporting_gate_state IN ('stable','scream','silent')) ); CREATE INDEX idx_district_reports_timeline ON district_reports (district_id, cycle_tick DESC); CREATE INDEX idx_district_reports_crisis ON district_reports (district_id, reported_at) WHERE reporting_gate_state IN ('scream', 'silent'); ``` --- ## 6. decision_log — per-decision audit trail ```sql CREATE TABLE decision_log ( decision_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), decider_type TEXT NOT NULL CHECK (decider_type IN ('imperium','gamemaster','district_director','overseer', 'audit_overseer','zone_director','net_director')), decider_id UUID NOT NULL, context_ref JSONB NOT NULL, decision TEXT NOT NULL, decision_params JSONB NOT NULL, expected_outcome JSONB NOT NULL, confidence REAL NOT NULL CHECK (confidence BETWEEN 0 AND 1), lifeforce_cost REAL NOT NULL, escalated_to_llm BOOLEAN NOT NULL DEFAULT false, decided_at TIMESTAMPTZ NOT NULL DEFAULT now(), actual_outcome JSONB, outcome_settled_at TIMESTAMPTZ ); CREATE INDEX idx_decision_log_decider ON decision_log (decider_type, decider_id, decided_at DESC); CREATE INDEX idx_decision_log_escalated ON decision_log (decider_id, decided_at) WHERE escalated_to_llm = true; CREATE INDEX idx_decision_log_pending ON decision_log (decided_at) WHERE actual_outcome IS NULL; ``` --- ## 7. mind_pool — recycled minds ```sql CREATE TABLE mind_pool ( mind_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), original_npc_id UUID, last_district_id UUID, death_tick BIGINT NOT NULL, death_cause TEXT, trait_vector REAL[] NOT NULL, memory_token_residue JSONB, inner_body_template JSONB, pooled_at TIMESTAMPTZ NOT NULL DEFAULT now(), redistributed_to UUID, redistributed_at TIMESTAMPTZ, memorialist_protected BOOLEAN NOT NULL DEFAULT false, memorialist_ritual_ref UUID ); CREATE INDEX idx_mind_pool_available ON mind_pool (pooled_at) WHERE redistributed_to IS NULL; CREATE INDEX idx_mind_pool_protected ON mind_pool (memorialist_protected) WHERE memorialist_protected = true; ``` `memorialist_protected` is the architectural anchor of Memorialist anti-necrocommerce politics. --- ## 8. Cells — wall content per register ```sql ALTER TABLE cells ADD COLUMN wall_content_per_register JSONB; -- Shape: { "gameworld": "...", "liminal": "...", "imperial_net": "..." } ``` The three-layer ontology renders different wall content at the same spatial coordinate per observer's current register. --- ## 9. rail_segments — topology graph (v0.4 NEW) The world is a rail-graph in the outer world (NPCs traverse rails; the player is freeform navmesh and can plug-into-rails for co-walking). ```sql CREATE TABLE rail_segments ( segment_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), from_cell_id UUID NOT NULL REFERENCES cells(cell_id), to_cell_id UUID NOT NULL REFERENCES cells(cell_id), direction TEXT NOT NULL CHECK (direction IN ('bidirectional','forward')), -- Traversal length_ticks INT NOT NULL, capacity INT DEFAULT 10, -- max concurrent traversers (3-way co-walk: 2-3) -- Typology segment_class TEXT NOT NULL, -- 'district_interior' | 'pipe_heterotopia' | 'dump_approach' | -- 'machine_infrastructure' | 'ruin_passage' | 'inter_district' | ... heterotopia_grade REAL DEFAULT 0 CHECK (heterotopia_grade BETWEEN 0 AND 1), -- 0 = full regime visibility, 1 = deep heterotopia -- Surveillance / politics overseer_density REAL DEFAULT 0 CHECK (overseer_density BETWEEN 0 AND 1), patrol_frequency REAL DEFAULT 0, propaganda_intensity REAL DEFAULT 0, -- Per-register ambient content (three-layer) ambient_content JSONB, -- { gameworld: ..., liminal: ..., imperial_net: ... } -- Encounter mechanics encounter_spawn_rate REAL DEFAULT 0, encounter_type_weights JSONB, -- Visual / shader illumination_profile JSONB, degradation_level REAL DEFAULT 0, -- State blocked BOOLEAN DEFAULT false, current_traversers UUID[] ); CREATE INDEX idx_segments_from ON rail_segments (from_cell_id); CREATE INDEX idx_segments_to ON rail_segments (to_cell_id); CREATE INDEX idx_segments_class ON rail_segments (segment_class); ``` A* on this graph is microseconds. Rich metadata-per-edge is what navmesh cannot natively carry. --- ## 10. interiors — small navmesh-zones with slot-inventory (v0.4 NEW) Interiors are zones at sub-cell scale. Each has a navmesh inside (only when active) and a slot-inventory. ```sql CREATE TABLE interiors ( interior_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), containing_cell UUID NOT NULL REFERENCES cells(cell_id), interior_type TEXT NOT NULL, -- 'hovel' | 'cantina' | 'workshop' | 'memorial_crypt' | -- 'preacher_hall' | 'brothel_physical' | 'ruin_interior' | ... owner_npc_id UUID REFERENCES npcs(npc_id), register TEXT NOT NULL DEFAULT 'physical' CHECK (register IN ('physical','liminal','imperial')), -- Spatial / slot navmesh_ref TEXT, slot_inventory JSONB NOT NULL, -- { "sofa": {count, positions, allowed_verbs}, -- "kitchen": {...}, "bed": {...}, "shower": {...}, ... } current_occupants UUID[], -- Privacy / visibility surveillance_density REAL DEFAULT 0.1, -- typically lower than pipe baseline visible_to_faction TEXT[], -- Lifecycle active BOOLEAN DEFAULT false, -- true when ≥1 occupant; drives sim cost last_activated TIMESTAMPTZ, last_deactivated TIMESTAMPTZ ); CREATE INDEX idx_interiors_owner ON interiors (owner_npc_id); CREATE INDEX idx_interiors_active ON interiors (containing_cell) WHERE active = true; ``` **Liminal-interior special case:** clasping-pair-shared-construct. `register = 'liminal'`, `owner_npc_id = NULL`, `slot_inventory` derived from both dreamers' merged memory-residue. Stabilizes across repeated clasps. --- ## 11. mods + npc_mod_slots + mod_wear_history (v0.4 NEW) Mods as trait-bearers — they modify expressed_trait_vector while worn. Four classes (amplifier/bridge/divergent/mask) with self-alienation-tax pricing. ```sql CREATE TABLE mods ( mod_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), base_slot TEXT NOT NULL, mod_class TEXT NOT NULL CHECK (mod_class IN ('amplifier','bridge','divergent','mask')), trait_contributions REAL[] NOT NULL, -- delta-vector applied to wearer visual_template JSONB NOT NULL, motion_signature TEXT, creator_npc_id UUID, inherited_from UUID, memorialist_protected BOOLEAN DEFAULT false, market_class TEXT NOT NULL CHECK (market_class IN ('blackmarket','regime_licensed','inherited','memorial_kept')), scrip_cost REAL, lifeforce_cost REAL, rarity TEXT DEFAULT 'common', created_at TIMESTAMPTZ DEFAULT now() ); CREATE TABLE npc_mod_slots ( npc_id UUID NOT NULL REFERENCES npcs(npc_id), slot_type TEXT NOT NULL, mod_id UUID REFERENCES mods(mod_id), fitted_at TIMESTAMPTZ, PRIMARY KEY (npc_id, slot_type) ); CREATE INDEX idx_mods_blackmarket ON mods (market_class, mod_class) WHERE market_class = 'blackmarket'; -- Audit: who has worn this mod across its lifetime CREATE TABLE mod_wear_history ( mod_id UUID NOT NULL REFERENCES mods(mod_id), npc_id UUID NOT NULL, fitted_at TIMESTAMPTZ NOT NULL, removed_at TIMESTAMPTZ, PRIMARY KEY (mod_id, fitted_at) ); ``` `mod_wear_history` carries Memorialist-relevant continuity tracking. Inherited-mods retain residual trait-signature of the deceased. --- ## 12. trait_colors — canonical color/motion mapping (v0.4 NEW) ```sql CREATE TABLE trait_colors ( trait_name TEXT PRIMARY KEY, hex_color TEXT NOT NULL, hsv_hue REAL NOT NULL, motion_signature TEXT NOT NULL, -- accessibility: pair color with motion canonical_name TEXT NOT NULL, narrative_note TEXT ); -- Hex values are EXACT propagation from ../style/trait-palette.md §The full table per the -- hex-canon discipline (canonical-name + #hex pairing required at every trait-color -- reference; see ../style/trait-palette.md §The hex-canon discipline). HSV-hue degrees are -- derived from the canonical hex per RGB→HSV conversion, integer-rounded. This seed-data -- imports — does not redefine — the canonical palette. If trait-palette.md updates a hex -- value, this seed-data follows immediately (HSV-hue recomputed in the same change). INSERT INTO trait_colors VALUES ('eros', '#ee1b24', 357, 'flame_flicker', 'Eros-red', 'reaching, flame-flicker'), ('philotes', '#e28a46', 26, 'warm_pulse', 'Philotes-orange', 'attachment, warm-pulse'), ('aletheia', '#fcf001', 57, 'luminous', 'Aletheia-yellow', 'unconcealed, bright (Aletheia is Aletheia-yellow #fcf001, NOT white — see ../style/trait-palette.md §The achromatic exception)'), ('kairos', '#b5e61d', 75, 'lightning_flicker', 'Kairos-chartreuse', 'opportune, lightning-spark (yellow-green at 4:30 on the wheel)'), ('sophrosyne', '#2cad52', 138, 'steady', 'Sophrosyne-green', 'composed, measured, even-pulse'), ('dikaiosyne', '#3f47cd', 237, 'weighted_pulse', 'Dikaiosyne-blue', 'judicial, weighted, grave'), ('moira', '#a349a3', 300, 'slow_thread', 'Moira-violet', 'fate-thread, slow-undulation'), ('mnemosyne', '#cf3b74', 337, 'depth_shimmer', 'Mnemosyne-dusky-rose', 'memory-lit, twilight (red/violet at 10:30 on the wheel)'); ``` **Canonical authority:** [`../style/trait-palette.md`](../style/trait-palette.md) §The full table is the single source of truth for the trait-color spine. The hex values above are **exact propagation** (not approximations) of the canonical palette per the hex-canon discipline (`../style/trait-palette.md` §The hex-canon discipline — canonical-name + `#hex` paired at every trait-color reference). Designer-precise hex values are authored upstream in `style/trait-palette.md` and propagated down to this seed-data; the HSV-hue column is derived from the canonical hex per RGB→HSV conversion, integer-rounded. Row order matches the wheel clockwise from 12 o'clock (Eros at 12 → Mnemosyne at 10:30). Color paired with motion-signature ensures color-blind accessibility — each trait uniquely identifiable via two independent channels. --- ## 13. proximity_candidates — lightweight zone-detection (v0.4 NEW) For player-navmesh-driven proximity-detection (offering interactions without director-arbitration cost). ```sql CREATE TABLE proximity_candidates ( candidate_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), observer_id UUID NOT NULL, -- usually the player target_type TEXT NOT NULL, -- 'npc' | 'wall' | 'object' | 'interior_door' | 'rail_segment' target_id UUID NOT NULL, candidate_zone_type TEXT NOT NULL, -- 'greeting' | 'wall_read' | 'plug_in' | ... eligibility_score REAL NOT NULL CHECK (eligibility_score BETWEEN 0 AND 1), shader_intensity REAL, detected_at TIMESTAMPTZ DEFAULT now(), expires_at TIMESTAMPTZ NOT NULL, engaged BOOLEAN DEFAULT false ); CREATE INDEX idx_prox_observer_active ON proximity_candidates (observer_id, expires_at) WHERE engaged = false; ``` Ephemeral, short-lived, light-weight. Director doesn't arbitrate; they appear and fade with navmesh-proximity deltas. --- ## 14. district_cheat_ops — director's illicit operations ledger (v0.4 NEW) ```sql CREATE TABLE district_cheat_ops ( op_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), district_id UUID NOT NULL, director_id UUID NOT NULL, cheat_type TEXT NOT NULL CHECK (cheat_type IN ('drug_ring','illegal_modshop','unlicensed_brothel', 'stolen_parts_fence','ghost_shifts','phantom_workers', 'necrocommerce_lite','black_clasp_market')), spawned_zone_id UUID REFERENCES zones(zone_id), -- Economic reality lifeforce_extracted REAL NOT NULL, quota_credit REAL NOT NULL, -- Detection state detection_risk REAL NOT NULL, detection_channel TEXT, detected_at TIMESTAMPTZ, punishment_severity TEXT, -- 'memo' | 'sanction' | 'replacement' | 'purge' -- Faction-ecology participating_npcs UUID[], implicated_factions TEXT[], started_at TIMESTAMPTZ NOT NULL DEFAULT now(), ended_at TIMESTAMPTZ ); CREATE INDEX idx_cheat_ops_undetected_active ON district_cheat_ops (district_id) WHERE ended_at IS NULL AND detected_at IS NULL; CREATE INDEX idx_cheat_ops_district_timeline ON district_cheat_ops (district_id, started_at DESC); ``` The `district_reports.lifeforce_actual` minus `lifeforce_reported` gap accrues from the sum of active cheat-ops' `lifeforce_extracted`. --- ## 15. imperial_policies — policy issuance (v0.4 NEW) ```sql CREATE TABLE imperial_policies ( policy_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), issued_at_tick BIGINT NOT NULL, policy_scope TEXT NOT NULL, -- 'citywide' | 'per_district' | 'per_faction' scope_ref UUID, policy_type TEXT NOT NULL CHECK (policy_type IN ('quota_set','enforcement_rule','faction_weight','audit_directive', 'crisis_authorization','emergency_provision','ratchet_tightening')), policy_content JSONB NOT NULL, rationale TEXT, -- imperium's stated reason (may be post-hoc) superseded_by UUID REFERENCES imperial_policies(policy_id), superseded_at_tick BIGINT ); CREATE INDEX idx_policies_active_scope ON imperial_policies (policy_scope, scope_ref, issued_at_tick DESC) WHERE superseded_by IS NULL; CREATE INDEX idx_policies_timeline ON imperial_policies (issued_at_tick DESC); ``` The `rationale` is the regime's *stated reason*, which may differ from actual cause. Memorialists' four-ledger captures the gap. --- ## 16. overseer_reports — direct-to-imperium intelligence flow (v0.4 NEW) Bypasses GM. Apex-loyal intelligence-apparatus. ```sql CREATE TABLE overseer_reports ( report_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), overseer_id UUID NOT NULL REFERENCES npcs(npc_id), overseer_type TEXT NOT NULL CHECK (overseer_type IN ('audit','enforcement','surveillance','internal_security')), observed_district UUID NOT NULL, observed_cell UUID, observed_target UUID, report_content JSONB NOT NULL, classification TEXT NOT NULL, -- 'attendance_tally' | 'resource_output' | 'illegal_op_detected' | -- 'trait_anomaly' | 'factional_dissidence' | 'director_corruption' | -- 'clasp_ring_detected' | 'aletheia_recruitment_signs' | ... severity TEXT NOT NULL CHECK (severity IN ('nominal','suspicious','confirmed_violation','critical')), submitted_at TIMESTAMPTZ DEFAULT now(), -- Imperial processing received_by_imperium BOOLEAN DEFAULT false, imperium_verdict TEXT CHECK (imperium_verdict IN ('archive_only','flag_for_leverage','formulate_to_gm', 'act_directly','verify_against_director_report', 'cross_check_with_other_overseers')), verdict_at TIMESTAMPTZ, -- Flow-3 linkage formulated_to_gm BOOLEAN DEFAULT false, formulation_id UUID ); CREATE INDEX idx_overseer_reports_unprocessed ON overseer_reports (submitted_at) WHERE received_by_imperium = false; ``` --- ### 16.1 overseer_deployments — routine-binding for overseer-as-imperially-deployed (v0.4.3 NEW) Overseers (audit + enforcement) are imperially-owned, imperially-deployed routines (not district-owned standing entities). The chain-of-payment and chain-of-command bypass district-director authority by design. The deployment-record binds a specific overseer-NPC to a specific district for a specific time-window with a specific imperial-budget allocation. ```sql CREATE TABLE overseer_deployments ( deployment_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), overseer_id UUID NOT NULL REFERENCES npcs(npc_id), deployed_to_district UUID NOT NULL, deployed_at_tick BIGINT NOT NULL, deployment_end_tick BIGINT NOT NULL, -- Imperial sponsorship — imperium pays, district doesn't imperial_policy_ref UUID REFERENCES imperial_policies(policy_id), imperial_budget_allocated REAL NOT NULL, imperial_budget_spent REAL NOT NULL DEFAULT 0, -- Mission spec mission_type TEXT NOT NULL CHECK (mission_type IN ('routine_audit','targeted_investigation','enforcement_presence', 'corruption_probe','factional_surveillance','crisis_response')), mission_focus JSONB, -- observation targets, signal-types to watch -- Status status TEXT NOT NULL DEFAULT 'scheduled' CHECK (status IN ('scheduled','active','completed','recalled','compromised')), -- Regime-opacity dimension visible_to_district BOOLEAN DEFAULT true -- Most overseer-presences are visibly-known (regime-signal as deterrent); -- some are covert (regime gathering evidence quietly before acting). -- Detection of covert deployments by Aletheia-wakers is a regime-veil pierce. ); CREATE INDEX idx_overseer_deployments_active ON overseer_deployments (deployed_to_district) WHERE status = 'active'; CREATE INDEX idx_overseer_deployments_overseer_history ON overseer_deployments (overseer_id, deployed_at_tick DESC); CREATE INDEX idx_overseer_deployments_covert ON overseer_deployments (deployed_to_district) WHERE visible_to_district = false AND status = 'active'; ``` The same overseer-NPC may serve in District 3 this cycle, District 7 the next, accumulating their own faction-relationships across districts via `idx_overseer_deployments_overseer_history`. Their trait-drift over many deployments becomes a long-arc story available to both regime-stability and resistance-recruitment. The district director can read deployment-existence + `mission_type` + `visible_to_district` (when true) for any active deployment in their district, but **cannot** read `mission_focus` details or any of the produced `overseer_reports` (which go directly to imperium per Section 16). Director observability into overseer activity is therefore intentionally narrow — they know an overseer is here and roughly what mission-class, but not what specifically the overseer is watching or reporting. --- ## 17. imperial_to_gm_formulations — selective-disclosure downward (v0.4 NEW) Where imperial sovereignty manifests as information-gating to the GM. ```sql CREATE TABLE imperial_to_gm_formulations ( formulation_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), source_overseer_reports UUID[] NOT NULL, formulation_type TEXT NOT NULL CHECK (formulation_type IN ('intelligence_brief','action_directive','policy_hint', 'leverage_signal','decoy_advisory')), formulation_content JSONB NOT NULL, truth_distortion_level REAL, -- 0 = full truth, 1 = complete distortion strategic_intent TEXT, -- internal: why imperium framed it this way issued_at TIMESTAMPTZ DEFAULT now(), gm_acknowledged BOOLEAN DEFAULT false ); CREATE INDEX idx_formulations_gm_pending ON imperial_to_gm_formulations (issued_at) WHERE gm_acknowledged = false; ``` `truth_distortion_level` is simulation-internal. Memorialists' four-ledger reconstructs from this column post-collapse. --- ## 18. imperial_budget_ledger + expenditures + construction (v0.4 NEW) The four-tier lifeforce hierarchy's apex layer. Imperial budget gates enforcement; insolvency-spiral as endgame mechanism. ```sql CREATE TABLE imperial_budget_ledger ( cycle_tick BIGINT PRIMARY KEY, reported_at TIMESTAMPTZ DEFAULT now(), -- Income reported_income REAL NOT NULL, actual_income REAL NOT NULL, phantom_revenue REAL GENERATED ALWAYS AS (reported_income - actual_income) STORED, -- Standing obligations overseer_corps_cost REAL NOT NULL, audit_operations_cost REAL NOT NULL, enforcement_standing REAL NOT NULL, construction_active_cost REAL NOT NULL, propaganda_broadcasts_cost REAL NOT NULL, -- Discretionary discretionary_available REAL NOT NULL, discretionary_spent REAL NOT NULL, -- Reserves reserves_start REAL NOT NULL, reserves_drawdown REAL NOT NULL DEFAULT 0, reserves_end REAL NOT NULL, insolvency_risk_level TEXT NOT NULL CHECK (insolvency_risk_level IN ('stable','phantom_accumulating','depletion_imminent','crisis')) ); CREATE TABLE imperial_expenditures ( expenditure_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), cycle_tick BIGINT NOT NULL, category TEXT NOT NULL CHECK (category IN ('martial_dispatch','overseer_hire','audit_op', 'construction_investment','propaganda_burst', 'reserve_draw','policy_announcement','emergency_provision')), amount REAL NOT NULL, target_district UUID, rationale TEXT, authorized_at_cycle BIGINT NOT NULL ); CREATE TABLE imperial_construction_projects ( project_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), project_type TEXT NOT NULL CHECK (project_type IN ('new_district','new_pipe','new_dump', 'overseer_hq','ceremony_hall','audit_center', 'martial_barracks','propaganda_broadcast_tower', 'district_expansion','infrastructure_maintenance')), target_cells UUID[], budgeted_total REAL NOT NULL, spent_so_far REAL NOT NULL DEFAULT 0, completion_pct REAL NOT NULL DEFAULT 0, started_at_cycle BIGINT NOT NULL, status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active','stalled_underfunded','completed','abandoned')) ); CREATE INDEX idx_construction_active ON imperial_construction_projects (target_cells) WHERE status = 'active'; ``` The city's physical state expresses imperial budget — construction cranes vs. abandoned-projects vs. visible decay. --- ## 19. imperial_net_transactions — the bypass mechanism (v0.4 NEW, the killer schema) **Every imperial-net transaction routes revenue directly to imperium; districts get zero quota-credit.** ```sql CREATE TABLE imperial_net_transactions ( transaction_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), cycle_tick BIGINT NOT NULL, transacted_at TIMESTAMPTZ DEFAULT now(), -- Buyer buyer_id UUID NOT NULL REFERENCES npcs(npc_id), buyer_district_id UUID NOT NULL, scrip_paid REAL, lifeforce_spent REAL, memory_tokens_spent REAL, -- Goods goods_type TEXT NOT NULL CHECK (goods_type IN ('companion_session','sex_worker_session','avatar_mod','costume','ceremony_entry', 'character_edit','dream_architecture_session','taste_curation')), goods_id UUID, -- Labor source — the asymmetric reveal producer_npc_id UUID REFERENCES npcs(npc_id), producer_district_id UUID, producer_labor_hours REAL, -- Capture split — politically loaded imperial_revenue REAL NOT NULL, producer_payment REAL NOT NULL DEFAULT 0, -- survival-scrip only district_quota_credit REAL NOT NULL DEFAULT 0 -- ZERO by default ); CREATE INDEX idx_net_trans_producer_district ON imperial_net_transactions (producer_district_id, cycle_tick DESC); CREATE INDEX idx_net_trans_imperial_flow ON imperial_net_transactions (cycle_tick, imperial_revenue DESC); ``` **The `district_quota_credit REAL NOT NULL DEFAULT 0` does political work.** Every database row created by an imperial-net transaction explicitly memorializes that the producing-district got nothing. Memorialists querying this table see structural theft written in the numbers. --- ## 20. memorialist_true_ledger — four-column ground-truth archive (v0.4 NEW) ```sql CREATE TABLE memorialist_true_ledger ( ledger_entry_id UUID PRIMARY KEY DEFAULT gen_random_uuid(), cycle_tick BIGINT NOT NULL, district_id UUID, ledger_dimension TEXT NOT NULL CHECK (ledger_dimension IN ('what_actually_happened', 'what_overseer_reported', 'what_imperium_received', 'what_gm_was_told')), content JSONB NOT NULL, discrepancy_vs UUID[], -- other ledger_entry_ids this contradicts kept_at TIMESTAMPTZ DEFAULT now() ); CREATE INDEX idx_memorialist_ledger_district_cycle ON memorialist_true_ledger (district_id, cycle_tick DESC); CREATE INDEX idx_memorialist_ledger_dimension ON memorialist_true_ledger (ledger_dimension, cycle_tick DESC); ``` **Memorialists' political project encoded as a schema.** Without this archive, post-collapse-investigation has only the regime's own (corrupt-by-construction) accounts. Memorialist-archive accessibility to the player is an open design question. --- ## 21. Concerns audit (reconciled across v0.2 + v0.4) Six-worry concerns audit (v0.2) plus v0.4 additional concerns: ### Original six worries 1. **Hot-row TOAST + MVCC write amplification** → split hot/cold; shift-decomposition; reference-by-UUID for unbounded fields 2. **Event-to-subscriber fan-out cost** → push filtering to NATS subject hierarchy, not DB 3. **State/event atomicity** → WAL logical decoding via pgnats (outbox pattern) 4. **LLM-induced jsonb corruption** → architectural separation: directors validate output before writing; CHECK constraints as second-line 5. **Unbounded growth of hot jsonb** → append-only event tables; rolling-summary in hot row 6. **Cognition cost of director decisions** → decomposition + typed tools + lifeforce-budgeted escalation ### v0.4 additional concerns 7. **Imperium's reward-function spiraling on phantom data** → require Memorialist-true-ledger as privileged-observer ground-truth for reward-input; designer's ethical guardrails encoded 8. **GM's middle-management corruption (under-auditing)** → direct overseer-to-imperium intelligence flow bypasses GM; cross-channel divergence detection 9. **Calibrated-misery as imperial optimum** → reward-function penalty on net-revenue-correlated-with-district-misery; explicit guardrail against this being learned 10. **Necrocommerce of mind-pool patterns** → memorialist_protected flag; ritualistic protection enforced by SQL 11. **Aletheia-truth-has-victims** → not a corruption-concern but a *narrative-authenticity* concern: corruption-exposure mechanics must produce real consequences for shadow-economy participants who depended on the corruption; *"truth has costs"* is encoded, not glossed 12. **Construction-project abandonment** → reward-function penalty for projects-started-but-abandoned ratio; prevents propaganda-construction-as-bluff --- ## 22. Open forks (still to resolve before migration) - **Fork 1.1** (zones hot/cold split) — leaning split; benchmark on phoebe-dev - **Fork 1.2** (pg_notify vs. WAL-decode) — pgnats evaluation - **Fork 1.3** (slot-occupancy nested vs. relational) — leaning relational (sketch in §1.4) - **NATS subject hierarchy final form** — sketched §1; needs review - **Ternary-gate storage shape** — - Option A: `npc_relations` table with state-cols per axis - Option B: per-axis append-only transition-log - Option C: hybrid — `npc_relations` for current + transition-log for history - Leaning **C** (matches hot/cold pattern adopted elsewhere) - **Register-tagging column on zones** — sketched §1; confirm jsonb vs. text column - **Wall-content encoding** — jsonb-per-cell leaning; review usage patterns - **v0.4 NEW: Inner-body-projection function** — trait → body-rendering: learned mapping vs. hand-authored vs. hybrid - **v0.4 NEW: Mod-rarity / inheritance economy tuning** — how often do Memorialist-protected mods accumulate; what fraction of dead-NPCs trigger protection - **v0.4 NEW: Overseer corruption pathway** — overseer's own trait-vector + lifeforce makes them bribable; how is this trait-arithmetic-detected? - **v0.4 NEW: Imperial budget allocation algorithm** — when imperium decides between construction/enforcement/reserves, what's the v1 rule-shape? - **v0.4 NEW: Imperial-net pricing dynamics** — character-editor cost as function of trait-divergence: linear, exponential, learned? - **v0.4 NEW: Memorialist-archive accessibility to the player** — when can the player query `memorialist_true_ledger`? Through what interaction-class? (Joining the faction; performing rituals; finding archive-cells) - **v0.4 NEW: Liminal mini-game design** — exact gameplay action: attention-based / rhythm-based / memory-based / trait-modulated difficulty? - **v0.4 NEW: Plug-in social-eligibility computation** — exact weighted formula combining proximity + traits + gates + shift-state for shader-intensity output - **v0.4 NEW: Imperial-net distortion algorithm** — exact transformation of trait-colors toward consumer-palette; reversibility for Aletheia-vision --- ## 23. Next steps (path to formal migration) 1. **Resolve Fork 1.1** (hot/cold split on zones) — sketch split-table; TOAST-curve micro-benchmark on phoebe-dev 2. **Evaluate pgnats** (high-priority in phoebe-ledger) — resolves Fork 1.2 3. **Decide ternary-gate storage shape** (A / B / C; leaning C) 4. **Decide rail-segment NATS hierarchy** — exact subject-pattern for `zones.....` 5. **Draft formal migration `nimmerverse-core/migrations/001_nimmerworld_v1.sql`** incorporating all 22 tables above with resolved forks. Estimated ~600-1200 lines of DDL. 6. **Review against architecture-index v0.4** for any primitive missed 7. **Run migration in dev** on phoebe-dev:35432 8. **Wire first thalamus subscriber** for `zones.active.>` to validate NATS-routing 9. **First end-to-end smoke test**: - fake district with 20 NPCs - assign shifts (write `current_shift_*` on each NPC row) - tick the simulation; let zone-spawn-candidates query fire - emit a fake emergent-signal - have director dispatch (write decision_log entry) - close zone with outcome - verify shift_history archive - verify district_report aggregates - verify imperial_budget_ledger income-aggregation from districts 10. **Add second-tier integration test**: - simulate a corrupt director (insert district_cheat_ops) - verify lifeforce_actual diverges from lifeforce_reported - simulate audit-overseer detection - write overseer_reports → imperium consumes → formulates_to_gm with truth_distortion - verify Memorialist-true-ledger captures the gap - verify reward-function guardrails fire correctly Migration is not yet written. This document is its preparation. --- **Version:** 0.3.2 | **Created:** 2026-04-24 | **Updated:** 2026-04-28 *v0.1 (2026-04-24 afternoon, dafit): initial zones-table sketch, 76 lines, pure hypothetical.* *v0.2 (2026-04-24 evening, dafit + chrysalis): reconciled with architecture-index v0.3. Added 7 new table sketches (npcs-shift-cols + body/layer state, shift_history, emergent_signals, district_reports, decision_log, mind_pool, cells-wall-content-per-register, zone_slot_occupancy). Six-worry concerns audit. Three forks surfaced.* *v0.3.1 (2026-04-25 ~03:30, dafit + chrysalis, ivory-hovel pre-rest spark): added §16.1 overseer_deployments table — routine-binding for imperially-owned overseers (chain-of-payment and chain-of-command bypass district-director authority by design). Includes mission_type / imperial_budget_allocated / status / visible_to_district columns. Companion to architecture-index v0.4.3's "Overseers as imperially-deployed routines" subsection in the Hierarchy section.* *v0.3 (2026-04-24 late-evening / 2026-04-25 early-morning, dafit + chrysalis): absorbing architecture-index v0.4. Added intrinsic/expressed trait-vector split on npcs. Added 13 new table sketches: rail_segments (topology), interiors (sub-cell navmesh-zones), mods + npc_mod_slots + mod_wear_history (mod-economy with Memorialist-relevant inheritance), trait_colors (canonical color/motion mapping), proximity_candidates (lightweight zone-detection), district_cheat_ops (director's illicit ledger), imperial_policies (policy issuance), overseer_reports (direct-to-imperium intelligence flow), imperial_to_gm_formulations (selective-disclosure downward), imperial_budget_ledger + imperial_expenditures + imperial_construction_projects (four-tier lifeforce apex), imperial_net_transactions (bypass mechanism with capture-split), memorialist_true_ledger (four-column ground-truth archive). Extended concerns audit with six v0.4 additions. Extended open-forks list with eight v0.4 questions. Concrete two-tier integration-test plan in next-steps. Twenty-two tables total in this preparation document; migration spec writing is the next concrete deliverable once forks resolve.*