wip(physics): collision O(changed) delta-commit (O1-O3) - ON HOLD, feel-test failed
Publication-throughput rework per the D2 design (docs/research/ 2026-08-02-collision-throughput-handoff/design-note.md): O1 per-prefix installed-key ledgers replacing the seal's full-map scans; O2 per- landblock delta commit (LandblockReplacementApplyCursor against the active root) replacing whole-world TransferTo; O3 empty staging root, commit-time reflood (CObjCell::init_objects 0x0052B420 -> recalc_cross_cells 0x00515A30), journal/peer-rebase machinery deleted (~1,900 lines net). Automated gates green: Runtime 999, Core physics 2,135, App 4,039/3, Headless 79, complete solution 10,812/0/4; lifecycle gate PASS (connected-world-gate-20260802-193029). Soak 194423: publication-side acceptance fully met (37 -> 4 failures, all convergence dims zero, loadedLandblocks baseline-identical, waitCue 6/9 -> 1/9). COMMITTED AS WIP ON USER DIRECTION - NOT ACCEPTED. The user feel-test FAILED on this tree: monsters still pop into existence at close range, monsters spawned mid-air far ahead, static placements visibly wrong, plus 243x "Landblock already has a full retirement receipt" InvalidOperationException catch-retry loop during origin recenter (launch-feeltest-oclone.log). The 4 remaining soak failures (pendingLandblockRetirements 131/122 at the Caul->Sawato stops) and the implementer's "exposed pre-existing" classification are under re-judgment against that loop. Dual reviews were dispatched and then stopped mid-flight on user direction; NO review has passed this commit. Full problem inventory + next-agent instructions: docs/research/2026-08-02-collision-throughput-handoff/. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
c52ce14a07
commit
71604331cf
13 changed files with 6410 additions and 1894 deletions
|
|
@ -1983,6 +1983,78 @@ public sealed class ShadowObjectRegistry
|
|||
|
||||
internal uint GetOwnerSlot(int index) => _ownerSlots[index];
|
||||
|
||||
/// <summary>
|
||||
/// O3 (2026-08-02): commit-time owner application for one landblock
|
||||
/// delta, replacing the deleted staged whole-world reflood context.
|
||||
/// Retail hydrates a cell and refloods the objects associated with it —
|
||||
/// <c>CObjCell::init_objects</c> (0x0052B420) →
|
||||
/// <c>CPhysicsObj::recalc_cross_cells</c> (0x00515A30); the per-landblock
|
||||
/// streaming analogue is: adopt each staged owner's registration/shape
|
||||
/// payload and recalculate its cross-cells against the live post-delta
|
||||
/// world, retire the outgoing generation's authored statics that were not
|
||||
/// re-authored, and re-run the flood for every retained live owner
|
||||
/// touching the replaced landblock.
|
||||
/// </summary>
|
||||
internal void ApplyCommittedOwnerReplacement(
|
||||
ShadowObjectRegistry stagingSource,
|
||||
uint ownerId,
|
||||
uint landblockId)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(stagingSource);
|
||||
if (stagingSource.HasLogicalOwner(ownerId))
|
||||
{
|
||||
// Staged owner (authored target static, or an owner registered
|
||||
// directly into the generation): adopt its payload, then
|
||||
// recalc_cross_cells against the live world — the staged flood
|
||||
// only saw the target-only staging root, so a seam footprint
|
||||
// completes here.
|
||||
MirrorOwnerFrom(stagingSource, ownerId);
|
||||
RefloodOwnerForLandblock(ownerId, landblockId);
|
||||
return;
|
||||
}
|
||||
if (IsStaticOwnerRootedIn(ownerId, landblockId))
|
||||
{
|
||||
// Outgoing generation's authored static, not re-authored by the
|
||||
// replacement: it ends with its landblock (same lifetime rule as
|
||||
// RetireOwnerFromLandblock's static branch).
|
||||
DeregisterCore(ownerId, publishMutation: false);
|
||||
RemoveOwnerPrefixMembership(ownerId);
|
||||
_ownerVersions.Remove(ownerId);
|
||||
AdvanceMutationRevision();
|
||||
return;
|
||||
}
|
||||
// Retained live owner touching the replaced landblock: recalculate its
|
||||
// cross-cells against the new topology. Suspended or since-removed
|
||||
// owners no-op inside the reflood.
|
||||
RefloodOwnerForLandblock(ownerId, landblockId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// O3 (2026-08-02): retail <c>CObjCell::init_objects</c> refloods every
|
||||
/// object associated with the hydrated cell at hydration time. Owners
|
||||
/// that became associated with the replaced landblock after the sealed
|
||||
/// capture (a mover entering the prefix mid-publication) are present in
|
||||
/// the live prefix-owner slots but absent from the sealed owner list;
|
||||
/// recalculate their cross-cells against the just-installed topology.
|
||||
/// </summary>
|
||||
internal void RefloodPrefixOwnersAfterReplacement(
|
||||
uint landblockId,
|
||||
IReadOnlyList<uint> sealedOwnerIds)
|
||||
{
|
||||
uint prefix = landblockId & 0xFFFF0000u;
|
||||
if (!_prefixOwnerSlots.TryGetValue(prefix, out List<uint>? slots))
|
||||
return;
|
||||
var applied = new HashSet<uint>(sealedOwnerIds);
|
||||
int limit = slots.Count;
|
||||
for (int index = 0; index < limit; index++)
|
||||
{
|
||||
uint ownerId = slots[index];
|
||||
if (ownerId == 0u || !applied.Add(ownerId))
|
||||
continue;
|
||||
RefloodOwnerForLandblock(ownerId, landblockId);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes one staging owner from the exact active payload, then floods
|
||||
/// it against the staging generation's complete cell graph. The returned
|
||||
|
|
@ -2321,14 +2393,16 @@ public sealed class ShadowObjectRegistry
|
|||
if (_stagingSlotIndex < _stagingSlotLimit)
|
||||
{
|
||||
uint ownerId = _stagingSlots![_stagingSlotIndex++];
|
||||
if (_staging._entityReg.TryGetValue(
|
||||
ownerId,
|
||||
out RegistrationRecord? registration)
|
||||
&& registration.IsStatic
|
||||
&& (registration.SeedCellId & 0xFFFF0000u) == _prefix)
|
||||
{
|
||||
// O2 (2026-08-02): every staged logical owner in the
|
||||
// target's prefix slots — authored statics AND owners
|
||||
// registered directly into the staging generation —
|
||||
// must reach the active world through the delta
|
||||
// commit's owner installs; the old whole-root transfer
|
||||
// carried them implicitly. Mirrored owners identical
|
||||
// to their active state reinstall in place, so the
|
||||
// wider filter stays exact and prefix-scoped.
|
||||
if (_staging._entityReg.ContainsKey(ownerId))
|
||||
AddOwner(ownerId);
|
||||
}
|
||||
WorkUnits++;
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue