The canonical trait-palette in style/trait-palette.md v0.1 (Eros-red,
Philotes-orange, Aletheia-yellow, Kairos-chartreuse, Sophrosyne-green,
Dikaiosyne-blue, Moira-violet, Mnemosyne-dusky-rose) was being contradicted by
old-palette references in three downstream files. This commit clears the drift
and enforces the import-don't-redefine discipline (per trait-palette.md
§Cross-domain rendering: "All sub-guides import these definitions; none
redefine them.").
topology-and-rendering/architecture.md:
- Replaced the redefining trait-color table with a pointer to
trait-palette.md per the import-don't-redefine rule. The old table was
using the retired luminous-white-Aletheia + multiple wrong color-trait
assignments (Sophrosyne-blue, Dikaiosyne-gold, Mnemosyne-violet,
Moira-crimson, Eros-orange, Philotes-rose, Kairos-yellow).
- Updated imperial-net distortion text and faction color-signatures table
to use canonical color-names: Aletheia-white -> Aletheia-yellow;
Mnemosyne-violet -> Mnemosyne-dusky-rose; Moira-crimson -> Moira-violet;
Dikaiosyne-gold -> Dikaiosyne-blue; Sophrosyne-blue -> Sophrosyne-green;
Philotes-rose -> Philotes-orange; Eros-orange -> Eros-red; Kairos-yellow
-> Kairos-chartreuse.
- Added clarifying note: imperial-net's clean-white-backgrounds +
gold-rim-light are achromatic-and-cosmology palette choices distinct
from the trait-color register being distorted (per the achromatic
exception + imperial-cult/cosmology.md aesthetic palette).
schemas/findings.md:
- Updated trait_colors INSERT seed-data with hex codes matching the new
canonical hue-families and renamed canonical_name fields to match
(Eros-red, Philotes-orange, Aletheia-yellow, Kairos-chartreuse,
Sophrosyne-green, Dikaiosyne-blue, Moira-violet, Mnemosyne-dusky-rose).
Reordered rows clockwise from 12 o'clock per wheel-position.
- Added authority-comment pointing at trait-palette.md as the single source
of truth and noting that the seed-data is reification, not redefinition;
designer-precise hex values should be authored upstream and propagated.
runtime-engine/architecture.md:
- Updated cosmetic-feedback example: warm-rose Philotes / cool-blue
Sophrosyne -> warm-orange Philotes / green Sophrosyne; added pointer to
trait-palette.md.
architecture-index.md:
- Fixed typo "Eris" -> "Eros" in the v0.5 trait-axis-mapping open-question
enumeration (the canonical 8 traits do not include Eris).
Verification: post-fix grep confirms zero remaining old-palette name
occurrences or old hex codes; new canonical names appear in all expected
locations.
SEPARATE FINDING flagged for designer review (NOT auto-fixed):
runtime-engine/architecture.md line 424 contains
`(Philotes >= +1) AND (Eris <= 0)`
as a multi-axis-goal example. This uses "Eris" with semantic intent
(discord / faction-tension) but Eris is not in the canonical 8-trait list.
Left untouched because the fix could be either (a) typo-correction Eris -> Eros
or (b) rewrite-to-canonical-axis-with-different-example, depending on whether
"Eris" was intended as a 9th non-canonical axis or simply as a typo. Designer
decision.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
457 lines
41 KiB
Markdown
457 lines
41 KiB
Markdown
# 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** — 2–3 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-waifu-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 waifu-folder exception
|
||
|
||
A specific opt-in special case for player-stored visual-content:
|
||
|
||
- A wealthy player who already has waifu-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 | 2–4 dialog | director | persistent |
|
||
| Street brawl | physical | fighter + spectator | director | persistent |
|
||
| Ritual | physical | fixed ceremonial | director | persistent |
|
||
| Maintenance | physical | 1–2 workbench | director | persistent |
|
||
| Wall-writing | physical / liminal | 1 author + witnesses | director | persistent / ephemeral |
|
||
| Market exchange | physical | 2–3 + ambient | director | persistent |
|
||
| Memorial gathering | physical | 1 mourner + N witnesses | director | persistent |
|
||
| Salvage | physical (dump) | N scavengers | director | persistent |
|
||
| Transit-encounter | physical (pipe) | 2–6, 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) |
|
||
| **Waifu 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 (Eris <= 0)` for "rescue NPC_A AND keep faction-tension low."
|
||
|
||
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-26 | **Origin:** Split from architecture-index.md v0.7 (2026-04-26)
|