fix(review): close the C5b architecture-review findings (D2/D3/D4, L1-L5, S1)
Follow-up to C5b (735f0a72). The retail-conformance review passed, so no production behaviour line moved: the flag truth table and the refreshPosition:false withhold are untouched. This is blast radius, test discrimination and documentation fidelity - plus two findings I could not confirm and am rebutting rather than complying with. D3 - THE PUBLISH-CONSERVATION TEST DID NOT DISCRIMINATE. The reviewer was right and it was the worst finding here: proof obligation 3's test passed identically with C5b reverted. Its only delta assertion FILTERED (Assert.Single(deltas, Rebucketed && parentGuid)), so the pre-C5b stream [Rebucketed] and the post-C5b stream [Updated, Rebucketed] both satisfied it, and childSpatialBefore+1 held in both worlds because whichever site did not move the cell propagated idempotently. It now asserts the complete ordered parent stream plus each element's CellId and Position.ObjCellId. Sabotage: restoring refreshPosition:acceptedPosition turns it red (it was green before), together with the withhold test and the new L5 test. That cardinality change was itself unfiled and is now AP-147: a cell-changing accepted Position publishes TWO entity deltas where it published one, and the intermediate Updated pairs the OLD CellId with the NEW wire Position - a torn pair that did not exist pre-C5b, since both halves used to move inside one publish. No production consumer reads a delta's paired fields, but a recorder/plugin/bot event log would capture it. The row states why suppressing the Updated is not available at that layer (the merge cannot know whether its caller reaches W2). D4 - THE PROJECTILE DOC COMMENT WAS FALSE AND ITS RETAIL ARGUMENT WAS INVERTED. SyncPresentationFromResolvedBody claimed record.FullCellId is "the WIRE cell ... stamped by the merge's RefreshDerivedState/SetFullCell, before classification ever runs" and argued from retail's store_position @0x00515CE2 that the destination cell is the right one. C5b falsified the premise; the missile arm also returns before W2, so nothing stamps the wire cell for a projectile at all. Rewritten. The honest conclusion, which the old text would have called wrong: on a stored outcome presentation now pairs the DESTINATION world position with the SOURCE cell. That is not a choice this method can make differently - StoreAcceptedDestinationPose writes only Position/Orientation, so record.FullCellId and body.CellPosition.ObjCellId now hold the same source cell and reading either yields the same value. The divergence is AP-138 item (1)'s store-writes-pose-but-not-cell residual, retiring via #309, not a field choice here. Projecting the wire cell instead would invent a residency the placement declined - the AP-1 shape C5b closed. L3/L4/L5 - PINNING GAPS, ALL THREE CONFIRMED AND CLOSED. L3: the matrix's oracle passed HasAnimations as a literal, so the merge's old.MotionTableId ?? old.Physics?.MotionTableId and RuntimeAcceptedPositionRouteRequests.Build's canonical-snapshot twin were textually identical and pinned by nothing. The oracle is now BUILT by the production constructor. L4: every fixture set both MotionTableId halves to the same value, so deleting either operand of the ?? was undetectable while the production comment said the mixed case is the real-world one. Six mixed rows added, including the explicit-zero row (a present-but-zero top half is not null, so ?? never reaches the physics half). L5: the retained Rebucketed ternary had zero coverage through TryApplyPosition - every restoreCancelledPark test called Forget directly. Now driven through the real merge, with the wire cell deliberately the SOURCE while the park's committed body cell is the DESTINATION, so the restored residency can only have come from the rollback. Sabotage (each red, each restored): merge ?? -> top half only, 1 red; -> physics half only, 2 red; Build's ?? -> physics half only, 2 red; ternary -> constant Updated, exactly the L5 test red. L1/L2 - THE MISSING TEST IS ADDED; THE DEFECT IS NOT THERE. The reviewer was right that C5b's "no fixture covers pickup at that layer" was inaccurate - LiveEntityNetworkOnPositionCollapseMatrixTests drives the real OnPosition at ~26 sites - and the end-to-end test is added: withdraw -> accepted Position -> IsSpatiallyProjected && FullCellId == wireCell, both guid classes. But ChildUnparentDisposition.Pending is NOT a live defect, because it is production-unreachable. The sole production _withdrawProjection binding (LivePresentationComposition.cs:599) is LiveEntityProjectionWithdrawalController.WithdrawExact, whose only Pending mint is inside its catch block and therefore always carries a non-null Failure - and AdvanceUnparentTransition rethrows at EquippedChildRenderController.cs:1307 BEFORE the return Pending at :1309. The named drop scenario does not reach it anyway (BeginDetachedRemoval has already emptied the capture list) and would be correct if it did: a previously-equipped child is LegacyImmediate, so the FullCellId != 0u gate at DatLiveEntityProjectionMaterializer.cs:767 is never consulted and re-projection uses the wire cell at LiveEntityRuntime.cs:824. Measured while building that test, and NOT what C5b assumed: W2 and W3 are REDUNDANT on the remote tail. Sabotaging W2 alone - adopting the committed cell instead of the wire cell, OR skipping the rebucket outright - leaves the whole file green, because W3's RemoteMotion.CellId write reads through to canonical FullCellId via CommitCanonicalCell, whose CellCommitted recovery re-installs the bucket. Only removing BOTH goes red, and then the new test is the only red in the file. So it is named for what it pins, and AD-60 is amended with the measurement: neither channel is individually load-bearing, so a future retirement of one is caught by nothing else. D2 - REBUTTED, WITH THE REAL GAP FILED INSTEAD. The reviewer's hypothesis was that TryApplyInitialCreateCompletionPresentation's staleness guard lost its ability to detect an intervening steady-state Position when C5b stopped the merge stamping the wire cell, and asked for a PositionAuthorityVersion term. I do not think that is right and did not add it. The receipt's facts are the canonical BODY's pose and cell at publish (PublishExecutorCompletion builds both from the record). Exactly two owners can move them: a Runtime SetPosition commit/withdrawal, every one of which calls AdvancePlacementCommit - the only caller family is RuntimeSetPositionState - and a rebucket, which moves FullCellId. Both are already covered by the two existing terms. An accepted steady-state Position is neither, and C5b did not make it one: the merge refreshes the snapshot and advances PositionAuthorityVersion but never wrote the body, and the App generic tail writes the RENDER entity. The wire-cell half stays covered because W2/W3 commit it in the same call; the paths that return before them leave the record at the last committed cell, which IS the receipt's own cell - correctly not a supersession. Adding the term would decline receipts whose facts are still true, on the entity's FIRST world-visible moment: the pose write and RebucketLiveEntityPresentationOnly would be skipped while TryPublishPlace still publishes, so a packet returning before the render write would leave the sidecar visible at its materialized pose in a wrong bucket. That is the handoff's own "removed the invariant failure while leaving the bug" shape. There IS one supersession neither term covers, and it predates C5b: RuntimeRemotePlacementDriveController.StoreAcceptedDestinationPose writes body.Position/Orientation on the far-snap Refused/Contention arm with no placement commit and no cell move. Filed as #323 with the FIFO-blocking argument for why a receipt can still be pending when it lands, an explicit "not established as reachable", and an explicit "do not fix it with PositionAuthorityVersion". The guard's comment now carries the whole argument instead of one sentence. S1 - DANGLING POINTER CLOSED. InboundPhysicsStateController.cs:610 still said the two-callers-one-rule debt was "tracked for the eventual cutover unification ... See docs/ISSUES.md", which pointed at nothing after C5b closed #275 without a successor. Filed #322, cited from both the comment and #275's closure, including why widening TryApplyPosition's signature to take a route would be the wrong unification. AP-138 amended: C5b staled its round-3 measurement that "both accepted-Position callers commit the accepted wire cell to record.FullCellId before submitting". Route 2 submits from TryExecuteAcceptedLocalPosition ahead of W2, so on a first submit PlacementTouchesPrefix's CurrentCellId arm now names the SOURCE landblock, not the destination. Confined to which prefix the quiescence pre-flight matches, which that row already established is not the correctness mechanism. GATES. Release build 0 errors. Complete suite 11,134 passed / 4 skipped / 0 failed, from the 11,125 / 4 baseline ated806997: net +9, all new tests, no test deleted or weakened, no new skip. Runtime.Tests 1195 -> 1202 (+6 mixed-motion-table rows, +1 park-rollback fact); App.Tests 4132 -> 4134 (+2 guid rows). None of #302/#308/#321 appeared. Not connected-gated - nothing here changes runtime behaviour. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
ed8069976c
commit
23aa62f292
9 changed files with 637 additions and 62 deletions
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue