Flips the SetPositionSimple classification (contact, PlayerDistance >= 96 m) for remotes onto 4b-1's drive controller and deletes both legacy far blocks, both duplicated 96f/4f constant pairs, and both `?? Vector3.Zero` fabrications. The 4 m constant now exists exactly once. Teleport and cell-less stay legacy for 4b-3. Retail: MoveOrTeleport @0x00516330's far branch runs StopInterpolating @0x005163CB before SetPositionSimple @0x005163D9 and returns 1 @0x005163E8 regardless — the SetPositionError is discarded — so HandleReceivedPosition arms ConstrainTo @0x00454272 post-move on commit AND on failure. The x87 parity decode at @0x00516393-@0x0051639E puts exactly 96.0 on the far branch. SetPositionSimple @0x005162B0 builds flags 0x1012 at @0x005162C4. Non-commit outcomes still advance the body, because retail's SetPositionInternal @0x00515BD0 commits the destination via store_position @0x00515CE2 when no cell resolves. The partition is by STAGE, not heuristic, enforced by an exhaustive switch: Refused/Contention/NotApplicable/RejectedPreparation store (the placement never executed); Committed/Deferred/RejectedByPlacement do not (the engine ran and refused, matching retail's non-storing returns @0x00515CB2 and @0x00515CD5). Without this a refused far snap froze the remote with an emptied queue. Also fixes a shipped defect this route made live: ParkDeferred's quiescence parks withdrew the entity (InWorld=false, clock suspended, residency removed) and were never restorable, while Forget(restoreCancelledPark: true) runs for every accepted Position on every entity. The restorable decision now lives inside ParkDeferred AFTER SnapToCell, reading body.CellPosition.ObjCellId — the value RestoreParkWithdrawal actually restores at — against every live quiescence rather than one minimum-OperationId token. The three pre-snap fields are hoisted into locals because SnapToCell ends with InWorld = true. ParkCollisionResidents passes restorableOnCancel: false explicitly; the plain unplaceable park is provably unchanged. RestoreParkWithdrawal re-tests the prefix at restore time so a retained route-2 park cannot re-admit into a prefix that began quiescing during the park. CanAttemptDestination is retained as an OPTIMISATION only, with the two Core predicates it cannot reproduce written down at the pre-flight, plus the two properties that depend on it staying there. Four fix rounds and eight Opus reviews. The slice was fully green at 10,990, 10,997 and 11,004 while containing real defects — a frozen remote pinned as correct by its own test, a fallback that over-wrote on the exact retail paths that decline to store, and a park guard incomplete on two independent axes. Register: AP-137 (leftover classifications take AP-87's catch-up; states the cell-less enqueue-vs-place delta deferred to 4b-3, that RejectedData is applied anyway, and the headless divergence), AP-138 (the refusable far placement), AP-136 narrowed to match the relocation. #309's acceptance steps rewritten — step 5 previously asserted a recovery the code does not perform — and gated on a new ACDREAM_PROBE_PARK=1 signal so the check cannot pass while broken. Suite 11,009 passed / 4 skipped / 0 failed against a measured 10,968 baseline. The 10,973 figure recorded earlier was wrong and is corrected here. Connected gate outstanding: the two-client far-snap walk and #309. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
211 lines
12 KiB
Markdown
211 lines
12 KiB
Markdown
# C4 route 4b-2 — round 3 correction (2026-08-04)
|
|
|
|
Both round-2 reviews returned **FAIL**. The findings are now small and local;
|
|
this is a closing-out round, not a structural change.
|
|
|
|
**Do NOT revert the shared-core park change.** Both reviewers verified it removes
|
|
a session-permanent strand from routes 1 and 2:
|
|
`RuntimeEntityObjectLifetime.cs:1767-1769` calls
|
|
`Forget(canonical, restoreCancelledPark: true)` on **every** accepted Position for
|
|
**every** entity, so before this round a local-player ForcePosition or a
|
|
first-entry placement that hit either quiescence park was left `InWorld = false`,
|
|
clock suspended, `FullCellId = 0`, with its operation destroyed by the next
|
|
packet. The change is directionally right and fixes shipped behaviour.
|
|
|
|
## A1 — one relocation closes both shared-core MAJORs
|
|
|
|
`IsRestorableQuiescencePark` (`RuntimeSetPositionState.cs:3877-3880`) has two
|
|
independent defects, and moving the decision fixes both:
|
|
|
|
1. **It compares against one quiescence, not the set.** It tests
|
|
`quiescence.Token.LandblockPrefix` — the token `TryGetBlockingQuiescence`
|
|
returned — but both overloads (`:3906-3925`, `:3927-3949`) return the
|
|
**minimum-`OperationId`** match, not the only one. `_collisionPrefixQuiescence`
|
|
is a per-prefix dictionary (`:589`, `:885`) and streaming opens one per
|
|
landblock mutation (activation `RuntimePhysicsState.cs:1820-1824`, retirement
|
|
`:2025-2030`), so a recenter has several live. Source `S` quiescing before
|
|
destination `D`: the predicate tests `D != S`, returns true, and the restore
|
|
re-admits the spatial root into `D`, which *is* quiescing — the AP-136 pin. At
|
|
5-10 Hz the park→cancel→restore→re-park cycle can starve `D`'s mutation
|
|
permission for as long as `S` stays quiescing (`:927`).
|
|
2. **Its input is not the value the restore uses.** It is fed `deferred.CellId` /
|
|
`held.CellId` (`:2982`, `:3036`), but `RestoreParkWithdrawal` reads
|
|
`body.CellPosition.ObjCellId` (`:3481`), set by `ParkDeferred`'s
|
|
`body.SnapToCell` (`:4346-4349`) → `PhysicsBody.StageDormantCellFrame`
|
|
(`PhysicsBody.cs:212-223`), which for any outdoor cell runs
|
|
`LandDefs.AdjustToOutside`. That function's own doc (`LandDefs.cs:115-122`)
|
|
says the resulting cell id **may belong to a neighbour landblock**.
|
|
Reachability NOT VERIFIED, and the relocation removes the question.
|
|
|
|
**Fix: move the restorable decision inside `ParkDeferred`, after `SnapToCell`,
|
|
and express it as `!IsCollisionPrefixQuiescing(body.CellPosition.ObjCellId)`.**
|
|
That method (`:827-829`) already exists, is `internal`, masks its own argument,
|
|
and is the pre-flight's own predicate; it subsumes the current test exactly.
|
|
Make it non-static as needed; the `CollisionPrefixQuiescence` parameter then goes
|
|
away.
|
|
|
|
**Blast radius note that must not be lost:** the remote far-snap arm is *masked*
|
|
from defect 1 by `CanAttemptDestination`'s destination pre-flight
|
|
(`RuntimeRemotePlacementDriveController.cs:599`, `:1155`). The exposed callers are
|
|
**routes 1 and 2**, which have no such pre-flight
|
|
(`RuntimeAcceptedPositionDriveController.TryExecuteAcceptedLocalPosition:330-392`
|
|
goes straight from `ClassifyForcePosition` to `TryBeginExclusiveAuthoredPlacement`).
|
|
All three new quiescence tests drive the remote arm and explicitly assert the
|
|
**safe** configuration (`:1193`, `:1268`), so none of them can see it.
|
|
|
|
## A2 — two tests the round is missing
|
|
|
|
- **Concurrent quiescences**, source `OperationId` < destination `OperationId`,
|
|
far snap `S → D`: assert the record is not re-admitted as a spatial root in `D`,
|
|
or that `D`'s mutation permission still converges.
|
|
- **A route-2 local-player ForcePosition** parking at `:2948` under a quiescing
|
|
source: assert `body.InWorld && record.ObjectClock.IsActive &&
|
|
record.FullCellId != 0` after the next packet's merge-time `Forget`.
|
|
|
|
## A3 — say "blocking prefix", or make it true
|
|
|
|
`IsRestorableQuiescencePark`'s doc (`:3866-3868`) and AP-136's narrowed row both
|
|
claim "the rollback re-admits nothing into the retiring prefix." It re-admits
|
|
nothing into **the blocking** prefix, which is a different statement. A1's fix
|
|
makes the stronger claim true; if any wording survives it, scope it.
|
|
|
|
## A4 — #309's acceptance steps are now stale
|
|
|
|
AP-136 says this needs the two-client connected check in #309, but
|
|
`docs/ISSUES.md` is **unmodified in this diff**. #309's steps (`docs/ISSUES.md:82-95`)
|
|
describe only "a landblock the observer has not streamed" — the plain
|
|
unplaceable park. They do not exercise a quiescing **source** or a quiescing
|
|
**swept neighbour**, which are exactly the shapes this round newly makes
|
|
restorable, and step 4 asks only that route 2's corrections "still land
|
|
unchanged" without naming the local-player-parks-into-a-quiescing-landblock case
|
|
that is now behaviourally different. **Deferring the run is fine; leaving its
|
|
scope stale is not.** Update the steps in this commit. Also AP-136's Risk column
|
|
still says "a remote" — the local player now traverses the same restore.
|
|
|
|
## A5 — record the dependency at `CanAttemptDestination`
|
|
|
|
N3's "a retained retry can no longer strand" property and MAJOR 1's masking
|
|
**both** depend on the pre-flight staying in place. The class doc calls it "an
|
|
optimisation" with no mention of either. If it is ever deleted as redundant, both
|
|
re-open silently. Write that down at the pre-flight.
|
|
|
|
(The round's stated reason for declining N3's `CurrentCellId` re-check — that it
|
|
would "re-derive a private Core predicate outside Core" — is false;
|
|
`CanAttemptDestination` already calls Core's own `internal`
|
|
`IsCollisionPrefixQuiescing`. The conclusion still holds, for the reason above.
|
|
Correct the reason.)
|
|
|
|
## B1 — a 36-line doc block was detached from its method
|
|
|
|
`RuntimeRemotePlacementDriveController.cs:1009-1085`. `CountLivePending()` was
|
|
inserted **between** `CountLiveAwaitingAcknowledgement`'s existing doc and its
|
|
method. Now `:1009-1044` (which describes pruning `_awaitingAcknowledgement`, the
|
|
**second** ownership registration, and `_awaitingAcknowledgementScratch`)
|
|
documents `CountLivePending()` at `:1066` — which prunes `_pending`, backs the
|
|
**first** registration, and uses `_pendingScratch`. Every specific is wrong for
|
|
the member it now sits on. `:1045-1065` is a second `<summary>` on the same
|
|
member, and `CountLiveAwaitingAcknowledgement()` at `:1085` has **no** doc.
|
|
|
|
## B2 — the stage rule is true by coincidence and stated as a falsehood
|
|
|
|
`:172-188` and `:993-1005` assert that `RejectedByPlacement`'s producers are
|
|
"returned AFTER `_physics.Engine.SetPosition` ran". `RuntimeSetPositionStatus.Rejected`
|
|
has **three** producers and only one is post-engine:
|
|
|
|
| site | what | stage |
|
|
|---|---|---|
|
|
| `:2854` | entry validation (`!ownsToken`, stage mismatch, null body, stale `IsPreparationAuthorityCurrent`, velocity-version mismatch) | **pre-engine** |
|
|
| `:2945` | `!IsStructurallyValid(canonicalRequest)` | **pre-engine** |
|
|
| `:3044` | `!result.IsSuccessful` after the engine ran at `:2997` | post-engine |
|
|
|
|
Both pre-engine sites reach `SubmitAndResolve`'s `default:` and are filed
|
|
`RejectedByPlacement` → **no store** — contradicting the round's own rule
|
|
(`RejectedPreparation`'s doc `:128-142`) that a producer which never reached the
|
|
engine stores.
|
|
|
|
The reviewer traced both **unreachable today**, but only by duplicated guards:
|
|
`PrepareMover` (`:1563-1577`) re-checks everything `:2830-2855` re-checks with
|
|
nothing reentrant between; `IsPreparationAuthorityCurrent` (`:5290-5306`) catches
|
|
all seven version dimensions one stage earlier as `RejectedAuthority` →
|
|
`RejectedPreparation`; the `AwaitingCell` divergence needs `DormantLocalActivation`,
|
|
which `:1380` forbids for a record with a body; and `:2945` is shadowed by
|
|
`PrepareMover:1636`'s identical check.
|
|
|
|
**Either state in the `default:` comment that `:3044` is the only reachable
|
|
producer and why, or thread the stage out of Core so the split is enforced.** As
|
|
written the comment says something false about Core — the same shape as round 1's
|
|
MAJOR A, which was also a false clause in that same comment.
|
|
|
|
## B3 — the deleted phrase came back
|
|
|
|
`RuntimeRemotePlacementDriveControllerTests.cs:1191`, an **added** line:
|
|
`// The complete pre-flight passes: it reads only the destination.`
|
|
`CanAttemptDestination`'s doc in the same diff (`:1111-1113`) says it is
|
|
"correcting this comment's earlier 'the complete pre-flight' framing", and the
|
|
whole of MAJOR B is that no pre-flight can be complete. The sentence also
|
|
contradicts itself in eight words.
|
|
|
|
## Minor
|
|
|
|
- **m1** — `TryAdoptWireCellAfterRouting`'s new scope paragraph
|
|
(`LiveEntityNetworkUpdateController.cs:1128-1143`) enumerates commit and
|
|
`RejectedByPlacement` and "every outcome that resolved NO cell". `Deferred` is
|
|
in neither: `ParkDeferred:4345-4349` snaps to the parked result cell,
|
|
`WithdrawCanonical` zeroes `FullCellId`, and `RestoreParkWithdrawal:3485-3491`
|
|
re-commits from `body.CellPosition.ObjCellId` — the **swept** cell for the
|
|
post-sweep park, not necessarily the wire cell. Behaviour is unaffected (the
|
|
suppression keys on the arm); the claim is not.
|
|
- **m2** — `Contention`'s doc (`:118-127`) names two producers; there are at
|
|
least four. `TryBeginExclusiveAuthoredPlacement:1349-1354` also refuses on
|
|
`HasRetainedCompletion(key)` — ordinary right after a `Committed` far snap
|
|
whose projection sink declined — and `BeginAcceptedPlacementCore:1404-1418` on
|
|
`!_entities.IsCurrent(record)`. Both pre-engine, so the store side is right.
|
|
- **m3** — the MAJOR D test (`:1516-1552`) reaches the superseded state via
|
|
`lifetime.Entities.RemoveActive(record)` and picks `Refused`, which never calls
|
|
`CancelToken`. It pins that the guard exists, not that it sits **after** the
|
|
synchronous cancellation receipt — the defect's actual mechanism.
|
|
- **m4** — `NotApplicable` via `record.Key is null` (body non-null) stores
|
|
(`:576-581` → `:800`); the enum doc `:97-101` justifies only the no-body
|
|
sub-case. Unreachable in production
|
|
(`RuntimeEntityObjectLifetime.cs:600-612`).
|
|
- **m5** — `ParkCollisionResidents` (`:3689-3696`) relies on `restorableOnCancel`
|
|
defaulting false. The old blanket doc was itself the guard against a forgetful
|
|
caller; now that it is gone, pass `false` explicitly.
|
|
- **n1** — `:644` cites classifier `:467` for `StopInterpolating: !nearby`; it is
|
|
`:468`. Pre-existing.
|
|
- **n2** — `ParkDeferred` carries two adjacent `<summary>` blocks
|
|
(`:4292-4301`, `:4302-4325`); only the second is emitted.
|
|
- **n3** — the Runtime test class doc (`:30-33`) asserts every test was
|
|
revert-verified, with no per-test mapping in the tree. Either map them or drop
|
|
the claim to what the file can show.
|
|
|
|
## Do not churn — verified across both reviews
|
|
|
|
Retail decode of `SetPositionInternal` @0x00515BD0 (both storing and non-storing
|
|
branches) is exact and matches the enum docs line-for-line. The 7-value switch is
|
|
exhaustive with `_ => throw`, and no consumer outside the controller reads the
|
|
value for a decision, so the `Rejected` split cannot silently miss a case.
|
|
`Deferred`-not-storing is right, with a stronger unreachability proof than the
|
|
comment gives (`ParkCollisionResidents:3563-3568` **throws** rather than parking
|
|
an entity that already holds an operation). MAJOR D's guard is the correct
|
|
predicate (`RuntimeEntityDirectory.cs:75-77`), sufficient, and correctly placed
|
|
after the receipt at both sites. **N5 is genuinely unconstructible** —
|
|
`:917-923`/`:935-940` throw on binding a component whose body differs from
|
|
canonical. Pose parity survives the `remote.Body` → `record.PhysicsBody` change
|
|
byte-for-byte. The neighbour test's construction is arithmetically verified
|
|
(`191.95 mod 24 = 23.95 > 24 - 0.1` → `lx+1` → `0xB3`), it provably hits the
|
|
post-sweep park, and its Z arm discriminates (terrain 7, authored 6). N7's
|
|
reframing is accurate. All six required tests discriminate; the
|
|
cancelled-after-commit construction is genuinely clever. Route 2's re-issue
|
|
funnel does **not** interact with the restore (it decides on
|
|
`PositionAuthorityVersion`/`_newestForce`, none of which the restore moves).
|
|
`RestoreParkWithdrawal` writes exactly five things and no sweep footprint,
|
|
cross-cell registration, or BSP residency among them. **No added line in the diff
|
|
carries a source line-number citation** — that failure mode is fixed.
|
|
|
|
## Gate
|
|
|
|
Complete Release suite. Baseline **10,968 / 4 / 0** at `1b631f12`. Round 2
|
|
measured **11,004 / 4 / 0** while containing everything above. Known flakes, do
|
|
not chase or conflate: **#302** (`PortalProjectionTests…`, App.Tests), **#308**
|
|
(`NakEmissionTests.LossSoak_…`, Core.Net.Tests).
|