README: infrastructure boundary and per-technology learning spine; commit architecture/runtime/schemas/style papers

This commit is contained in:
nyx committed 2026-11-06 14:12:49 +01:00
1 parent 529a411cb8
commit f6aad467e2
9 files changed
+647 -167

No files matched your search

+70 -167
View File
@@ -1,182 +1,85 @@
# Nimmerworld - Nyx Server
# Nimmerworld: Runtime Server
Nimmerworld is the always-on, event-driven server that runs Nyx:
- her identity, traits, memory, autonomy, and tools.
- 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, and Nyx owns her own loop.
## Runtime Decision
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.
Nimmerworld is a server that wakes on events and must run forever.
Therefore:
- 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.
Rule:
- Nimmerworld never duplicates client logic.
- Clients never implement Nyx's brain.
- Nimmerworld never borrows a brain either. It runs its own loop.
## Core Primitives (Lemniscate)
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 |
Always-on, event-driven server for the agent (Nyx). Central backend for Pi, Command Center, and future clients. Not a UI, not a client, not a dashboard.
## Architecture
Built from:
| Paper | Scope |
|---|---|
| [architecture/lemniscate.md](./architecture/lemniscate.md) | Runtime loop: topology, crossings, data flow, pulse clock, engine corrections. |
| [architecture/gates.md](./architecture/gates.md) | Gate layer: state, injection loop, closure guard, tags, probes, persistence. |
| [architecture/register.md](./architecture/register.md) | Registry: sensors, gates, actuators, clients, `drives`, arbitration, pods, placement. |
| [architecture/gates_index.md](./architecture/gates_index.md) | Reserved. |
| [schemas/README.md](./schemas/README.md) | Identity, impulse row, gate state, tag row, evidence request. |
| [schemas/gate_table.md](./schemas/gate_table.md) | Gate registry and state schema in Phoebe. |
| [runtime/stack.md](./runtime/stack.md) | Stack layers, two buses, JetStream replay, dependency budget. |
| [style/house-style.md](./style/house-style.md) | Paper register: engineer style rules, allowed voices per surface. |
- Lemniscate engine (this repo):
- lemniscate, zones, director, crossing semantics.
- nimmer-lib:
- 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.
## Folders
Nimmerworld is:
| Folder | Holds |
|---|---|
| architecture/ | Runtime engine and subsystem papers |
| runtime/ | Stack, pseudocode and successor, engine build order |
| storage/ | Storage layout and retention |
| database/ | Database schemas and migrations |
| schemas/ | Typed contracts and message schemas |
| tools/ | Runtime tooling |
| style/ | Voice, register, trait presentation |
- stateful:
- maintains Nyx's traits, mood, relational mode, world state.
- event-driven:
- subscribes to live events and reacts; the zone clock carries episodes.
- client-agnostic:
- any client talks to Nimmerworld via its APIs.
## Infrastructure boundary (truth of record)
Host information is NOT held in this paper.
- Host truth: [eachpath.local](../eachpath.local/eachpath.local.md)
(topology) and `eachpath.local/saturn.eachpath.local/vms/<host>.eachpath.local/`
(per-host records). Missing host file for a host we run on? Create it
from host-onboarding facts, the same day.
- This repo's `architecture/` papers describe the SERVICES we run on
those hosts and their relationships; each such paper links its host
record instead of duplicating host facts.
- Paper follows reality: any claim about a host in this repo must be
host-verified against eachpath.local records.
## Learning (per-technology resources)
Every piece of technology we run gets a learning folder, so we can drill
down on the subject itself before the next round-trip builds on it.
- Folder per technology (see curriculum below).
- Ritual per folder: source of truth (official docs/spec first, never
second-hand), estate mapping (our host, port, version, config quoted
from the host record in eachpath.local), drills (hands-on questions
answered on OUR estate), and the ten-word understood-check said back.
- Learning gate: a primitive runs for real only after its paper is read
and explained back. We build ON knowledge, not around it.
Curriculum, in strict dependency order:
| # | Technology | Host record (eachpath.local) | Status |
|---|------------|------------------------------|--------|
| 1 | NATS + JetStream | `saturn.eachpath.local/vms/nats-dev.eachpath.local/` | open |
| 2 | Python asyncio + nats-py | runtime: nimmerworld-dev | next |
| 3 | PostgreSQL (Phoebe) | `.../phoebe-dev.eachpath.local/` | later |
| 4 | Godot client (GDScript, WebSocketPeer) | mimas/lab; boundary rule: pure client | later |
| 5 | FreeIPA / DNS / VLANs | athena, remus, romolus, spine+access | later |
| 6 | OPNsense (vulkan) | `vulkan.eachpath.local/` | later |
## 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.
Client = one crossing callback on the effect side. Runtime-first build order.
Examples:
- Pi: sends user messages, receives replies and tool calls. Uses runtime as backend, not brain.
- Harness RPC (`omp --mode rpc`): long-lived headless JSONL session; host tools, URIs, UI callbacks. Harness is host, not brain.
- Command Center (Godot): pure client, no core logic. Renders worlds, bodies, tools, moods. Sends chat and interactions as gestures. Receives dialogue, autonomy commands, tool results as action calls. Subscribes to zone state and effect streams. See [command-center/README.md](../command-center/README.md).
- Future clients: mobile, web, VR; same runtime.
- Pi (coding harness):
- sends user messages.
- receives replies, tool calls.
- uses Nimmerworld as its backend, not as its brain.
Interaction loop: chat -> text gate; room gestures -> switchboard; L1 admits; L2 action call drives body and dialogue the room renders.
- Command Center (Godot):
- subscribes to zone state and renders it.
- sends:
- chat,
- interactions (tools, proximity, posture) as gestures.
- receives:
- dialogue,
- autonomy commands (poses, moods, movements),
- tool results.
## Safety and governance
- Future clients:
- mobile, web, VR, etc.
- all connect to the same Nimmerworld.
- No silent autonomy: significant actions visible, logged, reversible.
- Relational modes and guardrails: explicit, rule-bound, auditable.
- Operator (dafit): final override, always.
- Gate switchboard: operator presence is a gate input above the runtime attention policy; rule-bound, no LLM in loop. Physical form of final override.
## 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
- No silent autonomy:
- significant actions are visible, logged, reversible.
- Relational modes and guardrails:
- explicit, rule-bound, auditable.
- You (dafit):
- final override, always.
## 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.
- VM ID: 123
- Hostname: nimmerworld-dev.eachpath.local
- IP: 10.0.30.123/24
- VLAN: 30 (cubes)
- 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
- eachpath.local/eachpath.local.md - network and Saturn VM overview
All runtime/architecture details live here (nimmerworld.eachpath.local). Infra specifics are not duplicated.
**Version:** 0.2 | **Updated:** 2026-11-04
Version: 0.13 | Updated: 2026-11-04