use anyhow::{Context, Result, anyhow}; use cultmesh_rs::{CultMesh, CultMeshNode, CultMeshNodeOptions}; use cultnet_rs::{ CULTNET_RUDP_PROTOCOL_ID, CultNetMessage, CultNetRawPayloadEncoding, CultNetRudpOptions, recv_cultnet_message_rudp, send_cultnet_message_rudp, }; use odin_core::{ IdunnCommandBoundaryRecord, IdunnDaemonHealthRecord, IdunnDaemonSurgeryPlanRecord, IdunnDaemonTransportProfileRecord, IdunnDeploymentResultRecord, IdunnDesiredDaemonRecord, IdunnOperatorAlarmRecord, IdunnRestartResultRecord, IdunnRudpHealthIngressRecord, IdunnRuntimeTransportCheckRecord, IdunnSwarmSurgeryPlanRecord, OdinDocuments, plan_keepalive, }; use std::env; use std::net::{SocketAddr, UdpSocket}; use std::path::PathBuf; use std::process::{Child, Command, Stdio}; use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; use std::time::{Instant, SystemTime, UNIX_EPOCH}; #[derive(Clone, Debug)] struct DaemonTarget { daemon_id: String, verse_id: String, name: String, health_contract: HealthContract, health_command: Option, deploy_command: Option, restart_command: Option, enabled: bool, interval_seconds: u64, } #[derive(Clone, Debug)] struct HealthContract { id: String, default_failure_state: String, } fn health_contract(id: &str, default_failure_state: &str) -> HealthContract { HealthContract { id: id.to_string(), default_failure_state: default_failure_state.to_string(), } } #[derive(Clone, Debug)] struct CommonOptions { store_path: PathBuf, operator_alarm_command: Option, rudp_health_bind: Option, execute: bool, command_timeout_seconds: u64, } #[derive(Clone, Debug)] enum Mode { Single(DaemonTarget), Swarm(SwarmOptions), } #[derive(Clone, Debug)] struct SwarmOptions { profile: String, repo_root: PathBuf, } #[derive(Clone, Debug)] struct Options { common: CommonOptions, mode: Mode, } fn main() -> Result<()> { let options = Options::parse(env::args().skip(1))?; if let Some(parent) = options.common.store_path.parent() { std::fs::create_dir_all(parent) .with_context(|| format!("creating {}", parent.display()))?; } match &options.mode { Mode::Single(target) => { let store_lock = Arc::new(Mutex::new(())); let now = timestamp()?; publish_runtime_transport_check(&options.common, &store_lock, &now)?; run_target_cycle(target, &options.common, &store_lock) } Mode::Swarm(swarm) => run_swarm(swarm, &options.common), } } fn run_swarm(options: &SwarmOptions, common: &CommonOptions) -> Result<()> { let targets = swarm_targets(options)?; if targets.is_empty() { return Err(anyhow!( "Idunn swarm profile {} resolved to no targets", options.profile )); } validate_targets(&targets)?; println!( "Idunn swarm profile {} starting with {} targets.", options.profile, targets.len() ); println!("CultMesh store: {}", common.store_path.display()); let store_lock = Arc::new(Mutex::new(())); let now = timestamp()?; publish_runtime_transport_check(common, &store_lock, &now)?; start_rudp_health_ingress(common, &store_lock, &now)?; publish_surgery_plans(&options.profile, &targets, common, &store_lock, &now)?; let mut workers = Vec::with_capacity(targets.len()); for target in targets { let worker_common = common.clone(); let worker_store_lock = Arc::clone(&store_lock); workers.push(thread::spawn(move || { run_target_loop(target, worker_common, worker_store_lock) })); } for worker in workers { match worker.join() { Ok(Ok(())) => {} Ok(Err(error)) => return Err(error), Err(_) => return Err(anyhow!("Idunn swarm worker thread panicked")), } } Ok(()) } fn validate_targets(targets: &[DaemonTarget]) -> Result<()> { let mut issues = Vec::new(); for target in targets { if target.health_contract.id.trim().is_empty() { issues.push(format!("{} has no health contract", target.daemon_id)); } if target.health_command.is_none() { issues.push(format!("{} has no health command", target.daemon_id)); } if target.health_contract.default_failure_state == "stale-deployment" && target.deploy_command.is_none() { issues.push(format!( "{} treats probe failure as stale deployment but has no deploy command", target.daemon_id )); } } if issues.is_empty() { Ok(()) } else { Err(anyhow!( "Idunn target catalog is incoherent: {}", issues.join("; ") )) } } fn run_target_loop( target: DaemonTarget, options: CommonOptions, store_lock: Arc>, ) -> Result<()> { loop { if let Err(error) = run_target_cycle(&target, &options, &store_lock) { eprintln!( "Idunn swarm target {} cycle failed: {}", target.daemon_id, error ); } thread::sleep(Duration::from_secs(target.interval_seconds)); } } fn run_target_cycle( target: &DaemonTarget, options: &CommonOptions, store_lock: &Arc>, ) -> Result<()> { let now = timestamp()?; let desired = IdunnDesiredDaemonRecord { daemon_id: target.daemon_id.clone(), verse_id: target.verse_id.clone(), name: target.name.clone(), enabled: target.enabled, health_command: target.health_command.clone(), restart_command: target.restart_command.clone(), deploy_command: target.deploy_command.clone(), health_contract: target.health_contract.id.clone(), transport_profile_id: transport_profile_id(target), command_boundary_id: command_boundary_id(target), authority: "idunn.local-command".to_string(), max_silence_seconds: 60, observed_at: now.clone(), }; let health = read_fresh_daemon_published_health(options, store_lock, &desired, &now)? .unwrap_or_else(|| probe_health(target, options.command_timeout_seconds, &now)); let plan = plan_keepalive(&desired, &health, now.clone()); with_store_node(options, store_lock, |node| { let transport_profile = daemon_transport_profile(target, &now); let command_boundary = command_boundary(target, &now); node.put(&transport_profile.profile_id, &transport_profile)?; node.put(&command_boundary.boundary_id, &command_boundary)?; node.put(&desired.daemon_id, &desired)?; node.put(&health.daemon_id, &health)?; node.put(&plan.decision.decision_id, &plan.decision)?; if let Some(request) = &plan.deployment_request { node.put(&request.request_id, request)?; } if let Some(request) = &plan.restart_request { node.put(&request.request_id, request)?; } if let Some(alarm) = &plan.operator_alarm { node.put(&alarm.alarm_id, alarm)?; } Ok(()) })?; if let Some(request) = &plan.deployment_request { if options.execute { let result = run_deployment(request, &now, options.command_timeout_seconds); let alarm = if result.state != "succeeded" { Some(deployment_failure_alarm(&result, &now)) } else { None }; with_store_node(options, store_lock, |node| { node.put(&result.result_id, &result)?; if let Some(alarm) = &alarm { node.put(&alarm.alarm_id, alarm)?; } Ok(()) })?; println!( "Idunn deployment {} for {}: {}", result.state, result.daemon_id, result.detail ); if let Some(alarm) = alarm { println!( "Idunn raised operator alarm for {} through {}: {}", alarm.daemon_id, alarm.escalation_target, alarm.reason ); run_operator_alarm_command(options, &alarm); } } else { println!( "Idunn requested deployment for {} but did not execute it. Pass --execute to actuate.", request.daemon_id ); } } if let Some(request) = &plan.restart_request { if options.execute { let result = run_restart(request, &now, options.command_timeout_seconds); let alarm = if result.state != "succeeded" { Some(restart_failure_alarm(&result, &now)) } else { None }; with_store_node(options, store_lock, |node| { node.put(&result.result_id, &result)?; if let Some(alarm) = &alarm { node.put(&alarm.alarm_id, alarm)?; } Ok(()) })?; println!( "Idunn restart {} for {}: {}", result.state, result.daemon_id, result.detail ); if let Some(alarm) = alarm { println!( "Idunn raised operator alarm for {} through {}: {}", alarm.daemon_id, alarm.escalation_target, alarm.reason ); run_operator_alarm_command(options, &alarm); } } else { println!( "Idunn requested restart for {} but did not execute it. Pass --execute to actuate.", request.daemon_id ); } } if let Some(alarm) = &plan.operator_alarm { println!( "Idunn raised operator alarm for {} through {}: {}", alarm.daemon_id, alarm.escalation_target, alarm.reason ); run_operator_alarm_command(options, alarm); } println!( "Idunn decision for {}: {} ({})", plan.decision.daemon_id, plan.decision.action, plan.decision.reason ); Ok(()) } fn with_store_node( options: &CommonOptions, store_lock: &Arc>, write: F, ) -> Result where F: FnOnce(&mut CultMeshNode) -> Result, { let _store_guard = store_lock .lock() .map_err(|_| anyhow!("Idunn store lock is poisoned"))?; let mut node = CultMesh::create_node( &options.store_path, OdinDocuments, CultMeshNodeOptions { runtime_id: "idunn-daemon".to_string(), pull_on_start: true, }, )?; write(&mut node) } fn read_fresh_daemon_published_health( options: &CommonOptions, store_lock: &Arc>, desired: &IdunnDesiredDaemonRecord, now: &str, ) -> Result> { with_store_node(options, store_lock, |node| { let Some(health) = node.get::(&desired.daemon_id)? else { return Ok(None); }; if is_fresh_daemon_published_health(&health, desired, now) { Ok(Some(health)) } else { Ok(None) } }) } fn is_fresh_daemon_published_health( health: &IdunnDaemonHealthRecord, desired: &IdunnDesiredDaemonRecord, now: &str, ) -> bool { if health.daemon_id != desired.daemon_id { return false; } if health.health_contract != desired.health_contract { return false; } if health.publication_source != "daemon-published" { return false; } if health.transport != CULTNET_RUDP_PROTOCOL_ID { return false; } let Some(now_seconds) = parse_unix_timestamp(now) else { return false; }; let Some(observed_seconds) = parse_unix_timestamp(&health.observed_at) else { return false; }; if observed_seconds > now_seconds { return false; } now_seconds.saturating_sub(observed_seconds) <= u64::from(desired.max_silence_seconds) } fn parse_unix_timestamp(value: &str) -> Option { value.strip_prefix("unix:")?.parse().ok() } fn publish_runtime_transport_check( options: &CommonOptions, store_lock: &Arc>, observed_at: &str, ) -> Result<()> { let check = runtime_transport_check(observed_at); with_store_node(options, store_lock, |node| { node.put(&check.check_id, &check)?; Ok(()) }) } fn runtime_transport_check(observed_at: &str) -> IdunnRuntimeTransportCheckRecord { match verify_rudp_loopback() { Ok(transfer_id) => IdunnRuntimeTransportCheckRecord { check_id: "idunn-runtime-rudp-loopback".to_string(), runtime_id: "idunn-daemon".to_string(), transport: CULTNET_RUDP_PROTOCOL_ID.to_string(), state: "available".to_string(), detail: format!("loopback CultNet RUDP message acknowledged as transfer {transfer_id}"), observed_at: observed_at.to_string(), }, Err(error) => IdunnRuntimeTransportCheckRecord { check_id: "idunn-runtime-rudp-loopback".to_string(), runtime_id: "idunn-daemon".to_string(), transport: CULTNET_RUDP_PROTOCOL_ID.to_string(), state: "failed".to_string(), detail: format!("loopback CultNet RUDP check failed: {error}"), observed_at: observed_at.to_string(), }, } } fn verify_rudp_loopback() -> Result { let sender = UdpSocket::bind("127.0.0.1:0")?; let receiver = UdpSocket::bind("127.0.0.1:0")?; let receiver_addr = receiver.local_addr()?; let options = CultNetRudpOptions { ack_timeout: Duration::from_millis(100), retries: 3, ..CultNetRudpOptions::default() }; let receiver_options = options.clone(); let handle = thread::spawn(move || -> Result<()> { let (message, _source, _transfer_id) = recv_cultnet_message_rudp(&receiver, &receiver_options)?; match message { CultNetMessage::Hello { runtime_id, .. } if runtime_id == "idunn-daemon" => Ok(()), other => Err(anyhow!("unexpected loopback CultNet message: {other:?}")), } }); let transfer_id = send_cultnet_message_rudp( &sender, receiver_addr, &CultNetMessage::Hello { runtime_id: "idunn-daemon".to_string(), runtime_kind: "keepalive".to_string(), agent_id: None, role: Some("idunn.runtime-transport-self-check".to_string()), display_name: Some("Idunn RUDP self-check".to_string()), supported_document_types: Some(vec!["idunn.runtime_transport_check".to_string()]), supported_mutation_contracts: None, supported_message_versions: Some(vec!["cultnet.hello.v0".to_string()]), supports_schema_catalog: Some(false), }, &options, )?; handle .join() .map_err(|_| anyhow!("Idunn RUDP loopback receiver thread panicked"))??; Ok(transfer_id) } fn start_rudp_health_ingress( options: &CommonOptions, store_lock: &Arc>, observed_at: &str, ) -> Result<()> { let Some(bind_address) = options.rudp_health_bind else { return Ok(()); }; let ingress_id = "idunn-rudp-health-ingress".to_string(); let socket = match UdpSocket::bind(bind_address) { Ok(socket) => socket, Err(error) => { let failed = rudp_health_ingress_record( &ingress_id, bind_address, "failed", &format!("failed to bind RUDP health ingress: {error}"), observed_at, ); with_store_node(options, store_lock, |node| { node.put(&failed.ingress_id, &failed)?; Ok(()) })?; return Err(error.into()); } }; let local_addr = socket.local_addr()?; socket.set_read_timeout(Some(Duration::from_millis(500)))?; let active = rudp_health_ingress_record( &ingress_id, local_addr, "active", "listening for raw idunn.daemon_health documents over CultNet RUDP", observed_at, ); with_store_node(options, store_lock, |node| { node.put(&active.ingress_id, &active)?; Ok(()) })?; let worker_options = options.clone(); let worker_store_lock = Arc::clone(store_lock); thread::spawn(move || { if let Err(error) = run_rudp_health_ingress_loop(socket, worker_options, worker_store_lock) { eprintln!("Idunn RUDP health ingress stopped: {error}"); } }); Ok(()) } fn rudp_health_ingress_record( ingress_id: &str, bind_address: SocketAddr, state: &str, detail: &str, observed_at: &str, ) -> IdunnRudpHealthIngressRecord { IdunnRudpHealthIngressRecord { ingress_id: ingress_id.to_string(), bind_address: bind_address.to_string(), transport: CULTNET_RUDP_PROTOCOL_ID.to_string(), accepted_schema: "idunn.daemon_health".to_string(), state: state.to_string(), detail: detail.to_string(), observed_at: observed_at.to_string(), } } fn run_rudp_health_ingress_loop( socket: UdpSocket, options: CommonOptions, store_lock: Arc>, ) -> Result<()> { let rudp_options = CultNetRudpOptions { ack_timeout: Duration::from_millis(100), retries: 3, ..CultNetRudpOptions::default() }; loop { match recv_cultnet_message_rudp(&socket, &rudp_options) { Ok((message, source, transfer_id)) => { let observed_at = timestamp()?; match health_from_rudp_message(&message) { Ok(mut health) => { health.publication_source = "daemon-published".to_string(); health.transport = CULTNET_RUDP_PROTOCOL_ID.to_string(); with_store_node(&options, &store_lock, |node| { node.put(&health.daemon_id, &health)?; Ok(()) })?; println!( "Idunn accepted RUDP health for {} from {} transfer {}.", health.daemon_id, source, transfer_id ); } Err(error) => { let failed = rudp_health_ingress_record( "idunn-rudp-health-ingress", socket.local_addr()?, "degraded", &format!("rejected RUDP health message from {source}: {error}"), &observed_at, ); with_store_node(&options, &store_lock, |node| { node.put(&failed.ingress_id, &failed)?; Ok(()) })?; } } } Err(error) if error.downcast_ref::().is_some_and(|io| { matches!( io.kind(), std::io::ErrorKind::WouldBlock | std::io::ErrorKind::TimedOut ) }) => {} Err(error) => return Err(error), } } } fn health_from_rudp_message(message: &CultNetMessage) -> Result { let CultNetMessage::DocumentPutRaw { document, .. } = message else { return Err(anyhow!("expected cultnet.document_put_raw.v0")); }; if document.schema_id != "idunn.daemon_health" { return Err(anyhow!( "expected idunn.daemon_health schema, received {}", document.schema_id )); } if document.payload_encoding != CultNetRawPayloadEncoding::Messagepack { return Err(anyhow!("expected MessagePack raw payload encoding")); } let health: IdunnDaemonHealthRecord = rmp_serde::from_slice(&document.payload)?; if document.record_key != health.daemon_id { return Err(anyhow!( "record key {} does not match health daemon_id {}", document.record_key, health.daemon_id )); } Ok(health) } fn publish_surgery_plans( profile: &str, targets: &[DaemonTarget], options: &CommonOptions, store_lock: &Arc>, updated_at: &str, ) -> Result<()> { let swarm_plan = swarm_surgery_plan(profile, targets, updated_at); let plans = daemon_surgery_plans(targets, updated_at); with_store_node(options, store_lock, |node| { node.put(&swarm_plan.plan_id, &swarm_plan)?; for target in targets { let transport_profile = daemon_transport_profile(target, updated_at); let command_boundary = command_boundary(target, updated_at); node.put(&transport_profile.profile_id, &transport_profile)?; node.put(&command_boundary.boundary_id, &command_boundary)?; } for plan in &plans { node.put(&plan.plan_id, plan)?; } Ok(()) }) } fn swarm_surgery_plan( profile: &str, targets: &[DaemonTarget], updated_at: &str, ) -> IdunnSwarmSurgeryPlanRecord { let has_odin = targets.iter().any(|target| target.daemon_id == "odin"); let next_target = if has_odin { "odin" } else if let Some(target) = targets.iter().find(|target| target.enabled) { target.daemon_id.as_str() } else { "none" }; IdunnSwarmSurgeryPlanRecord { plan_id: format!("swarm-surgery:{profile}"), profile: profile.to_string(), status: "active-transport-migration".to_string(), owner: "Idunn swarm supervisor".to_string(), objective: "Move daemon awareness from compatibility probes to daemon-published typed CultNet/RUDP state." .to_string(), current_mechanism: "Idunn publishes per-daemon desired state, surgery plans, transport profiles, command boundaries, runtime RUDP self-checks, and RUDP health ingress; compatibility command probes remain fallback evidence until each daemon publishes its own health." .to_string(), invariants: vec![ "Daemon truth is typed CultCache/CultMesh state carried over cultnet.transport.rudp.v0.".to_string(), "Compatibility commands, HTTP, WebSocket, SSH, and systemd probes are evidence only and must not own daemon health.".to_string(), "Idunn consumes daemon-published RUDP health before compatibility probes and actuates only advertised lifecycle authority.".to_string(), "Each migrated daemon must publish the same health contract that Idunn expects for its target.".to_string(), ], phases: vec![ "1. Publish Idunn's own RUDP substrate and ingress state.".to_string(), "2. Install daemon-published RUDP health in one Rust daemon and prove Idunn consumes it live.".to_string(), "3. Extend CultLib RUDP publication support across TypeScript, C#, and remaining daemon runtimes.".to_string(), "4. Promote provider advertisements, command boundaries, and transport profiles to daemon-owned CultNet/RUDP records.".to_string(), "5. Delete or demote compatibility probes once every target has daemon-owned publication and advertised lifecycle authority.".to_string(), ], current_phase: "Phase 5: move Odin's own provider health from compatibility command evidence to daemon-published RUDP state." .to_string(), next_target: next_target.to_string(), cut_line: "All Muninn lanes now publish daemon-owned RUDP health. Odin remains the next critical provider-health cut before its local command probe can be demoted." .to_string(), verification_layer: "CultMesh keepalive store records plus live Idunn decision cycles, not process exit codes or chat summaries." .to_string(), updated_at: updated_at.to_string(), } } fn transport_profile_id(target: &DaemonTarget) -> String { format!("transport:{}", target.daemon_id) } fn command_boundary_id(target: &DaemonTarget) -> String { format!("command-boundary:{}", target.daemon_id) } fn daemon_transport_profile( target: &DaemonTarget, observed_at: &str, ) -> IdunnDaemonTransportProfileRecord { IdunnDaemonTransportProfileRecord { profile_id: transport_profile_id(target), daemon_id: target.daemon_id.clone(), target_transport: "cultnet.transport.rudp.v0".to_string(), current_transport: "compatibility.local-command".to_string(), state: "migration-required".to_string(), health_contract: target.health_contract.id.clone(), publication_schema: "idunn.daemon_health.v1".to_string(), compatibility_mechanism: target .health_command .clone() .unwrap_or_else(|| "none".to_string()), cut_line: "Compatibility command probes are evidence only; daemon truth moves to CultNet/RUDP health publication and advertised command boundaries." .to_string(), observed_at: observed_at.to_string(), } } fn command_boundary(target: &DaemonTarget, observed_at: &str) -> IdunnCommandBoundaryRecord { let restart_authority = target .restart_command .as_ref() .map(|_| "idunn.local-command.restart") .unwrap_or("none") .to_string(); let deploy_authority = target .deploy_command .as_ref() .map(|_| "idunn.local-command.deploy") .unwrap_or("none") .to_string(); let compatibility_commands = [ target.health_command.as_ref(), target.restart_command.as_ref(), target.deploy_command.as_ref(), ] .into_iter() .flatten() .cloned() .collect(); IdunnCommandBoundaryRecord { boundary_id: command_boundary_id(target), daemon_id: target.daemon_id.clone(), owner: "idunn.local-command-compatibility".to_string(), restart_authority, deploy_authority, health_authority: "compatibility.probe-only".to_string(), alarm_authority: "bifrost.operator-notification".to_string(), compatibility_commands, forbidden_authority: "Health commands, HTTP endpoints, WebSocket decks, SSH probes, and systemd status do not own daemon truth." .to_string(), observed_at: observed_at.to_string(), } } fn daemon_surgery_plans( targets: &[DaemonTarget], updated_at: &str, ) -> Vec { targets .iter() .map(|target| daemon_surgery_plan(target, updated_at)) .collect() } fn daemon_surgery_plan(target: &DaemonTarget, updated_at: &str) -> IdunnDaemonSurgeryPlanRecord { let mut severity = "high"; let mut status = "transport-surgery-required"; let mut owner = "daemon-owned CultLib update"; let mut objective = format!( "{} publishes daemon-owned health, provider state, command boundary, and transport profile through CultNet/RUDP.", target.name ); let mut current_mechanism = format!( "Idunn target {} currently uses local compatibility health command {:?} under contract {}.", target.daemon_id, target.health_command, target.health_contract.id ); let mut intended_authority = "Daemon publishes typed CultMesh/CultNet documents over cultnet.transport.rudp.v0; Idunn consumes those records and only actuates advertised lifecycle commands.".to_string(); let mut cut_line = "Cut HTTP, WebSocket, SSH, systemd, and command-exit probes as sources of daemon truth once the daemon's CultLib can publish the RUDP health contract.".to_string(); let mut steps = vec![ "Update the daemon's runtime CultLib dependency to a build that can speak CultNet over RUDP.".to_string(), "Publish daemon_health, provider_advertisement, command_boundary, and transport_profile typed records over cultnet.transport.rudp.v0.".to_string(), "Teach Odin to accept the daemon's RUDP provider records into the service/catalog surface.".to_string(), "Switch Idunn from the compatibility health command to the daemon-owned RUDP health record.".to_string(), "Delete or demote the old probe to a xenos-boundary compatibility check with no lifecycle authority.".to_string(), ]; let mut blockers = Vec::new(); match target.daemon_id.as_str() { "odin" => { severity = "critical"; owner = "Odin core"; current_mechanism = "Odin still exposes local health and Eve deck compatibility surfaces over HTTP/WebSocket while Idunn verifies liveness through a command probe." .to_string(); intended_authority = "Odin owns accepted Verse discovery and provider catalog truth as typed CultMesh/CultNet records over cultnet.transport.rudp.v0." .to_string(); cut_line = "HTTP/WebSocket deck and health endpoints become browser/lowering bridges only; they no longer decide daemon health, discovery, or provider truth." .to_string(); steps[2] = "Make Odin ingest RUDP provider advertisements directly into its accepted service/catalog surface." .to_string(); } "nightwing-gjallar" => { severity = "critical"; owner = "Gjallar C# runtime plus Odin provider feed"; current_mechanism = "Gjallar currently proves visible composition through service checks and /var/log/gjallar.status, fed by Odin's WebSocket deck compatibility bridge." .to_string(); intended_authority = "Gjallar subscribes to Odin/provider deck state over CultNet/RUDP and publishes framebuffer composition health as typed CultMesh/CultNet state." .to_string(); cut_line = "Cut Odin WebSocket deck consumption as the compositor truth path; keep it only as a browser/debug lowering if needed." .to_string(); blockers .push("Requires native C# CultNet/RUDP subscription path for Gjallar.".to_string()); } "stonks" => { owner = "Stonks TypeScript runtime"; current_mechanism = "Stonks has a repaired CultCache startup path, but health and market projection are still checked through local HTTP/WebSocket compatibility surfaces." .to_string(); blockers.push("Requires TypeScript CultLib RUDP publication support.".to_string()); } "mimir-eve-dashboard" => { severity = "high"; owner = "Mimir dashboard runtime"; current_mechanism = "Mimir dashboard health is currently a local compatibility probe with no Idunn restart authority." .to_string(); blockers.push( "No restart/deploy command authority is currently advertised to Idunn.".to_string(), ); } "weksa" => { severity = "medium-high"; owner = "Weksa provider runtime"; current_mechanism = "Weksa has provider advertisement bones, but Idunn still relies on compatibility process/health probes." .to_string(); } "voidbot" => { severity = "medium-high"; owner = "VoidBot internal provider stack"; current_mechanism = "VoidBot has CultMesh/CultCache swarm state, but Idunn still treats stack health through a compatibility command; Discord remains an external xenos boundary." .to_string(); intended_authority = "VoidBot publishes internal swarm, repo-face, and provider health over CultNet/RUDP; Discord delivery remains a boundary adapter, never daemon truth." .to_string(); } "starfire-muninn" | "muninn" | "nightwing-muninn" => { owner = "Muninn Rust runtime"; current_mechanism = "Muninn has typed telemetry state, but Idunn still validates continuity through local or remote script probes." .to_string(); intended_authority = "Muninn publishes telemetry, Quest/Move access, and daemon health over CultNet/RUDP; activation commands remain separate from keepalive." .to_string(); } "vili" => { owner = "Vili animation runtime"; current_mechanism = "Vili is watched through compatibility health/deck checks instead of daemon-owned CultNet/RUDP animation health." .to_string(); } "nightwing-eve-dashboard" | "nightwing-eve-browser-reference" => { severity = "medium"; owner = "Eve lowering/runtime owner"; current_mechanism = "Nightwing Eve runtime services are watched through local service probes; browser-facing transports are lowering bridges." .to_string(); intended_authority = "Eve runtimes subscribe to provider-owned CultMesh/CultNet state; any browser/WebSocket bridge is display-only and does not own daemon health." .to_string(); cut_line = "Cut display/runtime liveness from provider truth. Browser-compatible bridges may remain only as lowering targets." .to_string(); } "yggdrasil-heimdall" | "yggdrasil-repixelizer" | "yggdrasil-streampixels" => { severity = "medium"; owner = "Yggdrasil service owner plus gamecult-ops deploy lane"; current_mechanism = "Yggdrasil source apps are currently checked and deployed through SSH/systemd/source-artifact compatibility scripts." .to_string(); intended_authority = "Public HTTP remains the product boundary, but deployment freshness, daemon health, and lifecycle commands publish as internal CultNet/RUDP state." .to_string(); cut_line = "SSH/systemd probes stop deciding freshness once hosted services publish internal RUDP health and deployment manifests." .to_string(); } "idunn-swarm-deployment-coverage" => { severity = "medium"; status = "catalog-coherence-probe"; owner = "Idunn"; objective = "Keep Idunn's deployment target catalog honest while daemon-owned RUDP publication is being installed." .to_string(); current_mechanism = "A local coverage command verifies deployment authority categories for the swarm target catalog." .to_string(); intended_authority = "Daemon provider advertisements and command_boundary records make deploy/restart ownership inspectable without a local coverage shim." .to_string(); cut_line = "Delete this probe after every deployable daemon publishes command_boundary and transport_profile over CultNet/RUDP." .to_string(); } _ => {} } IdunnDaemonSurgeryPlanRecord { plan_id: format!("surgery:{}", target.daemon_id), daemon_id: target.daemon_id.clone(), severity: severity.to_string(), status: status.to_string(), owner: owner.to_string(), objective, current_mechanism, intended_authority, cut_line, steps, blockers, updated_at: updated_at.to_string(), } } fn swarm_targets(options: &SwarmOptions) -> Result> { let repo_root = options.repo_root.display().to_string(); let script = |name: &str| format!(r"{}\scripts\{}", repo_root, name); match options.profile.as_str() { "starfire-local" => Ok(vec![ DaemonTarget { daemon_id: "odin".to_string(), verse_id: "starfire.local".to_string(), name: "Odin all-seer".to_string(), health_contract: health_contract("odin.cultnet-rudp-provider-health", "failed"), health_command: Some(script("health-odin.cmd")), deploy_command: None, restart_command: Some(script("restart-odin.cmd")), enabled: true, interval_seconds: 30, }, DaemonTarget { daemon_id: "mimir-eve-dashboard".to_string(), verse_id: "starfire.local".to_string(), name: "Mimir Eve dashboard".to_string(), health_contract: health_contract("mimir.cultnet-rudp-provider-health", "failed"), health_command: Some(script("health-mimir-eve-dashboard.cmd")), deploy_command: None, restart_command: None, enabled: true, interval_seconds: 30, }, DaemonTarget { daemon_id: "stonks".to_string(), verse_id: "starfire.local".to_string(), name: "Stonks market pulse".to_string(), health_contract: health_contract("stonks.cultnet-rudp-market-health", "failed"), health_command: Some(script("health-stonks.cmd")), deploy_command: None, restart_command: Some(script("restart-stonks.cmd")), enabled: true, interval_seconds: 30, }, DaemonTarget { daemon_id: "voidbot".to_string(), verse_id: "starfire.local".to_string(), name: "VoidBot local stack".to_string(), health_contract: health_contract("voidbot.cultnet-rudp-stack-health", "failed"), health_command: Some(script("health-voidbot.cmd")), deploy_command: None, restart_command: Some(script("restart-voidbot.cmd")), enabled: true, interval_seconds: 300, }, DaemonTarget { daemon_id: "weksa".to_string(), verse_id: "starfire.local".to_string(), name: "Weksa intent and utterance lowering service".to_string(), health_contract: health_contract("weksa.cultnet-rudp-provider-health", "failed"), health_command: Some(script("health-weksa.cmd")), deploy_command: None, restart_command: Some(script("restart-weksa.cmd")), enabled: true, interval_seconds: 60, }, DaemonTarget { daemon_id: "starfire-muninn".to_string(), verse_id: "starfire.local".to_string(), name: "Starfire Muninn telemetry and Quest access daemon".to_string(), health_contract: health_contract( "muninn.cultnet-rudp-local-telemetry-and-quest-access", "failed", ), health_command: Some(script("health-starfire-muninn.cmd")), deploy_command: None, restart_command: Some(script("restart-starfire-muninn.cmd")), enabled: true, interval_seconds: 30, }, DaemonTarget { daemon_id: "muninn".to_string(), verse_id: "raven.local".to_string(), name: "Muninn telemetry Verse assembler".to_string(), health_contract: health_contract( "muninn.cultnet-rudp-remote-telemetry-health", "failed", ), health_command: Some(script("health-muninn.cmd")), deploy_command: None, restart_command: Some(script("restart-muninn.cmd")), enabled: true, interval_seconds: 30, }, DaemonTarget { daemon_id: "vili".to_string(), verse_id: "raven.local".to_string(), name: "Vili Persona animation daemon".to_string(), health_contract: health_contract("vili.cultnet-rudp-animation-health", "failed"), health_command: Some(script("health-vili.cmd")), deploy_command: None, restart_command: Some(script("restart-vili.cmd")), enabled: true, interval_seconds: 60, }, DaemonTarget { daemon_id: "idunn-swarm-deployment-coverage".to_string(), verse_id: "starfire.local".to_string(), name: "Idunn swarm deployment coverage".to_string(), health_contract: health_contract("idunn.deployment-catalog-coherence", "degraded"), health_command: Some(script("health-idunn-swarm-deployment-coverage.cmd")), deploy_command: None, restart_command: None, enabled: true, interval_seconds: 30, }, DaemonTarget { daemon_id: "yggdrasil-heimdall".to_string(), verse_id: "yggdrasil.local".to_string(), name: "Yggdrasil Heimdall".to_string(), health_contract: health_contract( "yggdrasil.source-deployment-freshness", "stale-deployment", ), health_command: Some(script("health-yggdrasil-heimdall.cmd")), deploy_command: Some(script("deploy-yggdrasil-heimdall.cmd")), restart_command: None, enabled: true, interval_seconds: 300, }, DaemonTarget { daemon_id: "yggdrasil-repixelizer".to_string(), verse_id: "yggdrasil.local".to_string(), name: "Yggdrasil Repixelizer".to_string(), health_contract: health_contract( "yggdrasil.source-deployment-freshness", "stale-deployment", ), health_command: Some(script("health-yggdrasil-repixelizer.cmd")), deploy_command: Some(script("deploy-yggdrasil-repixelizer.cmd")), restart_command: None, enabled: true, interval_seconds: 300, }, DaemonTarget { daemon_id: "yggdrasil-streampixels".to_string(), verse_id: "yggdrasil.local".to_string(), name: "Yggdrasil StreamPixels".to_string(), health_contract: health_contract( "yggdrasil.source-deployment-freshness", "stale-deployment", ), health_command: Some(script("health-yggdrasil-streampixels.cmd")), deploy_command: Some(script("deploy-yggdrasil-streampixels.cmd")), restart_command: None, enabled: true, interval_seconds: 300, }, DaemonTarget { daemon_id: "nightwing-gjallar".to_string(), verse_id: "nightwing.local".to_string(), name: "Nightwing Gjallar framebuffer compositor".to_string(), health_contract: health_contract( "gjallar.cultnet-rudp-framebuffer-composition-health", "dependency-unavailable", ), health_command: Some(script("health-nightwing-gjallar.cmd")), deploy_command: Some(script("deploy-nightwing-gjallar.cmd")), restart_command: Some(script("restart-nightwing-gjallar.cmd")), enabled: true, interval_seconds: 30, }, DaemonTarget { daemon_id: "nightwing-muninn".to_string(), verse_id: "nightwing.local".to_string(), name: "Nightwing Muninn telemetry and Move HID daemon".to_string(), health_contract: health_contract( "muninn.cultnet-rudp-remote-telemetry-and-move-hid", "failed", ), health_command: Some(script("health-nightwing-muninn.cmd")), deploy_command: None, restart_command: Some(script("restart-nightwing-muninn.cmd")), enabled: true, interval_seconds: 30, }, DaemonTarget { daemon_id: "nightwing-eve-dashboard".to_string(), verse_id: "nightwing.local".to_string(), name: "Nightwing Eve dashboard broker".to_string(), health_contract: health_contract( "nightwing.cultnet-rudp-eve-dashboard-health", "failed", ), health_command: Some(script("health-nightwing-eve-dashboard.cmd")), deploy_command: None, restart_command: Some(script("restart-nightwing-eve-dashboard.cmd")), enabled: true, interval_seconds: 30, }, DaemonTarget { daemon_id: "nightwing-eve-browser-reference".to_string(), verse_id: "nightwing.local".to_string(), name: "Nightwing Eve browser reference".to_string(), health_contract: health_contract( "nightwing.cultnet-rudp-browser-reference-health", "failed", ), health_command: Some(script("health-nightwing-eve-browser-reference.cmd")), deploy_command: None, restart_command: Some(script("restart-nightwing-eve-browser-reference.cmd")), enabled: true, interval_seconds: 30, }, ]), other => Err(anyhow!("unknown Idunn swarm profile: {other}")), } } fn restart_failure_alarm( result: &IdunnRestartResultRecord, raised_at: &str, ) -> IdunnOperatorAlarmRecord { IdunnOperatorAlarmRecord { alarm_id: format!("alarm:restart-failed:{}:{}", result.daemon_id, raised_at), daemon_id: result.daemon_id.clone(), severity: "operator-action-required".to_string(), reason: format!( "restart command failed for request {}: {}", result.request_id, result.detail ), escalation_target: "bifrost.operator-notification".to_string(), raised_at: raised_at.to_string(), } } fn deployment_failure_alarm( result: &IdunnDeploymentResultRecord, raised_at: &str, ) -> IdunnOperatorAlarmRecord { IdunnOperatorAlarmRecord { alarm_id: format!("alarm:deployment-failed:{}:{}", result.daemon_id, raised_at), daemon_id: result.daemon_id.clone(), severity: "operator-action-required".to_string(), reason: format!( "deployment command failed for request {}: {}", result.request_id, result.detail ), escalation_target: "bifrost.operator-notification".to_string(), raised_at: raised_at.to_string(), } } impl Options { fn parse(args: impl Iterator) -> Result { let mut store_path = PathBuf::from("scratch/idunn/idunn.keepalive.cc"); let mut operator_alarm_command = None; let mut rudp_health_bind = Some("127.0.0.1:17870".parse::()?); let mut execute = false; let mut command_timeout_seconds = 30; let mut daemon_id = None; let mut verse_id = "local".to_string(); let mut name = None; let mut health_command = None; let mut deploy_command = None; let mut restart_command = None; let mut enabled = true; let mut interval_seconds = None; let mut swarm_profile = None; let mut repo_root = env::current_dir().context("determining current directory")?; let mut args = args.peekable(); while let Some(arg) = args.next() { match arg.as_str() { "--store" => store_path = PathBuf::from(take_value(&mut args, "--store")?), "--daemon" => daemon_id = Some(take_value(&mut args, "--daemon")?), "--verse" => verse_id = take_value(&mut args, "--verse")?, "--name" => name = Some(take_value(&mut args, "--name")?), "--health-command" => { health_command = Some(take_value(&mut args, "--health-command")?) } "--deploy-command" => { deploy_command = Some(take_value(&mut args, "--deploy-command")?) } "--restart-command" => { restart_command = Some(take_value(&mut args, "--restart-command")?) } "--operator-alarm-command" => { operator_alarm_command = Some(take_value(&mut args, "--operator-alarm-command")?) } "--rudp-health-bind" => { let value = take_value(&mut args, "--rudp-health-bind")?; rudp_health_bind = if value.eq_ignore_ascii_case("none") { None } else { Some( value .parse() .with_context(|| "--rudp-health-bind must be a socket address")?, ) }; } "--disabled" => enabled = false, "--execute" => execute = true, "--interval-seconds" => { interval_seconds = Some( take_value(&mut args, "--interval-seconds")? .parse() .context("--interval-seconds must be a positive integer")?, ) } "--command-timeout-seconds" => { command_timeout_seconds = take_value(&mut args, "--command-timeout-seconds")? .parse() .context("--command-timeout-seconds must be a positive integer")? } "--swarm-profile" => { swarm_profile = Some(take_value(&mut args, "--swarm-profile")?) } "--repo-root" => repo_root = PathBuf::from(take_value(&mut args, "--repo-root")?), "--help" | "-h" => return Err(anyhow!(help_text())), other => { return Err(anyhow!( "unknown Idunn argument: {other}\n\n{}", help_text() )); } } } if command_timeout_seconds == 0 { return Err(anyhow!( "--command-timeout-seconds must be greater than zero" )); } let common = CommonOptions { store_path, operator_alarm_command, rudp_health_bind, execute, command_timeout_seconds, }; let mode = match (swarm_profile, daemon_id) { (Some(profile), None) => Mode::Swarm(SwarmOptions { profile, repo_root }), (Some(_), Some(_)) => { return Err(anyhow!( "use either --swarm-profile or --daemon, not both\n\n{}", help_text() )); } (None, Some(daemon_id)) => { let interval_seconds = interval_seconds.unwrap_or(30); if interval_seconds == 0 { return Err(anyhow!("--interval-seconds must be greater than zero")); } Mode::Single(DaemonTarget { daemon_id: daemon_id.clone(), verse_id, name: name.unwrap_or(daemon_id), health_contract: health_contract("manual.command-health", "failed"), health_command, deploy_command, restart_command, enabled, interval_seconds, }) } (None, None) => { return Err(anyhow!( "either --daemon or --swarm-profile is required\n\n{}", help_text() )); } }; Ok(Self { common, mode }) } } fn take_value(args: &mut impl Iterator, name: &str) -> Result { args.next() .ok_or_else(|| anyhow!("{name} requires a value")) } fn probe_health( target: &DaemonTarget, command_timeout_seconds: u64, observed_at: &str, ) -> IdunnDaemonHealthRecord { match &target.health_command { Some(command) => match run_shell(command, command_timeout_seconds) { Ok(output) if output.status.success() => IdunnDaemonHealthRecord { daemon_id: target.daemon_id.clone(), state: "active".to_string(), detail: command_output_detail("health command exited successfully", &output), health_contract: target.health_contract.id.clone(), publication_source: "compatibility-command".to_string(), transport: "compatibility.local-command".to_string(), observed_at: observed_at.to_string(), }, Ok(output) => { let detail = command_output_detail( &format!("health command exited with {}", output.status), &output, ); IdunnDaemonHealthRecord { daemon_id: target.daemon_id.clone(), state: health_state_from_detail(&detail, target).to_string(), detail, health_contract: target.health_contract.id.clone(), publication_source: "compatibility-command".to_string(), transport: "compatibility.local-command".to_string(), observed_at: observed_at.to_string(), } } Err(error) => IdunnDaemonHealthRecord { daemon_id: target.daemon_id.clone(), state: "failed".to_string(), detail: format!("health command could not run: {error}"), health_contract: target.health_contract.id.clone(), publication_source: "compatibility-command".to_string(), transport: "compatibility.local-command".to_string(), observed_at: observed_at.to_string(), }, }, None => IdunnDaemonHealthRecord { daemon_id: target.daemon_id.clone(), state: "unknown".to_string(), detail: "no health command was provided".to_string(), health_contract: target.health_contract.id.clone(), publication_source: "compatibility-command".to_string(), transport: "compatibility.local-command".to_string(), observed_at: observed_at.to_string(), }, } } fn health_state_from_detail<'a>(detail: &'a str, target: &'a DaemonTarget) -> &'a str { for state in [ "stale-deployment", "dependency-unavailable", "degraded", "failed", ] { let marker = format!("idunn.health.state={state}"); if detail.contains(&marker) { return state; } } &target.health_contract.default_failure_state } fn run_restart( request: &odin_core::IdunnRestartRequestRecord, requested_at: &str, command_timeout_seconds: u64, ) -> IdunnRestartResultRecord { let result_id = format!("result:{}", request.request_id); match run_shell(&request.command, command_timeout_seconds) { Ok(output) if output.status.success() => IdunnRestartResultRecord { result_id, request_id: request.request_id.clone(), daemon_id: request.daemon_id.clone(), state: "succeeded".to_string(), detail: command_output_detail("restart command exited successfully", &output), completed_at: requested_at.to_string(), }, Ok(output) => IdunnRestartResultRecord { result_id, request_id: request.request_id.clone(), daemon_id: request.daemon_id.clone(), state: "failed".to_string(), detail: command_output_detail( &format!("restart command exited with {}", output.status), &output, ), completed_at: requested_at.to_string(), }, Err(error) => IdunnRestartResultRecord { result_id, request_id: request.request_id.clone(), daemon_id: request.daemon_id.clone(), state: "failed".to_string(), detail: format!("restart command could not run: {error}"), completed_at: requested_at.to_string(), }, } } fn run_deployment( request: &odin_core::IdunnDeploymentRequestRecord, requested_at: &str, command_timeout_seconds: u64, ) -> IdunnDeploymentResultRecord { let result_id = format!("result:{}", request.request_id); match run_shell(&request.command, command_timeout_seconds) { Ok(output) if output.status.success() => IdunnDeploymentResultRecord { result_id, request_id: request.request_id.clone(), daemon_id: request.daemon_id.clone(), state: "succeeded".to_string(), detail: command_output_detail("deployment command exited successfully", &output), completed_at: requested_at.to_string(), }, Ok(output) => IdunnDeploymentResultRecord { result_id, request_id: request.request_id.clone(), daemon_id: request.daemon_id.clone(), state: "failed".to_string(), detail: command_output_detail( &format!("deployment command exited with {}", output.status), &output, ), completed_at: requested_at.to_string(), }, Err(error) => IdunnDeploymentResultRecord { result_id, request_id: request.request_id.clone(), daemon_id: request.daemon_id.clone(), state: "failed".to_string(), detail: format!("deployment command could not run: {error}"), completed_at: requested_at.to_string(), }, } } fn command_output_detail(prefix: &str, output: &std::process::Output) -> String { let mut detail = prefix.to_string(); let stdout = String::from_utf8_lossy(&output.stdout); let stderr = String::from_utf8_lossy(&output.stderr); let stdout = stdout.trim(); let stderr = stderr.trim(); if !stdout.is_empty() { detail.push_str("; stdout: "); detail.push_str(&truncate_detail(stdout, 600)); } if !stderr.is_empty() { detail.push_str("; stderr: "); detail.push_str(&truncate_detail(stderr, 600)); } detail } fn truncate_detail(value: &str, max_chars: usize) -> String { let mut chars = value.chars(); let truncated: String = chars.by_ref().take(max_chars).collect(); if chars.next().is_some() { format!("{truncated}...") } else { truncated } } fn run_shell(command: &str, timeout_seconds: u64) -> Result { let mut process = if cfg!(windows) { let path = windows_command_path(); let command = format!(r#"set "PATH={path}" && set "Path={path}" && {command}"#); let mut process = Command::new("cmd"); process.arg("/D").arg("/S").arg("/C").arg(command); apply_windows_command_environment(&mut process, &path); process } else { let mut process = Command::new("sh"); process.arg("-c").arg(command); process }; let child = process .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn() .with_context(|| format!("running command {command:?}"))?; wait_for_child_with_timeout(child, Duration::from_secs(timeout_seconds), command) } fn run_operator_alarm_command(options: &CommonOptions, alarm: &IdunnOperatorAlarmRecord) { let Some(command) = options.operator_alarm_command.as_deref() else { return; }; if command.trim().is_empty() { return; } let mut process = if cfg!(windows) { let path = windows_command_path(); let command = format!(r#"set "PATH={path}" && set "Path={path}" && {command}"#); let mut process = Command::new("cmd"); process.arg("/D").arg("/S").arg("/C").arg(command); apply_windows_command_environment(&mut process, &path); process } else { let mut process = Command::new("sh"); process.arg("-c").arg(command); process }; let output = process .env("IDUNN_ALARM_ID", &alarm.alarm_id) .env("IDUNN_ALARM_DAEMON_ID", &alarm.daemon_id) .env("IDUNN_ALARM_SEVERITY", &alarm.severity) .env("IDUNN_ALARM_REASON", &alarm.reason) .env("IDUNN_ALARM_ESCALATION_TARGET", &alarm.escalation_target) .env("IDUNN_ALARM_RAISED_AT", &alarm.raised_at) .stdout(Stdio::piped()) .stderr(Stdio::piped()) .spawn(); match output { Ok(child) => match wait_for_child_with_timeout( child, Duration::from_secs(options.command_timeout_seconds), command, ) { Ok(output) if output.status.success() => { println!( "Idunn operator alarm command completed for {}.", alarm.daemon_id ); } Ok(output) => { eprintln!( "Idunn operator alarm command failed for {} with {}.", alarm.daemon_id, output.status ); } Err(error) => { eprintln!( "Idunn operator alarm command could not run for {}: {}", alarm.daemon_id, error ); } }, Err(error) => { eprintln!( "Idunn operator alarm command could not run for {}: {}", alarm.daemon_id, error ); } } } fn windows_command_path() -> String { [ r"C:\WINDOWS\system32", r"C:\WINDOWS", r"C:\WINDOWS\System32\Wbem", r"C:\WINDOWS\System32\WindowsPowerShell\v1.0", r"C:\WINDOWS\System32\OpenSSH", r"C:\Program Files\Git\cmd", r"C:\Program Files\nodejs", r"C:\Program Files\Docker\Docker\resources\bin", r"C:\Users\Meta\AppData\Local\Programs\Ollama", r"C:\Program Files\dotnet", r"C:\Users\Meta\.cargo\bin", ] .join(";") } fn apply_windows_command_environment(process: &mut Command, path: &str) { if !cfg!(windows) { return; } process.env("PATH", path); process.env("Path", path); } fn wait_for_child_with_timeout( mut child: Child, timeout: Duration, command: &str, ) -> Result { let started_at = Instant::now(); loop { if child .try_wait() .with_context(|| format!("waiting on command {command:?}"))? .is_some() { return child .wait_with_output() .with_context(|| format!("collecting output for command {command:?}")); } if started_at.elapsed() >= timeout { let _ = child.kill(); let _ = child.wait_with_output(); return Err(anyhow!( "command timed out after {} seconds: {command:?}", timeout.as_secs() )); } thread::sleep(Duration::from_millis(100)); } } fn timestamp() -> Result { let seconds = SystemTime::now() .duration_since(UNIX_EPOCH) .context("system clock is before Unix epoch")? .as_secs(); Ok(format!("unix:{seconds}")) } fn help_text() -> &'static str { "Usage: idunn --daemon [--name ] [--verse ] [--store ] [--health-command ] [--deploy-command ] [--restart-command ] [--operator-alarm-command ] [--rudp-health-bind ] [--execute] [--interval-seconds ] [--command-timeout-seconds ] [--repo-root ] [--swarm-profile ]\n\nIdunn can run one manual daemon probe lane with --daemon, or one built-in swarm supervisor with --swarm-profile starfire-local." } #[cfg(test)] mod tests { use super::*; use cultnet_rs::{CultNetRawDocumentRecord, CultNetRawPayloadEncoding}; fn target(default_failure_state: &str, deploy_command: Option<&str>) -> DaemonTarget { DaemonTarget { daemon_id: "test-daemon".to_string(), verse_id: "test.local".to_string(), name: "Test daemon".to_string(), health_contract: health_contract("test.contract", default_failure_state), health_command: Some("exit 0".to_string()), deploy_command: deploy_command.map(ToString::to_string), restart_command: Some("restart test".to_string()), enabled: true, interval_seconds: 30, } } #[test] fn target_catalog_requires_health_contract() { let mut target = target("failed", None); target.health_contract.id = String::new(); let error = validate_targets(&[target]).unwrap_err().to_string(); assert!(error.contains("has no health contract")); } #[test] fn stale_deployment_contract_requires_deploy_authority() { let error = validate_targets(&[target("stale-deployment", None)]) .unwrap_err() .to_string(); assert!(error.contains("has no deploy command")); } #[test] fn health_state_uses_contract_default_when_probe_has_no_marker() { let target = target("dependency-unavailable", None); assert_eq!( health_state_from_detail("plain command failure", &target), "dependency-unavailable" ); } #[test] fn swarm_surgery_plan_names_odin_after_muninn_cuts() { let starfire_muninn = DaemonTarget { daemon_id: "starfire-muninn".to_string(), verse_id: "starfire.local".to_string(), name: "Starfire Muninn".to_string(), health_contract: health_contract( "muninn.cultnet-rudp-local-telemetry-and-quest-access", "degraded", ), health_command: Some("health-starfire-muninn.cmd".to_string()), deploy_command: None, restart_command: Some("restart-starfire-muninn.cmd".to_string()), enabled: true, interval_seconds: 30, }; let nightwing_muninn = DaemonTarget { daemon_id: "nightwing-muninn".to_string(), verse_id: "nightwing.local".to_string(), name: "Nightwing Muninn".to_string(), health_contract: health_contract( "muninn.cultnet-rudp-remote-telemetry-and-move-hid", "failed", ), health_command: Some("health-nightwing-muninn.cmd".to_string()), deploy_command: None, restart_command: Some("restart-nightwing-muninn.cmd".to_string()), enabled: true, interval_seconds: 30, }; let raven_muninn = DaemonTarget { daemon_id: "muninn".to_string(), verse_id: "raven.local".to_string(), name: "Raven Muninn".to_string(), health_contract: health_contract( "muninn.cultnet-rudp-remote-telemetry-health", "failed", ), health_command: Some("health-muninn.cmd".to_string()), deploy_command: None, restart_command: Some("restart-muninn.cmd".to_string()), enabled: true, interval_seconds: 30, }; let odin = DaemonTarget { daemon_id: "odin".to_string(), verse_id: "starfire.local".to_string(), name: "Odin".to_string(), health_contract: health_contract("odin.cultnet-rudp-provider-health", "failed"), health_command: Some("health-odin.cmd".to_string()), deploy_command: None, restart_command: Some("restart-odin.cmd".to_string()), enabled: true, interval_seconds: 30, }; let plan = swarm_surgery_plan( "starfire-local", &[odin, starfire_muninn, nightwing_muninn, raven_muninn], "unix:100", ); assert_eq!(plan.plan_id, "swarm-surgery:starfire-local"); assert_eq!(plan.status, "active-transport-migration"); assert_eq!(plan.next_target, "odin"); assert!(plan.current_phase.contains("Odin")); assert!(plan.cut_line.contains("All Muninn lanes")); assert!(plan.verification_layer.contains("CultMesh keepalive store")); assert!( plan.invariants .iter() .any(|invariant| invariant.contains("cultnet.transport.rudp.v0")) ); } #[test] fn fresh_daemon_published_rudp_health_can_replace_probe_health() { let desired = IdunnDesiredDaemonRecord { daemon_id: "test-daemon".to_string(), verse_id: "test.local".to_string(), name: "Test daemon".to_string(), enabled: true, health_command: Some("exit 1".to_string()), restart_command: Some("restart test".to_string()), authority: "idunn.local-command".to_string(), max_silence_seconds: 60, observed_at: "unix:100".to_string(), deploy_command: None, health_contract: "test.cultnet-rudp-health".to_string(), transport_profile_id: "transport:test-daemon".to_string(), command_boundary_id: "command-boundary:test-daemon".to_string(), }; let mut health = IdunnDaemonHealthRecord { daemon_id: "test-daemon".to_string(), state: "active".to_string(), detail: "daemon published".to_string(), observed_at: "unix:95".to_string(), health_contract: "test.cultnet-rudp-health".to_string(), publication_source: "daemon-published".to_string(), transport: CULTNET_RUDP_PROTOCOL_ID.to_string(), }; assert!(is_fresh_daemon_published_health( &health, &desired, "unix:100" )); health.observed_at = "unix:1".to_string(); assert!(!is_fresh_daemon_published_health( &health, &desired, "unix:100" )); health.observed_at = "unix:95".to_string(); health.publication_source = "compatibility-command".to_string(); assert!(!is_fresh_daemon_published_health( &health, &desired, "unix:100" )); } #[test] fn runtime_transport_check_proves_rudp_loopback() { let check = runtime_transport_check("2026-06-15T00:00:00Z"); assert_eq!(check.check_id, "idunn-runtime-rudp-loopback"); assert_eq!(check.transport, CULTNET_RUDP_PROTOCOL_ID); assert_eq!(check.state, "available"); } #[test] fn rudp_health_ingress_accepts_raw_daemon_health_document() { let health = IdunnDaemonHealthRecord { daemon_id: "test-daemon".to_string(), state: "active".to_string(), detail: "published by daemon".to_string(), observed_at: "2026-06-15T00:00:00Z".to_string(), health_contract: "test.cultnet-rudp-health".to_string(), publication_source: "daemon-published".to_string(), transport: CULTNET_RUDP_PROTOCOL_ID.to_string(), }; let message = CultNetMessage::DocumentPutRaw { message_id: "test-health".to_string(), document: CultNetRawDocumentRecord { schema_id: "idunn.daemon_health".to_string(), record_key: health.daemon_id.clone(), stored_at: "2026-06-15T00:00:00Z".to_string(), payload_encoding: CultNetRawPayloadEncoding::Messagepack, payload: rmp_serde::to_vec(&health).unwrap(), source_runtime_id: Some("test-daemon".to_string()), source_agent_id: None, source_role: Some("daemon-health-publisher".to_string()), tags: Some(vec!["cultnet.transport.rudp.v0".to_string()]), }, }; assert_eq!(health_from_rudp_message(&message).unwrap(), health); } }