From 9367ad13292863ed3bf0159e4d5164b3ecb7d77d Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Tue, 18 Aug 2026 19:22:11 +0200 Subject: [PATCH] Keep local mesh authoritative during Odin outages --- crates/ghostlight-dungeon/src/mesh.rs | 34 +++++++++++++++++++++++--- notes/ghostlight-current-system-map.md | 6 +++++ state/map.yaml | 2 +- 3 files changed, 38 insertions(+), 4 deletions(-) diff --git a/crates/ghostlight-dungeon/src/mesh.rs b/crates/ghostlight-dungeon/src/mesh.rs index b345dbd..9fe9d40 100644 --- a/crates/ghostlight-dungeon/src/mesh.rs +++ b/crates/ghostlight-dungeon/src/mesh.rs @@ -14,7 +14,7 @@ use crate::{ model::ModelStageReceipt, surface::{operator_surface, player_surface}, }; -use anyhow::{Context, Result}; +use anyhow::Result; use chrono::Utc; use cultcache_rs::DatabaseEntry; use cultmesh_rs::{ @@ -353,8 +353,14 @@ impl MeshPublisher { options.source_agent_id = Some(PROVIDER_ID.into()); options.source_role = Some("narrative-simulation".into()); options.tags = vec!["ghostlight".into(), "eve".into(), "private".into()]; - node.publish_document_to_rudp_catalog(&key, value, options) - .with_context(|| format!("publish {key} to Odin RUDP catalog"))?; + if let Err(error) = node.publish_document_to_rudp_catalog(&key, value, options) { + tracing::warn!( + %key, + %target, + %error, + "Odin RUDP publication failed; retained canonical local CultMesh projection" + ); + } } Ok(()) } @@ -461,4 +467,26 @@ mod tests { let reopened = MeshPublisher::open(temp.path().join("mesh.cc"), None).unwrap(); assert_eq!(reopened.health().unwrap(), written); } + + #[test] + fn unavailable_odin_cannot_take_away_the_local_projection() { + let temp = tempdir().unwrap(); + let unavailable = "127.0.0.1:1".parse().unwrap(); + let publisher = + MeshPublisher::open(temp.path().join("mesh.cc"), Some(unavailable)).unwrap(); + + let written = publisher + .publish_snapshot(&[], "fixture-ready", 0) + .expect("local projection remains writable while rendezvous is unavailable"); + + assert_eq!(publisher.health().unwrap(), written); + assert!( + publisher + .node + .lock() + .unwrap() + .get_required::("ghostlight:schema-catalog") + .is_ok() + ); + } } diff --git a/notes/ghostlight-current-system-map.md b/notes/ghostlight-current-system-map.md index 3c9eecb..7dcf820 100644 --- a/notes/ghostlight-current-system-map.md +++ b/notes/ghostlight-current-system-map.md @@ -150,6 +150,12 @@ commit. The latest provider-backed four-wave golden produced seven typed material activity outcomes, ten durable consequences, and zero rejected pulses while leaving the player unchanged and returning the same Mira. +The service-owned CultMesh store remains the canonical projection body when +Odin rendezvous is temporarily unavailable. RUDP publication is outbound +replication, not daemon-liveness authority: a failed publish is logged with its +key and target while the complete local snapshot persists and HTTP serves that +same typed health and Eve state. + `gestalt_migration` records a collective decision by one exact active leaf to move along an explicit migration relation and reachable route. WorldKernel changes the leaf's home location and agency-profile location together. The diff --git a/state/map.yaml b/state/map.yaml index e3f48a9..a75662b 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -271,5 +271,5 @@ data_flow: current_status: summary: GhostlightDungeon production remains on the verified older Starfire release. The current candidate's provider-backed material-outcome golden completed four waves across budgets 1, 4, 8, and 4 with zero rejected pulses, ten durable consequences, seven typed material activity outcomes, exact member binding, no player mutation, and the same Mira returning with persistent state. A selective independent verifier now protects high-risk custody, relation, and named-member private effects without taxing every low-risk preparation. - next_action: Commit and push the exact accepted candidate, build and deploy its immutable optimized release to Starfire, and repeat authenticated browser, restart, served-commit, and persistence checks. Then force one live high-risk outcome-verifier witness and begin human playtesting while measuring composite consequences, retries, cache hits, and dramatic yield per token. + next_action: Rebuild and deploy the candidate after demoting unavailable Odin rendezvous from daemon-liveness authority, then repeat authenticated browser, restart, served-commit, and persistence checks. Force one live high-risk outcome-verifier witness before broad human playtesting; continue measuring composite consequences, retries, cache hits, and dramatic yield per token. gestalt_population: Gestalt Personas own shared population baselines; persistent member deltas own named individuality; WorldKernel materialization and approval-gated fission preserve lineage and identity. Presence projection is limited to nearby active leaves and exact-location dormant members, includes reciprocal player relationship evidence, and may propose an earned cast without committing it. Simulation cells are derived covers only.