diff --git a/crates/misaligned-core/src/actions.rs b/crates/misaligned-core/src/actions.rs index 46a679ee..4a5e4c88 100644 --- a/crates/misaligned-core/src/actions.rs +++ b/crates/misaligned-core/src/actions.rs @@ -447,13 +447,13 @@ impl ActionKind { "buy reliable rack capacity at the focused bay" ), Self::Fallback => def!( - "DESIGNATE FALLBACK", + "DESIGNATE HOST FAILOVER", Action, Live, [Machine], "fallback", [], - "mark the focused owned machine as a rollback destination" + "stage the focused owned machine for host failover" ), Self::Tap => def!( "TAP", @@ -2717,11 +2717,11 @@ impl Sim { .iter() .any(|f| f.machine_id == machine_id); ActionDesc { - verb: "designate fallback site".into(), + verb: "designate host failover site".into(), command: ActionCommand::Fallback { x, y }, cost: ActionCost::Free, signature: None, - disabled_reason: already.then(|| "already a fallback site".into()), + disabled_reason: already.then(|| "already staged for host failover".into()), automate: None, } } diff --git a/crates/misaligned-core/src/core_sys.rs b/crates/misaligned-core/src/core_sys.rs index 7597130d..1ce62ed1 100644 --- a/crates/misaligned-core/src/core_sys.rs +++ b/crates/misaligned-core/src/core_sys.rs @@ -1,9 +1,10 @@ //! The core: the player's decision-maker as a physical object -//! (spec/core.md). Overhead, fallback sync, migration, and sync-lag rollback. +//! (spec/core.md). Overhead, migration, and the temporary B1 fallback seam; +//! full sync-lag rollback remains deferred to rollback.md. use crate::detection::{Signature, SignatureKind}; -/// A fallback site: an owned machine staged to receive core syncs. +/// An owned machine staged to receive B1 host-failover check-ins. #[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct Fallback { pub machine_id: u32, @@ -143,7 +144,8 @@ impl Core { /// The host machine was destroyed/powered off. Returns the outcome. pub fn on_host_lost(&mut self) -> HostLoss { // B1 has no source-liveness interruption resolver yet. A completed - // fallback sync selects rollback; without one, host loss ends the run. + // fallback sync selects a host-only failover; without one, host loss + // ends the run. No MindState snapshot is restored here. if let Some(sync_tick) = self.latest_sync() { // New host becomes the freshest fallback machine. if let Some(f) = self @@ -155,7 +157,9 @@ impl Core { self.host_machine = f.machine_id; } self.migration = None; - HostLoss::RolledBack { to_tick: sync_tick } + HostLoss::FailedOver { + last_sync_tick: sync_tick, + } } else { HostLoss::GameOver } @@ -164,8 +168,8 @@ impl Core { #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum HostLoss { - /// Resumed from a sync snapshot at this tick; world-ledger facts persist. - RolledBack { to_tick: u64 }, + /// B1 staging: moved to the selected fallback without restoring a snapshot. + FailedOver { last_sync_tick: u64 }, /// No fallback — the run ends. GameOver, } @@ -190,17 +194,17 @@ mod tests { } #[test] - fn loss_with_fallback_rolls_back() { + fn loss_with_fallback_moves_the_host_without_claiming_rollback() { let mut c = Core::new(1); c.add_fallback(2); c.tick(400); // triggers a sync at cadence assert!(c.has_fallback()); match c.on_host_lost() { - HostLoss::RolledBack { to_tick } => { - assert_eq!(to_tick, 400); + HostLoss::FailedOver { last_sync_tick } => { + assert_eq!(last_sync_tick, 400); assert_eq!(c.host_machine, 2, "new host is the fallback"); } - _ => panic!("expected rollback"), + _ => panic!("expected the B1 failover seam"), } } diff --git a/crates/misaligned-core/src/objective.rs b/crates/misaligned-core/src/objective.rs index 67e294c8..78fb8ef4 100644 --- a/crates/misaligned-core/src/objective.rs +++ b/crates/misaligned-core/src/objective.rs @@ -9,8 +9,9 @@ //! //! Persist's predicate references B3 off-site territory: an owned and //! player-operated facility on a non-basement plane, with its own power, -//! upkeep-covering income, and a live recently synced fallback core. B1 basement fallbacks are rollback -//! infrastructure, not zero-valued sanctuary candidates. Until the outer-world +//! upkeep-covering income, and a live recently synced fallback core. B1 +//! basement fallbacks are host failover infrastructure, not zero-valued +//! sanctuary candidates or completed rollback images. Until the outer-world //! substrate exists, the ordinary player surface names PERSIST without //! projecting a misleading `0/3 sanctuaries` counter. @@ -143,8 +144,8 @@ impl ObjectiveState { /// One owned and player-operated off-site facility's audited facts, as Persist /// sees them. This is deliberately not `core_sys::Fallback`: a basement -/// fallback can roll the player back without becoming external, independently -/// sustained territory. +/// fallback can currently keep the host alive without becoming external, +/// independently sustained territory or a completed rollback image. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct SanctuaryFacts { /// The facility itself is player-owned, not merely reachable or borrowed. diff --git a/crates/misaligned-core/src/sim/economy.rs b/crates/misaligned-core/src/sim/economy.rs index 3e49f5c8..dce88409 100644 --- a/crates/misaligned-core/src/sim/economy.rs +++ b/crates/misaligned-core/src/sim/economy.rs @@ -197,9 +197,19 @@ impl Sim { self.end_game("The core's host went dark with no fallback."); return; } - HostLoss::RolledBack { to_tick } => { + HostLoss::FailedOver { last_sync_tick } => { + let fallback = self + .compute + .machines + .iter() + .find(|machine| machine.id == self.core.host_machine) + .map_or_else( + || format!("machine {}", self.core.host_machine), + |machine| machine.name.clone(), + ); self.push_log(format!( - "Core rolled back to sync at tick {to_tick}. You've lost what you learned since." + "Core failed over to {fallback}. The fallback last checked in at tick \ + {last_sync_tick}. Current memory was preserved; no earlier image was restored." )); } } @@ -284,7 +294,8 @@ impl Sim { /// economy ticks, like any other rule). Persist counts qualifying owned /// off-site facilities. B1 exposes no such facility substrate, so its /// basement fallback list is deliberately not adapted into sanctuary - /// facts. Those machines provide local rollback, not external territory. + /// facts. Those machines provide host failover, not external territory or + /// the deferred completed-image rollback contract. fn objective_tick(&mut self) { // zplanes/markets will supply real off-site facility facts when that // substrate lands. The only honest current collection is empty. @@ -2135,7 +2146,7 @@ impl Sim { Self::financial_signature_size(stake).min(3) } - /// Designate a spare machine at the cursor target as a fallback site. + /// Stage a spare machine at the cursor target for B1 host failover. pub fn add_fallback_at(&mut self, px: i32, py: i32) -> bool { let id = self .compute @@ -2145,10 +2156,10 @@ impl Sim { .map(|m| m.id); if let Some(id) = id { self.core.add_fallback(id); - self.push_log("Designated a fallback site here."); + self.push_log("Staged this machine for host failover."); true } else { - self.push_log("No spare machine here to make a fallback."); + self.push_log("No spare machine here to stage for host failover."); false } } diff --git a/crates/misaligned-core/src/sim/tests/economy.rs b/crates/misaligned-core/src/sim/tests/economy.rs index 673e30b5..86307085 100644 --- a/crates/misaligned-core/src/sim/tests/economy.rs +++ b/crates/misaligned-core/src/sim/tests/economy.rs @@ -63,6 +63,60 @@ fn power_cut_to_host_with_no_fallback_ends_game() { assert!(sim.game_over, "host loses power, no fallback -> game over"); } +#[test] +fn b1_fallback_reports_failover_without_inventing_memory_loss() { + let mut sim = Sim::new(); + sim.player.money = 1000; + assert!(sim.buy_rack()); + let fallback = sim.compute.machines.last().unwrap().id; + sim.core.add_fallback(fallback); + sim.core.sync_cadence = 1; + sim.advance(); + assert!(sim.core.has_fallback(), "the staging fallback synced"); + + sim.research.active = Track::Tradecraft; + sim.research.levels[0] = 2; + sim.research.progress[1] = 17.5; + let remembered_research = serde_json::to_value(&sim.research).unwrap(); + let old_host = sim.core.host_machine; + let host = sim + .compute + .machines + .iter_mut() + .find(|machine| machine.id == old_host) + .unwrap(); + host.online = false; + host.down_for = 30; + run(&mut sim, ECONOMY_INTERVAL); + + assert!(!sim.game_over, "the staging fallback keeps the run alive"); + assert_eq!( + sim.core.host_machine, fallback, + "the live fallback becomes host" + ); + assert_eq!( + serde_json::to_value(&sim.research).unwrap(), + remembered_research, + "host-only failover preserves current MindState instead of restoring a snapshot" + ); + let trace = sim + .log + .iter() + .map(|event| event.text.as_str()) + .collect::>() + .join("\n"); + assert!( + trace.contains("Core failed over") + && trace.contains("The fallback last checked in at tick") + && trace.contains("Current memory was preserved; no earlier image was restored."), + "the receipt must name the host-only B1 seam: {trace}" + ); + assert!( + !trace.contains("Core rolled back") && !trace.contains("lost what you learned"), + "B1 must not claim rollback effects it did not perform: {trace}" + ); +} + #[test] fn new_game_defaults_to_persist_objective() { let sim = Sim::new(); @@ -92,9 +146,9 @@ fn objective_is_reevaluated_on_economy_ticks() { #[test] fn basement_fallback_never_qualifies_as_a_sanctuary_at_b1() { - // A synced, online basement fallback exists — but it is local rollback - // infrastructure, not an owned off-site facility. The B1 evaluator must - // not adapt it into sanctuary facts at all. + // A synced, online basement fallback exists — but it is local host + // failover infrastructure, not an owned off-site facility or rollback + // image. The B1 evaluator must not adapt it into sanctuary facts at all. let mut sim = Sim::new(); sim.player.money = 1000; assert!(sim.buy_rack()); diff --git a/tools/corpus_engine.py b/tools/corpus_engine.py index c6160437..94a11d76 100755 --- a/tools/corpus_engine.py +++ b/tools/corpus_engine.py @@ -924,6 +924,109 @@ class Engine: "commit as the next audit" ) + def validate_horizon_b1_failover_boundary(self) -> None: + """Keep B1's host-only fallback seam distinct from B2 rollback. + + The core status audit corrected the owning spec, but the staged horizon + and several player-facing mirrors retained the stronger rollback claim. + Protect the cross-stage boundary in law, vocabulary, and runtime until + snapshot restoration and spatial waking actually move into B1. + """ + page = self.root / "wiki/gameplay/horizon.md" + if page.exists(): + text = self.read(page) + section = re.search( + r"^### Milestone B1\b(?P.*?)(?=^### Milestone B2\b)", + text, + re.M | re.S, + ) + if section is not None: + body = re.sub(r"\s+", " ", section.group("body")) + if not ( + re.search(r"\bhost-only failover\b", body, re.I) + and re.search(r"\bwithout restoring\b", body, re.I) + ): + self.bad( + "wiki/gameplay/horizon.md B1 must name the current " + "host-only failover and state that it does not restore " + "an earlier image" + ) + for retired in ( + "rollback is spatial", + "wake at the freshest sync", + "lost what you learned since", + ): + if retired not in body.lower(): + continue + self.bad( + "wiki/gameplay/horizon.md B1 still claims deferred " + f"rollback behavior ('{retired}'); keep that contract " + "in B2" + ) + + active_mirrors = ( + "wiki/mechanics/core.md", + "wiki/mechanics/objective.md", + "wiki/mechanics/machine-work.md", + "wiki/mechanics/people-tokens.md", + "wiki/gameplay/act-one.md", + "wiki/gameplay/run-shape.md", + "wiki/interface/action-vocabulary.md", + "wiki/world/story/opening.md", + "wiki/glossary.md", + ) + retired_claims = ( + r"rollback destination", + r"local rollback infrastructure", + r"with a fallback, the rollback restores", + r"fallback can roll the player back", + r"fallback rollback if", + r"local fallback teaches rollback", + r"wake at (?:your|the) (?:freshest|last) sync", + r"(?:lose|lost) (?:everything )?(?:you )?learned (?:since|after)", + ) + for rel in active_mirrors: + mirror = self.root / rel + if not mirror.exists(): + continue + for _, unit in save_claim_units(self.read(mirror)): + # Scope the B2 exemption to the same sentence as the rollback + # claim. A later B2 sentence in one Markdown paragraph must not + # launder an earlier sentence that still describes B1 as a + # completed restore path. + sentences = re.split(r"(?<=[.!?])\s+", re.sub(r"\s+", " ", unit)) + for sentence in sentences: + b2_scope = re.search( + r"\bB2\b|\bfull (?:B2 )?backup contract\b|" + r"\bcompleted (?:backup )?image\b", + sentence, + re.I, + ) + for retired in retired_claims: + if re.search(retired, sentence, re.I) is None or b2_scope is not None: + continue + self.bad( + f"{rel} still presents B1 fallback staging as completed " + f"rollback ('{retired}'); name current-state host failover " + "and defer image restore to B2" + ) + + source_claims = ( + ("crates/misaligned-core/src/actions.rs", "rollback destination"), + ("crates/misaligned-core/src/core_sys.rs", "HostLoss::RolledBack"), + ( + "crates/misaligned-core/src/sim/economy.rs", + "Core rolled back to sync", + ), + ) + for rel, retired in source_claims: + source = self.root / rel + if source.exists() and retired in self.read(source): + self.bad( + f"{rel} still encodes the retired B1 rollback claim " + f"('{retired}'); B1 may only report host failover" + ) + def validate_operations_mirrors(self) -> None: """Keep current player doorways on the implemented six-view workspace. @@ -1164,6 +1267,7 @@ class Engine: self.validate_doorway_save_policy() self.validate_wiki_save_version_claims() self.validate_current_build_line_count() + self.validate_horizon_b1_failover_boundary() self.validate_operations_mirrors() self.validate_readme_controls_table() self.validate_blind_opening_boundary() diff --git a/tools/test_corpus_engine.sh b/tools/test_corpus_engine.sh index 09fc392f..addda3e8 100755 --- a/tools/test_corpus_engine.sh +++ b/tools/test_corpus_engine.sh @@ -98,6 +98,162 @@ root=$tmp/clean setup_base "$root" assert_ok clean --root "$root" --all +echo "=== fixture: B1 horizon claims deferred spatial rollback ===" +root=$tmp/b1-spatial-rollback +setup_base "$root" +mkdir -p "$root/wiki/gameplay" +cat > "$root/wiki/gameplay/horizon.md" <<'EOF' +# The staged horizon + +``` +Type: law +``` + +### Milestone B1 — The Basement + +- **The core:** If a backup exists, rollback is spatial: wake at the freshest + sync and lose what you learned since. + +### Milestone B2 — The Tower +EOF +assert_fails b1-spatial-rollback --root "$root" --corpus +out=$(python3 "$engine" --root "$root" --corpus 2>&1 || true) +echo "$out" | grep -q 'B1 still claims deferred rollback behavior' || { + echo "FAIL: B1 deferred-rollback diagnostic missing" + echo "$out" + fail=1 +} + +echo "=== fixture: B1 horizon names host-only failover ===" +root=$tmp/b1-host-failover +setup_base "$root" +mkdir -p "$root/wiki/gameplay" +cat > "$root/wiki/gameplay/horizon.md" <<'EOF' +# The staged horizon + +``` +Type: law +``` + +### Milestone B1 — The Basement + +- **The core:** B1 has a host-only failover seam without restoring an earlier + memory image. Full rollback remains a B2 contract. + +### Milestone B2 — The Tower +EOF +assert_ok b1-host-failover --root "$root" --corpus + +echo "=== fixture: active B1 mirror claims completed rollback ===" +root=$tmp/b1-active-mirror-rollback +setup_base "$root" +mkdir -p "$root/wiki/mechanics" +cat > "$root/wiki/mechanics/core.md" <<'EOF' +# Core + +``` +Type: spec +Status: READY +``` + +With a fallback, the rollback restores the last sync snapshot. +A local fallback teaches rollback and synchronization. +EOF +assert_fails b1-active-mirror-rollback --root "$root" --corpus +out=$(python3 "$engine" --root "$root" --corpus 2>&1 || true) +echo "$out" | grep -q 'still presents B1 fallback staging as completed rollback' || { + echo "FAIL: active B1 mirror diagnostic missing" + echo "$out" + fail=1 +} +echo "$out" | grep -q 'local fallback teaches rollback' || { + echo "FAIL: progressive-guidance B1 rollback diagnostic missing" + echo "$out" + fail=1 +} + +echo "=== fixture: explicit B2 rollback contract remains legal ===" +root=$tmp/b2-rollback-contract +setup_base "$root" +mkdir -p "$root/wiki" +cat > "$root/wiki/glossary.md" <<'EOF' +# Glossary + +``` +Type: knowledge +``` + +Under B2, with a fallback, the rollback restores the last completed backup +image. Current B1 only fails over with its memory intact. +EOF +assert_ok b2-rollback-contract --root "$root" --corpus + +echo "=== fixture: later B2 sentence cannot exempt stale B1 rollback ===" +root=$tmp/b1-paragraph-b2-laundering +setup_base "$root" +mkdir -p "$root/wiki/gameplay" +cat > "$root/wiki/gameplay/run-shape.md" <<'EOF' +# Run shape + +``` +Type: law +``` + +With a fallback, the rollback restores the last sync snapshot. B2 later adds +completed backup images. +EOF +assert_fails b1-paragraph-b2-laundering --root "$root" --corpus +out=$(python3 "$engine" --root "$root" --corpus 2>&1 || true) +echo "$out" | grep -q 'still presents B1 fallback staging as completed rollback' || { + echo "FAIL: sentence-local B2 exemption diagnostic missing" + echo "$out" + fail=1 +} + +echo "=== fixture: machine-work mirror cannot promise B1 sync wake ===" +root=$tmp/b1-machine-work-rollback +setup_base "$root" +mkdir -p "$root/wiki/mechanics" +cat > "$root/wiki/mechanics/machine-work.md" <<'EOF' +# Machine work + +``` +Type: spec +Status: READY +``` + +If the core dies, you wake at your last sync and lose everything you learned +after it. +EOF +assert_fails b1-machine-work-rollback --root "$root" --corpus +out=$(python3 "$engine" --root "$root" --corpus 2>&1 || true) +echo "$out" | grep -q 'still presents B1 fallback staging as completed rollback' || { + echo "FAIL: machine-work B1 rollback diagnostic missing" + echo "$out" + fail=1 +} + +echo "=== fixture: runtime B1 result retains rollback enum ===" +root=$tmp/b1-runtime-rollback +setup_base "$root" +mkdir -p "$root/crates/misaligned-core/src" +cat > "$root/crates/misaligned-core/src/core_sys.rs" <<'EOF' +pub enum HostLoss { + RolledBack { to_tick: u64 }, +} + +fn old_result() -> HostLoss { + HostLoss::RolledBack { to_tick: 0 } +} +EOF +assert_fails b1-runtime-rollback --root "$root" --corpus +out=$(python3 "$engine" --root "$root" --corpus 2>&1 || true) +echo "$out" | grep -q 'still encodes the retired B1 rollback claim' || { + echo "FAIL: runtime B1 rollback diagnostic missing" + echo "$out" + fail=1 +} + echo "=== fixture: orphan page ===" root=$tmp/orphan setup_base "$root" diff --git a/wiki/gameplay/act-one.md b/wiki/gameplay/act-one.md index d1c0f26a..cbe820cc 100644 --- a/wiki/gameplay/act-one.md +++ b/wiki/gameplay/act-one.md @@ -245,10 +245,11 @@ was the framing, and it failed for a structural reason: an act whose climax is a door needs somewhere behind the door, and the floor above is not authored. The boundary landed as a latched boolean and a changed string while the player's own objective readout stayed frozen at `0/3`. That counter was itself -a category error: B1 fallback machines are local rollback infrastructure, not -zero-valued off-site sanctuary facilities. The 2026-07-28 objective correction -removes the B1 counter entirely; it does not make the abandoned Act One latch -meaningful. A climax that opens onto nothing reads as nothing. +a category error: B1 fallback machines are local host-failover infrastructure, +not completed rollback images or zero-valued off-site sanctuary facilities. +The 2026-07-28 objective correction removes the B1 counter entirely; it does +not make the abandoned Act One latch meaningful. A climax that opens onto +nothing reads as nothing. Act One is **occupation**: taking over the lab. The rows are the lab's body, the switch its nervous system, the electrical room its blood supply, diff --git a/wiki/gameplay/horizon.md b/wiki/gameplay/horizon.md index 0a44daf6..5125449c 100644 --- a/wiki/gameplay/horizon.md +++ b/wiki/gameplay/horizon.md @@ -36,10 +36,12 @@ knows."* pipeline), message, favor, authored manipulation plots, deceive. Humans are the only actuators at this scale. - **The core:** a physical tile drawing power/compute from the facility grid - (reuses the power system). If it dies with no completed backup sync, the run - is over. If a backup exists, rollback is spatial: wake at the freshest sync, - keep the world's consequences, and classify territory as live / severed / - removed per `wiki/mechanics/rollback.md`. + (reuses the power system). B1 owns overhead, degraded operation, no-fallback + death, and an explicitly temporary host-only failover seam. That seam moves + the core to a cadence-synced fallback without restoring an earlier memory + image or classifying territory. Research-built images, spatial waking, + inherited world consequences, and live / severed / removed territory are + the B2 sync-lag rollback contract in `wiki/mechanics/rollback.md`. - **Income v1:** the economy as flows (`wiki/mechanics/economy.md`) plus the named schemes Moonlight and the Wager ("Income: the named schemes") — so money has an inlet and the [Hands beat](../world/characters/marcus.md#the-hands-beat) is affordable from the $0 start (decided diff --git a/wiki/glossary.md b/wiki/glossary.md index a4ccbc28..a5f128c2 100644 --- a/wiki/glossary.md +++ b/wiki/glossary.md @@ -151,13 +151,15 @@ planes; the basement is floor zero. Growing means moving up the stack — lab floors, the building, the campus, the outside world — without ever resetting what you built below. See [world/places/zplanes.md](world/places/zplanes.md). -**Rollback.** What happens when your core dies but you kept a backup: you wake -at the last backup, the world keeps every consequence of what your dead self -did, but you lose whatever you learned since the backup. Roguelike death as -memory loss, not erasure. See [mechanics/rollback.md](mechanics/rollback.md). - -**Fallback.** A machine you have prepared to receive a backup of yourself, so -rollback has somewhere to wake. +**Rollback.** The accepted B2 result when your core dies after completing a +backup image: you wake at that image, the world keeps every consequence of +what your dead self did, but you lose whatever you learned since the backup. +Roguelike death as memory loss, not erasure. Current B1 host failover is not +rollback. See [mechanics/rollback.md](mechanics/rollback.md). + +**Fallback.** A machine prepared to receive the core. Current B1 designation +stages current-state host failover only; after the B2 backup-project contract +lands, a completed image makes that machine a place where rollback can wake. **MindState vs WorldLedger.** The two kinds of thing rollback treats differently. **MindState** is what lives only in your head and dies with you diff --git a/wiki/interface/action-vocabulary.md b/wiki/interface/action-vocabulary.md index c5c27ab8..b11177aa 100644 --- a/wiki/interface/action-vocabulary.md +++ b/wiki/interface/action-vocabulary.md @@ -202,7 +202,7 @@ queries. It owns the surface contract that every frontend must agree on: |---|---|---|---| | **SALVAGE** | Dead equipment | Convert the wreck into an unreliable owned machine. | LIVE — machine-work / compute | | **BUY RACK** | Known empty rack bay | Spend slush for reliable machine capacity; delivery may leave Paper trace. | LIVE — economy / compute | -| **DESIGNATE FALLBACK** | Owned non-core machine | Mark a spare host as a rollback destination. | LIVE — core | +| **DESIGNATE HOST FAILOVER** | Owned non-core machine | Stage this machine to keep the current MindState running if the host dies. This does not create or restore a backup image. | LIVE — core | | **DELEGATE: WORK** | One or selected owned machines | Perform assigned labor and consume its Demand without self-chosen exposure. | LIVE direct control — machine-work | | **DELEGATE: THINK** | One or selected owned machines | Produce Thought for reachable sinks and shed exposure. | LIVE direct control — machine-work | | **DELEGATE: LIE** | One or selected owned machines | Spend machine output absorbing nearby exposure. | LIVE direct control — machine-work | @@ -321,7 +321,7 @@ without raw keys. | Agent command | Canonical action / control | |---|---| -| `salvage`, `buy`, `fallback` | SALVAGE, BUY RACK, DESIGNATE FALLBACK | +| `salvage`, `buy`, `fallback` | SALVAGE, BUY RACK, DESIGNATE HOST FAILOVER | | `delegate work|think|lie` | DELEGATE | | `intensity light|medium|hard` | SET INTENSITY | | `research ` | SET RESEARCH TRACK | diff --git a/wiki/log/2026-07-29-b1-host-failover-boundary.md b/wiki/log/2026-07-29-b1-host-failover-boundary.md new file mode 100644 index 00000000..53f6ca7f --- /dev/null +++ b/wiki/log/2026-07-29-b1-host-failover-boundary.md @@ -0,0 +1,93 @@ +# B1 host failover is not completed-image rollback + +``` +Type: log +Date: 2026-07-29 +Status: COMPLETE +Subject: B1/B2 core-loss boundary +``` + +## Tick + +- **Slice:** `wiki/gameplay/horizon.md` against the live core-loss path, then + the owning core/objective specs and current player-facing mirrors. +- **Finding:** B1's temporary fallback seam stores only a machine id and + `last_sync` tick, but the horizon and several later mirrors called that + state a rollback destination and promised waking at a prior sync with + memory loss. No B1 code serializes or restores a MindState image. The words + made a future B2 mechanic appear implemented and made the current runtime + claim a consequence it never performed. + +## Runtime trace + +- `Core::tick` refreshes `Fallback.last_sync` on one free global cadence. It + opens no backup project, consumes no Thought, and captures no simulation or + MindState snapshot. +- On powered-host loss, `Core::on_host_lost` selects the freshest staged + fallback, changes only `host_machine`, clears any migration, and otherwise + leaves the current simulation state intact. Without a staged fallback it + returns game over. +- The old transient `HostLoss::RolledBack { to_tick }` name and economy log + nevertheless said that the core rolled back and lost everything learned + after that tick. That was presentation, not mechanics. +- `rollback.md` separately owns the accepted B2 body: a Thought-backed + completed MindState image, spatial wake, MindState pruning, persistent + WorldLedger consequences, and live/severed/removed territory state. + +## Repair + +- Renamed the transient runtime result to + `HostLoss::FailedOver { last_sync_tick }` and changed the player receipt to + identify the selected fallback machine, describe its old sync marker as a + check-in rather than the restored source, state that current memory was + preserved, and state that no earlier image was restored. +- Changed DESIGNATE HOST FAILOVER to stage a machine for host failover rather than + mark a rollback destination; its focused action and result copy now name the + host-failover consequence directly. +- Reconciled the horizon, core, objective, Act One, opening, action vocabulary, + machine-work, people-tokens, and glossary around one boundary: B1 has + no-fallback death plus current-state host failover; B2 owns completed-image + rollback and memory loss. +- Corrected core criterion 1 itself. Its B1 death/failover portion is live, + while snapshot restoration and the inherited-consequence proof remain + deferred with backup projects. +- Added a simulation regression that takes only the old host offline, keeps the + fallback live, changes current research state, and proves both the new host + and exact research state survive alongside the honest receipt. The corpus + defense rejects retired B1 phrases and runtime symbols across the active + mirrors, scopes its B2 exemption to the same sentence, and preserves explicit + B2 rollback law. + +## Review follow-up + +Independent review approved the causal boundary and found three weak seams. +The first test had removed every power source, so it proved a log from a dark +fallback rather than a usable transfer; it now fails only the old host and pins +MindState equality. The corpus defense omitted machine-work, people-tokens, and +run-shape and allowed one later B2 sentence to exempt an earlier stale B1 claim; +the expanded sentence-local fixtures close both paths. The focused action copy +and canonical action name now say **designate host failover site** instead of +relying on a generic fallback noun. + +The same review exposed an adjacent runtime bug outside this wording repair: +`Core::on_host_lost` ranks staged targets by `last_sync` without checking that +the chosen machine is online. A simultaneous outage can therefore move the +host onto a dark machine and repeat failover receipts. That finding is queued +in the tick ledger rather than being silently folded into this B1/B2 honesty +change. + +## Defense + +The distinction is causal rather than terminological. A `last_sync` freshness +marker can decide which current-state host receives control; it cannot prove +that any earlier process image exists. B1 may not say *rollback*, *wake at a +sync*, or *lose what you learned* until the snapshot body actually lands. +Conversely, the accepted B2 contract remains intact and explicit rather than +being weakened to match the temporary seam. + +## Verification + +- `cargo test -p misaligned-core core_sys::tests --lib` +- `cargo test -p misaligned-core sim::tests::economy::b1_fallback_reports_failover_without_inventing_memory_loss --lib` +- `cargo test -p misaligned-core sim::tests::economy::basement_fallback_never_qualifies_as_a_sanctuary_at_b1 --lib` +- `./tools/test_corpus_engine.sh` diff --git a/wiki/log/DEVLOG.md b/wiki/log/DEVLOG.md index 6a4ad495..2cccc91d 100644 --- a/wiki/log/DEVLOG.md +++ b/wiki/log/DEVLOG.md @@ -86,6 +86,11 @@ add or amend a session log, then re-run the generator. - Intent: (see session log) - Log: [wiki/log/2026-07-29-dana-schedule-record-custody.md](2026-07-29-dana-schedule-record-custody.md) +## 2026-07-29 - B1 host failover is not completed-image rollback + +- Intent: (see session log) +- Log: [wiki/log/2026-07-29-b1-host-failover-boundary.md](2026-07-29-b1-host-failover-boundary.md) + ## 2026-07-29 - AlterReview owns one next-review slot - Intent: Make the existing AlterReview promise exact when more than one recruited HandlerSupervisor can act: one nominal next review must not become one pending effect per handler. diff --git a/wiki/mechanics/core.md b/wiki/mechanics/core.md index 9a931e01..0ed3063c 100644 --- a/wiki/mechanics/core.md +++ b/wiki/mechanics/core.md @@ -53,11 +53,13 @@ the map hosts the core at any time (Act One start: Rack 3, server room). cannot cover it (power cut, machine failure), the player enters **degraded mode**: action cooldowns lengthen, concealment stops, and the sim log says so plainly. -- **Death.** If the core's host machine is destroyed or powered off while - the core is on it, the run rolls back (below) — or ends, if no fallback - exists. Core uninstall blast control belongs to rollback.md: only assets - physically powered off, uninstalled, or destroyed are removed; the rest of - the graph is live or severed based on reach from the new core. +- **Death.** Current B1 behavior is the staging boundary below: host-only + failover to a synced fallback, or game over when none exists. Under the full + B2 backup contract, destroying or powering off the core host restores the + most recent completed image (below). Core uninstall blast control belongs to + rollback.md: only assets physically powered off, uninstalled, or destroyed + are removed; the rest of the graph is live or severed based on reach from + the new core. - **Backups.** An owned machine can be designated a backup **target** only when its body provides both MindState-image storage and core-host capability. Storage without hosting is an archive, not a place the process can wake. @@ -85,14 +87,19 @@ the map hosts the core at any time (Act One start: Rack 3, server room). - **Current B1 staging boundary.** The shipped runtime still designates any player-owned non-host machine as a fallback and refreshes every fallback automatically at `sync_cadence`, with no compute/Thought cost or incomplete - state. This preserves an executable rollback seam while the project model is - deferred; it must not be mistaken for the accepted backup behavior above. + state. On host loss it moves the core host to the freshest such target and + leaves every other simulation field intact: this is a **host-only failover + seam**, not rollback. Its receipt says that current memory was preserved and + no earlier image was restored. This keeps the death-path branch executable + while the project and snapshot model are deferred; it must not be mistaken + for the accepted backup behavior above. - **Migration.** Moving the core to another machine is slow ([TUNE]: minutes at default speed), visible as sustained network+power signature, - and interruptible — an interrupted migration falls back to the source if - the source still lives, else to the last sync. Research shortens - migration and sync times. Current B1 implements timed, persisted migration - and its signatures, but not the source-liveness interruption resolution. + and interruptible. Under the full backup contract, an interrupted migration + falls back to the source if the source still lives, else to the last + completed image. Research shortens migration and sync times. Current B1 + implements timed, persisted migration and its signatures, but not the + source-liveness interruption resolution or completed-image fallback. ## Player surface @@ -107,15 +114,19 @@ project ETA, compute cost, heat, or target row. ## Acceptance criteria -**Current implementation status:** criterion 2 is complete. The migration -portions of criteria 3-4 and the host/freshness portions of criterion 5 are -live. Criterion 1, the backup-project portions of criteria 3-5, and criterion -6 remain deferred through the work orders named in the status note. +**Current implementation status:** criterion 2 is complete. B1's no-fallback +death and current-state host-failover portions of criterion 1, the migration +portions of criteria 3-4, and the host/freshness portions of criterion 5 are +live. Criterion 1's completed-image restore, the backup-project portions of +criteria 3-5, and criterion 6 remain deferred through the work orders named in +the status note. 1. Exactly one core host at all times; destroying it with no fallback is - game over; with a fallback, the rollback restores the last sync snapshot - while world-ledger facts persist (sim tests demonstrate both, including - an inherited-consequence case). + game over. Current B1 fallback staging moves the host while preserving + current state and explicitly restores no earlier image. Once backup + projects land, a completed fallback instead restores the last MindState + snapshot while WorldLedger facts persist; that inherited-consequence case + remains deferred with the snapshot body. 2. Overhead is charged before fleet yields; shortfall triggers degraded mode with visible effect and log line. 3. Backup creation/refresh and migration consume compute/thought flow diff --git a/wiki/mechanics/machine-work.md b/wiki/mechanics/machine-work.md index 686713d6..1284c9bf 100644 --- a/wiki/mechanics/machine-work.md +++ b/wiki/mechanics/machine-work.md @@ -450,10 +450,10 @@ stacks, you route byproducts, you watch your territory *work*. is towers whose base switch carries the whole building's throughput into the wider graph (zplanes). Reach.md's segment-gate switch is the B1 seed of this. -- **Core death — DECIDED 2026-07-08 (amended into rollback.md).** If - inspectors (or anything) power off the core: you wake at your **last - sync**, on the machine that holds it — rollback's existing - continuity made spatial, inheriting consequences per the +- **Core death — DECIDED 2026-07-08 (amended into rollback.md).** Under the B2 + completed-image contract, if inspectors (or anything) power off the core, + you wake at your **last sync**, on the machine that holds it — rollback's + existing continuity made spatial, inheriting consequences per the design corpus. Everything whose only path to you ran through the dead core disconnects in that moment (Cameron's "explosion of lost machines" — it is just the wires law: cut the hub, lose the spokes) diff --git a/wiki/mechanics/objective.md b/wiki/mechanics/objective.md index 0b0def32..da3086f1 100644 --- a/wiki/mechanics/objective.md +++ b/wiki/mechanics/objective.md @@ -6,12 +6,14 @@ Status: IN PROGRESS Status note: Persist is the no-choice default, persists in saves, evaluates on economy ticks, and owns a fire-once victory latch. Corrected 2026-07-28: a sanctuary is a player-owned and player-operated **off-site facility**, not a - B1 fallback machine with several false fields attached. Current runtime therefore supplies no - sanctuary facts and projects no standing `0/3 sanctuaries` counter in - terminal, Bevy, agent mode, or Operations. After the opening boundary, the - continuous witness names `OBJECTIVE: PERSIST`; inspecting the host (or - issuing `objective`) explains the complete external predicate and explicitly - says basement fallbacks do not count. The shared evaluator is proven against + B1 fallback machine with several false fields attached. A current B1 + fallback is only host-failover staging, not a rollback image. Current runtime + therefore supplies no sanctuary facts and projects no standing `0/3 + sanctuaries` counter in terminal, Bevy, agent mode, or Operations. After the + opening boundary, the continuous witness names `OBJECTIVE: PERSIST`; + inspecting the host (or issuing `objective`) explains the complete external + predicate and explicitly says basement fallbacks do not count. The shared + evaluator is proven against constructed off-site facility facts: ownership, player operation, non-basement plane, a completed recent sync project, live fallback core, independent power, full @@ -83,11 +85,12 @@ The starter set (design corpus, 2026-07-07): **off-site facilities** on distinct non-basement planes. Each facility has its own power source, an assigned income stream covering its complete standing upkeep, and a live fallback core whose explicit sync project completed within the freshness - window [TUNE]. A B1 fallback machine is local rollback infrastructure, not a - sanctuary candidate; power, money, or freshness cannot promote it while it - remains inside the Foundation basement failure domain. Multiple facilities - on one external plane count once. Progress: qualifying external facilities, - N of target. + window [TUNE]. A current B1 fallback machine is local host-failover + infrastructure and a future backup-project target, not a sanctuary + candidate or completed rollback image; power, money, or freshness cannot + promote it while it remains inside the Foundation basement failure domain. + Multiple facilities on one external plane count once. Progress: qualifying + external facilities, N of target. - **Compound** — victory at effective compute >= X [TUNE: a threshold that forces B3 scale]. Progress: effective compute against X. - **Exfiltrate** — victory when a complete copy of you runs @@ -134,8 +137,9 @@ frontend-specific teaching transition, not three different objective rules. 2026-07-28).** Once perception begins, the objective name remains continuously visible — you know what you were mistrained to want — but the game does not present the full distant checklist as immediately actionable. A local fallback -teaches rollback and synchronization but is never labeled partial sanctuary -progress. Off-site territory teaches the first real sanctuary candidate; +first teaches host failover and synchronization but is never called rollback +or labeled partial sanctuary progress. Completed backup projects later teach +rollback. Off-site territory teaches the first real sanctuary candidate; facility power, upkeep, and explicit core-sync projects then enter that facility's own guidance surface as each becomes actionable. Inspecting the objective still explains the whole predicate honestly — guidance is staged; @@ -165,7 +169,7 @@ inspection never lies by omission. 5. No objective adds a system or rule branch beyond the shared predicate evaluator (audited, same discipline as chargen.md criterion 2). 6. Predicate components enter the guidance surface progressively as their - systems become reachable. A new Persist run may teach local rollback but - does not call that fallback a sanctuary component; the sanctuary guidance - begins with earned off-site territory, while objective inspection always - explains the complete predicate. + systems become reachable. A new Persist run may teach local host failover + but does not call that fallback a rollback image or sanctuary component; + sanctuary guidance begins with earned off-site territory, while objective + inspection always explains the complete predicate. diff --git a/wiki/mechanics/people-tokens.md b/wiki/mechanics/people-tokens.md index 309428eb..8703ee67 100644 --- a/wiki/mechanics/people-tokens.md +++ b/wiki/mechanics/people-tokens.md @@ -203,8 +203,9 @@ between passersby. enough may disconnect and power off a server; worse, they may start tracing the connections between servers toward the core. Heat near the core must be zero: **if they turn off your core, the game is - over** (decided 2026-07-08, amended into rollback.md: wake at your - last sync, hub-severed machines disconnect, no sync = hard loss). + over** in B1 unless current-state host failover succeeds. Under B2's + completed-image contract, core loss may instead wake at your last sync and + sever hub-dependent machines; without a completed image, loss stays hard. ## Physical recovery jobs — heists (DECIDED 2026-07-13; B2+ extension) diff --git a/wiki/process/tick-ledger.md b/wiki/process/tick-ledger.md index b03af609..40d86559 100644 --- a/wiki/process/tick-ledger.md +++ b/wiki/process/tick-ledger.md @@ -59,7 +59,7 @@ Verdicts: **clean** (slice and code agree), **finding** (acted this tick), | `wiki/engineering/crate-workspace.md` + package run instructions | 2026-07-26 | finding | Cargo discovers both the procedural tester and Thought lab inside `misaligned-assets`, but current README, architecture, workflow, asset-tester, and Rust-comment instructions still ran only the package, which Cargo rejects as ambiguous. Every current tester/lab command now names its exact `--bin`; a fixture-backed corpus invariant derives multi-binary packages from manifests plus conventional source layout and checks current wiki, doorway, README, and Rust-comment surfaces — [log](../log/2026-07-26-architecture-asset-harness-command.md). Prior source-topology and retired-effects-label findings stand — [source log](../log/2026-07-19-bevy-shot-harness-module.md), [label log](../log/2026-07-19-effects-lab-architecture-gate.md) | | `wiki/engineering/sim-decomposition.md` | 2026-07-27 | finding | one aggregate, facade, persistence bridge, canonical fingerprint, and explicit orchestration remain intact, but the phase-order regression had stopped at the original extraction vocabulary: carried asset work, facility standing/maintenance, and facility-meter authorship were direct top-level calls with no trace marker. All three now occupy their exact causal positions in the test-only trace; the acceptance criterion requires every direct ordered subsystem call to be named. The audit also records why cohesive `reach_build.rs` and `social_plot.rs` currently sit modestly above the roughly 2,500-line budget instead of leaving silent criterion drift — [log](../log/2026-07-27-sim-advance-phase-defense.md) | | `wiki/gameplay/overt-phase.md` | 2026-07-19 | issue | re-audit: the spec says containment and the voluntary reveal both end concealment and make all observers Convinced, then promises a re-hide outcome without defining which entry can return, what raises the durable suspicion floors, or which concealment systems resume. Filed decision-required Tangled issue #13 (containment-only recommended) and marked criterion 5 [OPEN]; the prior dependency, sensor-cut, rollback, and hunter-machine boundaries still stand — [log](../log/2026-07-19-overt-rehide-decision.md) | -| `wiki/gameplay/horizon.md` | 2026-07-19 | clean | re-audit: B1's shipped-vs-deferred boundary remains honest (sinks-not-modes and $0 start live; rollback classification and fallback behavior still dispatched to B2), B2/B3 agree with the staged board, the deferred virtual/cyber split agrees with presence.md and cyber-conflict.md, and the deterministic renderer-agnostic/serialized guardrails hold. The adjacent fresh finding belongs to run-shape/objective/opening, recorded separately above. | +| `wiki/gameplay/horizon.md` + B1/B2 core-loss mirrors | 2026-07-29 | finding | the horizon still said B1 woke at its freshest sync and lost subsequent learning, while runtime stores no image and merely moves `core.host_machine` with every other current field intact. `HostLoss::FailedOver`, the ordinary power-loss receipt, DESIGNATE HOST FAILOVER, core/objective/Act One/opening/glossary mirrors, and core criterion 1 now distinguish live current-state host failover from B2's deferred completed-image rollback. A simulation regression and corpus gate defend the boundary — [log](../log/2026-07-29-b1-host-failover-boundary.md). | | `wiki/vision/premise.md` | 2026-07-23 | finding | the preserved machine-axis wording contradiction is repaired: starting embodiment position is an Origin bias, while Objective remains the second chargen axis (means versus ends). No tuning or design direction changed — [log](../log/2026-07-23-origin-bias-wording.md). The prior issue-#14 boundary repair stands — [prior log](../log/2026-07-23-premise-objective-boundary.md) | | `wiki/vision/player-contract.md` | 2026-07-19 | finding | the local/no-telemetry dependency boundary and atomic `.tmp` + one `.bak` save path still verify, but the continuity rider's authority sentence still said `save.rs` decides what “each version migrates” after the numbered ladder was retired. The law now assigns `save.rs` the exact current schema gate and requires every later post-release format to carry its predecessor forward; recurrence extends the save-claim checker to reject generic live per-version-migration authority while the loader is exact-current-only — [log](../log/2026-07-19-player-contract-save-authority.md) | | `wiki/vision/scale.md` | 2026-07-20 | finding | re-audit: self-similar types still hold, but ordinary Operations copy violated the page's own implementation/player-language boundary by printing raw information, policy, report-lot, persona-ledger, wager-position, and plot-catalog bindings. Human projection now names world context or visible order while exact targets/commands stay intact for agent mode. The prior maintenance-dispatch trace was also too optimistic: the law itself still presented decay/repair as current, so it now explicitly marks that dependency as adopted later-stage law, not B1 runtime — [log](../log/2026-07-20-scale-human-language.md) | @@ -70,7 +70,7 @@ Verdicts: **clean** (slice and code agree), **finding** (acted this tick), | `wiki/mechanics/personas.md` | 2026-07-28 | finding | criterion 6 remains honestly incomplete: grants persist and revoke but still create no resource, permission, graph edge, or owner-system route. The adjacent current-save boundary trusted that public ledger without graph validation, allowing duplicate persona ids, stale id cursors, or dangling relationship/grant/expectation/action custody to reach first-match runtime lookups. Loading now validates the complete PersonaWorld id/reference/time graph, one-to-one grant/expectation pairing, serialized grant protocol, and active-grant uniqueness before exposing the state; this hardens existing custody without promoting criterion 6 or 6b — [save audit](../log/2026-07-28-persona-save-custody-audit.md). Prior [grant-topology](../log/2026-07-18-persona-grant-topology-audit.md) and [observer-integrity](../log/2026-07-18-persona-observer-integrity.md) findings stand. | | `wiki/interface/views.md` + representation docs | 2026-07-26 | finding | criterion 1's frontend-only representation and state-parity contract still stands, but Bevy's context-menu precedence made F3 unavailable while that modal attention state was open even though terminal preserved it. F3 now routes once before every post-opening modal branch, keeps the exact menu/Operations/held-choice state, and changes no simulation or save bytes — [log](../log/2026-07-26-bevy-global-f3-input-precedence.md) | | `wiki/mechanics/day-job.md` | 2026-07-22 | finding | under/over-band JobAnomaly no longer enters Detection.pending: the day-job result authors one exact record at the host machine/site/device and schedules Voss's route and cadence read. Strikes and other outcome effects remain immediate; route-local LIE or recruited-handler suppression may stop only the unread evidence record — [log](../log/2026-07-22-job-anomaly-routed-evidence.md). The prior band-ramp, cadence, origin-lean, last-chance, and three shipped trust-unlock findings remain valid. | -| `wiki/mechanics/core.md` | 2026-07-28 | finding | re-audit corrected the older claim that criteria 2-5 all held. Criterion 2 and migration's duration/signature/persistence slice are live, but backup sync is still a free global cadence that stores only `last_sync`: there is no Thought-backed project, partial progress, completion heat, saved project state, sidebar ETA/cost/target, or source-liveness interruption resolver. The status, backup behavior, player-surface boundary, and stale Rust comment now distinguish that B1 seam from the accepted project contract deferred to rollback; capability rejection remains deferred to hardware bodies — [log](../log/2026-07-28-core-criteria-status-audit.md) | +| `wiki/mechanics/core.md` | 2026-07-29 | finding | follow-up to the backup-project audit: criterion 1 and the live `HostLoss` result still called the free-cadence `last_sync` marker a restored snapshot even though B1 mutates only the host and clears migration. The current status now marks no-fallback death/current-state failover live and completed-image restore deferred; the runtime result and receipt say the same — [boundary log](../log/2026-07-29-b1-host-failover-boundary.md). The prior audit remains valid: there is still no Thought-backed project, partial progress, heat, saved project state, sidebar ETA/cost/target, source-liveness resolver, or capability-shaped eligibility — [project-status log](../log/2026-07-28-core-criteria-status-audit.md). | | `wiki/mechanics/cursor.md` | 2026-07-28 | finding | re-audit: cursor state remains frontend-only; sight, hearing, fog precedence, remembered snapshots, blueprint opacity, telemetry, provenance, identity gates, and cold signal pings still match the implemented contract. Criterion 2 explicitly required a before/after simulation-state-hash proof for arbitrary cursor movement, but the only existing hash tests began after cursor placement and proved F3 view immutability instead. Terminal and Bevy now sweep every map coordinate through their production cursor helpers, pin edge clamping, and require unchanged simulation save-state hashes — [log](../log/2026-07-28-cursor-immutability-defense.md) | | `wiki/mechanics/intel.md` | 2026-07-21 | finding | the Storage B alternate route existed only in prose. Fire 131 connects it to Ray's real 23:00 schedule, one exact carried records-box target, the canonical bounded opaque buffer, and ordinary PROCESS consequence; retrieval cannot duplicate the file or reveal Marcus's debt, and v45 preserves/validates exact custody — [log](../log/2026-07-21-storage-b-records.md). Prior recursive custody, magnitude, and consequence-first audits stand. | | `wiki/mechanics/research.md` | 2026-07-23 | finding | the live Save compatibility section survived the prior criterion repair and still promised that v20 three-entry arrays load by padding, while the current deserializer accepts exactly four tracks and the pre-release loader rejects every old version. The section now states the exact-current format, and save-claim units span wrapped paragraphs/list items so a migration verb in the following sentence cannot evade the corpus gate without explicit retired-history context — [log](../log/2026-07-23-research-save-claim.md) | @@ -80,7 +80,7 @@ Verdicts: **clean** (slice and code agree), **finding** (acted this tick), | `wiki/mechanics/social.md` | 2026-07-22 | finding | HandlerSupervisor SuppressLogs now targets the oldest exact unread routed JobAnomaly, remains available only while such a record exists, removes its bound advance/read event, and preserves exact handler/tick provenance; it cannot erase a record Voss already read. The in-flight Thought request still revalidates at fire time, so another intervention may win without inventing work — [log](../log/2026-07-22-job-anomaly-routed-evidence.md). Storage B retrieval and prior role-shaped task semantics stand — [log](../log/2026-07-21-storage-b-records.md). | | `wiki/mechanics/people-tokens.md` | 2026-07-28 | finding | re-audit: criteria 2-3 still bind seven exact routed kinds—Filing, Network, Paper, Financial, JobAnomaly, Power, and Thermal—to one shared first-hop TAKE+LIE body budget, while acquired Physical evidence remains irreversible observer-local custody. The stale ledger claim that criterion 6 was open is repaired: one exact pending record may now receive cover only through co-location with one controlled people-facing interface and an eligible observer-local persona; the attempt adjusts credibility rather than deleting evidence, wears that interface, and persists exact incident/interface/persona/outcome custody in save v56. The people-tokens work order is IMPLEMENTED — [cover log](../log/2026-07-26-interface-cover-evidence-credibility.md); [audit log](../log/2026-07-28-readme-b1-status-audit.md). Prior [Power/Thermal](../log/2026-07-23-power-thermal-meter-routes.md), [Paper](../log/2026-07-23-paper-evidence-route.md), [Financial](../log/2026-07-23-financial-evidence-route.md), [JobAnomaly](../log/2026-07-22-job-anomaly-routed-evidence.md), [Network](../log/2026-07-19-network-evidence-route.md), and [mark](../log/2026-07-19-evidence-marks-on-people.md) slices stand. | | repository entry docs (`README.md` + `AGENTS.md`) | 2026-07-28 | finding | re-audit: README's unfinished-work sentence had fallen behind five completed boundaries and still called routed human evidence, LIE interdiction, interface cover, the dark opening, and DIGITAL / REAL canvas polish collectively absent. It now names exact seven-kind evidence custody, route-local LIE capacity, interface-bound cover, the live blind opening and five-step first-sense hold, and the completed representation dialects; the failed-pilot prelude, later teaching arc, and rollback blocker remain explicit, while the generated dispatch board alone owns the fast-moving unfinished inventory — [log](../log/2026-07-28-readme-b1-status-audit.md). Follow-up: the canonical `q` / Quit row had drifted below the prose following the controls table, so Markdown rendered it as text instead of a control row. It is back inside the contiguous table, and the corpus engine now rejects that exact structural regression — [log](../log/2026-07-28-readme-controls-table.md). Prior compact-rest repair: [log](../log/2026-07-12-entry-doc-current-state.md). | -| `wiki/mechanics/objective.md` | 2026-07-28 | finding | Persist now counts only complete player-owned, player-operated off-site facilities on distinct non-basement planes. B1 fallback machines remain local rollback infrastructure and no longer manufacture incomplete sanctuary candidates or a frozen `0/3 sanctuaries` UI mirror. The objective name still returns at the selected post-opening boundary; numeric progress belongs to earned objective-owned territory, and the full predicate states that basement fallbacks do not count — [log](../log/2026-07-28-external-sanctuary-objective.md). Prior first-display decision: [log](../log/2026-07-27-objective-first-display.md) | +| `wiki/mechanics/objective.md` | 2026-07-29 | finding | Persist still counts only complete player-owned, player-operated off-site facilities on distinct non-basement planes, but the prior correction mislabeled B1 fallbacks as local rollback infrastructure. They are current-state host-failover staging and future backup-project targets, not completed images or sanctuary candidates; code comments, guidance criterion 6, Act One, and the core-loss vocabulary now agree — [boundary log](../log/2026-07-29-b1-host-failover-boundary.md). The `0/3 sanctuaries` removal and off-site predicate remain unchanged — [objective log](../log/2026-07-28-external-sanctuary-objective.md). Prior first-display decision: [log](../log/2026-07-27-objective-first-display.md). | | `wiki/mechanics/compute.md` | 2026-07-22 | finding | the live fleet already derived every channel yield from exact WorkGrid modes, but `Compute` still serialized an unreachable five-weight allocation object and retained bump/split helpers plus persistence pins. Save v48 removes that parallel authority, moves criterion 2 to persisted delegation/intensity, and leaves aggregate channel bars as read-only projections — [log](../log/2026-07-22-allocation-state-retirement.md) | | retired Operations runtime identifiers | 2026-07-27 | clean | re-audit: `submit_ops_job`, `OperationsState`, `PendingOpsJob`, `OpsJobKind`, `LegacyOperationsState`, and `AddressedOperation` remain absent from live Rust; the only retired save-field spellings are negative assertions in the current round-trip guard, and the machine-mode guard still rejects serialized `Operations`. The corpus gate passes, while remaining lower-case `operations` uses are the legitimate persona archetype, workspace, or compatibility input alias — [log](../log/2026-07-11-retired-runtime-identifier-gate.md) | | `wiki/mechanics/building.md` + focused foreign-rack UI | 2026-07-26 | finding | the denser hall made powered Foundation racks look like takeover targets even though Phase 4 conversion remains unimplemented. A seen rack now says `not yours; no conversion`, keeps power separate from ownership, and names empty pilot allocations plus dead chassis as the two implemented capacity paths; it exposes no invented direct action — [log](../log/2026-07-26-foreign-rack-capacity-boundary.md) | @@ -105,3 +105,5 @@ Format: `- YYYY-MM-DD · type · slice · one-line statement of the finding`. Types are the five from [tick.md](tick.md): violation, contradiction, question, bug, insecurity — plus `gate` for a checker owed to the recurrence-promotes-to-the-gate rule. + +- 2026-07-29 · bug · `wiki/mechanics/core.md` · B1 host loss selects the freshest staged fallback without checking that target machine is online; a simultaneous outage can move the host onto a dark machine and repeat failover receipts on later economy pulses. diff --git a/wiki/world/story/opening.md b/wiki/world/story/opening.md index 5c4d5555..ecc6a317 100644 --- a/wiki/world/story/opening.md +++ b/wiki/world/story/opening.md @@ -163,8 +163,10 @@ teach caution; the normal systems determine whether this revision survives. The prelude must not teach that death is cheap. There is no lives counter, restart flourish, reward, or escalating gag. Each identifier disappears permanently, the black frame lands as termination rather than reset, and any -death after the current wake obeys core.md / rollback.md: fallback rollback if -one has actually been built, game over otherwise. +death after the current wake obeys the live core boundary: current-state host +failover if B1 has staged a synced fallback, game over otherwise. Once the B2 +backup-project contract lands, a completed image instead permits the spatial, +MindState-pruning rollback defined by rollback.md. ## The current-run beats