# C4 route 7 — retail-conformance review (independent) **Date:** 2026-08-04 **Reviewer role:** independent retail-conformance reviewer, review-only (no edits, no commits, no fixes). **Subject:** the uncommitted working-tree diff at branch `claude/acdream-physics-divergence-5aa784`, HEAD `ca96ea5e` (`git diff HEAD` + the two untracked files `docs/research/2026-08-04-c4-route-7-contract.md` and `tests/AcDream.Runtime.Tests/Entities/RuntimeEntityChildCellPropagationTests.cs`). The route-7 contract and the route-3 scoping docs are inputs, not subject. --- ## VERDICT: **FAIL** Narrow fail. The retail mechanism this slice ports is **correct** — I re-read every cited address in `docs/research/named-retail/acclient_2013_pseudo_c.txt` and the propagation research is accurate on all of them (see §A). The directory chokepoint is genuinely the sole funnel (§B). `ConstrainTo` is never armed (§C). `TryCommitParent` still holds exactly zero `LeaveWorld` calls (§D). D7 adopts retail's real order and is genuinely inert (§E). The fail is on three counts, all small to fix: 1. **R1 (MAJOR)** — retail's `enter_cell` gates the ENTIRE cell write *and the recursion* on `this->part_array != 0` @0x00510ed8. The shipped propagation has no analogue and **no register row**. The propagation research itself flagged this guard as "Guard, load-bearing" (§3); the contract's §0 item 1 enumerated `enter_cell`'s five writes and silently dropped the guard, and the code inherited the omission. Register rule 1: a deviation found without a row is a bug twice over. 2. **R2 (MAJOR)** — D4's presentation half is **untested**. The one App-layer assertion is satisfied by a line that runs before, and independently of, the demoted call. `RebucketEquippedChildPresentation` has zero references in `tests/` repo-wide. This is exactly the layer contract §6 test 10 named ("the child's render entity moved buckets (spatial index / visibility state)") and exactly the #184 / route-4a-R1 regression D4's own text calls its specific risk. 3. **R3 (MAJOR)** — `TickChild` discards the demoted call's `bool`, and the new `HasCommittedParent` guard introduces a silent-false path the old `RebucketLiveEntity` did not have. Contract D4 said "**assert** the record has a committed parent relation"; the code returns `false` and the caller ignores it. Route 5's A1 defect class, verbatim. Everything else is MINOR. Build is green (`dotnet build AcDream.slnx -c Debug`: 0 errors) and the focused Runtime suites pass (21/21, including all 12 new propagation tests and the 2 new headless D5 tests). Per process rule 5 that is not evidence, and it is not what this verdict rests on. --- ## A. Retail ground truth — verified first-hand, not inherited Every claim below was re-read from `docs/research/named-retail/acclient_2013_pseudo_c.txt` at the stated address. | Claim under review | Verdict | |---|---| | `change_cell` @0x00513390 delegates: `leave_cell` @0x0051339f, `enter_cell` @0x005133af, early return @0x005133b5; removal tail @0x005133c1 zeroes only **this**'s `objcell_id`, `cell = nullptr` @0x005133d8. **No child loop of its own.** | ✓ CONFIRMED verbatim | | `enter_cell` @0x00510ed0 self-recurses over `children->objects.data[i]` @0x00510f03; per level writes `CObjCell::add_object` @0x00510ee2, `objcell_id` @0x00510f1e, part-array cell id @0x00510f2b, `cell` pointer @0x00510f35, lights @0x00510f3e. Unbounded depth. | ✓ CONFIRMED verbatim | | `leave_cell` @0x00510f50 mirrors it: self-recursion @0x00510f84, `remove_object` @0x00510f5e, `cell = nullptr` @0x00510fa7, and **never** writes `objcell_id` (source of the stale-id asymmetry). Per-level guard `this->cell != 0` @0x00510f5b prunes an already-cell-less subtree. | ✓ CONFIRMED verbatim | | **The depth-1 loop @0x0051539c-@0x005153d8 is the SAME-CELL fast path.** It sits inside `if (this->cell == curr_cell)` @0x0051536d; the `else` @0x00515372 is `change_cell`. The loop writes child `+0x4c` (`m_position.objcell_id`) @0x005153bd and child `+0x10`'s part-array cell id @0x005153cc — **id only, never `+0x90` (`cell`)**, and **not** recursive. | ✓ CONFIRMED — this is the design's load-bearing claim and it holds | | `update_object` @0x00515d10 early-returns on `parent != 0` @0x00515d40 (`this_3->parent != 0 \|\| this_3->cell == 0 \|\| state & 0x1000000`), clearing `transient_state & ~0x80` and returning. A child never runs its own tick. | ✓ CONFIRMED verbatim | | `DoPickupEvent` @0x00452240 = timestamp gate, stamp write @0x00452278, `unset_parent` @0x0045227f, `leave_world` @0x00452286. **No placement, no `ConstrainTo`, no `HandleReceivedPosition`.** | ✓ CONFIRMED — the `unset_parent`-before-`leave_world` ORDER is unambiguous | | `DoParentEvent` @0x00452290 = gate, `SetParentedState(1)` for a non-player parent gaining its first child @0x004522f4, `set_parent` @0x00452305, `SetPlacementFrame` @0x00452313. No placement, no `ConstrainTo`. | ✓ CONFIRMED verbatim | | `set_parent` @0x00515a90 has **exactly ONE** `leave_world` @0x00515ac1, after `unset_parent` @0x00515aba; then `parent =` @0x00515ac6, `if (edi->cell != 0)` @0x00515ad1, `change_cell` @0x00515ad6, `UpdateChild` @0x00515b0e, `recalc_cross_cells` @0x00515b15, NoDraw inheritance @0x00515b26. | ✓ CONFIRMED — one, and only one, `leave_world` | | Per-move path calls the **non-recursive** `calc_cross_cells` @0x0051551b / shadow rebuild @0x0051553e-4c; the recursive `recalc_cross_cells` @0x00515a30 runs at attach only. | ✓ CONFIRMED | **Research-document defects found (2, both minor, neither changes the verdict):** - **The "read verbatim" blocks are normalized, not verbatim.** e.g. research §2 prints `if ((state & 0x1000) == 0)` where the file reads `if ((*(uint8_t*)((char*)((int16_t)this->state))[1] & 0x10) == 0)`. Same bit, but the doc's own §7 ledger calls these "read directly from the pseudo-C (verbatim, cited)". Paraphrase presented as transcript. Harmless here; a hazard if a future reader diffs against the file. - **The `DoPickupEvent` / `DoParentEvent` gates are NOT readable from this source.** Binary Ninja lowered both to `if (-((eax_4 - eax_4)) != 0)` — a literal always-false expression — because the x87/flag-based wrapped-sequence comparison was lost. The contract's §2 row cites "gate @0x0045224B-0x00452274" as if it were legible; only its *shape* (a wrap-aware sequence compare against `update_times[0]`) is. **Flagged as unverifiable rather than guessed.** It does not affect D7 (the ORDER is legible) or D6 (whose argument is that acdream already enforces the POSITION_TS gate in `InboundPhysicsStateController`, which I verified at `InboundPhysicsStateController.cs:180-186/:263-271/:308-314`). --- ## B. D2's chokepoint claim — independently verified Contract §12 open question 1 asks whether any canonical cell write bypasses the funnel. Repo-wide grep for `SetFullCell` / `RefreshDerivedState` / `CanonicalLandblockId =` over `src/**` (excluding bin/obj) returns: - `RuntimeEntityRecord.SetFullCell` (`RuntimeEntityRecord.cs:244-251`) — two callers only: `RuntimeEntityDirectory.SetFullCell` (`:348-356`, now hooked) and `RuntimeEntityRecord.RefreshDerivedState` (`:230-242`). - `RefreshDerivedState` — reached from the record constructor (`:29`, no children possible) and `RuntimeEntityDirectory.RefreshSnapshot` (`:234-247`, now hooked with an explicit `previousCell` compare). - `LiveEntityRecord.FullCellId` / `.CanonicalLandblockId` setters (`LiveEntityRuntime.cs:189-204`) route to `_directory.SetFullCell`; `LiveEntityRecord.RefreshDerivedState` (`:353-354`) routes to `_directory.RefreshSnapshot`. **No App-side bypass.** - All eight producers (`CommitRebucket`, `RuntimePhysicsState.CommitCanonicalCell`, `RuntimeSetPositionState`'s four writes, the withdrawal family, the executor's `:2188`) call `Entities.SetFullCell`. **Conclusion: the chokepoint holds. No hole.** I also confirmed `canonicalLandblockId` is uniformly `(cell & 0xFFFF0000) | 0xFFFF` at every producer, so D2's skip-on-equal-`FullCellId` cannot leave a stale landblock id. Cycle termination and re-entrancy were checked by construction: the propagation writes fields and bumps a version only, never mutates the relation tables it is iterating, and `ChildrenAttachedToParent` returns the stored `List` or `Array.Empty` (0 B). --- ## C. Route 7 arms nothing — verified `ConstrainTo` / `ConstrainPhase` / `PositionManager` / park / service-window / `CanAttemptDestination` appear **nowhere** in the diff's production hunks. The D8 inversion is respected. `RuntimeEntityChildCellPropagationTests .NeverArmPartition_D8_...` asserts the SetPosition operation ledger is unchanged across attach + five crossings + pickup + delete, and the committed-relation count converges to zero. ✓ ## D. T8 — `TryCommitParent` `LeaveWorld` omission preserved `RuntimeEntityObjectLifetime.TryCommitParent` (`:1400-1453`) still has zero `Physics.CollisionReports.LeaveWorld` calls; the F4 comment (`:1430-1437`) is intact and its retail citation (@0x00515A90's single `leave_world`) is correct per §A. No second `LeaveWorld` was added anywhere in the parent commit family. ✓ ## E. D7's inertness — verified, and the implementer's honest report is CORRECT The implementer reported that reverting D7's ordering leaves all 12 propagation tests green, and reported it rather than manufacturing a test. **That is true, and "unobservable" is genuinely true against today's code**, for a reason worth writing down: - `EndChildProjection(guid)` → `RemoveCommittedChild(guid)` removes the entity as a **child** (`_lastAcceptedByChild` + its parent's committed list). It does **not** touch `_committedChildrenByParent[(guid, incarnation)]` — the entity's own children. `RemoveCommittedParentReferences` would, and is not called. - The only work between the two positions is `CollisionReports.LeaveWorld` → `SetPosition.Forget` → `SuspendObjectClock` → `SetFullCell(0,0)`. I checked every `ChildrenAttachedToParent` consumer (`RuntimeSetPositionState.cs:6015-6063`, `ArmLostFamilyDeadlines` / `CancelLostFamilyDeadlines`): both enumerate `operation.Record`'s **own** children, i.e. the picked-up entity's subtree, which `EndChildProjection` does not alter. Nothing else reads the child-relation table in that window. - Even in a hostile A→B/B→A cycle both orders converge to the same values. So: **no observable difference exists that anyone failed to construct.** The correctness is contingent on "no consumer reads the child-relation table between those two points" — a property of today's code, not a semantic equivalence — so adopting retail's real order is right on principle and the change should stand. See R5 for the half that was missed. --- ## Findings ### R1 — MAJOR — retail's `part_array != 0` guard is dropped, with no register row **File:** `src/AcDream.Runtime/Entities/RuntimeEntityDirectory.cs:381-403` (`PropagateFullCellToChildren`) and `src/AcDream.Runtime/Entities/RuntimeEntityObjectLifetime.cs:1517-1535` (D1). **Retail address contradicted:** `CPhysicsObj::enter_cell` @0x00510ed8. Retail: ``` 00510ed0 void __thiscall CPhysicsObj::enter_cell(CPhysicsObj* this, CObjCell* arg2) 00510ed8 if (this->part_array != 0) <-- the ENTIRE body, including the 00510ee2 CObjCell::add_object(...) child recursion, is inside this 00510f03 enter_cell(child, arg2) guard 00510f1e objcell_id = ... 00510f35 this->cell = arg2 ``` A child with a null `part_array` receives **nothing** — no `add_object`, no `objcell_id`, no `cell` pointer — and **its whole subtree is skipped**, because the recursion is inside the guard. The propagation research called this out explicitly and named it load-bearing (§3, "Guard, load-bearing"). The route-7 contract's §0 item 1 lists the five writes and omits the guard entirely, and the shipped propagation writes the child's cell unconditionally. **Why it matters in acdream specifically:** `FullCellId` is the residency/liveness predicate at 45+ sites (the contract's own §0 item 6). Writing a nonzero cell for an object retail would leave nowhere makes it "resident" to every one of those predicates — the #184 shape, arrived at from the other direction. The graphical host's `ValidateParentProjection` checks `parent.HasPartArray` (`EquippedChildRenderController.cs:902`) — the **parent**'s, not the child's — so it is not the analogue. **Correct behaviour:** either port the per-level guard (acdream has a `HasPartArray` notion on the graphical record, but not on the canonical one, so this may be a deliberate impossibility headless), **or** file a register row stating that acdream's canonical record has no part-array concept, that the guard is therefore not reproducible at the canonical layer, and what the consequence is. Register rule 1 requires the row in the same commit. Right now neither exists, and AP-142 — which is otherwise a careful, honest row — reads as if the port were complete. ### R2 — MAJOR — D4's presentation half has zero effective coverage **File:** `tests/AcDream.App.Tests/Rendering/EquippedChildProjectionWithdrawalTests.cs:334-374` (assertions at `:368-373`), against `src/AcDream.App/Rendering/EquippedChildRenderController.cs:403` vs `:409-415`. The test's only presentation assertion is: ```csharp Assert.Equal(newCell, child.WorldEntity!.ParentCellId!.Value); ``` `TickChild` sets that field at **line 403**: ```csharp child.Entity.ParentCellId = parent.ParentCellId; // :403 — unconditional ... if (TryResolveExactAttachment(child, out parent) && parent.ParentCellId is { } parentCellId) // :409 { _liveEntities.RebucketEquippedChildPresentation(...); // :412 — the demoted call } ``` The assertion is therefore satisfied whether or not `RebucketEquippedChildPresentation` runs, returns `false`, or is deleted. Grep confirms `RebucketEquippedChildPresentation` has **zero** references under `tests/`. The spatial bucket (`_spatial.RebucketLiveEntity`), the visibility resolution (`IsLiveEntityProjectionResident`), and `PublishProjectionVisibilityChanged` — the things `RebucketLiveEntityPresentationOnly` actually does — are unasserted. Contract §6 test 10 required exactly this and required a sabotage check. The test's own doc comment claims sabotage verification, but the sabotage described ("reverting TickChild to call the public `RebucketLiveEntity` again makes the final assertion fail, because that call always bumps `SpatialAuthorityVersion`") only exercises the **canonical** half. The presentation half — "left behind at a landblock boundary", D4's named specific risk, and #184's layer — is unguarded. **Correct behaviour:** assert the spatial index / visibility state moved (the route-4a R1 lesson), and sabotage-verify by no-op'ing `RebucketEquippedChildPresentation`. ### R3 — MAJOR — the demoted call's status is discarded, and its new guard can fail silently **File:** `src/AcDream.App/Rendering/EquippedChildRenderController.cs:412-415`; `src/AcDream.App/World/LiveEntityRuntime.cs:1085-1101`. ```csharp internal bool RebucketEquippedChildPresentation(uint serverGuid, uint parentCellId) { if (!_directory.ParentAttachments.HasCommittedParent(serverGuid)) return false; // NEW failure mode if (!_projections.TryGetCurrent(serverGuid, out LiveEntityRecord? record) || record.WorldEntity is not { } entity) return false; // NEW failure mode ... } ``` `TickChild` ignores the return and still returns `true` (`:417`). The old `RebucketLiveEntity` had no committed-relation precondition, so both of these are paths that previously could not exist. `EndChildProjection` / `RemoveCommittedChild` run at several points while a projection is still installed (`EquippedChildRenderController.cs:270`, `:1175`, `:1274`, `:1316`; `RuntimeInitialCreateContinuationExecutor.cs:1998`, `:2189`), so a tick landing in that window now silently stops moving the draw bucket, and the pose loop reports success. Contract D4 pinned "the entry point is child-scoped (**assert** the record has a committed parent relation…)". A silent `false` swallowed by the caller is the route-5 A1 class the contract's own predecessor list names: *"an App glue site discarding the Runtime seam's status and advancing presentation on write-nothing outcomes."* **Correct behaviour:** either throw/assert on the guard (it is an invariant, not a condition), or propagate the `false` into `TickChild`'s result so the existing `WithdrawForPoseLoss` path handles it. Note this finding is only *observable* today because of R2 — with a real bucket assertion, a fix for R3 would be test-covered. ### R4 — MINOR — contract §6 test 2 shipped 2 of 4 writer families; P2/P4/P5/P6/P8 are unstated **File:** `tests/AcDream.Runtime.Tests/Entities/RuntimeEntityChildCellPropagationTests.cs`. Shipped: (a) `CommitRebucket` and (d) the wire merge (`RefreshSnapshot`). **Missing:** (b) `RuntimePhysicsState.CommitCanonicalCell` (the simulation commit — the writer that actually fires per tick in live play) and (c) a `RuntimeSetPositionState` canonical placement commit. I verified by reading that both reach `Entities.SetFullCell` (`RuntimePhysicsState.cs:2148`, `RuntimeSetPositionState.cs:2743/:3660/:5003/:5224`), so the hook does fire — the gap is regression coverage, not present-tense correctness. P5 (per-writer-family re-entrancy) has no test at all; P6 (0 B/crossing) has none; P2 asserts only `ObjectClock.IsActive` on one path, not "no workset / not a spatial root / body inactive after N crossings and a teleport"; P4 (the child broadphase story) and P8 (the `Rebucketed` consumer enumeration) are stated nowhere in the tree. For P8 I did the enumeration myself: `RuntimeEntityChange.Rebucketed` has **no** production consumer that branches on it (only `GameRuntimeEvents.cs:43`'s enum member and two test assertions). D2's silent-publication default is safe. That should be written into the commit, per §5, rather than left for a reviewer. ### R5 — MINOR — D7 is half-applied; the executor's replayed pickup keeps the inverted order **File:** `src/AcDream.Runtime/Entities/RuntimeInitialCreateContinuationExecutor.cs:2183-2189`. ```csharp _entities.AdvancePositionAuthority(canonical); _physics.CollisionReports.LeaveWorld(canonical); // leave_world ... SetPosition.Forget / SuspendObjectClock / SetFullCell(0,0) _entities.ParentAttachments.EndChildProjection(canonical.ServerGuid); // unset_parent LAST ``` This is the dormant-residence replay of the **same** wire event (`SmartBox::DoPickupEvent` @0x00452240), whose retail order is `unset_parent` @0x0045227f **before** `leave_world` @0x00452286. D7 corrected `RuntimeEntityObjectLifetime.TryApplyPickup` and left this one. Inert for the same reason (§E), but the new comment at `RuntimeEntityObjectLifetime.cs:1304-1306` — "This was inverted; EndChildProjection now runs first" — now reads as a codebase-wide statement that is only half true. (The `TryApplyPosition` unparent edge at `:1908` **is** correctly scoped out as route 4's surface in contract §9; this one is not.) ### R6 — MINOR — D5's deferred-residence flavor is neither driven nor declared a non-goal **File:** `src/AcDream.Runtime/Session/RuntimeLiveEntitySessionController.cs:339-379`. `ResolveAndCommitChildAttachment` runs `Resolve` → `TryCommitParent` → `CommitProjection` → `CommitAcceptedParentCellless` synchronously. When the child has a pending initial residence, `Resolve`'s accept callback lands in `RuntimeEntityObjectLifetime.TryApplyParent`'s dormant branch (`:1354-1391`), which advances the gate via `TryAcceptDeferredParent` and `EnqueueDormant`s a `Parent` continuation, returning `true` — so the relation is **staged**, and the immediately following `TryCommitParent` is gated on `gate.PositionTimestamp == positionSequence && child.PositionSequence == positionSequence` (`InboundPhysicsStateController.cs:308-314`), which the deferred merge has not yet satisfied. The drive returns `false`. Nothing re-drives it: the executor's `CommitParentAttachment` deliberately does **not** commit the attach ("it is the App-layer `EquippedChildRenderController`'s job" — `RuntimeInitialCreateContinuationExecutor.cs:2110-2123`), and headless has no such controller and no post-drain retry hook. So headless, a ParentEvent arriving during a pending initial residence leaves the child staged and cell-less indefinitely. Not a regression (headless committed nothing before), and the invariant-9 deferrals are correctly untouched. But the plan doc's new closure text and D5's doc comment both read as if the headless gap is closed. Contract D5 required "state what is deliberately not driven"; this case is not stated. **Flagging the `TryCommitParent` rejection as inferred-from-reading, not executed** — no test covers it. ### R7 — MINOR — AP-143 under-describes what the headless drive skips **File:** `docs/architecture/retail-divergence-register.md:173`; `src/AcDream.Runtime/Session/RuntimeLiveEntitySessionController.cs:339-379`. AP-143 records only the `Setup.HoldingLocations` check. The graphical `ValidateParentProjection` (`EquippedChildRenderController.cs:894-919`) also rejects **self-parenting** (`:897-898`) and requires the parent to have a **part array** (`:902` — retail's @0x00510ed8 guard, and the closest thing acdream has to it). The headless drive performs neither. Self-parenting turns out to be inert by construction (the D1 gate sees `parent.FullCellId == 0` because the child was just zeroed, and D2's skip-on-equal terminates the one-node cycle), but the row should say what it skips, not one of three things. Contract §6 gave zero coverage of the headless rejection paths. ### R8 — MINOR — the headless drive is not the "same protocol" for nested/recovery cases **File:** `src/AcDream.Runtime/Session/RuntimeLiveEntitySessionController.cs:381-393`. - The graphical retry is `_relationRecoveryOrder.RealizeDescendants(parentGuid, Relations.ChildrenWaitingForParent, ResolveAndTryRealize)` (`EquippedChildRenderController.cs:925-931`) — a **transitive, parent-first** descent. `RetryChildrenWaitingForParent` iterates the direct waiters on one guid only, so after committing a child, grandchildren waiting on **that** child are not retried in the same pass. The doc comment claims it "mirrors `RetryWaitingDescendants`'s role"; it mirrors a subset. - The drive never calls `MarkProjected`, so `_recoveryByChild` retains every committed relation headless, and it never handles the recovery branch the graphical `ResolveAndTryRealize` handles (`:835-844`). Benign today (recovery is a re-projection concept that does not exist headless, and the entries are cleared by `EndChildProjection`/`EndGeneration`/`Clear`), but undeclared. Given AP-142 explicitly ships unbounded-depth recursion as a design commitment, a depth-limited headless realize is worth a sentence somewhere. ### R9 — MINOR — a doc comment now describes the wrong test method **File:** `tests/AcDream.Runtime.Tests/Session/RuntimeLiveEntitySessionControllerTests.cs:316-331` and `:426-431`. The pre-existing `` for `FirstEntryDriveServesOneRouteAtATimeAndScopesClearToTheOwner` (the C3c-R1 F6 latch) was left in place and the two new tests were inserted **after** it, so: - `DirectSink_D5_StandaloneParentEventCommitsChildToParentsExactCell` now carries **two** `` elements, the first of which describes drive-controller route latching. - `FirstEntryDriveServesOneRouteAtATimeAndScopesClearToTheOwner` now carries the D5 *deferred-parent* summary. Exactly the endemic stale-comment class this campaign keeps hitting, in the commit that was supposed to be checking for it. ### R10 — MINOR — AP-142 clause (b) overstates the equivalence **File:** `docs/architecture/retail-divergence-register.md:172`; `src/AcDream.Runtime/Entities/RuntimeEntityDirectory.cs:391-395`. The skip guard (`child.FullCellId == fullCellId → continue`) does two things: it subsumes retail's same-cell id refresh (accurate, as the row says) **and** it prunes the child's entire subtree. Retail's `enter_cell` has no such pruning — it recurses unconditionally (@0x00510f03) and only `leave_cell` prunes (@0x00510f5b, on `cell != 0`). So acdream matches retail exactly on the removal side and diverges on the entry side. Currently unreachable-by-construction (after D4 nothing writes a grandchild's cell independently of its parent), but the row claims a clean equivalence it does not have, and this is precisely the class of "row asserting behaviour the code lacks" in the other direction. ### R11 — MINOR — the demotion drops `SynchronizePhysicsBodyActiveState` on a child's first projection **File:** `src/AcDream.App/World/LiveEntityRuntime.cs:923-927` (legacy branch, no longer reached for children) vs `:995-1067` (presentation-only branch). The legacy `RebucketLiveEntity` ran `record.SuspendObjectClock(); SynchronizePhysicsBodyActiveState(record);` when `!wasProjected && !isOrdinaryRoot` — true on a child's first tick after realize. `RebucketLiveEntityPresentationOnly` does neither. The canonical clock is suspended by Runtime (`CommitAcceptedParentCellless`'s `Entities.SuspendObjectClock`), and `SynchronizePhysicsBodyActiveState` no-ops when `record.PhysicsBody is null` (the equipped-item case), so this is very likely inert — but P2's "body (if any) inactive" is the obligation that would have proven it, and it is unproven. **Flagged as unverified rather than asserted.** --- ## Register discipline — assessed row by row | Row | Assessment | |---|---| | **AP-142** (parented-child single-field cell model) | Clauses (a) and (c) describe shipped behaviour accurately (verified: `PropagateFullCellToChildren` + `WithdrawCommittedChildrenToCellless` + the D1 half). Clause (b) overstates — see R10. **Missing the `part_array` guard clause — see R1.** Anchors all correct. | | **AP-143** (headless holding-location skip) | Accurately describes the skip and the reason. Under-describes the scope — see R7. The claim "repo-wide grep confirms nothing under `src/AcDream.Content`/`AcDream.Bake` carries `HoldingLocations`" is consistent with what I saw; the row correctly refuses to extend the bake format. | | **AP-136** writer-list shrink | ✓ Correct: line 289 now reads "…demoted the third, `EquippedChildRenderController.TickChild`, to a presentation-only bucket move that no longer touches `record.FullCellId`". Matches the code. | | **AP-138** writer-list shrink | ✓ Correct, same shape. | | `RuntimeSetPositionState.cs:4536-4548` doc comment | ✓ Corrected; singular "writer" now, projection materializer only. Matches the code. | | `RuntimeRemotePlacementDriveController.cs:1613-1626` doc comment | ✓ Corrected. Matches the code. | | 4b-3 contract closure note | ✓ Honest and correct. It states plainly that the old `cause=cellless` recipe no longer fires, explains why that is the retail-faithful direction, marks test 4 as a synthetic fixture that must not be relabelled, and says the replacement provocation is UNESTABLISHED rather than inventing one. This is the best-written doc change in the diff. | | Placement-cutover plan gap statement | ✓ Correctly moved to past tense and closed, with the one caveat that "the direct headless regression test … now passes" is true for the non-deferred flavor only (R6). | | No row deletions | ✓ AP-124/131/132/133/135 untouched. | --- ## Contract defects found 1. **§0 item 1 dropped `enter_cell`'s `part_array != 0` guard** (@0x00510ed8), which the research it cites called load-bearing. The contract enumerated the five writes and not the gate around them; the implementation inherited the omission. This is the root of R1 — process rule 1 ("the contract causes the defect") in action. 2. **§2's `DoPickupEvent`/`DoParentEvent` gate citations are not readable from the named-retail source** (BN lowered both to a literal always-false expression). The contract presents them as verified. Nothing downstream depends on it, but "✓" is the wrong mark. 3. **§4 D4 said "assert"; §6 test 10 said "assert the child's render entity moved buckets".** The implementation did neither, and the contract's own sabotage instruction ("break D2's propagation and confirm THIS test fails on the canonical half **while presentation still moves** — if it stays green, the test is asserting the wrong layer") was applied to the canonical half only. The contract was right; it was not followed. R2/R3. 4. **§5's proof obligations are not stated anywhere in the working tree.** P4 and P8 in particular were explicitly "must prove, not assume". P8's answer is benign (I checked), P4's is unwritten. ## Propagation research defects found Two, both cosmetic, listed in §A: the "verbatim" blocks are normalized paraphrase, and §7's read/inferred ledger is otherwise scrupulous and correct. **The verdict, the addresses, the recursion claim, the same-cell-fast-path disambiguation, the `update_object` clincher, and the cross-cells trap are all correct.** The research is the strongest artifact in this slice; the contract weakened one of its findings on the way through (R1). --- ## What would flip this to PASS - R1: a `part_array` register clause (or the guard, if a canonical analogue exists). - R2: an App test that asserts the spatial bucket / visibility state moved, with the demoted call sabotage-verified. - R3: assert-or-propagate on `RebucketEquippedChildPresentation`'s two guards. R4–R11 are worth folding in but none of them alone blocks the slice.