After route 2 I pinned a falsifiable bet: routes 4-7 reuse the seam route 2 built, so their marginal cost should be well under 400 production lines, and if route 4 also cost ~900 the bet was dead. Scoping estimates 1,500-2,500 lines plus ~1,700 lines of test re-modelling. Honouring the bet: no implementation pass until the scope is re-planned. The bet failed for an instructive reason. The seam generalises fine — the begin/prepare/submit chain has no local-player precondition, the classifier's remote branches are already retail-exact, and all remote physics state is already in Runtime. Route 2 was simply not a representative unit: one entity vs N, one disposition vs four, one execution path vs two (canonical SetPosition AND the interpolation queue), no teleport hook, no constrain phase, two duplicate authorities vs six. Picking the simplest route first and then calibrating everything against it was the error. Four findings that change the campaign plan, not just route 4: - Route 4's Create half is already done (C3b/C3c). The remaining work is steady-state remote Position plus deletions; the route title misleads. - AP-131 cannot be retired by route 4. Route 2 did not fix its FORCE_POSITION half, and its local ordinary-Apply half is owned by no route in the inventory. - #277's safety bound breaks: it argues about Creates, while a steady-state Position can carry a remote out of the collision window with no Create at all. Needs a Position-time service-window guard on both hosts; the graphical host has no such predicate today. - N3 (headless never calls RetryPending) stops being latent the moment route 4 makes headless remotes produce placement receipts. Also records three previously unfiled divergences found while scoping: the NPC airborne hard-snap that ignores the wire IsGrounded bit, ConstrainTo armed before the operation instead of after, and ConstrainTo never armed on the remote teleport branch. Route 4 fixes all three by construction, which makes it a behaviour change to every visible creature rather than a refactor. Allocation is NOT the blocker the inventory feared: the steady state classifies to Interpolate, which runs no SetPosition at all. Recommends splitting route 4 into 4a (near/interpolate + airborne no-op — the observable win, no park hazard) and 4b (teleport/far/cellless — where the parks, the service-window guard, N3 and #277 live). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
175 lines
9.3 KiB
Markdown
175 lines
9.3 KiB
Markdown
# C4 route 4 — scoping, and a stop-and-re-plan (2026-08-03)
|
|
|
|
Scoped at HEAD `e3b766d9`, after route 2 shipped. **This is not a contract.** The
|
|
scoping says route 4 is materially larger than the budget it was given, so the
|
|
correct next action is a user decision, not an implementation pass.
|
|
|
|
## The budget, and how it failed
|
|
|
|
After route 2 I pinned a falsifiable bet: *routes 4-7 reuse the seam route 2
|
|
built, so their marginal cost should be far lower — well under 400 production
|
|
lines. If route 4 also costs ~900, the bet is dead and that is the signal to
|
|
stop and simplify.*
|
|
|
|
**Estimate: 1,500-2,500 lines of new/changed production code**, plus ~1,700
|
|
lines of test re-modelling. The bet failed before implementation started.
|
|
|
|
But it failed for a reason worth stating precisely, because it changes what to
|
|
do about it: **the seam generalises fine. Route 2 was just not a representative
|
|
unit.**
|
|
|
|
| | route 2 | route 4 |
|
|
|---|---|---|
|
|
| entities | 1 (local player) | N (every visible remote) |
|
|
| dispositions | 1 (ForcePosition) | 4 (SetPosition / SetPositionSimple / Interpolate / NoPositionOperation) |
|
|
| execution paths | 1 | 2 (canonical SetPosition **and** the interpolation queue) |
|
|
| teleport hook | never | `BeforePositionOperation` |
|
|
| constrain phase | never | `AfterPositionOperation` |
|
|
| duplicate authorities to delete | 2 | **6** |
|
|
| outbound ack | owns it | none |
|
|
| frequency | ~never | 5-10 Hz x N |
|
|
|
|
I chose route 2 first because it was simplest to reason about, then used it to
|
|
calibrate everything after it. That was the error: a one-entity, one-disposition,
|
|
no-interpolation route is the floor, not the median.
|
|
|
|
## What is genuinely reusable (the good news)
|
|
|
|
- The begin/prepare/submit/commit chain is **entity-kind agnostic** — no
|
|
local-player precondition anywhere in `TryBeginExclusiveAuthoredPlacement` →
|
|
`TryPrepareAndSubmitAuthoredPlacement` → `SubmitPreparedPlacementCore`.
|
|
- The classifier's remote branches are **retail-exact already** (verified against
|
|
`CPhysicsObj::MoveOrTeleport` @0x00516330 on all five behaviours).
|
|
- The placement receipt → presentation path is already entity-agnostic; C3c
|
|
drives remote Creates through it today.
|
|
- **All remote physics state already lives in Runtime** (J5.5) — `RemoteMotion`,
|
|
`EntityPhysicsHost`, the interpolation queue. No assembly boundary to cross.
|
|
- **`RuntimeAcceptedPositionDriveController` itself is ~15-20% liftable** — the
|
|
architecture, not the code. It is single-entity and ack-owning by construction
|
|
(`_pending` is one slot and `RetainPending` throws on a second).
|
|
|
|
## Four findings that change the campaign plan, not just route 4
|
|
|
|
**1. Route 4's Create half is already done.** C3b/C3c landed
|
|
`RuntimeRemoteFirstEntryState` + `RuntimeRemoteBodyDescription` and flipped both
|
|
hosts' Creates onto the residence conductor. Route 4's remaining work is
|
|
**steady-state remote Position plus the deletions**. The route title is
|
|
misleading and will send an implementer hunting for a flip that already happened.
|
|
|
|
**2. AP-131 cannot be retired by route 4.** The row covers two halves: the
|
|
`!HasAnims` gate on `SetPlacementFrame`, and the FORCE_POSITION branch skipping
|
|
`unset_parent`. Route 2 did **not** fix the second — it consumes an
|
|
already-merged snapshot, so a ForcePosition still passes
|
|
`installPlacementFrame: true, clearParent: true`. Retiring AP-131 needs the
|
|
unconditional merge gone for *every* Position: remote (route 4), local
|
|
ForcePosition (a route-2 residual), **and local ordinary-Apply — which no route
|
|
in the eight-route inventory owns.** Either widen route 4 or move AP-131 to C5
|
|
with those two as prerequisites. Pinning "route 4 retires AP-131" pins something
|
|
route 4 alone cannot deliver.
|
|
|
|
**3. #277's bound breaks.** Its safety argument is that the collision window is
|
|
strictly larger than ACE's Create-broadcast group, so the far set is empty. That
|
|
is a statement about *Creates*. A steady-state Position can carry a remote out of
|
|
the window with no Create at all — a creature wandering off, or the >=96 m
|
|
far-snap branch by definition targeting something distant. Route 4 introduces a
|
|
second producer of far parks the radius argument never covered. Needs a
|
|
Position-time service-window guard on **both** hosts; headless has the predicate,
|
|
the graphical host has none and one must be built.
|
|
|
|
**4. N3 stops being latent.** The route-2 round-2 finding — headless never calls
|
|
`RetryPending` after construction, so a declined `Place` would wedge the ordered
|
|
stream — was filed as latent because headless remotes produced no placement
|
|
receipts. Route 4 makes them produce receipts for the first time. **Fix N3 in
|
|
route 4 or the headless stream wedges.**
|
|
|
|
## Three unfiled divergences found during scoping
|
|
|
|
Our production remote path diverges from the retail classifier on five
|
|
behaviours; three have no register row:
|
|
|
|
- **NPC airborne hard-snap** (`LiveEntityNetworkUpdateController.cs:1819-1823`)
|
|
writes `Body.Position`/`Orientation` and never consults `update.IsGrounded` at
|
|
all — it branches on the client-tracked `rmState.Airborne`. Retail returns 0
|
|
and writes nothing (@0x0051636D).
|
|
- **`ConstrainTo` armed before the operation, unconditionally** (`:1522-1529`),
|
|
so it arms on the airborne no-op retail skips and anchors to the *pre*-move
|
|
position on the far branch. Retail arms it *after* a nonzero `MoveOrTeleport`,
|
|
anchored to the post-move `m_position` (@0x00454254-@0x00454272).
|
|
- **`ConstrainTo` never armed on the remote teleport branch** (the path returns
|
|
at `:1504`, before `:1522`), where retail *does* re-arm after `teleport_hook`'s
|
|
`UnConstrain`.
|
|
|
|
Route 4 fixes all three by construction — which means **route 4 is a behaviour
|
|
change to every visible creature in the game, not a refactor.**
|
|
|
|
## Allocation: not the blocker anyone feared
|
|
|
|
The inventory's "frame-frequency routes are blocked on placement allocation"
|
|
warning was written pre-C2 and before anyone checked which branch remotes take.
|
|
The steady state — nearby, grounded, non-teleporting — classifies to
|
|
**`Interpolate`, which runs no SetPosition at all**. The 944 B/op cost applies
|
|
only to teleports, cellless first placements, and >=96 m remotes.
|
|
|
|
Arithmetic (assumptions, not a capture): 40 remotes x 7 Hz with ~10% on a
|
|
SetPosition branch ~= 26 KB/s. Pathological dense-town worst case ~= 264 KB/s,
|
|
about 2.4% of the Slice-G5 profile. **Not a blocker — provided the near branch
|
|
stays out of `SetPosition`.** The contract must forbid routing every remote
|
|
Position through it "for uniformity".
|
|
|
|
Unmeasured and worth measuring before pinning a budget: the legacy path's actual
|
|
cost (no gate covers `PhysicsEngine.SetPosition`), and the real near/far split in
|
|
live play.
|
|
|
|
## Route 4's one big advantage: it is trivially observable
|
|
|
|
Route 2 cost five review rounds largely because nothing a user could do would
|
|
trigger it. Route 4 is the opposite — every remote entity exercises it
|
|
continuously. Six checks, all within two minutes of ordinary play with a second
|
|
character:
|
|
|
|
1. **Near interpolate** — second character walks/runs in a circle 5-15 m away.
|
|
Smooth motion, no per-packet stepping.
|
|
2. **Airborne no-op** — they jump, and jump off a ledge. Clean parabola, clean
|
|
landing. Watch for invisible-but-solid, the #184 signature.
|
|
3. **Far-snap** — they run >96 m and back. No freeze at the boundary, no wrong Z.
|
|
4. **Remote teleport** — portal/recall out and back, plus an admin `@teleto`.
|
|
Arrive grounded, animating, immediately targetable.
|
|
5. **The leash** — route 4 moves `ConstrainTo` from before to after, stops arming
|
|
it on the airborne no-op, starts arming it on teleport. #167 was a leash bug.
|
|
6. **Creature blast radius** — pull a drudge, let it chase, melee it, let it die.
|
|
|
|
Weight this gate heavily. All four route-2 states were green and three were
|
|
defective; route 4 finally has a real oracle.
|
|
|
|
## The decision
|
|
|
|
Route 4 is worth doing — it fixes three unfiled divergences affecting every
|
|
creature, retires the largest duplicate-authority cluster in the codebase, and
|
|
builds the seam route 5 needs (the classifier gives Projectile *identical*
|
|
branches to Remote). But it is a 1,500-2,500 line behaviour change, not a wiring
|
|
job, and it should not start on a budget everyone knows is wrong.
|
|
|
|
Options, in the order I would rank them:
|
|
|
|
**A. Split route 4 into 4a and 4b.** 4a = the interpolation/near path plus the
|
|
airborne no-op (the steady state, highest visible value, no park hazard, no
|
|
service-window work). 4b = teleport/far/cellless, which is where the parks, the
|
|
service-window guard, N3 and #277 all live. Each gets its own contract, gate and
|
|
review. Roughly halves the blast radius per commit and puts the observable win
|
|
first.
|
|
|
|
**B. Do route 4 whole against a corrected budget** (~2,000 lines, 2-3
|
|
implementation passes, one adversarial review per pass). Honest, but it is a
|
|
large single commit touching every visible creature.
|
|
|
|
**C. Defer route 4; do routes 5-7 first.** Rejected — route 5 needs the same
|
|
seam, so this just moves the cost.
|
|
|
|
**D. Stop the campaign here and simplify instead.** The complexity concern that
|
|
prompted the budget is real, and `RuntimeSetPositionState` at 5,652 lines is the
|
|
obvious target. But route 4 is where three live divergences get fixed, so
|
|
stopping leaves known-wrong behaviour in the client.
|
|
|
|
**Recommendation: A.** It respects the budget's intent — keep each landing small
|
|
enough to review — without abandoning work that fixes real bugs. It also front-
|
|
loads the part with a clean live gate and defers the part with the known traps.
|