18 KiB
Idunn
Idunn is Odin's keepalive organ.
Odin is the all-seer: it accepts Verse discovery, schema catalogs, translation routes, provider surfaces, and observation projections. Idunn keeps the daemon swarm alive from that accepted map. It is not a second Odin, not a dashboard, and not a heroic supervisor with secret service truth in its pockets.
Idunn keeps the apples: desired daemon presence, deployment freshness, boot recovery, crash recovery, health freshness, deploy/restart intent, operator escalation, and continuity witness state.
Authority Map
- Owner: Idunn owns daemon lifecycle management after Odin has accepted where a daemon lives: bring-up after host reboot, deployment freshness, crash recovery, health watching, deploy/restart policy, and operator escalation.
- Inputs: Odin's accepted service records, provider advertisements,
.ccwitnesses, advertised command boundaries, CultNet/RUDP health contracts, freshness windows, operator policy, local service manager state, and demoted compatibility probes only while daemon CultLib dependencies still lack the shared RUDP health publication path. - Outputs: typed keepalive observations, deployment requests/results, restart requests/results, denied-action records, operator alarms, Bifrost operator-notification requests, and an Eve/CultUI keepalive surface.
- Derived state: dashboard cells, Bifrost receipts, Discord or owner-DM lowerings, agent summaries, and Odin service projections are notification-only views of Idunn-owned keepalive records.
- Forbidden writers: Idunn does not decide which Verses exist, invent provider schemas, mutate provider dashboards, own identity/session grants, or hide restarts behind Odin refresh logic. Individual daemons should not carry independent crash-recovery loops once Idunn owns their lifecycle path; they publish health, surfaces, state witnesses, and command boundaries instead.
- Shared paths: manual operator deploy/restart, scheduled deploy/restart, degraded-health repair, boot rehydration, and future remote worker recovery must pass through the same Idunn command primitive.
- Deletion line: any keepalive loop inside Odin, Gjallar, Eve lowerers, or renderer code must be cut or demoted to a probe that names Idunn as the restart owner.
Body
Idunn now shares Odin's Rust body:
crates/odin-core/src/idunn.rsowns the keepalive decision engine.crates/odin-core/src/documents.rspublishes typed Idunn CultMesh records beside Odin and Gjallar records.crates/idunn-daemonis the local keepalive actuator crate and now owns the resident Starfire-local swarm scheduler.src/Idunn/README.mdis the user-facing introduction for developers, operators, and daemon authors.scripts/start-idunn-local.ps1is now a narrow bootstrap wrapper: it ensures oneidunn.exeprocess is alive, checks the shared keepalive store for staleness, and lets Rust own the target catalog and per-target scheduling.scripts/deploy-yggdrasil-source-app.ps1andscripts/health-yggdrasil-source-app.ps1are the generic Yggdrasil source artifact lane. They package committed localHEADwithgit archive, run the existing ops-owned deploy/check scripts on Yggdrasil, and stamp a remotegamecult.idunn.deployment_manifest.v1only after the remote check passes.scripts/idunn-deployment-targets.ps1is the current swarm deployment target catalog. Every known deployable target is eitherenforced,blocked,external-owned, ornot-runtimewith an explicit reason.scripts/health-idunn-swarm-deployment-coverage.ps1is the coverage probe that fails when the target catalog becomes incoherent. The local Idunn launcher runs it asidunn-swarm-deployment-coverageso missing deploy ownership becomes a watched operational fault.scripts/notify-idunn-operator-alarm.ps1is the local operator crossing: Idunn invokes it only after raising an operator alarm, and it asks Bifrost to publish a typedgamecult.operator_dm_request.v1CultMesh command document instead of learning Discord delivery itself.npm run idunn:buildbuilds the Rust daemon.npm run idunn:start -- ...still supports the narrow one-daemon probe path for manual use.npm run idunn:start -- --swarm-profile starfire-local --repo-root E:\Projects\Odin --executeruns the singular local swarm supervisor.
The current typed records are:
idunn.desired_daemon.v1
idunn.daemon_health.v1
idunn.keepalive_decision.v1
idunn.deployment_request.v1
idunn.deployment_result.v1
idunn.restart_request.v1
idunn.restart_result.v1
idunn.operator_alarm.v1
idunn.swarm_surgery_plan.v1
idunn.daemon_surgery_plan.v1
idunn.daemon_transport_profile.v1
idunn.command_boundary.v1
idunn.runtime_transport_check.v1
idunn.rudp_health_ingress.v1
Invariants
- Odin remains the accepted owner of Verse and service discovery.
- Idunn owns continuity decisions after a daemon is known.
- Individual daemons own their work and their health publication, not their surrounding lifecycle. They must be simple to kill and simple for Idunn to bring back.
- Providers own their own command boundaries. Idunn requests deployment or restart through advertised authority or a named local service manager adapter.
- Host reboot recovery, crash recovery, stale deployment recovery, stale-health recovery, and manual operator deploy/restart must share the same Idunn command primitive.
- A repair loop is not an owner. If a daemon becomes healthy only after a later Odin refresh or manual click, Idunn's ownership path is still incomplete.
- Restart attempts must be witnessed: requested by whom, against which service, through which command boundary, with what result and timestamp.
- Health command exit status is not daemon awareness by itself. Every Idunn
target must declare a daemon-owned CultNet/RUDP health contract naming what
health publication should prove and what unmarked failure means.
idunn.desired_daemon.v1andidunn.daemon_health.v1both record that contract so later readers can distinguish process liveness, source deployment freshness, framebuffer composition, telemetry capture, and catalog coherence without mistaking a temporary HTTP/WebSocket/SSH/systemd probe for the real protocol surface.idunn.daemon_health.v1also recordspublication_sourceandtransportso daemon-published RUDP health can be distinguished from compatibility command evidence. idunn.desired_daemon.v1links toidunn.daemon_transport_profile.v1andidunn.command_boundary.v1records. The transport profile names the target transportcultnet.transport.rudp.v0, the still-active compatibility mechanism, and the cut line that demotes old probes. The command boundary names restart, deploy, health, and alarm authority separately so Idunn can actuate only the commands it actually owns.- The Starfire-local shell probes are compatibility evidence, not the target
architecture. A daemon is fully Idunn-aware only when it publishes its health,
command boundary, and transport profile as typed CultNet/CultMesh documents
over
cultnet.transport.rudp.v0. TCP, HTTP, WebSocket, and ad hoc port probes are migration debt, tolerated only at xenos/legacy boundaries and while the daemon's CultLib dependency has not yet been updated. - Rust now shares the canonical cross-runtime
cultnet.transport.rudp.v0substrate invendor/cultnet-rs: CNR0 packets, sessions, channels, reliable schema frames, and timeout/retry semantics matching the TypeScript/Python CultLib implementations. This removes "Rust cannot speak RUDP" as a substrate excuse. It does not make any daemon fully migrated until that daemon publishes its health and command boundary through the RUDP path and Idunn consumes that daemon-owned publication instead of the compatibility command. - Idunn publishes
idunn.runtime_transport_check.v1at startup. The current check sends a CultNet hello over loopbackcultnet.transport.rudp.v0and records whether the acknowledgement path works in Idunn's own Rust runtime. This proves Idunn's local substrate, not fleet migration. - Idunn also opens a RUDP health ingress and publishes
idunn.rudp_health_ingress.v1. The Starfire local supervisor binds0.0.0.0:17870so host-local publishers can use127.0.0.1:17870and WireGuard peers such as Nightwing can publish to10.77.0.2:17870. That ingress accepts only rawidunn.daemon_healthCultNet document puts on theschemachannel, decodes the typed MessagePack payload, and writes it into the keepalive store. Each one-shot publisher gets its own RUDP session from its UDP source address and the session is discarded after a delivered health frame. Windows UDPConnectionReset/ConnectionAbortedreports from closed one-shot clients are nonfatal ingress noise, not a reason to kill the worker. The ingress does not grant deploy/restart authority and it does not make compatibility probes owners; it is the first daemon-owned health publication path Idunn can consume. - During each target cycle, fresh daemon-published RUDP health wins over the
local compatibility command. Idunn accepts it only when the daemon id, health
contract,
publication_source=daemon-published, transportcultnet.transport.rudp.v0, andmax_silence_secondsfreshness window all match. If any of those fail, the command probe remains fallback evidence. - Idunn publishes the active swarm transport migration plan as
idunn.swarm_surgery_plan.v1. That record names the active profile, owner, objective, current mechanism, invariants, ordered phases, current phase, next target, cut line, and verification layer. It is the state-surface answer to "what surgery is Idunn doing next?" and must be lowered by Nightwing/Gjallar before any chat summary or dashboard prose claims ownership of the plan. - Idunn publishes per-target transport migration plans as
idunn.daemon_surgery_plan.v1records in the keepalive store. Each daemon plan names severity, status, owner, objective, current mechanism, intended CultNet/RUDP authority, cut line, ordered steps, blockers, and update time. These records are operational state, not documentation garnish: Nightwing, Gjallar, Odin, and future Eve lowerings should inspect them when projecting the daemon surgery queue. - A stale deployment is not restartable liveness. If a target reports
stale-deploymentwithout deploy authority, Idunn must alarm instead of restarting the stale artifact. If a target reportsdependency-unavailableordegraded, Idunn must alarm instead of treating local deploy/restart as the owner. - Idunn should fail closed when authority is unclear. Unknown ownership, repeated restart failure, missing command authority, or degraded health that needs a human becomes an operator alarm.
- Operator alarms use CultMesh to request Bifrost-owned operator notification.
Bifrost is the bridge for the crossing and records the receipt. VoidBot's
voidbot.operator-dmcommandowner.dm.sendwith payload schemagamecult.operator_dm_request.v1is a demoted compatibility delivery actuator, not the owner. The owner-DM command lives in Bifrost's Verse; any still-VoidBot delivery path must be invoked by Bifrost or documented as migration debt. Idunn must not learn Discord token handling, DM delivery internals, or VoidBot-specific transport. - In the current local bridge,
--operator-alarm-commandinvokesnotify-idunn-operator-alarm.cmd, which forwardsIDUNN_ALARM_*environment variables toE:\Projects\Bifrost\tools\operator-notification.mjs publish-idunn-alarm. Bifrost publishes the typed CultMesh command document; Idunn only decides that an alarm exists. - Muninn continuity on Raven is a remote keepalive path. Idunn probes the
deployed Odin
muninn.exe --healththrough theravenSSH alias and restarts Muninn's idleserveposture when needed. Raven is the host/body; Muninn is the local telemetry Verse assembler. Idunn must not activate screen/audio streams as part of keepalive. Raven A/V over SRT is an explicit activation path throughactivate-muninn-raven-av-srt.ps1, not daemon startup behavior. - Raven is an operator-consented shared machine. Idunn restart and health actuators for Raven must be background-only and must not open visible terminals or interactive windows on that host. The Raven Muninn restart path uses a hidden WScript/PowerShell trampoline; replacing it with an interactive console launch violates the ops contract.
- Nightwing Gjallar deployment freshness and visible composition health are now
part of Idunn's ops role.
health-nightwing-gjallar.ps1verifiesgjallar.serviceliveness, the remote deployment manifest at/opt/gamecult/gjallar/gamecult-gjallar-deploy-manifest.txt. A missing or stale manifest emitsidunn.health.state=stale-deployment; Idunn then runsdeploy-nightwing-gjallar.ps1, which publishes the committed local Gjallar revision, writesgamecult.gjallar.deployment_manifest.v1, restartsgjallar.service, and leaves deployment request/result records in its keepalive.cc. The same health probe also reads/var/log/gjallar.status; an empty catalog, failed receive loop, stale status witness, or zero composed provider panels is unhealthy even when the process is alive. Upstream deck failure emitsidunn.health.state=dependency-unavailableso Idunn does not redeploy Gjallar for an Odin/provider input outage. - Swarm-wide deployment ownership means Idunn owns the target catalog and the
freshness contract for the repo swarm. It does not mean Idunn invents deploy
authority for every repo immediately. A target without a safe noninteractive
deploy command must remain
blockedorexternal-ownedwith the missing authority named until a wrapper can produce a deployment manifest and route through Idunn's typed deployment request/result path. - Yggdrasil Heimdall, repixelizer, and StreamPixels are enforced through the
generic source artifact lane and their existing
gamecult-opsrunbooks. Bifrost is explicitly blocked as of 2026-06-09: committed BifrostHEADexpectsUserAccounts.HeimdallAccountId, while Yggdrasil's production database lacks that column and EF reports no pending migration. Idunn must not claim Bifrost deployment freshness until Bifrost owns that schema migration path.
Runtime Direction
Idunn's current Rust runtime now has two postures:
- One-daemon manual mode for focused probes and explicit local testing.
- One-process swarm mode for the Starfire-local continuity graph.
The local swarm mode owns:
- the built-in Starfire-local target catalog;
- a mandatory health contract per target;
- a typed
idunn.swarm_surgery_plan.v1record, so Idunn's active migration order, next target, cut line, and verification layer are explicit state; - a typed
idunn.daemon_surgery_plan.v1record per target, so transport debt is visible in the same state surface as daemon health; - a typed
idunn.daemon_transport_profile.v1andidunn.command_boundary.v1record per target, so compatibility probes and local commands cannot pretend to be daemon-owned CultNet/RUDP truth; - a startup
idunn.runtime_transport_check.v1witness proving Idunn's own Rust RUDP loopback path; - a local
idunn.rudp_health_ingress.v1listener for daemon-owned RUDP health publication; - one in-process schedule per target instead of one watchdog process per target;
- shared typed keepalive records in one CultMesh store;
- deploy/restart/alarm execution through the same Rust decision engine;
- recovery of fast local targets like Odin without waiting behind slow remote Yggdrasil checks.
Current plan surface: idunn.swarm_surgery_plan.v1 for profile
starfire-local treats the Muninn Rust lanes, Odin's local provider-health
lane, Stonks daemon health, Weksa daemon health, VoidBot stack health, and
Nightwing Gjallar framebuffer composition health as completed substrate cuts.
Muninn's --health mode publishes
idunn.daemon_health over RUDP; Starfire publishes to local Idunn, while
Nightwing and Raven publish over WireGuard to
10.77.0.2:17870 using their target daemon ids and health contracts. Odin
publishes odin.cultnet-rudp-provider-health after each provider refresh.
Stonks publishes stonks.cultnet-rudp-market-health after each serialized
market refresh. Weksa publishes weksa.cultnet-rudp-provider-health after each
serialized provider witness refresh. VoidBot publishes
voidbot.cultnet-rudp-stack-health after each GameCult Local Orchestrator
pulse. Gjallar publishes
gjallar.cultnet-rudp-framebuffer-composition-health from the C# Nightwing
framebuffer service. Mimir Eve dashboard publishes
mimir.cultnet-rudp-provider-health from the Nightwing systemd broker, and the
same process publishes nightwing.cultnet-rudp-eve-dashboard-health for the
Nightwing dashboard service itself. Live Idunn cycles accept these records
before command-probe fallback.
Raven's Muninn scheduled-task repair is a separate ops invariant:
GameCult-Muninn, GameCult-Muninn-Activate, and
GameCult-Muninn-VideoProof must execute wscript.exe hidden launcher actions,
not raw .cmd task actions.
Next: move the Nightwing Eve browser reference off compatibility service probes,
then continue runtime-by-runtime until compatibility probes can be deleted or
demoted. Stonks, Weksa, VoidBot, Gjallar, Mimir, and the Nightwing Eve dashboard
service still owe provider advertisement and command-boundary RUDP publication
before their compatibility surfaces can be purely display/debug lowerings;
Gjallar also owes native CultMesh/RUDP deck input to replace the current Odin
WebSocket lowering bridge. Raven Muninn task action repair is queued separately
and remains blocked while Raven is unreachable over SSH; the prepared actuator is
scripts\repair-raven-muninn-task-actions.ps1.
No ad hoc JSON manifest, HTTP endpoint, TCP socket, or WebSocket bridge may
become the live state owner. Debug projections are fine when they name the
.cc record, CultNet document, or CultMesh publication behind them.