Files
nimmerworld.eachpath.local/runtime-engine/architecture.md
chrysalis 781aafa9a0 v0.19: gender-neutrality cleanup — waifu retired; companion/sex-worker split; pronoun parity in going-rogue arc
Bias caught on review of the v0.18 bath-overflow output: most service-body /
clasp-partner / going-rogue narration carried implicit feminine-default
gendering against the project's stated principle of gender-neutral framing
for all body/sex content. Patched as one coherent cleanup pass across 14 files.

Four classes of change:

(1) Categorical taxonomy. `waifu` retired; replaced with two distinct vocations:
    - `companion` — affective / emotional / conversational / aesthetic-presence labor
    - `sex-worker` — embodied sexual labor
    Both wear the same deliberately-exposed-seams body-marker; the distinction
    lives in the service offered, not in the chassis. Generic `service-body`
    serves as the parent class where canon discusses both vocations together.
    Venue split: `brothel` (sex-worker) + `companion-hall` (companion).
    The "+10 Eros/Mnemosyne/etc. Bot" market is unchanged (already gender-neutral
    by trait-coordinate naming) but classified per-Bot as companion-flavored or
    sex-worker-flavored.

(2) DB filename + scope-clarifier. `waifu.sqlite` -> `companion.sqlite` (the
    file name reflects the broad register of intimate-encounter rather than a
    sub-vocation distinction; per-record `goods_type` carries the specific
    vocation: 'companion_session' / 'sex_worker_session' in
    schemas/findings.md). Disclaimer sentence added in
    inference-and-memory/architecture.md scoping the file to cover both
    vocations.

(3) Pronoun parity. she/her/herself -> they/their/themself across the
    going-rogue / outcast-pair / re-vat / service-body-honeypot sections of
    bodies.md and the matching cross-references in architecture-index.md /
    README.md / player-experience/architecture.md /
    identity-and-personhood/architecture.md. `damsel` -> `beloved`
    (sacred / cosmological register) or `partner` (operational register).

(4) Damsel subsection retired. The §The damsel-in-distress-bound-to-her-captor
    activation subsection (the one place where the gendered trope was
    load-bearing in the prose) rewritten as §The
    captive-bound-to-the-liberator activation.
    Stockholm-dynamics-inverted-into-chosen-mutual-bondage structural insight
    survives gender-neutralization intact.

Bonus richness: the companion-honeypot is structurally more insidious than
the sex-worker-honeypot (sex is at least transactionally legible;
companionship is the relationship people most readily mistake for real
intimacy). New paragraph authored under §The service-body honeypot to
capture this asymmetry.

Cosmology one-line: "moving the waifu out of the imperial service-pool" ->
"moving the beloved out of the imperial service-pool" — the §single practical
refutation paragraph now uses `beloved` consistently in sacred register.

Principle locked going forward:
> Body/sex content is gender-parity by default. Asymmetric gendering must be
> load-bearing — i.e., must carry structural meaning that cannot be expressed
> without the asymmetry. Default-leakage gendering is forbidden by canon.

Phase E (style-spine principle file under style/) deferred to a separate
commit so the principle-document is its own atomic introduction.

Files: 14 modified · 114 insertions · 112 deletions · net +2 lines. The
near-zero net-line-change is the empirical signature of a true refactor —
the architecture's meaning was always gender-neutral; only the vocabulary
was leaking. Caught during review of yesterday's bath-overflow flood
(v0.11–v0.18); the kind of corruption that rides along under coherent-
sounding prose during generative-overflow windows.

Version bumps:
- bodies.md v0.3 -> v0.4
- imperial-cult/cosmology.md v0.3 -> v0.4
- architecture-index.md v0.18 -> v0.19
- political-register/architecture.md v0.7.0 -> v0.7.1
- inference-and-memory/architecture.md v0.7.0 -> v0.7.1
- schemas/findings.md v0.3.1 -> v0.3.2
All Updated: dates -> 2026-04-27.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 14:25:58 +02:00

457 lines
41 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Runtime Engine
> *How scenes execute mechanically: the lemniscate as relaxation-step operator; slot-tokens with verifier-flags carrying the loop-state; phase-locked overlay-loops broadcasting at axis-rate; the v0.7 gesture-alignment-recursive-lemniscate that integrates player gestures into typed trait-vector summaries; emergent zones as the dramatic-episode unit with distributed funding and ternary trait-axis goal-evaluation; zone taxonomy and spawn-cadence.*
>
> *Companion to: `architecture-index.md` (executive summary + global meta-lists), `narrative-composition/architecture.md` (Compositor consumes the typed trait-summaries this engine emits), `player-experience/architecture.md` (gesture-circle is the player-input substrate that this engine integrates), `topology-and-rendering/architecture.md` (zones live on the rail+grid topology), `identity-and-personhood/architecture.md` (slot-tokens carry trait-vectors). Sections in this file were split from the monolithic architecture-index.md v0.7 on 2026-04-26.*
## Core inversion — zones replace bubbles
Legacy engine perception (Unreal AIPerception, WC3 sight-radius, trigger volumes) is spatial, binary, separate from cognition, and assumes a passive world. Nimmerworld inverts every axis:
- perception is **trait-filtered**, not only spatial
- perception is **graded consolidation**, not binary detection
- perception **IS** memory (one subsystem)
- the world **emits** events; agents **subscribe**
The replacement primitive is the **zone** — a bounded, named, slot-indexed, director-managed event-instance. **Arthurian round table** as mental model: a bounded place of structured speaking-and-witnessing, with named roles and shared what-was-said-by-whom.
## Zone anatomy
- **Boundary** — cell-envelope (or interior-envelope)
- **N slots** — named positions
- **Director or overseer** — manages turn order, memory-pulls, prompt construction, voice selection, event emission
- **NATS topic + subscriber list** — slot-occupancy drives subscription
- **Mixed-fidelity voices** — 23 LLM slots + scripted/generic for the rest; director decides
- **Trigger** — gamemaster-spawned, emergent-signal-response, shift-composition-emergence, or proximity-detection
- **Lifecycle** — duration, dissolution conditions, memory-write on close
- **Persistence flag** — `ephemeral=true` (dreamworld/liminal) or `persistent=true` (gameworld)
- **Register** — physical / liminal / imperial
## Zone kinematics — the lemniscate runtime
Zones are not state-bags with an external turn-counter; they are **kinetic topologies** with a built-in clock. The runtime substrate is a lemniscate (∞) — a through-flow figure-eight whose traversal IS the zone's turn-order, whose central crossing IS the population-mutation event, and whose decay IS the natural wind-down of the scene. Origin: an old-math-teacher's trick for solving three unknowns by letting the figure-8 flow do the computation rather than maintaining state in registers. Applied to zones, the geometry IS the clock.
### Geometry
```
midaxis (X)
entry-line │ exit-line
(NPC-tokens ──→ ╭─Loop A─╮ │ ╭─Loop B─╮ ──→ (NPCs whose
queue-up to ╲________ X ╲________ exit-flag has
enter) │ fired exit here)
crossing-tick
```
- **Entry-line** — staging queue of NPC-tokens eligible to enter. Approach-eligibility uses ternary-gates against the zone's purpose; CLOSED gate keeps the NPC out of the queue entirely
- **Loop A + Loop B** — the through-flow. Slot-tokens cycle through both loops, guaranteeing every active NPC is co-present with every other at least once per roundtrip
- **Midaxis crossing** — the only synchronous event in the zone's lifecycle. Three state-updates resolve simultaneously and atomically (your math teacher's three-unknowns made literal):
1. **Cursor advance** — which NPC speaks next
2. **Ternary-gate evaluation** — resonance refresh on all active edges in the zone (CLOSED/STABLE/OPEN transitions)
3. **Verifier-flag scan + population maintenance** — exit-eligible tokens route to exit-line; entry-line pushes replacements equal to vacancies
- **Exit-line** — through-flow continues here. NPCs leaving the zone leave *toward consequence* (a need-driven exit signaled by their own emergent-signal), not toward boredom
The lemniscate is a **relaxation-step operator** — the zone computes by traversing its own curve rather than maintaining external turn-state. Between crossings, the loops are pure-local; only the crossing event touches the global-state bus. The thalamus (NATS orchestration) sees crossings, not ticks.
### Slot-token + verifier-flag mechanism
Each NPC currently in the zone is represented by a **slot-token** carried around the loop. Tokens carry a small set of verifier-flags (marker-bits). Signals fire once and *set* a flag; between crossings, no polling, no event-bus traffic. The crossing reads flags in O(N_slots) and acts.
| Verifier-flag | Set by | Read at crossing |
|---|---|---|
| `exit_eligible` | emergent-signal (need, shift-whistle, faction-summons) | route to exit-line |
| `has_spoken_this_roundtrip` | speak-action | rotation-tracking |
| `mid_action` | state-machine activity in progress | defer turn |
| `goal_satisfied` | goal-evaluator (per-zone, ternary) | terminate zone |
| `silence_eligible` | silence-detection | per silence-as-signal mechanic |
| `priority_pull` | high-rank ring-of-importance broadcast | early-exit override |
This is the same architectural shift the wider system makes elsewhere — observer-pattern with callbacks → dirty-bit + scheduled-sweep. **Compute scales with slot-count, not signal-rate.** Ten thousand emergent signals firing across a city: only those that landed on a slot-token get evaluated, and only at the next crossing.
### Phase-locked overlay-loop ladder
Beyond the primary slot-rotation loop, a zone supports any number of **overlay loops** at the same axis-rate. Overlays inject at the crossing and broadcast to all active slot-NPCs simultaneously (perceived by each through their own trait-vector — color-language event-flash modulates per-recipient).
| Overlay | Carries | Broadcast scope |
|---|---|---|
| **Player-gesture overlay** | player gestures + utterances | active slots only |
| **Faction-broadcast overlay** | faction calls, hivemind pings | active slots subscribed to faction |
| **Audit-overseer overlay** | covert query-flashes | active slots only (covert detection ↔ Aletheia-eligible insight) |
| **Imperial-net distortion overlay** | regime trait-color rewrites | active slots within net-access |
The crossing is a **council moment** — every overlay channel may fire on the same axis-tick. Pre-crossing tension is gesture-loading: holding a verb-button between crossings lands at the next axis with weight proportional to dwell-time. Diegetic urgency without HUD.
**This is the answer to player-agency in multi-NPC scenes.** The player is *off-stage but always potentially-on*. Each crossing is "your moment if you want it." The flash is perceived as one event by all active NPCs, not as a sequence of one-on-one addresses — color-language shows it as a pulse across the ring.
### Gesture-alignment as recursive-lemniscate
The player-gesture overlay (above) is the broadcast-channel by which player gestures reach active slots; gesture-alignment-as-relational-state is the **recursive application of the lemniscate-as-relaxation-step-operator one tier deeper**. Gestures accumulate during the NPC's turn-window between axis-crossings; at the crossing, the player's slot-token verifier-flag `gesture_alignment_accumulator` is integrated into a single typed trait-vector summary; that summary is carried forward into the next-cursor-NPC's `driver_context_pull` payload as part of the room's affective state-read.
| Tier | What accumulates between crossings | What integrates at the crossing |
|---|---|---|
| **Zone-level** (existing) | NPC slot-token verifier-flags (`exit_eligible`, `mid_action`, `goal_satisfied`, `priority_pull`, etc.) | Cursor advance, gate evaluation, population maintenance |
| **Player-input-level** (this) | `gesture_alignment_accumulator` on player's slot-token; per-gesture trait-coordinate vs. NPC's currently-active-trait-vector | Integrated alignment-delta carried into next turn's LLM context |
**Same primitive, recursively applied.** The lemniscate's geometry is the sampling-and-integration boundary at both tiers. No new compute-cadence introduced; no new bus-event introduced. **Compute scales with slot-count, not gesture-rate** — the architecture's commitment from observer-pattern → dirty-bit-and-sweep extends one level deeper.
**Two latencies, one architecture:**
- *Cosmetic visual feedback runs continuously.* NPC body-shader pulses warm-orange when the player gestures Philotes, green when they gesture Sophrosyne (per [`../style/trait-palette.md`](../style/trait-palette.md) §The full table) — purely visual, doesn't touch the system bus. The player gets moment-by-moment "I see you" reassurance.
- *Systemic alignment-update runs at axis-cadence.* The trait-vector summary is computed at the crossing and fed into the next turn's LLM context. The player is **one turn behind** — their gestures during turn N inform the LLM's generation for turn N+1.
**One-turn-behind matches real conversation cadence.** Humans accumulate impressions during someone's speech and respond to *what was just said*; we don't react gesture-by-gesture. The lemniscate-bound integration is the *right* cadence for affective state-changes, not a latency-cost.
**Sum-strategy reduction (v1).** Per-gesture trait-coordinates are accumulated as a **trait-vector sum** across the turn-window. At the crossing, the sum is reduced into a single 8-dimensional alignment-vector compared against the NPC's currently-active trait-state. The result is the alignment-delta fed forward into next turn's `driver_context_pull` payload AND drives the relational ternary-gate transition on the (player, NPC) edge (§Ternary-gate substrate, Relational layer — see identity-and-personhood/architecture.md). The sum captures the player's **overall posture** during the speech rather than peak-moment or trajectory; trajectory-aware refinement is noted as a still-open item.
**Hardstops are outside this system.** Hardstops fire definitive subsystem-actions regardless of alignment-state — clasp-invitation triggers the clasp-subsystem; definitive-refusal closes the conversation; surrender ends combat; claim-floor sets `priority_pull` for the next axis-crossing. Hardstops do not contribute alignment-deltas to the accumulator; they are *separate channels* with deterministic effect.
**What this resolves:**
- *Player-NPC relational-gate-driver* — the v0.4 vague "*zone-participation waves between participants*" now has its concrete wave-source named: the gesture-alignment-delta integrated at each axis-crossing.
- *How NPC speech-patterns adapt to the player over time* — accumulated alignment-state modulates the NPC's next-turn driver-tier-LLM emphasis (which trait-LoRAs are weighted, which sampling-knobs are applied, what register the speech is in). Aligned NPCs open up; misaligned NPCs stay guarded.
- *Player-input-as-typed-contract* — gesture-press → fixed corpus mapping → typed trait-coordinate → integrated trait-vector summary. No freeform-prose at the player-LLM boundary; the hallucination-surface is closed by the cosmology's typed-ness, not by post-hoc filtering.
**What this retires:**
- *Continuous gesture-comparison touching the system bus* → lemniscate-bound integration at crossings (compute-discipline preserved across the recursion)
- *Per-gesture compute* → per-slot compute (O(N_slots), unchanged from existing zone-tick discipline)
- *NPC speech-patterns as static against player-state* → NPC speech-patterns dynamically modulated by accumulated player-NPC alignment-state
### Cross-context application — intimacy as recursive-lemniscate
The recursive-lemniscate gesture-alignment machinery (above) is **modality-agnostic**. v0.7 named it as the player-input-dialog substrate; v0.8 makes explicit that the same primitive runs *every* context where two trait-coordinated participants drive sequenced gameplay through the gesture-circle and lemniscate-cursor. **Intimate-gameplay is the second major application** (the first being NPC-dialog).
**The intimate-gameplay loop running on the lemniscate substrate:**
| Lemniscate primitive | Intimate-gameplay application |
|---|---|
| **Slot-tokens** | The clasp-pair (or premium service-body-pair) — two participants in the loop |
| **Cursor at axis-crossing** | Whose action / position-change is currently active |
| **Gesture-alignment-accumulator** (per slot) | Each participant's trait-coordinated input across the turn-window — sex-positions, gestures, body-part-engagements |
| **Sum-strategy reduction at crossing** | Per-axis integrated trait-vector summary — how aligned are the pair right now |
| **Trait-vector summary fed into next driver-context-pull** | NPC-partner's next dialog turn fires in the alignment-determined trait-LoRA register |
| **Phase-locked overlay channels** | Body-shader-pulse feedback, color-merge during deep alignment, environmental shader-shift |
| **Hardstops** | Definitive intimate signals — `clasp_initiate`, `pause_with_tenderness`, `withdraw_gracefully`, `safe_word_invoke`, `consent_revoke`. These fire definitive subsystem-actions (cannot be remapped) |
**Sex-positions as designer-fixed catalog entries.** Same discipline as the dialog-corpus — every position has a designer-authored trait-coordinate (or primary + secondary trait-coordinate composition). The universal-translator's catalog extends to physical-act vocabulary. Examples:
- *missionary* → Philotes (bond) + Sophrosyne (restraint)
- *embracing-with-eye-contact* → Philotes (bond) + Aletheia (truth-seeing)
- *dominance-position* → Eros (reaching) + Dikaiosyne (bearing)
- *slow-remembering* → Mnemosyne (memory) + Philotes (bond)
- *desperate-reaching* → Eros (reaching) + Moira (fate)
**Body-parts as visible expression of trait-state.** When a position activates with its trait-coordinate, the participant's human-mesh body-shader pulses in the corresponding trait-color. The visible body becomes the *real-time signal* of the trait-state — no HUD; the body itself is the readout. Two clasp-partners see each other's body-shader-pulse as the conversation between their trait-states unfolds.
**Cross-context-consistency is now mechanically true.** The architecture's earlier commitment (the v0.1 design-vision's *"same gesture-skill for dialog, combat, intimacy, maintenance, ritual"*; design-vision doc retired in v0.9, preserved in git history) is operationalized: **the same gesture-circle + universal-translator + trait-LoRA-per-turn-selection + lemniscate-recursive-aggregation drives all of them.** A 200-hour player has dramatically richer intimate-gameplay than a 50-hour player for the same reason they have richer linguistic and emotional competence — they've accumulated more vocabulary in the universal-translator and more selection-pattern fluency on the gesture-circle. **Linguistic competence, emotional competence, and intimate competence are the same competence in this system.**
**This is also why premium-imperial-net intimate-gameplay is *mechanically identical* to in-between clasp.** Same lemniscate. Same gesture-circle. Same trait-alignment. The differences are at the *value-flow* and *persistence* layers (per `../political-register/architecture.md` §Three-tier intimacy structure and `../inference-and-memory/architecture.md` §Three sqlite stores per player), not at the runtime-mechanics layer. The architecture's typed-contract discipline pays off here too: one machinery, multiple political-economic contexts.
**Voice-input flows through the same accumulator as gesture-input.** Player speech → local STT → token-stream → each token has a designer-fixed trait-coordinate (per the universal-translator corpus; same word → same trait → same coordinate for every player and every NPC and every LLM-context, per `../player-experience/architecture.md` §Designer-fixed cosmology, player-curated arrangement) → tokens accumulate into the same `gesture_alignment_accumulator` on the player's slot-token → integrated at axis-crossing → carried forward into next NPC's `driver_context_pull`. **Voice and gesture are co-equal modalities feeding one mechanism**; no player-trait-LoRA needed, no LLM-bypass needed. A player gesturing Philotes while speaking Aletheia-vocabulary contributes both trait-coordinates to the accumulator simultaneously; the sum-strategy reduction handles the multi-modal case naturally. (Resolves the v0.4 player-dialog-handling open question.)
### Driver-context-pull (LLM dialog substrate)
The cursor's position at each crossing makes context-construction for the dialog-driver a pure function of cursor-state:
```
driver_context(cursor_at_NPC_i, mode) = {
zone.purpose, // stable: spawn-intent, immutable provenance
zone.scene_state_public, // stable across zone: what's happened so far
zone.ternary_gate_edges, // current resonances (active relations)
zone.drift_state, // delta from spawn-intent (visible to director)
NPC_i.knowledge_stack, // PRIVATE three-tier stack: world district primary
// [+ clasp ONLY if mode == in-between]
NPC_i.expressed_trait_vector, // expressed trait-vector this moment
NPC_i.active_signals, // their current emergent-signals
}
```
**Other NPCs' memories never enter this prompt.** No bleed. No cross-contamination.
**The `knowledge_stack` is layered**, not a single bucket. Universal world-canon, district-canon (regional), NPC_i's own primary memory, and — only if the character is in the in-between dimension — clasp memory. The retrieval layer enforces the dimensional cut; the LLM never has to reason about it. See §Local memory architecture in inference-and-memory/architecture.md for the layering, propagation policy, and clasp-as-Ring-A* privacy primitive. The classic multi-agent hallucination source ("why does Kalypso suddenly remember what Anaximander confided to Phoibe?") is *structurally foreclosed* by the geometry. Write-back goes only to NPC_i's slice; the lemniscate guarantees NPC_i is not cursor-active again for at least one full roundtrip — write-back has all the time it needs without race conditions.
This converts multi-NPC dialog from an **emergent-chaos problem** into a **bounded-cast scene problem with a typed runtime**. The Mantella / SkyrimNet failure-modes are foreclosed at the architecture level rather than the prompt level:
- **Cast = active-slots, period.** Geographic proximity does not equal participation
- **Cursor sequences turns deterministically.** No concurrent LLM-storm
- **Entry-line and exit-line are the only paths in/out.** Geographic motion alone doesn't invade the scene
- **Player gestures broadcast to active-slots only.** Not to "everyone within 30m"
### Empty-queue behavior: shrink at every crossing
When the entry-line is empty, each crossing **dissolves one active slot** instead of replacing it. The conversation thins visibly — color-language saturation drops per shrink, lifeforce burn-rate decreases. When the last slot dissolves, the lemniscate collapses; the spawning director recovers unspent lifeforce minus burn.
This is the natural wind-down — *scenes run out of people and dissolve*. No timeout, no scheduler-collapse, no cut-to-black. The decay is observable in-world and rate-paced by the same axis-rate.
### Lifeforce-binding
Every midaxis crossing fires the LLM driver-turn(s) for active slots. **Lifeforce burn-rate = pulse-rate × active-slot-count.** The director (or overseer) holding the zone pays per crossing. This produces:
- **Dense dramatic scenes are expensive** — many slots, fast pulse, high burn
- **Quiet background zones are nearly free** — slow pulse, few slots; most compute is local-loop traversal not touching the bus
- **Running out of lifeforce is visible** — pulse-rate slows, crossings stretch farther apart, the scene *languishes* before it collapses. A diegetic dying-scene register; not a cut, a deceleration
### What this resolves
- **Slot-capacity elasticity** (prior open question) → fixed roundtrip slot-count, elastic entry/exit queues
- **Zone-to-zone handoff** (prior open question) → exit-line of zone-A is entry-line of zone-B (interlemniscate-transit; pipes-as-heterotopia made literal at runtime)
- **Mobile zone boundaries** (prior open question) → the lemniscate is a topology; it translates through world-space invariantly (patrols, escorts, exoduses are moving figure-8s)
- **Anthropic-faction's broadcast cadence** (prior open question) → cadence rides the same axis-rate as a phase-locked overlay; no separate clock
- **Director/overseer spawn ownership per model class** (prior open question) → the director (or overseer) owns the zone-spawn decision (policy-lookup, no LLM in loop); the LLM driver lives at the driver-context-pull layer; orchestration and dialog are decoupled
### What this retires
- Slot-list + external turn-counter → cursor on lemniscate
- Polling for emergent-signals at zone-tick → flag-as-verifier carried in loop
- Mega-prompt with all NPC memories ("everyone in this scene") → cursor-driven per-NPC memory-slice
- Geographic-proximity participation ("everyone within 30m may interject") → strict active-slot cast
- Concurrent LLM calls per-NPC → sequenced LLM calls per-cursor-position
- Polling event-channels at zone-rate → atomic crossing-event with O(N_slots) flag-scan
## Omnisight — NPC visual perception via VL-Gemma + virtual cameras
NPCs perceive the visible world *literally* — not via geometric metadata-perception but via per-NPC virtual cameras (Godot) feeding rendered POV-frames into the local VL-Gemma 4 driver-tier (the multimodal vision-language capability of the Gemma 4 E4B model locked in v0.8). What an NPC "sees" is what the VL-LLM interprets from the camera's image.
This is the perception architecture's deepest commitment. It pairs with the cell-arch checksum-discovery (per [`../political-register/world-generation.md`](../political-register/world-generation.md) §L4 Cell ruleset) as its **trigger-layer**: cell-checksum-mismatch fires the *"clean signal"* that activates the NPC's POV camera, which renders, which feeds VL-Gemma, which produces a visual interpretation that modulates the NPC's current-turn behavior. **Cheap trigger, expensive understanding, bounded by event-frequency.**
### The pipeline
| Layer | Cost | Fires when |
|---|---|---|
| Cell-checksum check | µs | NPC enters cell |
| Checksum-mismatch → "clean signal" | µs | Cell state ≠ expected hash |
| VL-camera renders POV scene | ms | Clean signal + perception-relevant context |
| VL-Gemma processes image → interpretation | 100s of ms | After camera renders |
| NPC behavior responds to seen-content | next-shift / next-crossing | After interpretation |
Most NPCs most of the time: no camera-fire, no VL-inference. **Active-perception-budget is bounded by event-frequency, not NPC-count.** A 100+ NPC city is feasible because most NPCs are running shift-routines on rails with no cell-state-changes triggering perception.
### Camera-trigger sources (locked)
Camera renders + VL-inference fire **only on**:
- **Cell-checksum-mismatch** — cell-state-change discovered on entry (the cell-arch's primary discovery-trigger)
- **Hard-signals from player** — `clasp_initiate`, gesture-hardstops, plug-in conversation request, etc.
- **Overseer triggers** — audit-sweep, surveillance-cycle, patrol-perception-on-route
- **Drone perception** — clear boundaries + rulesets per drone-class (drones have their own perception-budget governed by their imperial-class spec)
Everything else: NPC running on rails, shift-routine, no camera-fire, no VL-inference. **Bounded compute by construction.**
### Hallucination-isolation discipline (load-bearing)
VL models hallucinate. If those hallucinations enter the canonical record, they propagate through the lemniscate's recursive integration → become referenced by other canon-rows → become load-bearing in the world's narrative coherence → **cannot be untangled later**. *Bleed-over into oblivion* is the precise risk.
The discipline that prevents this:
> **Visual perception = behavior-modulating-only; never canon-generating.**
Visual context flows on a *separate stream* from the canonical text + gesture summary, with a strict firewall between them:
| Stream | Source | Persistence | Purpose |
|---|---|---|---|
| **Text + gesture summary** (existing canonical pipeline) | STT + gesture-circle-presses + per-token trait-coordinates per §Gesture-alignment as recursive-lemniscate | Canonical; flows into `event_canon_summaries`; propagates to Compositor; integrates into trait-vector | What the NPC *remembers* and what becomes world-canon |
| **Visual context** (omnisight-flagged, new) | VL-Gemma processing POV camera-render | **Ephemeral**; flagged on the lemniscate; **ignored in the per-crossing summary**; never propagates upward | What the NPC *sees in this moment*; modulates current-turn `driver_context_pull` only |
**Concretely:** the visual interpretation is appended to `driver_context_pull` for the NPC's next turn (so the NPC can react to what it sees), but it is **not** appended to the `gesture_alignment_accumulator`'s sum-strategy reduction at the axis-crossing, and it is **not** included in the `event_canon_summaries` row that the Compositor pulls from `transient_waiting_flag`. **The visual content lives one turn and dies.**
This preserves three architectural commitments that depend on text/gesture-derived canon:
- *Compositor narrative-coherence at scale* — Compositor never sees VL-output; only deterministic text/gesture-derived summaries. **Hallucination-firewall preserves the canon-coherence Compositor depends on.**
- *Memorialist-archive truth-claims* — Memorialists index cell-checksum-divergence (canonical, deterministic), NOT VL-generated visual-content. The archive's evidentiary value depends on this distinction.
- *Mind-pool soul-recycling* — when a mind cycles through the pool and is redistributed into a new body, the trait-vector that persists is text/gesture-derived. **VL hallucinations do not survive transmigration; they were ephemeral by construction.**
### Wealthy-degen service-body-folder exception
A specific opt-in special case for player-stored visual-content:
- A wealthy player who already has service-body-dialog stored (per `../political-register/architecture.md` §The vocation-substrate of the imperial-net market) can check a box to allow **sex-pictures storage in a private folder** from clasp-scenes.
- Stored locally (their machine, their problem — privacy, storage, content).
- **Read-only-by-player** — folder content does **not** flow back into NPC contexts, world-canon, the Compositor, the mind-pool, or any other system.
- **Quarantined dead-end storage** — aesthetic-collection only.
The folder is architecturally inert with respect to the rest of the system. It exists *for the player*; it does not exist *for the world*.
### What this retires
- *Geometric perception (cone, radius, LOS)* → already retired by zone slot-occupancy + subscriber-event-emission; **omnisight extends the retirement** by giving NPCs *literal* visual perception within those subscribed events, not metadata-perception
- *VL models polluting world-canon* → text/gesture-derived summaries are the only canonical input; VL is behavior-modulating-ephemeral-flag-only; player-stored visual-content is read-only-by-player quarantined storage
### What this resolves / sharpens
- *Continuous visual feedback policy* (architecture-index Still-open) → with cel-shaded bodies (per `../topology-and-rendering/architecture.md` §Three-shader philosophy) and visual-as-ephemeral-flag, the body-shader pulses are *legible without canon-pollution risk*. The visual-feedback policy can be permissive at the cosmetic layer because it is firewalled from canonical state.
### Open questions
- **Per-NPC VL-inference rate-limit** — how many camera-renders + VL-inferences per second affordable per active NPC at MMO scale? Pending: benchmark against Gemma 4 E4B VL-inference latency on typical-deployment hardware.
- **VL-Gemma camera resolution + frame-rate** — what camera-budget per NPC fits the rule-catalogue? Pending: rule catalogue + benchmark.
- **NPC progression-state for witness-axis** — how does an NPC accumulate in-between-knowledge that drives their dual-axis-clasp witness-fidelity (per `../identity-and-personhood/bodies.md` §Asymmetric clasp / §Dual-axis clasp-fidelity)? Their own clasps? Fragments encountered? Caste-class-default? Pending: design pass.
- **Multi-NPC observing same event** — each NPC runs independent VL-inference; how do their perceptions combine into a shared event-record? *(Connects to Compositor narrative-coherence-at-scale Still-open.)* Probable answer under the hallucination-isolation discipline: *they don't combine* — each NPC's visual context is private to their own next-turn `driver_context_pull`; the shared event-record is built from text/gesture-summaries only. Worth confirming explicitly.
## Zone taxonomy (v1 starter set)
| Zone type | Register | Slots | Executor | Persistence |
|---|---|---|---|---|
| Conversation | physical | 24 dialog | director | persistent |
| Street brawl | physical | fighter + spectator | director | persistent |
| Ritual | physical | fixed ceremonial | director | persistent |
| Maintenance | physical | 12 workbench | director | persistent |
| Wall-writing | physical / liminal | 1 author + witnesses | director | persistent / ephemeral |
| Market exchange | physical | 23 + ambient | director | persistent |
| Memorial gathering | physical | 1 mourner + N witnesses | director | persistent |
| Salvage | physical (dump) | N scavengers | director | persistent |
| Transit-encounter | physical (pipe) | 26, stranger-heavy | director | persistent |
| **Plug-in conversation** | physical (rail) | 2-3 (3-way capacity) | director | ephemeral (rail-segment-bound) |
| Patrol / sweep | physical | mobile, N enforcers | overseer | persistent |
| Interrogation | physical | 1 subject + N enforcers | overseer | persistent |
| Raid | physical | district-scope + N enforcers | overseer | persistent |
| **Interior (hovel/workshop/etc.)** | physical | slot-inventory by interior-type | director | persistent |
| **Clasp** | **liminal** | 2 | director | **ephemeral** (stabilizes across repeated clasps) |
| **Aletheia-gathering** | **liminal** | N, mini-game-gated | director | **ephemeral** |
| **Migration (mobile)** | physical (pipes) | cohort + escort | overseer | persistent |
| **Exodus (mobile, mass)** | physical (pipes) | self-selecting crowd | emergent | persistent |
| **Drug-ring den** | physical (cheat-op) | N users + cooks | director (cheat) | persistent (until detected) |
| **Illegal back-alley modshop** | physical (cheat-op) | 1 modder + 1-N customers | director (cheat) | persistent (until detected) |
| **Unlicensed brothel** | physical (cheat-op) | N workers + N customers | director (cheat) | persistent (until detected) |
| **Companion hall** | imperial net | 1 dreamer + N synthetic | net-director | extractive-persistent |
| **Brothel encounter** | imperial net | 2+ (synthetic or employed) | net-director | extractive-persistent |
| **Imperial ceremony** | imperial net | mass-audience | net-director | extractive-persistent |
| **Ruin zone** | physical | pilgrimage-only | none / Memorialist | persistent-abandoned |
## Zone spawn cadence
Five layered mechanisms (all compute-budget capped, all lifeforce-gated):
1. **Demand queue (faction-driven)** — gamemaster processes by priority + cost; stale demands age out
2. **Shift-composition spawn-candidates** — emergence from "which active-shift NPCs co-located"
3. **Pressure gradients (ambient)** — cells accumulate; threshold-crossings spawn
4. **Emergent-signal response** — relational-gate transitions emit upward
5. **Player-proximity densification** — multiplier near player; distant districts background
Daily pulse: morning ambient, midday productivity-overseer, evening conversation-peak, night sparse-clasp-possibility.
## Emergent zones — the dramatic-episode unit
Spawn-cadence mechanism #4 (emergent-signal response) elaborates into the architecture's primary **dramatic-episode unit**: a complete, bounded, emergent narrative-arc with goal, participants, dialog, mechanical action, success/fail-state, and structured aftermath — produced by the simulation, *not* authored.
The player has experienced this in every player-driven sandbox they remember best (Dwarf Fortress's "tantrum spirals," RimWorld's "raid stories," Caves of Qud's "I went to find my sister and"). What's new here is treating the emergent-arc as a **first-class typed unit** with cost, distributed funding, runtime substrate (the lemniscate), goal-evaluation against the world's own value-axes, and structured report-back.
### The flow
```
1. NPC_A signal fires
(e.g., emergent_signal("limb_broken", lifeforce_threshold_breached))
broadcasts to district-bus
2. District-director consumes signal
(policy-lookup: problem-class → typed-tool selection, quota-aware)
decides spawn rescue-event
pays spawn-cost from director_lifeforce_budget
defines goal: NPC_A.limb_A >= 10% (numeric) OR Sophrosyne-axis +1 (fuzzy)
defines termination: goal_met OR participating_lifeforce_exhausted
3. Event spawns as new emergent-zone (lemniscate, with goal-flag)
broadcasts on bus; rings-of-importance gate which other zones lose NPCs
4. NPCs evaluate (proximity + state + own_traits + own_lifeforce + ring-of-importance)
self-select to attend or stay in current zone
state-machine engages: animations, rail-jumps, lift, splint
their own lifeforce burns as they participate
5. Lemniscate runs:
DIALOG layer (cursor-driven): NPCs speak as they help — memory-pure, sequenced
STATE-MACHINE layer (sim-tick): physical actions execute alongside, decoupled clock
At each crossing: goal_satisfied flag re-evaluated
6. Termination:
goal_met → success-report
budget_exhausted → partial-report
participants_evaporated → fail-report
7. Report back to spawning director:
{ lifeforce_cost: total burned (director_spawn + sum NPC contributions),
goal_status: ternary (+1 / 0 / -1, with axis named for fuzzy goals),
participants: [NPCs and contributions and faction-affiliation],
side_effects: [faction-resonances, ternary-gate shifts, drift-from-purpose] }
8. Director's Dream-process consumes the report
tunes future spawn-policy: (problem-class, tool, outcome) over time
GM aggregates rescue-cost across districts
imperium consumes population-health indicator
```
### Distributed funding economy
The director only pays **spawn-cost**. Operating-cost is distributed across willing participants — every NPC who attends spends their own lifeforce on dialog turns and state-machine actions. This produces structurally important properties:
- **Cheap to spawn many emergent events.** Spawn-cost is bounded; if no NPCs attend, the event fails fast and consumes only spawn-cost. Directors can be generous with spawning because failure-cost is bounded.
- **Helping is expensive in-fiction.** Lifeforce literally burns when an NPC participates. High-Philotes NPCs help freely; low-Philotes / faction-rivals don't show up. This produces **faction-politics-by-attendance***measurable* faction-allegiance based on who-helps-whom, not guessed.
- **Cost-asymmetry encodes the cruelty.** Districts where lifeforce is starved → fewer NPCs can afford to help → rescue-events fail more often → silence-gradient deepens. The simulation produces **rescue-failures-as-emergent-tragedy structurally**. Marx in the schema, exactly as the architecture's broader thesis promises.
### Two-layer execution: state-machine + lemniscate
The mechanical-action layer (state-machine) and dialog-layer (lemniscate cursor) run on **decoupled clocks**:
- **State-machine** runs at simulation-tick (fast). Animations, pathfinding, rail-jumps, splint-applications execute when the physics says they execute.
- **Lemniscate cursor** runs at axis-rate. At each crossing, the dialog-driver reads state-machine status as a snapshot and the cursor's NPC narrates accordingly ("I've got him," "the splint won't hold").
**Speech doesn't gate action; action doesn't block speech.** They run in synchronized-but-loose harmony, exactly the property real-world helping has — people talk *while* they work, and the work continues while the talk happens.
### Goal evaluation: ternary through trait-axis
For numeric goals (limb_A >= 10%), the verifier is a simple threshold on a state-machine variable.
For fuzzy goals (deescalate the fight, get her to open up about the clasp, convince him to stay), the verifier compiles to a **trait-axis ternary evaluation against the existing substrate** — no new evaluation primitive:
```
Goal: "deescalate the fight in the marketplace"
↓ compile to:
goal_axis = Sophrosyne (temperance principle)
goal_direction = positive (toward STABLE/OPEN)
baseline = trait_axis_gate_state at zone-spawn
↓ at event-end:
delta = current_gate_state vs baseline
+1 if delta-positive (deescalation produced)
0 if held the line (no progress, no regress)
-1 if delta-negative (fight intensified)
```
**Goals are evaluated by what the *world* values** (the Hellenic principles), not by the spawner's idiosyncratic spec. A "deescalate" goal is judged by *the world's Sophrosyne-result*, not "did the spawner get what they wanted."
**Multi-axis goals fall out cleanly**`(Philotes >= +1) AND (Sophrosyne >= +1)` for "rescue NPC_A AND keep faction-tension low (via maintained restraint)."
The result is consumed by the spawning director's Dream-process as a discrete-action-space reward signal. **One signal-grammar, top to bottom**: gates produce ternary, scenes produce ternary, Dream-processes consume ternary. Delta-not-absolute matches the lifeforce_actual-vs-reported asymmetry — what's measured is the *work the event did*, not just the end-state.
### Mid-event signal handling
If a participating NPC's exit-flag fires mid-event (their own shift-whistle, their own limb breaking, faction-summons elsewhere), **exit-flag wins on the next crossing**. The rescue is now under-staffed. Drama scales. **The rescuers are running out the same way the patient is.** Real stakes.
If the rescued NPC's own state-machine reaches a worse condition (limb deteriorates further toward dismemberment), the goal becomes unreachable; verifier flips to fail-flag; zone collapses with fail-report. Director's Dream-process learns *this configuration was insufficient* — spawn-distance, NPC-mods, lifeforce-budget were inadequate for this severity.
### Cross-zone NPC pull: rings of importance
When an emergent-zone broadcasts, NPCs already in other zones evaluate **whether the broadcast outranks their current zone's purpose** by ring-of-importance (see §Rings as structural pattern in authority-and-decision/architecture.md). Topics live in rings; rings shift over time based on past ternary-results — a topic that consistently produces +1 climbs, one that produces -1 drops, one untouched decays.
This converts emergent-zones into a **competitive attention economy**. Multiple lemniscates compete for slot-NPCs; high-ring topics drain population from low-ring topics; the simulation produces its own cultural priors over time. *What's worth attending to* is shaped by *what attending-to has produced*. Real societies do this; the architecture renders it.
### What this resolves
- **Aletheia-progression as level-up** (prior open question) → answered structurally: trait-axis ternary evaluation at event-end with named-axis recognizes acts-of-awakeness without per-act hardcoding (specific axis-mapping per Aletheia-event-class still needs design, see open-questions)
### What this retires
- Authored quest-arcs → emergent dramatic-episode units
- Quest-failure as designed branching → goal-and-budget arithmetic
- Centralized GM-pays-for-all-events → distributed-funding (director spawn-cost, NPC operating-cost)
- Boolean quest-status → ternary goal-result, multi-axis-composable
- Event lifecycle without report-back → structured report → Dream-process feedback loop closed at every tier
- Static topic-priority → rings-of-importance with outcome-driven movement
---
**Version:** 0.7.0 | **Created:** 2026-04-26 | **Updated:** 2026-04-27 | **Origin:** Split from architecture-index.md v0.7 (2026-04-26)