A local-player ForcePosition had TWO independent writers for one accepted
packet: LocalForcePositionTransaction snapped the physics body
(PlayerMovementController.BlipPosition, a raw SnapToCell with no collision
resolve), while LiveEntityNetworkUpdateController's generic tail separately
wrote position/cell/rotation to the render WorldEntity from the raw wire and
rebucketed it. Two stores, one packet — the divergence class 670f307c fixed on
the remote path. The outbound AutonomousPosition ack also fired BEFORE any
canonical commit existed: we told ACE "got it, I'm here" before deciding where
"here" was, and the trailing isCurrent() could only suppress the continuation,
never recall the packet.
RuntimeAcceptedPositionDriveController is now the one Runtime-owned seam. Both
hosts call the identical TryExecuteAcceptedLocalPosition; App and headless
project the committed result through the existing placement projection sink
(LiveEntityRuntime.TryApplyRuntimePlacementPlace already performed the same
four writes, from committed state rather than a wire guess).
Retail: SmartBox::HandleReceivedPosition @0x00453FD0's FORCE_POSITION branch is
get_heading -> Frame::set_heading -> SmartBox::BlipPlayer @0x00453940 -> stamp
POSITION_TS -> SendPositionEvent @0x00454091 -> return @0x0045409D. BlipPlayer
is CPhysicsObj::SetPositionSimple @0x005162B0 with flags 0x1012
(Teleport|Slide|SendPositionEvent) — a real collision-resolving SetPosition,
not a snap. The pinned classifier already encoded this exactly.
Named behaviour changes:
* The ack is now an OUTPUT of the committed route, fired strictly after the
canonical commit and exactly once per accepted force packet.
* The ForcePosition route no longer re-arms the constraint leash. The force
branch returns at 0x0045409D, ahead of all three ConstrainTo sites
(0x00454272, 0x0045418A, 0x004541EC); the old re-arm cited retail's "Player,
normal" branch, which BlipPlayer is not on. The teleport, CommitPreparedPosition
and first-entry callers legitimately still constrain and are untouched.
* A force correction that terminates WITHOUT committing still sends its
position event and is not retried — retail's BlipPlayer discards
SetPositionSimple's SetPositionError return and acks unconditionally.
A single _pending funnel owns the in-flight placement, deciding on the token's
PositionAuthorityVersion against the record's: equal -> clear; advanced with the
newest accepted event still a force -> re-issue, re-classified; advanced to an
ordinary Apply -> clear, since newer server truth owns that pose. This closes a
double-apply/double-ack and a silently-dropped correction that two earlier
iterations of this slice each introduced.
AD-62 records the residual: a ForcePosition our async collision publication
cannot carry to a committed placement is not re-applied. Retail has no park —
its world is fully resident and its placement synchronous — so the state is
unreachable there. AP-131 is NOT retired; its legacy Position caller is route 4.
Deleted: LocalForcePositionTransaction, PlayerMovementController.BlipPosition,
HeadlessSessionWorldProjection.BlipLocalPlayer.
Gates: complete Release solution 10,858 passed / 4 skipped / 0 failed (baseline
10,844/4/0). Two independent Opus reviews (retail-conformance and
architecture/adversarial) PASS on the final diff after three FAIL rounds; every
intermediate state was fully green, so the suite caught none of the four real
defects. Connected acceptance is NOT run: nothing a user can do makes ACE emit
a ForcePosition without retail's @pklite, which acdream does not implement — see
docs/research/2026-08-03-c4-route-2-visual-gate.md.
Known gap, recorded not claimed: the plan's acceptance item 2 is unmet. The App
double-write check is a source pin, and "the committed projection moves the
render entity" is uncovered at any layer (#292). Filed alongside: #286-#291,
#293-#296.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
26 KiB
C4 route 2 — dual review findings and required fixes (2026-08-03)
Both mandated reviews returned FAIL on the first implementation pass. Nothing is committed. This is the consolidated fix list; it supersedes the implementer's own closing report where they disagree.
Reviews: retail-conformance (Opus) and architecture/adversarial (Opus), run independently against the same uncommitted diff.
Verified correct — do not churn these
Both reviews independently confirmed, with addresses:
AuthoritativeTeleportFlags=Teleport|Slide|SendPositionEvent=0x1012, byte-exact againstCPhysicsObj::SetPositionSimple@0x005162B0.- Leash re-arm removal is retail-correct: the FORCE_POSITION branch returns at
0x0045409D, strictly before all three
ConstrainTosites (0x00454272, 0x0045418A, 0x004541EC). The teleport /CommitPreparedPosition/ArmConstraintLeashAtCommittedPlacementcallers correctly still constrain. - Heading preservation happens exactly once, upstream in
InboundPhysicsStateController.ApplyAcceptedPosition:788-798. The seam does not re-apply or drop it. - Ack ordering is correct and fires exactly once on both the synchronous and
the deferred path; the
CanSendPositionEventgate matches retail'sCommandInterpreter::SendPositionEvent@0x006B4770, and correctly does NOT applyShouldSendPositionEvent's rate limit (retail's force branch calls SendPositionEvent directly). - Route-request field derivation matches the continuation executor field for field.
- Contract items 2, 4 (the Runtime command itself), 6, and 7 pass. AP-131 correctly not retired.
- The re-modelled
PlayerMovementControllerTestsare relocations, not weakenings.
Required fixes, in priority order
R1 — HIGH — the DeferredCell park cannot survive in production
RuntimeEntityObjectLifetime.cs:1636 calls Physics.SetPosition.Forget(canonical)
on EVERY accepted Position, which unconditionally cancels the entity's in-flight
operation. ACE broadcasts at 5-10 Hz, so any park lasting longer than ~100-200 ms
is guaranteed to be cancelled before its collision generation commits — exactly
the far-destination case the deferred path exists to serve.
Chain: park -> cancelled -> RetryDeferred never runs -> no Place receipt ->
ReconcileAndAcknowledge never runs -> the body is never moved and no ack is
ever sent. The old LocalForcePositionTransaction / BlipLocalPlayer pair
applied the correction synchronously and unconditionally. Retail's BlipPlayer
@0x00453940 has no "give up quietly" state at all.
Park-and-hope is not a valid mechanism here. Required direction:
- Do not open a park that can never wake. Before submitting, establish that the
destination's collision is publishable (R2), and mirror the existing
C3c-R1-F7 guard shape (
IHeadlessCollisionNeighborhood.IsWithinServiceWindow,HeadlessSessionWorldProjection.cs:20-27) rather than inventing a new one. - Where a park still legitimately occurs, the seam must detect that its
operation was cancelled —
RuntimeSetPositionState.IsPlacementCompletionTracked(:1245) is the existing read-only query — and re-issue the placement from the current canonical snapshot on the next accepted Position orAdvance(). The snapshot already carries the latest accepted pose, so re-issuing is correct, not a replay of stale state. - A force correction must never be silently dropped. That is the retail invariant this route exists to preserve.
Do NOT resolve this with a timeout, a settle window, a retry counter, or by
exempting ForcePosition from Forget. If you conclude the correct answer is a
deliberate, cited divergence, STOP and report rather than shipping one.
R2 — HIGH — headless lost its destination-collision publication
HeadlessSessionWorldProjection.BlipLocalPlayer (deleted) called
_collision.CenterOn(position.LandblockId). The headless collision neighborhood
is a hard 3x3 window (BuildPublicationPlan, :462-488) moved ONLY by
CenterOn. The surviving callers are spawn (:562), the controller-null login
branch (:603), teleport prep (:640) and portal arrival (:683) — a
ForcePosition on a live local player now reaches none of them. PumpFirstEntry
(:624) polls the stale _requestedLocalPlayerCell, which nothing updates on
this path either.
Restore a real mechanism (re-center plus the _requestedLocalPlayerCell
update), or gate on IsWithinServiceWindow and handle out-of-window explicitly.
The deleted CenterCount assertion in HeadlessSessionHostTests.cs:430 is the
invariant; restore it rather than the changed number.
The in-test justification ("retail's BlipPlayer has no streaming-window concept") is true of retail and irrelevant: the window is OUR adaptation, and retail has no equivalent because retail has every landblock resident.
R3 — HIGH — login-window ForcePosition now does nothing at all
RuntimeLiveEntitySessionController.cs:229-254. Previously every accepted local
Position ran _worldProjection.ProjectPosition, whose controller-null branch
(HeadlessSessionWorldProjection.cs:593-607) set _requestedLocalPlayerCell,
called CenterOn, and pumped _firstEntry.DriveAll(). Now a ForcePosition
takes the new branch, the drive returns NotApplicable (residence active), and
nothing happens.
Restore the pump for the controller-absent case, and delete the comment at
:239-240 claiming "there is no legacy fallback to run instead" — there was
one; it is the else branch this change routed around.
R4 — MEDIUM-HIGH — the force-ack steals a receipt the sink declined
RuntimeAcceptedPositionDriveController.cs:366-375 unconditionally calls
AcknowledgeProjection(outcome.Projection). RuntimePlacementProjectionSubscription
deliberately leaves a declined Place at the FIFO head for a later retry
(:118-121); this consumes and destroys it.
The sink declines for real production reasons — !_spatial.IsLoaded(landblock)
(LiveEntityRuntime.cs:1210-1219) and stale transit authority
(RuntimePlacementPresentationSink.cs:90-96). In those cases entity.SetPosition
/ Rotation / ParentCellId / RebucketLiveEntity / IsSpatiallyProjected
are never written, and because the generic tail is now skipped there is no
second writer to cover it — the render entity silently stays put while the
canonical body moved.
The RuntimeFirstEntryDriveController mirror is safe ONLY because a residence
makes the sink decline by design and a follow-up ExecutorCompleted receipt
re-binds presentation. Route 2 has no such follow-up. Drop the force-ack and let
the subscription's retry contract stand, or provide a real follow-up binding.
R5 — MEDIUM-HIGH — Contention and Rejected silently drop the correction
RuntimeAcceptedPositionDriveController.cs:265-271 returns Contention when
TryBeginExclusiveAuthoredPlacement fails; neither status creates a pending
entry, and both hosts then return without blipping or acking
(LiveEntityNetworkUpdateController.cs:1140). The Contention doc comment
promises "a later accepted Position, or this controller's own Advance pump,
retries" — the pump provably cannot retry something never recorded, and a later
Position carries a different pose. Retail always applies.
The most likely trigger is R1's parked operation, which makes every subsequent
ForcePosition Contention. Fixing R1 largely fixes this; the status handling
must still not silently drop.
Also fix the Rejected enum doc: it claims "No SetPosition ran; no ack was
sent", which is false at the two SubmitAndResolve sites (:361, :415) where
a SetPosition ran and was cancelled.
R6 — MEDIUM — _pending leaks and can be silently overwritten
RuntimeAcceptedPositionDriveController.cs:289-324. Advance() exits only on
record-key release or acknowledged completion. A mid-session cancellation
(supersession, lost-cell deadline, ParkCollisionResidents, generation cancel —
all route through ForgetPlacementCompletionCore) leaves _pending set
forever, so AcceptedPositionDrivePendingCount keeps IsConverged false for
the rest of the session. GameWindowLifetime.DisposeGameRuntime:490-498 throws
on non-convergence.
Plan §4c required dropping the pending ack on cancellation, supersession,
teardown, generation change and reset. Only teardown and reset shipped. Use
IsPlacementCompletionTracked. Also: the _pending = null cleanups are all
guarded by if (!firstAttempt), and SubmitAndResolve(firstAttempt: true)
assigns _pending without inspecting an existing one — make it refuse to
overwrite a live pending.
R7 — MEDIUM — the 0.48 fixture, the changed assertion, and the false doc
This is a test-fixture artifact, NOT a production regression. The headless
fixture's LoadedSetupCollisionSource returns one sphere
(Vector3.Zero, 0.48f) — centre AT the origin, bottom 0.48 m below the feet.
The real human Setup 0x02000001 is (0,0,0.475) r=0.48 plus
(0,0,1.350) r=0.48 (Ts46SphereListConformanceTests.cs:35-39), so the foot
sphere's bottom is origin - 0.005 and a settled origin lands on the floor within
5 mm. The control is in this same changeset: the new Runtime fixture uses the
dummy sphere (offset == radius) and asserts the origin lands exactly on the
floor (RuntimeAcceptedPositionDriveControllerTests.cs:178).
Required:
- Give the headless fixture the retail offset
(0f, 0f, 0.475f) r=0.48and restore theZ == 50fassertion. Changing an assertion to match new output is the plan's own forbidden move. - Delete the false comment at
HeadlessSessionHostTests.cs:419-427— it describes the sphere CENTRE and then asserts it aboutcontroller.Position, which is the ORIGIN (PlayerMovementController.cs:304->PhysicsBody.cs:153, retailCPhysicsObj::m_position.frame.origin). - Correct the
docs/ISSUES.md#285 "retail fidelity gain" paragraph. Retail'sBlipPlayerhas never lifted the origin by a sphere radius. Left as-is this becomes the citation a future session trusts.
R8 — MEDIUM — acceptance gaps
- No App-layer test exists proving the generic tail no longer double-writes the local player and that the committed projection is what moves the render entity. The plan's acceptance item 2 is unmet; three App tests were deleted and replaced with a comment. Given R4, this is precisely the seam that is broken.
RuntimeAcceptedPositionDriveControllerTests.cs:310-311assertsacksAfterFirstResolve <= 1, so the test passes with zero acks — the DeferredCell park -> wake -> commit -> single-ack sequence is unverified, whiledocs/ISSUES.mdclaims it is covered. Fix the fixture so the contact gate is satisfied and assert exactly one, or state plainly that it is unverified. Do not leave the overclaim in the record.
R9 — LOW — hygiene
RuntimeAcceptedPositionDriveControllerispublic sealedwith an internal ctor and all-internal members; its templateRuntimeFirstEntryDriveControllerisinternal sealed. Make it internal unless the public surface is genuinely required (if it is, say why).PlayerMovementController.cs:632has a stale<see cref="BlipPosition"/>to a deleted member. Harmless only whileGenerateDocumentationFileis off;TreatWarningsAsErrorsis on, so it breaks the build the day docs are enabled.HeadlessSessionHost._currentSessionis never cleared on teardown.- Headless without a content lease leaves the drive controller null, so the
ForcePosition and its ack are dropped entirely
(
HeadlessSessionHost.cs:568-581); previously the ack fired unconditionally. LiveEntityNetworkUpdateController.cs:1140-1155firesMarkLiveOwnerPoseDirtyandObserveAcceptedLocalPositionfor ANY non-NotApplicablestatus includingRejectedandContention— moving the streaming observer to a landblock we explicitly refused to place into.
Gate
Unchanged: complete Release solution suite, not a focused subset. Pre-change baseline is 10,844 / 4 skipped / 0 failed; the first pass reached 10,848 with the defects above, so a green suite is necessary and demonstrably not sufficient. Both reviews must be re-run on the fixed diff before commit.
ROUND 2 — residuals after the R1-R9 fix round (2026-08-03)
Both delta reviews returned FAIL again. Suite is green at 10,853 / 4 / 0, which again proves nothing. R2, R3, R4, R5, R6, R7 and R9 are confirmed genuinely fixed and must not be churned. Three blocking residuals remain, and two of them are defects in the R1 reissue mechanism itself.
Root of the problem: _pending has no single owner and no single lifecycle
rule. Round 1 bolted reissue onto ad-hoc per-branch bookkeeping. B1 wants MORE
reissuing, N1 wants LESS, and N2 wants reissue to be a DIFFERENT route — they
look contradictory only because there is no unifying rule. There is one.
The unified mechanism (implement exactly this — it replaces the ad-hoc rules)
RuntimeEntityPlacementToken already carries PositionAuthorityVersion
(RuntimeSetPositionState.cs:50). Make that the single decision input.
One rule: the drive owns at most one in-flight placement for the local
player. After any terminal outcome, and on every Advance(), compare the
committed/parked token's PositionAuthorityVersion against the live record's
current PositionAuthorityVersion:
- Equal — the canonical accepted authority has not moved since this
operation began. Nothing is outstanding. Clear
_pending. Do not reissue. - Advanced — a newer accepted Position arrived while we were in flight, and
it may have been the thing that killed our operation. Consult the newest
accepted event's disposition (do NOT reuse
stale.Route):- still ForcePosition — reissue, re-classifying from the current record.
- now an ordinary Apply — clear
_pendingand do NOT reissue. The correction was superseded by newer server truth; the ordinary route owns that pose. This is not a silent drop: retail applies each event as it arrives, and a force correction overtaken by a newer position is moot.
Route every terminal branch through one _pending funnel. No branch may assign
or clear it directly.
B1 — BLOCKING — a force correction is still silently dropped (conformance)
When a parked operation wakes and its Place is ACCEPTED by the sink, the
operation leaves _operations but the completion is retained. CancelCoreDeferred
then returns early at RuntimeSetPositionState.cs:5141 without reaching
ForgetPlacementCompletionCore, so the retained completion survives. The next
ForcePosition hits HasRetainedCompletion (:1319) -> invalid token ->
Contention (RuntimeAcceptedPositionDriveController.cs:289-295); both hosts
return without placing or acking, and the next Advance() consumes the OLD
completion and acks the OLD pose. That packet's correction is lost.
One-frame window on the graphical host only (_session.Tick() inbound dispatch
precedes RetryPending() in RetailLiveFrameCoordinator); headless is immune
because its pump is adjacent to the readiness check. The DECLINED-Place
variant is unaffected and needs no change.
The unified rule fixes this: the new packet advanced PositionAuthorityVersion
past the committed token, and the newest event is a ForcePosition, so it
reissues.
N1 — BLOCKING — stale _pending causes a second placement AND a second ack
SubmitAndResolve(firstAttempt: true) (:297) never inspects _pending, and
only the !firstAttempt branches clear it (:508-511, :482-484, :549-551).
So: park -> Forget wipes the watch -> the same packet's ForcePosition Begins
cleanly and Commits -> ack fires -> _pending still holds the dead P1 -> next
Advance() finds the watch dead -> ReissueFromCanonical -> a second
canonical placement and a second outbound AutonomousPosition for one server
correction.
That is the double-apply/double-ack class this entire slice exists to delete
(670f307c), reintroduced. AssignPending does not catch it because it is only
reached on the DeferredCell/retryable branches. The unified funnel fixes it:
equal versions -> clear, no reissue.
N2 — BLOCKING — reissue applies force semantics to an ordinary pose
ReissueFromCanonical (:418-447) reuses stale.Route verbatim —
SetPositionSimple + Teleport|Slide|SendPositionEvent +
SendPositionImmediately: true. But the commonest way a park dies is an
ordinary Apply Position, whose retail route
(RuntimeAuthoritativePositionRouteClassifier.cs:368-388) is
Interpolate/NoPositionOperation, PhysicsSetPositionFlags.None,
ConstrainPhase.BeforePositionOperation, SendPositionImmediately: false.
So the reissue converts an ordinary server echo into a hard Teleport|Slide
canonical placement, sends an ack retail would never send on that branch, and
skips the ConstrainTo the ordinary branch runs. My round-1 direction sanctioned
re-issuing THE CORRECTION; it did not sanction re-classifying a different
disposition's pose as a force. The unified rule fixes this by consulting the
newest accepted disposition.
If any residual divergence remains after this, it needs a
docs/architecture/retail-divergence-register.md row in the same commit.
B2 — BLOCKING (record accuracy) — the plan claims coverage it does not have
docs/plans/2026-08-02-placement-cutover.md:287 reads "R8 added the App-layer
double-write source pins the plan's own acceptance item required." That is a
claim of coverage. The truth, per the adversarial review:
- acceptance item 2's first half is source-pinned, not proven — the
Assert.Singleregex would still pass if a second write were spelled differently, and no test exercises the branch; - acceptance item 2's second half — "the committed projection is what moves
the render entity" — is uncovered at any layer. No test drives a route-2
ForcePosition through
RuntimePlacementPresentationSink/TryApplyRuntimePlacementPlaceand asserts theWorldEntitymoved.
Correct the text to record the gap explicitly. A documented gap is acceptable; a false claim of coverage is not. Same rule that produced R7.
Non-blocking — record, do not fix in this round
- N3 — headless never calls
RetryPendingafter construction (grep finds no caller outsidesrc/AcDream.App/). R4's fix depends on the subscription's retry, so a declined headlessPlacewould wedge the ordered stream. Latent, not proven reachable. File it. - N4 —
Advance()lacks the_drivingreentrancy latch its templateRuntimeFirstEntryDriveController.DriveAll:128-148has. No live re-entrant path today. Hygiene. - N5 —
CenterOnAcceptedForcePositiondoes not restorecontroller.LocalEntityId = record.LocalEntityId ?? 0u(inert today, but an unreplaced deletion);_movementTruthDiagnostics.OnServerEchono longer fires for a local ForcePosition (diagnostic only). - R9 residue —
ConstraintManager.cs:25andPhysicsBody.cs:442still cite the deletedBlipPositionin<c>tags (build-safe, but false docs). - Route-1 ack — the plan required confirming whether the ack fires while an
initial-Create residence owns the record. It does not;
SendPositionImmediatelyis consumed only as a trace fact in the continuation executor (:717,:2576). Not a regression, but the plan said file it. File it. - AD register row — the headless 3x3 collision window is now a named member
of the Runtime-facing
IRuntimeDirectWorldProjectioncontract with an ordering requirement retail has no analogue for, and no existing row covers it (AD-6 is retired; AD-2 is the graphical reveal barrier). Recommend a row. - Stale comment — the
HeadlessSessionHostTestscomment references "the previous 50.48f assertion", which does not exist at HEAD.
ROUND 3 — final round (2026-08-03)
The round-3 adversarial review returned PASS. The round-3
conformance review returned FAIL on one item. This round closes that
item and files the adversarial review's non-blocking findings. The round-2
unified _pending funnel was confirmed sound by both reviewers and was NOT
restructured.
The blocker — a terminal-without-commit sent no ack (CLOSED)
SettlePending's Equal branch was reached both by a successful commit and by a
terminal outcome that never committed (non-retryable prepare failure, the
default: Rejected/Cancelled branch, and both Advance death branches). In the
non-commit case the body never moved AND no outbound AutonomousPosition left.
The conformance reviewer proposed a committed flag plus a
one-re-issue-per-Advance guard. That is more than retail requires, and the
retail evidence was re-verified from
docs/research/named-retail/acclient_2013_pseudo_c.txt before coding:
SmartBox::BlipPlayer@0x00453940 (line 92528) callsCPhysicsObj::SetPositionSimple(this->player, edi_1, 1)@0x00453968 and discards its return value.BlipPlayeritself returnsvoid.CPhysicsObj::SetPositionSimple@0x005162B0 (line 284276) is declaredenum SetPositionError __thiscall. Other retail call sites DO test it —if (CPhysicsObj::SetPositionSimple(...) == OK_SPE)at @0x0055605D and @0x00556021 — which proves the discard inBlipPlayeris deliberate, not a decompiler artifact.SmartBox::HandleReceivedPosition@0x00453FD0's FORCE_POSITION branch callsSmartBox::BlipPlayer@0x00454074, stampsupdate_times[0]@0x00454079, then runscmdinterp->SendPositionEvent()@0x00454091 unconditionally and returns @0x0045409D.
Retail's semantics are therefore: attempt the placement once; if it fails the body simply does not move; acknowledge regardless; never retry. No commit flag and no recursion guard are needed to express that.
Implemented. The ack is now sent exactly once per BEGUN placement, at its
terminal outcome — from ReconcileAndAcknowledge on the commit path, or from
SettlePending on a non-commit terminal. SettlePending gained a
positionEventOwed parameter; Pending gained a PositionEventOwed field so
the re-issue retry marker (which stands for a packet whose placement was never
begun) cannot double-ack. The commit paths pass false because their ack has
already left. The non-commit ack runs no reconciliation — the body did not move,
so there is no committed frame to reconcile — and therefore carries the body's
unchanged pose, which is exactly what retail's ack carries after a failed
SetPositionSimple and is informative to the server: its force did not take.
The CanSendPositionEvent gate was left untouched; it is retail's own
(CommandInterpreter::SendPositionEvent @0x006B4770 tests the transient-state
contact bits), so a legitimately airborne body still suppresses the send on both
paths.
ReconcileAndAcknowledge was split so both paths share one outbound site,
SendPositionEvent.
Other items closed this round
- AD-62 rewritten. The
DeferredCell-park precondition is dropped — it was never required, and the never-parked failure paths reach the same outcome. The row now leads with the general rule and keeps the named shapes as examples, adds the externally-blockedContentionshape (nothing recorded, nothing pumps it) and the otherPositionAuthorityVersionadvances (TryApplyPickupRuntimeEntityObjectLifetime.cs:1116,CommitPositionChannelUpdate:2041,AdvanceCreateAuthority:2466), and separates the shapes that now lose only the re-apply from the narrower shapes that still lose the ack too. - Overstated doc corrected.
AcceptedForceObservation's comment claimed the record's current version equals the recorded force's version if and only if the newest accepted event was that force. False —AdvancePositionAuthorityhas four call sites. It is now stated as the one-way test it actually is. - Vacuous assertion deleted. The
gameActions.Count <= 2assertion inAdvanced_ReissuesWhenTheNewestAcceptedEventIsStillAForcePositioncould not fail: that fixture'sCommitLandblockCollisionadds both landblocks atworldOffsetX/Y: 0fwhile the world frame places the deferred landblock at +192/+192, so the body lands over no terrain,InContactis false, and every ack is suppressed — the count is 0. It was also too loose to encode "at most one per packet". Deleted rather than shipped; the test's real discriminators (body position,PendingCount) stay.
Tests
Two added, both with a verified discrimination check (the implementation was temporarily broken in each direction and the intended test observed to fail, then reverted and re-verified):
TerminalWithoutCommit_SendsExactlyOnePositionEventAndLeavesTheBodyUnmoved— a park retired without committing sends exactly oneAutonomousPosition, performs no placement of its own, and never repeats on further pumps.Committed_SendsExactlyOnePositionEventAcrossTheCommitAndTheSettle— the new settle-side ack does not become a second ack on the committed path.
Two existing tests changed their ack expectation from Assert.Empty to
Assert.Single, because they exercise terminal-without-commit paths whose
Empty encoded the defect this round removes:
Equal_ClearsPendingWithoutReissuingWhenNoNewerAcceptedAuthorityArrived and
Advanced_DoesNotReissueWhenTheNewestAcceptedEventIsAnOrdinaryApply. In the
latter the single ack belongs to the FORCE packet, not to the ordinary echo —
retail's ordinary branch has no unconditional SendPositionEvent.
Measurement note, recorded because it corrects an assumption in this file's
round-2 text: the DeferredCell park these fixtures use is the POST-engine
quiescence park, so _physics.Engine.SetPosition has already moved the
canonical body to the destination while the placement itself is withdrawn and
parked. The new test therefore captures its unmoved/no-further-placement
baselines at the park, and asserts them across the terminal settle, which is the
thing under test.
Filed, not fixed
docs/ISSUES.md #293 (the DeferredCell branch still consumes Withdraw
receipts the sink may have declined — the same shape R4 removed for Place),
#294 (ReconcileAndAcknowledge runs before the funnel's currency guard on the
deferred wake), #295 (the retry marker inflates
AcceptedPositionDrivePendingCount, which is an in-flight-placement counter),
#296 (a retryable prepare is reported to hosts as Contention, conflating a
retained-and-pumping case with a dropped one).
Gate
Complete Release solution suite, unchanged discipline: green is necessary and demonstrably not sufficient — all four prior states were green and three were defective.