From 0695b19b42ab6265e1c6cc1de0bc71f653daefaa Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Tue, 25 Aug 2026 04:30:01 +0200 Subject: [PATCH] Ground topology correction in explicit routes --- crates/ghostlight-dungeon/src/compiler.rs | 10 ++++++++-- crates/ghostlight-dungeon/src/domain.rs | 9 +++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/crates/ghostlight-dungeon/src/compiler.rs b/crates/ghostlight-dungeon/src/compiler.rs index 4cc54c0..ca2bf23 100644 --- a/crates/ghostlight-dungeon/src/compiler.rs +++ b/crates/ghostlight-dungeon/src/compiler.rs @@ -556,7 +556,7 @@ impl WorldCompiler { let previous_structure = serde_json::to_string(&compiled_seed_structure(&seed))?; correction = format!( - "\n\nLOCAL VALIDATOR REJECTED THE PREVIOUS CANDIDATE: {error}\nPREVIOUS_CANDIDATE_STRUCTURE:\n{previous_structure}\nReturn a corrected complete candidate against the same START and EVIDENCE. Preserve valid detail, but make every reference use an ID declared by the corrected candidate." + "\n\nLOCAL VALIDATOR REJECTED THE PREVIOUS CANDIDATE: {error}\nPREVIOUS_CANDIDATE_STRUCTURE:\n{previous_structure}\nReturn a corrected complete candidate against the same START and EVIDENCE. Preserve valid detail, but make every reference use an ID declared by the corrected candidate. ROUTE REPAIR REQUIREMENT: routes are directed movement authority and container_id is geometry only. The corrected candidate must contain an explicit bidirectional spanning route tree rooted at the player's location: every supplied location must have a directed route chain from the player and a directed route chain back. A physically navigable contained location should normally connect to its container in both directions; otherwise connect it through the nearest legitimate occupancy node. Each route map key is a stable route ID and each route value names an exact supplied destination_id, a distance, and positive travel_minutes. Before returning, internally trace player-to-location and location-to-player paths for every location. Do not emit the trace separately." ); } Err(error) => { @@ -3934,7 +3934,13 @@ mod tests { && request .lived_stream .contains("\"destination_id\":\"missing\"") - && request.lived_stream.contains("\"id\":\"yard\""), + && request.lived_stream.contains("\"id\":\"yard\"") + && request + .lived_stream + .contains("explicit bidirectional spanning route tree") + && request + .lived_stream + .contains("container_id is geometry only"), Ordering::SeqCst, ); Ok(output) diff --git a/crates/ghostlight-dungeon/src/domain.rs b/crates/ghostlight-dungeon/src/domain.rs index a95446e..b11aedf 100644 --- a/crates/ghostlight-dungeon/src/domain.rs +++ b/crates/ghostlight-dungeon/src/domain.rs @@ -71,13 +71,22 @@ pub struct VaultManifest { pub struct Location { pub id: String, pub name: String, + #[schemars( + description = "Geometric containment only. This does not create an implicit movement edge." + )] pub container_id: Option, + #[schemars( + description = "Explicit directed movement edges keyed by stable route ID. Containment never substitutes for a route; a playable opening must provide route chains from the player location to every supplied location and back." + )] pub routes: BTreeMap, pub persistent_features: Vec, } #[derive(Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq)] pub struct Route { + #[schemars( + description = "Exact ID of another supplied location reached by this directed route." + )] pub destination_id: String, pub distance: String, #[schemars(range(min = 1))]