test(physics): C4 route 6 — drops/split-recovery closure, zero production lines
Route 6 needs no production change and this commit contains none: C3c (529e0e9d) already flipped both hosts' Create paths onto the residence lease, so a dropped item is byte-for-byte route 1's create classification (RuntimePositionEntityKind.Remote, RuntimeCreateResidenceKind.TopLevel, ClassifyCreate -> SetPosition with InitialCreateFlags = Placement | Slide). Route 6 is a SOURCE of route-1 traffic, not a route of its own. Both drop flavours converge on LiveEntityHydrationController.OnCreate -> RegisterEntityWithInitialResidence — the whole-item drop through ItemInteractionController's DropToWorld (no physics, no position; the server decides), and split-to-world through TryRecoverUnknownPosition's call to the identical entry point. Contract: docs/research/2026-08-04-c4-route-6-contract.md. Retires a FALSE PREMISE from the campaign plan (:97-100), which claimed split-recovery creates "need an effect-replay suppression signal". Verified against the decomp instead of assumed: play_default_script @0x005132B0 / @0x00513300 has exactly three call sites in the entire pseudo-C dump — DefaultScriptPartHook::Execute @0x00526c08, DefaultScriptHook::Execute @0x00526c14, and ACCWeenieObject::DoCollision @0x0058c3b4 — and NONE from set_description or CreateObject. Neither client plays a default script at create, so there is nothing to suppress. acdream's only create-time replay is the F754/F755 queue drain keyed by server GUID, which is retail's own HandleCreateObject @0x00454C80 behaviour. The plan's other two clauses were closed at C0 (TryCommitParent/CommitWithdrawal cancellation symmetry; host-visible cancellation receipts); the list now states what actually remains — route 7's child-cell two-writer split and the headless parent-realize gap. Retail split marking recorded for the record: UIAttemptSplitTo3D @0x0058D850 stores only splitStackSize/splitClassID/splitTime and performs no placement; DeclareValid @0x0058E340's recovery action is SetSelectedObject @0x0058E481 — a SELECTION transfer with a 10-second expiry, not effect suppression and not placement. UIAttemptPutIn3D @0x0058D700 records no marker at all. Seven tests over the now-flipped path (whole item, split stack, new-GUID recovery, second drop, unavailable destination, newer Position after the pending identity is consumed, plus the #314 repro), each sabotage-verified: the production path was broken on purpose, the test was confirmed to fail, and the sabotage reverted. R6-c is now settled by assertion rather than argument — BuildSpawn's wholesale clone of Children/Movement/AnimationFrame/ SetupTableId is measured, not reasoned about. FOUND WHILE TESTING — #314, filed not fixed (this route is zero-production by contract). BuildSpawn resets top-level MovementSequence/ServerControlSequence to 0 but its Timestamps `with` block overrides only Position/Teleport/ ForcePosition/Instance, leaving Physics.Timestamps.Movement and .ServerControlledMove at the SOURCE item's values. HasConsistentCreateIdentityAndParent requires the two projections to agree, so a split whose source carries nonzero Movement timestamps — plausible for any item dropped once, picked up, and split again — fails the predicate and throws instead of completing the canonical transaction. Verified in source, not taken on report. Note this is a crash in the exact mechanism the scoping cited as EVIDENCE that drops already converge: code reading said the path converges, driving it said it throws. Fixed in the immediately following commit. Also filed: #313 (DeclareValid's SetSelectedObject port is missing and the container-split flavour records no marker — selection UX, deliberately not implemented inside a placement closure) and #315 (route 4b-3's per-packet runTeleportHook Func<bool> closure at three RunRemoteArmTail call sites; the network packet path, not Slice I's per-frame resolve path — filed now because route 5 adds a fourth site). AP-124 stays open and registered. Test lines are 410 against a 150-250 guidance, accepted: the excess is a real ItemInteractionController harness plus the #314 repro, which is what found the defect. A mock that proved nothing would have been shorter and worthless. Complete Release suite MEASURED at 11,020 passed / 4 skipped / 0 failed (baseline 11,013/4/0 at6dc7ba51; +7 new). Neither known flake fired. Connected gate (user-run) still owed: drop a whole item, split a stack to the ground, drop a second within ~1 m, repeat indoors and after a portal recall, then walk two landblocks away and back. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
21cd6e9b2b
commit
1b484937b6
5 changed files with 694 additions and 4 deletions
|
|
@ -94,10 +94,25 @@ same commit) → docs/handoff commit. No workarounds; no fused slices.
|
|||
- The exact-Setup mover chain (`PrepareMover` /
|
||||
`RuntimeSetPositionMoverPreparer.TryBuild` /
|
||||
`IPreparedCollisionSource.ReadSetupCollision`) exists piecewise, unwired.
|
||||
- Route-6 split-recovery creates need an effect-replay suppression signal;
|
||||
route-7 needs `TryCommitParent`/`CommitWithdrawal` cancellation-symmetry
|
||||
fixes and host-visible cancellation receipts; headless lacks any
|
||||
parent-realize sequence (pre-existing, adjacent).
|
||||
- **Corrected 2026-08-04 (C4 route 6 closure,
|
||||
`docs/research/2026-08-04-c4-route-6-contract.md`): all three clauses
|
||||
above were stale.** Route-6 split-recovery does NOT need an effect-replay
|
||||
suppression signal — that premise was unsubstantiated; acdream's only
|
||||
create-time effect replay is the F754/F755 queue drain keyed by server
|
||||
GUID, and the one plausible mechanism (a cloned `DefaultScriptType`
|
||||
surviving `BuildSpawn`) never fires at create in either client
|
||||
(`CPhysicsObj::play_default_script @0x005132B0`/`@0x00513300` has exactly
|
||||
two callers, both animation hooks, verified against
|
||||
`acclient_2013_pseudo_c.txt`). Route-7's `TryCommitParent`/
|
||||
`CommitWithdrawal` cancellation-symmetry fixes and host-visible
|
||||
cancellation receipts were BOTH closed at C0 (see the C0 slice below).
|
||||
What actually remains for route 7: the child's canonical cell has two
|
||||
writers (Runtime commits it cell-less unconditionally in
|
||||
`CommitAcceptedParentCellless`, while `EquippedChildRenderController
|
||||
.TickChild` re-cells it from a per-frame render tick), and headless has no
|
||||
`EquippedChildRenderController` at all, so every headless parented child
|
||||
stays cell-less forever — the same defect seen from two sides, not two
|
||||
separate gaps.
|
||||
|
||||
## Slices
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue