diff --git a/crates/ghostlight-dungeon/src/bin/ghostlight-gestalt-dynamics-smoke.rs b/crates/ghostlight-dungeon/src/bin/ghostlight-gestalt-dynamics-smoke.rs index a30710a..0f96748 100644 --- a/crates/ghostlight-dungeon/src/bin/ghostlight-gestalt-dynamics-smoke.rs +++ b/crates/ghostlight-dungeon/src/bin/ghostlight-gestalt-dynamics-smoke.rs @@ -88,10 +88,7 @@ fn write_wave_failure( async fn main() -> anyhow::Result<()> { use chrono::Utc; use ghostlight_dungeon::{ - domain::{ - SimulationCellMode, StrategicMemberMigration, StrategicTickPlan, TickSource, - WorldCommand, - }, + domain::{SimulationCellMode, TickSource, WorldCommand}, gestalt::GestaltPresencePlanner, kernel::{CommandResult, WorldKernel}, model::{DeepSeekPort, ModelPort}, @@ -102,6 +99,7 @@ async fn main() -> anyhow::Result<()> { scheduler::propose_resolution_wave, turn::SnapshotPermit, }; + use sha2::{Digest, Sha256}; use std::{collections::BTreeSet, path::PathBuf, sync::Arc, time::Instant}; let secret = std::env::var_os("GHOSTLIGHT_DEEPSEEK_BLOB") @@ -111,10 +109,10 @@ async fn main() -> anyhow::Result<()> { .unwrap_or_else(|_| "gestalt-dynamics-refugee-return".into()); let require_migration = std::env::var("GHOSTLIGHT_LIVE_FIRE_REQUIRE_MIGRATION") .is_ok_and(|value| value == "1" || value.eq_ignore_ascii_case("true")); - let seed_migration = std::env::var("GHOSTLIGHT_LIVE_FIRE_SEED_MIGRATION") - .is_ok_and(|value| value == "1" || value.eq_ignore_ascii_case("true")); - if require_migration && seed_migration { - anyhow::bail!("strict live migration and deterministic migration setup are exclusive") + let baseline_result_path = + std::env::var_os("GHOSTLIGHT_LIVE_FIRE_BASELINE_RESULT").map(PathBuf::from); + if require_migration && baseline_result_path.is_some() { + anyhow::bail!("strict live migration and a committed migration baseline are exclusive") } let fairness_stress_waves = std::env::var("GHOSTLIGHT_LIVE_FIRE_FAIRNESS_WAVES") .ok() @@ -147,35 +145,49 @@ async fn main() -> anyhow::Result<()> { let member_before = base_campaign.gestalt_members["mira-venn"].clone(); let capabilities_before = effective_member_capabilities(&base_campaign, "mira-venn")?; let knowledge_before = effective_member_knowledge(&base_campaign, "mira-venn")?; - let store = CampaignStore::open(root.join("campaign.cc"))?; - store.create_campaign(&base_campaign, &[], &[])?; - let kernel = WorldKernel::start(store.clone()); - let (campaign, setup_migration_commit) = if seed_migration { - let setup = kernel - .command(WorldCommand::AdvanceStrategicTick { - expected_revision: base_campaign.revision, - source: TickSource::Scheduler, - plan: Some(StrategicTickPlan { - member_migrations: vec![StrategicMemberMigration { - member_id: "mira-venn".into(), - source_gestalt_id: "refugees-east".into(), - destination_gestalt_id: "harbor-neighbors".into(), - destination_location_id: "south-harbor".into(), - public_channels: vec!["public-bulletin".into()], - }], - ..Default::default() - }), - model_receipt_hash: None, - resolution_wave: None, + let (campaign, baseline_receipt) = if let Some(path) = baseline_result_path { + let bytes = std::fs::read(&path)?; + let result: serde_json::Value = serde_json::from_slice(&bytes)?; + let campaign: ghostlight_dungeon::domain::Campaign = + serde_json::from_value(result.pointer("/commit/campaign").cloned().ok_or_else( + || anyhow::anyhow!("baseline result lacks committed campaign state"), + )?)?; + let member = campaign + .gestalt_members + .get("mira-venn") + .ok_or_else(|| anyhow::anyhow!("baseline result lost Mira"))?; + if member.gestalt_id != "harbor-neighbors" + || member.last_location_id.as_deref() != Some("south-harbor") + || member.materialized_actor_id.is_some() + || member.name != member_before.name + || member.relationships != member_before.relationships + || member.memories != member_before.memories + || effective_member_capabilities(&campaign, "mira-venn")? != capabilities_before + || effective_member_knowledge(&campaign, "mira-venn")? != knowledge_before + || campaign.actors[&campaign.player_actor_id] != player_before + || campaign.resolution_cover.as_ref().is_none_or(|cover| { + cover.cells.len() != 1 + || cover.cells[0].mode != SimulationCellMode::Arena + || cover.cells[0].subject_ids.len() != 24 }) - .await?; - let CommandResult::Committed { campaign, .. } = &setup else { - anyhow::bail!("deterministic migration setup did not commit") - }; - (campaign.clone(), Some(setup)) + { + anyhow::bail!("baseline result is not the committed strict migration golden") + } + ( + campaign, + Some(serde_json::json!({ + "path":path, + "sha256":format!("sha256:{:x}", Sha256::digest(&bytes)), + "scenario_id":result.get("scenario_id"), + "campaign_revision":result.pointer("/commit/campaign/revision"), + })), + ) } else { (base_campaign, None) }; + let store = CampaignStore::open(root.join("campaign.cc"))?; + store.create_campaign(&campaign, &[], &[])?; + let kernel = WorldKernel::start(store.clone()); let model_calls = Arc::new(std::sync::Mutex::new(Vec::new())); let model: Arc = Arc::new(LiveFireModelRecorder { inner: DeepSeekPort::from_machine_dpapi(secret)?, @@ -301,7 +313,7 @@ async fn main() -> anyhow::Result<()> { if advanced.actors[&advanced.player_actor_id] != player_before { anyhow::bail!("background simulation puppeted the player") } - if migration_proposal.is_none() && !seed_migration { + if migration_proposal.is_none() && baseline_receipt.is_none() { if advanced.gestalt_members["mira-venn"] != member_before { anyhow::bail!("explicit inaction changed Mira's dormant identity") } @@ -578,8 +590,7 @@ async fn main() -> anyhow::Result<()> { "cell_mode":root_cell.mode, "rivals_share_arena":true, "migration_proposal":migration_proposal, - "seeded_migration":seed_migration, - "setup_migration_commit":setup_migration_commit, + "migration_baseline":baseline_receipt, "initial_background_action_count":background_action_count, "sustained_background_subject_ids":background_subject_ids, "sustained_detail_focus_subject_ids":detail_focus_subject_ids, diff --git a/docs/architecture/ghostlight-multiresolution-agency.md b/docs/architecture/ghostlight-multiresolution-agency.md index d64d190..65763fb 100644 --- a/docs/architecture/ghostlight-multiresolution-agency.md +++ b/docs/architecture/ghostlight-multiresolution-agency.md @@ -506,11 +506,11 @@ single stage's one-correction rule or rebase stale output. The callback and fairness claims are independently falsifiable. Strict live mode requires Mira's Persona to choose resettlement and proves the later -callback without forcing that choice. Fairness mode may instead establish the -same already-proven migration through a validated `AdvanceStrategicTick` setup -command, then spend all 24 provider-driven ticks on budget-one debt rotation. -The setup still traverses WorldKernel validation and is explicitly identified -in the result; it is not presented as a Persona decision. +callback without forcing that choice. Fairness mode may instead branch from the +exact committed campaign inside that strict golden's result, then spend all 24 +new provider-driven ticks on budget-one debt rotation. The baseline path and +SHA-256 are recorded in the result; no migration command or Persona decision is +fabricated during fairness setup. A deterministic diaspora test drives two durable people from the same depth-two refugee leaf to two different depth-two destination branches in one diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index 3054593..1663315 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -231,10 +231,11 @@ not add a second retry inside Projector/Interpreter validation. Do not resample Mira until she performs for the fairness test. Three consecutive `bc19c8a` Personas validly gave away the berth or waited. The strict callback golden already proves emergent migration. For fairness, set -`GHOSTLIGHT_LIVE_FIRE_SEED_MIGRATION=1`, leave strict migration off, and keep -`GHOSTLIGHT_LIVE_FIRE_FAIRNESS_WAVES=23`: a validated setup tick moves Mira, -then the initial provider wave plus 23 sustained waves provide 24 debt foci. -The result distinguishes `setup_migration_commit` from model proposals. +`GHOSTLIGHT_LIVE_FIRE_BASELINE_RESULT` to the strict golden's `result.json`, +leave strict migration off, and keep `GHOSTLIGHT_LIVE_FIRE_FAIRNESS_WAVES=23`: +the initial provider wave plus 23 sustained waves provide 24 new debt foci. +The harness validates the baseline's committed campaign, dormant Mira identity, +arena cover, and player state, then records its path and SHA-256 in the result. The multiresolution body is deployed on Starfire. Typed health matched the immutable release, DeepSeek was ready, and the disposable live strategic-cell diff --git a/state/map.yaml b/state/map.yaml index 173a470..144f834 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -268,5 +268,5 @@ data_flow: current_status: summary: GhostlightDungeon production remains on the verified Starfire release. The strict 24-subject multiresolution golden is complete: a budget-one rival arena, independent population/member migration, 26 background consequences across 11 subjects, stable identity through 1/4/8/4 resolution changes, and automatic rematerialization of the same refugee. Production state remains untouched. - next_action: Run the 24-tick budget-one fairness stress from the explicit WorldKernel-validated migration setup, with bounded fresh scheduler pulses after rejected waves. Require every canonical subject to receive runtime-selected debt focus, reject inactive lineage parents, preserve Mira through sustained aggregate activity, and rematerialize the same person. Then run the 1/4/8/32 scale matrix and compare cache and cognitive-efficiency profiles. + next_action: Run the 24-tick budget-one fairness stress from the exact committed strict-golden campaign, with bounded fresh scheduler pulses after rejected waves. Require every canonical subject to receive runtime-selected debt focus, reject inactive lineage parents, preserve Mira through sustained aggregate activity, and rematerialize the same person. Then run the 1/4/8/32 scale matrix and compare cache and cognitive-efficiency profiles. 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. Simulation cells are derived covers only.