Docs: Idunn owns deployment and daemon survival; Odin does discovery only
README and architecture.md called Idunn "Odin's keepalive organ", listed crates/idunn-daemon (not in this repo) and the deleted odin-core idunn.rs as its body, described the Node coordinator's process lifecycle, refresh loop and Docker/ADB probes as Odin's runtime body, and pointed at the deleted start-odin.ps1. Rewritten to the live truth: Idunn builds, activates, restarts and brakes every target, Odin included; odin-daemon reads Idunn's projection, admits presences, publishes correlation records and answers RUDP requests; process lifecycle is not Odin's. The dated ledger (transport-shortcut-inventory.md), notes/ and the Hermodr extraction plan are history and are left as written. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
779c24ba80
commit
106dfb8327
2 changed files with 54 additions and 137 deletions
101
README.md
101
README.md
|
|
@ -70,75 +70,47 @@ Local package surfaces:
|
|||
|
||||
## Idunn
|
||||
|
||||
Idunn is Odin's keepalive organ: the daemon package that should keep the known
|
||||
swarm alive after Odin has accepted where each daemon lives and what authority
|
||||
path may touch it. Individual daemons publish health and command boundaries;
|
||||
Idunn brings them up after reboots or crashes, watches health, and escalates
|
||||
operator-needed failures through Bifrost's CultMesh bridge. VoidBot owner-DM
|
||||
delivery is a demoted compatibility actuator, not the owner; the command belongs
|
||||
in Bifrost's Verse. Odin sees the daemons; Idunn keeps the apples from rotting.
|
||||
Agents do not deploy daemons directly. They configure Idunn's target catalog,
|
||||
release targets, migration commands, and command boundaries so Idunn can run
|
||||
the shared rollout primitive and leave typed witnesses behind.
|
||||
|
||||
Deployment consequence has one final owner: immediately before every migration,
|
||||
deploy, or restart process spawn, Idunn re-opens the root-owned deployment-brake
|
||||
CultCache and the dedicated operator public anchor. A released record must bind
|
||||
the canonical runtime (`yggdrasil` for `yggdrasil-local`), exact source revision
|
||||
(or `restart:<daemon>`), exact request id, operator, signature, and short expiry.
|
||||
Missing, corrupt, engaged, expired, foreign, wrong-scope, substituted, or
|
||||
badly-signed state fails closed. Planning and lifecycle-command publication do
|
||||
not bypass or cache this decision. The store and its sibling `.lock` live in
|
||||
`/var/lib/gamecult/idunn-authority`, a root-owned `root:idunn` `0750` directory;
|
||||
both files are `root:idunn` `0640`, and the daemon's systemd sandbox exposes the
|
||||
directory read-only. Idunn holds the lock shared from its final snapshot read
|
||||
through process spawn, so an engage cannot be defeated by previously captured
|
||||
released bytes. A release is not one-shot: its exact request/revision grant
|
||||
covers each migration and deploy spawn in that rollout until its short expiry;
|
||||
every spawn independently reopens and validates the same grant.
|
||||
Idunn (`GameCult/Idunn`) owns deployment and daemon survival for every GameCult
|
||||
target, Odin included: it builds from the target's recipe, activates and
|
||||
restarts the admitted incarnation, and holds the deployment and lifecycle
|
||||
brakes. Odin owns none of that. Odin does discovery, schema awareness,
|
||||
rendezvous, and interface aggregation, and it reads Idunn's topology projection
|
||||
to learn which incarnations exist. Agents do not deploy daemons directly: they
|
||||
configure the target's recipe and binding and let Idunn run the transaction.
|
||||
|
||||
Local package surfaces:
|
||||
|
||||
- Organ contract: `docs/idunn.md`
|
||||
- User README: `src/Idunn/README.md`
|
||||
- Rust daemon crate: `crates/idunn-daemon`
|
||||
- Rust lifecycle logic: `crates/odin-core/src/idunn.rs`
|
||||
- Runtime store: `scratch/idunn/idunn.keepalive.cc`
|
||||
- Hosted VoidBot release: upstream `main` -> Yggdrasil-local Idunn -> the
|
||||
root-owned `/srv/odin/deploy-manifests/voidbot` actuator. Local checkouts are
|
||||
development and diagnostics only; do not create a local deployment.
|
||||
- Hosted Odin release: branch `codex/ygg-idunn-independent-bootstrap` plus the
|
||||
exact CultLib commit in `deploy/cultlib.commit` -> one immutable
|
||||
`/srv/odin/releases/<commit>` body -> `/srv/odin/current`. Odin signs its own
|
||||
liveness to Idunn, while Idunn starts independently and owns later restart or
|
||||
deployment actuation.
|
||||
- Operator escalation: Bifrost-owned CultMesh crossing; current compatibility
|
||||
delivery calls `scripts\notify-idunn-operator-alarm.ps1`, which asks Bifrost
|
||||
to publish a typed `gamecult.operator_dm_request.v1` CultMesh command document
|
||||
only after Idunn raises an alarm
|
||||
- Deployment recipe: `deployment/idunn/recipe.toml`
|
||||
- Operator binding: `/etc/gamecult/idunn/bindings/odin.toml` on the host, not in
|
||||
this repository
|
||||
- Live deployment and admission map: `state/map.yaml`
|
||||
- Idunn's contract, brakes, and runbooks: the `GameCult/Idunn` repository
|
||||
|
||||
## Authority Map
|
||||
|
||||
- Owner: Odin owns the network-wide Verse registry, schema catalog index, translation map, and accepted provider catalog/proxy surfaces.
|
||||
- Inputs: CultMesh/CultNet peer announcements, schema catalog responses, daemon
|
||||
health/provider publications over `cultnet.transport.rudp.v0`, local
|
||||
Docker/ADB debug facts, and provider-owned Eve/CultUI surfaces.
|
||||
health/provider publications over `cultnet.transport.rudp.v0`, Idunn's
|
||||
read-only topology projection, and provider-owned Eve/CultUI surfaces.
|
||||
- Outputs: CultCache-backed Odin state, CultMesh documents, and CultNet
|
||||
schema/catalog messages. Browser, GUI, TUI, and framebuffer renderers lower
|
||||
those documents outside Odin instead of asking Odin to host web surfaces.
|
||||
- Derived state: Gjallar's aggregate surface is derived from Odin/provider state; Eve clients derive pixels from that aggregate.
|
||||
- Forbidden writers: renderers do not probe the network or decide Verse truth; individual projects do not maintain private incompatible discovery ledgers once Odin can see them.
|
||||
- Shared paths: human dashboards, worker schedulers, Verse bootstrap code, and compact TUI views consume the same registry and schema catalog.
|
||||
- Deletion line: old per-host coordinator scripts should be deleted or reduced to deployment wrappers that start Odin.
|
||||
- Not Odin's: process lifecycle, restart, deployment, and daemon survival belong to Idunn.
|
||||
|
||||
## Run Locally On Starfire
|
||||
## Runtime Body
|
||||
|
||||
```powershell
|
||||
.\scripts\start-odin.ps1 -IdunnRudpHealth $env:IDUNN_RUDP_HEALTH
|
||||
```
|
||||
Odin runs as `odin-daemon` under Idunn on Yggdrasil, built from
|
||||
`deployment/idunn/recipe.toml`. There is no local start script. The daemon:
|
||||
|
||||
`-IdunnRudpHealth`, `ODIN_IDUNN_RUDP_HEALTH`, or `IDUNN_RUDP_HEALTH` must name
|
||||
the Idunn RUDP health endpoint. Odin does not assume a localhost health target.
|
||||
- reads Idunn's read-only projection to learn which incarnations of which
|
||||
targets exist;
|
||||
- admits provider presences over RUDP for those incarnations and persists them
|
||||
through CultMesh/CultCache;
|
||||
- publishes signed runtime-topology correlation records;
|
||||
- answers CultNet/RUDP snapshot and document requests on its route.
|
||||
|
||||
Odin's native document catalog is addressed by CultMesh URI. Concrete RUDP
|
||||
bootstrap is configured behind CultMesh URI resolution by the operator or by
|
||||
|
|
@ -152,28 +124,9 @@ That URI accepts typed document publication and schema/catalog requests through
|
|||
the shared CultMesh runtime. Consumers that need Odin's accepted surface can
|
||||
still request the current CultNet snapshot after CultMesh resolves the transport.
|
||||
|
||||
Legacy browser/deck lowerers must consume Odin's CultMesh state through their
|
||||
own lowering process. Odin no longer hosts browser-deck surfaces or publishes
|
||||
deck URLs as discovery seed material.
|
||||
|
||||
State and logs live under ignored `scratch/odin/`.
|
||||
|
||||
## Current First Body
|
||||
|
||||
The first executable is deliberately narrow:
|
||||
|
||||
- publishes provider catalog `odin.providers`;
|
||||
- persists the latest surface through local CultMesh/CultCache when `CultLib` packages are available at `E:\Projects\CultLib\packages`;
|
||||
- writes `scratch/odin/latest-surface.json` only when `--write-debug-surface-json` or `ODIN_WRITE_DEBUG_SURFACE_JSON=1` is explicitly supplied;
|
||||
- observes Starfire Docker and Periwinkle ADB as local debug/edge facts;
|
||||
- derives remote Verse presence from provider-owned CultMesh/CultNet
|
||||
advertisements and interface records, not TCP/SSH/systemd probes.
|
||||
- publishes explicit `verse` and `service` nodes for compact Eve/CultUI lowerers.
|
||||
- ingests provider-owned Eve/CultUI dashboards, including `mimir.live.stats` and `voidbot.swarm`, and embeds them as Odin `interface` nodes;
|
||||
- accepts live `gamecult.eve.provider_advertisement.v1` announcements through Odin's CultMesh/RUDP rendezvous path so daemons can announce schemas, surfaces, commands, nested Verses, and style capabilities without Odin scraping private dashboards;
|
||||
- accepts explicit local debug imports only when `--interfaceBindingStore` / `ODIN_INTERFACE_BINDING_STORES` entries are written as `cultmesh-store:file://...` URIs; raw filesystem paths are not discovery configuration;
|
||||
- preserves provider semantic addresses such as `asgard.starfire.bifrost/eve/tui` and `asgard.starfire.bifrost/eve/gui`, with CultNet routes carried as transport metadata rather than identity;
|
||||
- persists operator tiling intent as `odin.interface_layout.v1` in the Odin CultMesh store; ignored `scratch/odin/interface-layout.json` is migration input only.
|
||||
Browser and deck lowerers consume Odin's CultMesh state through their own
|
||||
lowering process. Odin does not host browser-deck surfaces or publish deck URLs
|
||||
as discovery seed material.
|
||||
|
||||
Provider advertisements and CultNet/RUDP transport profiles are the discovery
|
||||
path. External host probes, product health checks, port probes, and renderer
|
||||
|
|
|
|||
|
|
@ -46,35 +46,24 @@ The first Rust core lives in `crates/odin-core`:
|
|||
- `repository.rs`: `OdinRepository` abstraction, in-memory mock repository, and
|
||||
CultMesh-backed repository.
|
||||
|
||||
The Rust spine owns the future architecture. The CommonJS daemon remains the
|
||||
legacy operational body until each organ crosses this typed boundary.
|
||||
The deployed body is `crates/odin-daemon`, built and run by Idunn from
|
||||
`deployment/idunn/recipe.toml`. `crates/odin-core` holds the typed record spine
|
||||
that the rest of the machine grows into.
|
||||
|
||||
## Runtime Body
|
||||
|
||||
Odin's executable body is split by ownership:
|
||||
|
||||
- `crates/odin-core`: Rust target core. Owns typed Odin documents, ingest
|
||||
ports, normalization, and CultMesh/CultCache repository boundaries. This is
|
||||
the replacement spine; JavaScript remains legacy runtime scaffolding until
|
||||
each organ has crossed the typed boundary.
|
||||
- `src/odin-coordinator.cjs`: process lifecycle, serialized refresh loop,
|
||||
persistence, health, and transport wiring. Refreshes must not overlap because
|
||||
a refresh publishes Odin's daemon health.
|
||||
- `src/odin/config.cjs`: runtime paths, refresh intervals, and CultLib module path setup.
|
||||
- `src/odin/documents.cjs`: CultCache/CultMesh document definitions accepted by Odin.
|
||||
- `src/odin/idunn-rudp.cjs`: daemon-owned Odin provider health publication to
|
||||
Idunn over the canonical CultNet RUDP `schema` channel.
|
||||
- `src/odin/probes.cjs`: local Docker/ADB debug lowerings for Starfire and
|
||||
Android edge visibility. Remote Verse health is not probed here; it comes
|
||||
from provider-owned CultMesh/CultNet records.
|
||||
- `src/odin/interfaces.cjs`: provider advertisements, CultMesh interface
|
||||
bindings, accepted interface projection, and renderer-lowering metadata.
|
||||
Renderer routes are lowerings outside Odin, not Odin-hosted transport.
|
||||
- `src/odin/layout.cjs`: `odin.interface_layout.v1` read/write and merge policy.
|
||||
- `src/odin/marquee.cjs`: canonical marquee tape assembly from Stonks securities and ordered VoidBot poem lines.
|
||||
- `src/odin/surface.cjs`: `gamecult.eve.surface.v1` tree projection.
|
||||
- `src/odin/state.cjs`: one refresh's input records into Odin's provider catalog/proxy state.
|
||||
The entrypoint is not allowed to grow new probe, surface, provider, layout, or renderer policy. If a new owner is needed, name the owner and its invariant before adding code.
|
||||
- `crates/odin-daemon`: the deployed process. Reads Idunn's read-only topology
|
||||
projection, admits provider presences over RUDP for the incarnations Idunn
|
||||
projects, persists them through CultMesh/CultCache, publishes signed
|
||||
runtime-topology correlation records, and answers CultNet/RUDP snapshot and
|
||||
document requests. Deployment, restart, and survival of this process are
|
||||
Idunn's.
|
||||
- `crates/odin-core`: typed Odin documents, ingest ports, normalization, and
|
||||
CultMesh/CultCache repository boundaries.
|
||||
|
||||
If a new owner is needed, name the owner and its invariant before adding code.
|
||||
|
||||
The accepted document registry is also the persistence admission boundary.
|
||||
Unknown schemas may be observed for diagnostics but are not silently persisted
|
||||
|
|
@ -94,19 +83,15 @@ the typed `gjallar.overview` Eve surface. Eve clients own graphical, terminal,
|
|||
and framebuffer lowering. Gjallar must not own the underlying registry, probe,
|
||||
provider truth, client pixels, or translation decisions.
|
||||
|
||||
Idunn is the named keepalive organ for daemon continuity. Its current Rust
|
||||
body lives in `crates/idunn-daemon` and `crates/odin-core/src/idunn.rs`. Idunn may read
|
||||
Odin-owned service records and provider advertisements, then bring daemons up
|
||||
after reboots or crashes, watch health, emit keepalive observations, restart
|
||||
requests, denied-action records, and operator alarms. When human action is
|
||||
needed, Idunn uses CultMesh to request a Bifrost-owned operator
|
||||
notification crossing. VoidBot's `voidbot.operator-dm` command `owner.dm.send`
|
||||
is a demoted compatibility delivery actuator, not the owner. The target command
|
||||
lives in Bifrost's Verse; any still-VoidBot delivery path must be invoked by
|
||||
Bifrost or documented as migration debt. Idunn must not own Verse discovery,
|
||||
schema truth, provider dashboards, identity grants, Discord delivery, owner-DM
|
||||
delivery, or renderer layout. Keepalive loops belong in Idunn, not Odin's
|
||||
coordinator or individual daemons.
|
||||
Idunn (`GameCult/Idunn`) owns deployment and daemon survival, including Odin's.
|
||||
It builds from each target's recipe, activates and restarts the admitted
|
||||
incarnation, and holds the deployment and lifecycle brakes. Odin publishes what
|
||||
it can see and reads Idunn's topology projection; it does not start, restart,
|
||||
deploy, or health-probe any daemon, and no Odin code path keeps a process alive.
|
||||
When human action is needed, Idunn uses CultMesh to request a Bifrost-owned
|
||||
operator notification crossing. Idunn must not own Verse discovery, schema
|
||||
truth, provider dashboards, identity grants, Discord delivery, owner-DM
|
||||
delivery, or renderer layout.
|
||||
|
||||
Muninn is the portable local telemetry Verse assembler. Its Rust body lives in
|
||||
the `GameCult/Muninn` repository and publishes `muninn.telemetry_surface.v1`
|
||||
|
|
@ -213,19 +198,10 @@ This is not a reporting nicety. It is how Odin prevents services from becoming
|
|||
private little islands with separate websites, dashboards, state formats, and
|
||||
separate command languages.
|
||||
|
||||
## Current Service Surface
|
||||
## Service Surface
|
||||
|
||||
Odin currently publishes service squares for:
|
||||
|
||||
- Starfire: Odin, Docker, ADB, Odin CultCache, and running Docker containers.
|
||||
- Nightwing: SSH, Eve broker, Eve browser reference, visible TUI, Docker unit state, and NVIDIA GPU state.
|
||||
- EVE: SSH/native Eve reachability.
|
||||
- Periwinkle: ADB reachability.
|
||||
- Periwinkle: local ADB edge status plus any provider-owned surface or advertisement Odin receives through CultMesh/Odin discovery.
|
||||
- Raven: SSH reachability.
|
||||
- Yggdrasil: compatibility host reachability plus nginx,
|
||||
StreamPixels, Heimdall, Repixelizer, and Bifrost systemd state until those
|
||||
daemon surfaces publish health and command boundaries over CultNet RUDP.
|
||||
Odin's service records come from provider-owned presences and advertisements
|
||||
received through CultMesh/RUDP, not from host probes.
|
||||
|
||||
Gjallar consumes Odin's accepted CultMesh/Eve state and composes every visible
|
||||
provider surface into one typed aggregate on Yggdrasil. EveCanvas, browser, and
|
||||
|
|
@ -250,8 +226,8 @@ interactive language; they are not separate dashboard products. Huginn's `.cc`
|
|||
inspection surface is the current clean example: Huginn inspects CultCache bytes
|
||||
and emits Eve DSL, while Eve or any other runtime owns presentation.
|
||||
|
||||
Provider advertisements are the promotion path out of probing. Odin's CJS
|
||||
document set already accepts `gamecult.eve.provider_advertisement.v1` alongside
|
||||
Provider advertisements are the promotion path out of probing. Odin's document
|
||||
registry already accepts `gamecult.eve.provider_advertisement.v1` alongside
|
||||
`gamecult.eve.interface_binding.v1` and `gamecult.eve.surface_state.v1`.
|
||||
Daemons should publish advertisements that name service id, Verse id, schema
|
||||
catalog, `.cc` witnesses, Eve surface keys, command boundaries, nested Verses,
|
||||
|
|
@ -290,18 +266,6 @@ identity.
|
|||
The canonical contract lives in
|
||||
`E:\Projects\Eve\docs\provider-advertisement-contract.md`.
|
||||
|
||||
Odin persists operator layout intent as `odin.interface_layout.v1` in the Odin CultMesh store under record key `odin.providers`. The ignored `scratch/odin/interface-layout.json` file is migration input only; Odin no longer writes layout truth back to that sidecar. Layout intents name the provider id and request focus, move, resize, or visibility changes; renderers are input devices for those intents, not local layout owners.
|
||||
|
||||
Odin now derives dense top-level layout intent from each provider's retained
|
||||
`surface.root` tree: element count, leaf count, branch count, depth, text-cell
|
||||
pressure, and list-like branches. Provider explicit preferred sizes are capped
|
||||
at the Odin wrapper boundary unless the current intent is fullscreen, so stale
|
||||
layout files cannot keep empty panels huge. The renderer should use
|
||||
`props.tree`, `props.layout.signalWeight`, and `props.packing` to allocate space
|
||||
to nested signal, then recursively lower provider children. Flattening a
|
||||
provider surface into one log/list is a compatibility failure when the retained
|
||||
tree has children.
|
||||
|
||||
## Observation Surface
|
||||
|
||||
Odin no longer tails Mimir JSONL artifacts for observation truth. Device and
|
||||
|
|
|
|||
Loading…
Reference in a new issue