fix(streaming): block login on complete world reveal

Make initial login and portal arrival consume one WorldRevealReadinessBarrier that joins near-tier mesh publication, destination composite uploads, and collision residency before normal world geometry becomes visible. This ports retail SmartBox's blocking-cell completion edge into the asynchronous client instead of exposing a ground-only login.

Add focused outdoor, indoor, texture, and invalid-claim tests; update the retail pseudocode, architecture, divergence record, issue ledger, roadmap baseline, and synchronized agent guidance.

Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-20 16:08:03 +02:00
parent 6c3bd4ce4b
commit b60cb67009
14 changed files with 360 additions and 102 deletions

View file

@ -24,9 +24,9 @@ public sealed class AutoEnterPlayerModeTests
public bool LiveInWorld;
public bool PlayerEntityPresent;
public bool PlayerControllerReady;
// Defaults TRUE: the hydration hold is not under test in the
// original K.2 cases (see SpawnGroundNotReady test for it).
public bool SpawnGroundReady = true;
// Defaults TRUE: the world-reveal hold is not under test in the
// original K.2 cases (see WorldNotReady test for it).
public bool WorldReady = true;
public int EnteredCount;
public PlayerModeAutoEntry Build() =>
@ -34,23 +34,20 @@ public sealed class AutoEnterPlayerModeTests
isLiveInWorld: () => LiveInWorld,
isPlayerEntityPresent: () => PlayerEntityPresent,
isPlayerControllerReady: () => PlayerControllerReady,
isSpawnGroundReady: () => SpawnGroundReady,
isWorldReady: () => WorldReady,
enterPlayerMode: () => EnteredCount++);
}
[Fact]
public void TryEnter_Armed_SpawnGroundNotReady_DoesNotFire()
public void TryEnter_Armed_WorldNotReady_DoesNotFire()
{
// #106 gate-2 (2026-06-09): player physics must not start before
// the terrain under the spawn position has streamed in — entering
// earlier free-falls the player into the void (gravity integrates
// against an empty world; retail never has this state because it
// loads cells synchronously). The guard holds until the streaming
// pipeline registers the spawn landblock.
// #229 extends #106's ground-only hold to retail's complete blocking
// cell-load edge. Player mode must not expose the viewport until the
// render, composite-texture, and collision domains have all converged.
var s = new State
{
LiveInWorld = true, PlayerEntityPresent = true,
PlayerControllerReady = true, SpawnGroundReady = false,
PlayerControllerReady = true, WorldReady = false,
};
var guard = s.Build();
guard.Arm();
@ -59,8 +56,8 @@ public sealed class AutoEnterPlayerModeTests
Assert.Equal(0, s.EnteredCount);
Assert.True(guard.IsArmed);
// Terrain hydrates → fires on the next tick.
s.SpawnGroundReady = true;
// Render, texture, and collision domains converge → next tick fires.
s.WorldReady = true;
Assert.True(guard.TryEnter());
Assert.Equal(1, s.EnteredCount);
}