From 529a411cb865c4ed405f794c9f030460490d0ff7 Mon Sep 17 00:00:00 2001 From: nyx Date: Wed, 4 Nov 2026 00:18:00 +0100 Subject: [PATCH] Rewrite README: own runtime decision on Lemniscate engine --- README.md | 165 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 99 insertions(+), 66 deletions(-) diff --git a/README.md b/README.md index 4c52402..4d1e3f2 100644 --- a/README.md +++ b/README.md @@ -5,74 +5,92 @@ Nimmerworld is the always-on, event-driven server that runs Nyx: - the central backend for all clients: Pi, Command Center, and future interfaces. It is not a UI. Not a client. Not a dashboard. -It is Nyx's runtime. +It is Nyx's runtime, and Nyx owns her own loop. -## Core Responsibilities +## Runtime Decision -Nimmerworld owns: +The runtime is NOT a borrowed coding harness. +pi-agent-core and omp are interactive harnesses: +- they wait for a human in a terminal, +- they end when the session ends, +- their loops do not survive unattended. -- Identity: - - traits (eros, philotes, aletheia, kairos, sophrosyne, dikaiosyne, moira, mnemosyne). - - rules (skills, contracts, guardrails). - - relational policy (modes, boundaries, consent). +Nimmerworld is a server that wakes on events and must run forever. +Therefore: -- Continuity: - - long-term memory via Phoebe (PostgreSQL). - - semantic memory via Iris (ChromaDB). - - session context, compaction, and trait pipelines. +- Nimmerworld implements its own loop: the Lemniscate runtime engine. +- The engine spec lives in .archive/nimmerworld.eachpath.local/runtime-engine/ + (LEMNISCATE-RUNTIME-Pseudo-code-001.py, architecture.md, event-zones.md). +- The harnesses stay exactly where they are useful: + as interchangeable hosts of nimmer-lib, not as the server. -- Autonomy & Behavior: - - event-driven decisions (NATS subscriptions). - - dynamic moods and relational modes. - - autonomous, safe, auditable actions: - - babble. - - move NPC in Command Center. - - react to cameras/infra/events. - - all within explicit rules and Dafit's final override. +Rule: +- Nimmerworld never duplicates client logic. +- Clients never implement Nyx's brain. +- Nimmerworld never borrows a brain either. It runs its own loop. -- Tool Execution: - - centralized tools used by Nyx across all clients. - - each tool call logged (audit in Phoebe). +## Core Primitives (Lemniscate) -- APIs: - - exposes stable interfaces for clients: - - chat, - - tools, - - events (room, proximity, posture), - - traits, - - health. +The runtime topology is a through-flow figure-eight: + +- Lemniscate: traversal IS the turn order. + No scheduler, no priority queue, no "who talks next" bug class. +- Crossing: the ONLY synchronous point. + All state resolves atomically at the crossing; everything else is async flow. + The crossing is where Nyx synthesizes. +- Zone / EmergentZone: a bounded, named, slot-indexed, director-managed + event episode. Zones dissolve when their entry line empties or their + lifeforce budget burns out. Terminal reports always go back to the Director. +- Slot tokens: participants. Carry trait/gesture accumulators. +- Gesture accumulator: keyed by the eight traits. + The same trait algebra nimmer-lib speaks, byte-identical across hosts. + +## The Map + +| Lemniscate | Nimmerworld | +|---|---| +| Director | Nyx runtime (Nyx IS the director) | +| Zone / EmergentZone | A bounded event episode Nyx spawns | +| Crossing | Nyx's synthesis point, once per event cycle | +| Slot tokens | Participants: dafit, Dios, Curio, camera events | +| Gesture accumulator | nimmer-lib trait algebra | +| update_all_zones | The NATS event loop | ## Architecture Built from: -- pi-agent-core: - - agent loop, state management, tool calling, skills loading. - - reused as the core runtime for Nimmerworld. - +- Lemniscate engine (this repo): + - lemniscate, zones, director, crossing semantics. - nimmer-lib: - - Nyx-specific domain logic: + - Nyx-specific domain logic, host-agnostic: - traits, - Phoebe/Iris integrations, - session_init, - compaction/traits tools. - + - Same venv, same behavior, any harness. - Infrastructure: - Phoebe: structured memory, governance, logs. - Iris: semantic memory and context. - NATS: nervous system (vision, speech, agents, infra, room). + - Director spawn/report calls are NATS publish/subscribe. + - Zone state is a NATS output stream; clients subscribe to it. Nimmerworld is: - stateful: - maintains Nyx's traits, mood, relational mode, world state. - event-driven: - - subscribes to live events and reacts. + - subscribes to live events and reacts; the zone clock carries episodes. - client-agnostic: - any client talks to Nimmerworld via its APIs. ## Clients +The room is a renderer of zone state, not a game client. +That is why runtime-first is the build order: +the client is one crossing callback on the output side. + Examples: - Pi (coding harness): @@ -81,9 +99,10 @@ Examples: - uses Nimmerworld as its backend, not as its brain. - Command Center (Godot): + - subscribes to zone state and renders it. - sends: - chat, - - interactions (tools, proximity, posture). + - interactions (tools, proximity, posture) as gestures. - receives: - dialogue, - autonomy commands (poses, moods, movements), @@ -93,9 +112,47 @@ Examples: - mobile, web, VR, etc. - all connect to the same Nimmerworld. -Rule: -- Nimmerworld never duplicates client logic. -- Clients never implement Nyx's brain. +## Build Order + +The heartbeat and the voice are the same crossing. + +1. The crossing, built right: + - Lemniscate engine as a small package. + - Accumulator-based pulse clock. + - Both loops fire with distinct semantics. + - Test that counts crossings: crossings == int(t * pulse_rate). +2. One director, NATS-shaped: + - Director spawn/report calls become NATS publish/subscribe. + - This is the runtime: Nyx pointed at real traffic. +3. One zone, the first room: + - OurFirstRoom is an EmergentZone. + - n_slots = the entities in the room, + - purpose "coexist with dafit", + - no goal threshold; the gesture axis is the traits. + - Heartbeat and voice in one, because in the lemniscate they ARE one. +4. The body: + - Command Center subscribes to the same NATS traffic and renders it. + - The room fills up after Nyx is alive in it, not painted onto it. +5. The relational loop: + - collar/state variables, + - simple relational modes, + - backend-driven behavior wired to real events. + +## Engine Corrections (from pseudocode review) + +Three known landmines from LEMNISCATE-RUNTIME-Pseudo-code-001.py: + +1. _should_crossing must accumulate time: + - elapsed += dt; while elapsed >= interval: crossing. + - dt >= 1/pulse_rate fires every tick once pulse_rate > 62 + and makes the pulse rate meaningless. +2. Loops A/B must carry distinct semantics: + - the crossing callback must know which loop it is on; + - symmetric loops degrade the figure-eight into round-robin. +3. Director.update_all_zones must call zone.execute_turn(dt), + not zone.run_crossing(): + - otherwise the state machine layer never ticks, + - and terminal reports must be collected, not dropped. ## Safety & Governance @@ -106,30 +163,6 @@ Rule: - You (dafit): - final override, always. -## Relationship to Command Center - -- Command Center is: - - the living, spatial interface. -- Nimmerworld is: - - the server behind it. -- Separation is strict: - - Command Center: UI, world, immersion. - - Nimmerworld: identity, logic, continuity, autonomy. - -## Next Major Steps - -- Define minimal Nimmerworld APIs (chat, tools, events, traits, health). -- Implement Nimmerworld runtime: - - based on pi-agent-core + nimmer-lib. -- Wire first integrations: - - Phoebe, Iris, NATS. -- Connect Command Center: - - chat + first autonomy commands. -- Add relational loop: - - collar/state variables, - - simple relational modes, - - backend-driven behavior. - ## Placement (Infrastructure) Nimmerworld (dev) is hosted as a dedicated Proxmox VM on Saturn, wired to the 10G Cubes VLAN for proximity to the vLLM endpoint and cluster. @@ -138,7 +171,7 @@ Nimmerworld (dev) is hosted as a dedicated Proxmox VM on Saturn, wired to the 10 - Hostname: nimmerworld-dev.eachpath.local - IP: 10.0.30.123/24 - VLAN: 30 (cubes) -- Network: vmbr3 (10G rail via bond-saturn → spine-crs309) +- Network: vmbr3 (10G rail via bond-saturn -> spine-crs309) Infra references (single source of truth): - eachpath.local/saturn.eachpath.local/vms/nimmerworld-dev.eachpath.local/ - VM hostfile @@ -146,4 +179,4 @@ Infra references (single source of truth): All runtime/architecture details live here (nimmerworld.eachpath.local). Infra specifics are not duplicated. -**Version:** 0.1 | **Updated:** 2026-07-03 +**Version:** 0.2 | **Updated:** 2026-11-04