feat(simulation): Sprint 19 — 7 server systems

Protocol handshake (#555): HandshakeMessage as first IPC frame,
HandshakeState resource, forward-compatible input handling.

State serialization (#96): serialize_npc_to_frozen/deserialize with
full D-024 axis coverage (10 new optional fields on NpcSaveState).

Scope tags (#98): ScopeTagKind enum, ScopePinned marker, automatic
assignment from KnowledgeGraph and RelationshipGraph.

Timestamp eviction (#97): LastInteractionTick, SimSpacePressure,
BinaryHeap LRU eviction respecting ScopePinned entities.

Save/load (#553): save_to_file/load_from_file via MessagePack,
SaveGame/LoadGame IPC commands, SaveLoadResultWire on snapshot.

Test infrastructure (#200): Layer 3 integration test entry point,
three-layer architecture documented per D-030.

Information boundary tests (#272): 4 negative tests proving no
passive KG leakage, LOS fog holds, tier boundary holds, save
isolation per NPC.

1063 tests passing, 0 failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-25 12:13:03 +01:00
co-authored by Claude Opus 4.6
parent 0dd33690f7
commit 6ed8d11502
22 changed files with 2561 additions and 35 deletions
+13 -2
View File
@@ -11,7 +11,7 @@ use bevy_app::prelude::*;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
use settled_reach_server::bridge::tcp::TcpBridge;
use settled_reach_server::bridge::{BridgePlugin, BridgeResource, ServerRunning};
use settled_reach_server::bridge::{BridgePlugin, BridgeResource, HandshakeState, ServerRunning};
use settled_reach_server::simulation::SimulationPlugin;
fn main() {
@@ -121,7 +121,17 @@ fn main() {
tracing::error!("Failed to accept: {}", e);
std::process::exit(1);
});
tracing::info!("Client connected, initializing simulation");
tracing::info!("Client connected, sending protocol handshake");
// Protocol handshake: first framed message on the wire (#555).
// Client reads this and validates protocol_version before sending any input.
use settled_reach_server::bridge::SimBridge;
bridge.send_handshake().unwrap_or_else(|e| {
tracing::error!("Failed to send handshake: {}", e);
std::process::exit(1);
});
tracing::info!("Handshake sent, initializing simulation");
// RNG seed: test-mode defaults to 42 for deterministic replay
let seed = seed_flag.unwrap_or(if test_mode { 42 } else { 0 });
@@ -138,6 +148,7 @@ fn main() {
});
app.add_plugins(settled_reach_server::content::ContentPlugin);
app.insert_resource(BridgeResource::new(bridge));
app.insert_resource(HandshakeState::Complete);
// Override SimRng with the chosen seed (SimulationPlugin defaults to seed 0)
app.insert_resource(settled_reach_server::simulation::rng::SimRng::new(seed));