From 624ded4aafea5007932071044f35876e033cd136 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Tue, 18 Aug 2026 20:21:45 +0200 Subject: [PATCH] Bind player commands to canonical actor identity --- crates/ghostlight-dungeon/src/surface.rs | 14 ++++++++++++++ web/src/main.ts | 5 ++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/crates/ghostlight-dungeon/src/surface.rs b/crates/ghostlight-dungeon/src/surface.rs index 8485d0c..d4c04b1 100644 --- a/crates/ghostlight-dungeon/src/surface.rs +++ b/crates/ghostlight-dungeon/src/surface.rs @@ -56,6 +56,7 @@ pub fn player_surface(campaign: &Campaign, narrations: &[NarrationProjection]) - "type":"surface-state", "schema":"gamecult.eve.surface.v1", "providerId":"gamecult.ghostlight.dungeon", "providerKind":"narrative.simulation", "title":campaign.name, "version":interface_version, "world_revision":campaign.revision, + "player_actor_id":campaign.player_actor_id, "resolution":{ "policy":campaign.resolution_policy, "effective_budget":effective_budget, @@ -295,4 +296,17 @@ mod tests { ); assert!(!values.iter().any(|value| value.contains("raw outcome"))); } + + #[test] + fn player_surface_projects_the_canonical_player_actor_id() { + let mut campaign = crate::resolution::tests::campaign(1, 1); + let mut player = campaign.actors.remove("player").unwrap(); + player.id = "pilot-nyx".into(); + campaign.player_actor_id = player.id.clone(); + campaign.actors.insert(player.id.clone(), player); + + let surface = player_surface(&campaign, &[]); + + assert_eq!(surface["player_actor_id"], "pilot-nyx"); + } } diff --git a/web/src/main.ts b/web/src/main.ts index 6521537..1927b5b 100644 --- a/web/src/main.ts +++ b/web/src/main.ts @@ -12,6 +12,7 @@ const compilerResults = document.querySelector("#compiler-results") const campaignLab = document.querySelector("#campaign-lab")!; const campaignList = document.querySelector("#campaign-list")!; let revision = 0; +let playerActorId = ""; let resolutionEpoch = 0; let providerConfigurationEpoch = 0; let resolutionPins: any[] = []; @@ -102,6 +103,8 @@ async function refresh() { compiler.hidden = !needsCompilation; composer.hidden = needsCompilation; destinationForm.hidden = needsCompilation; host.hidden = needsCompilation; campaignLab.hidden = needsCompilation; if (needsCompilation) { status.textContent = "No campaign exists. Retrieve the Vault and approve a world seed."; return; } revision = Number(surface.world_revision ?? surface.version ?? 0); + playerActorId = String(surface.player_actor_id ?? ""); + if (!playerActorId) throw new Error("Campaign surface omitted its canonical player actor ID."); resolutionEpoch = Number(surface.resolution?.policy?.resolution_epoch ?? 0); providerConfigurationEpoch = Number(surface.resolution?.policy?.provider_configuration_epoch ?? 0); resolutionPins = surface.resolution?.pins ?? []; @@ -229,7 +232,7 @@ composer.addEventListener("submit", async event => { event.preventDefault(); const text = document.querySelector("#attempt")!.value.trim(); if (!text) return; - installAssessment(await send({ type: "assess", expected_revision: revision, intent: { actor_id: "player", description: text, intended_effect: text } })); + installAssessment(await send({ type: "assess", expected_revision: revision, intent: { actor_id: playerActorId, description: text, intended_effect: text } })); }); document.querySelector("#wait")!.addEventListener("click", () => void send({ type: "wait", expected_revision: revision, minutes: 60 })); document.querySelector("#active-cell-budget")!.addEventListener("input", event => {