refactor(physics): hoist the live-entity collision builder to Runtime (#330 groundwork)
Some checks are pending
Headless portability / portable-headless (ubuntu-latest) (push) Waiting to run
Headless portability / portable-headless (windows-latest) (push) Waiting to run
Headless portability / linux-graphical (push) Waiting to run
Headless portability / linux-vulkan (push) Waiting to run
Some checks are pending
Headless portability / portable-headless (ubuntu-latest) (push) Waiting to run
Headless portability / portable-headless (windows-latest) (push) Waiting to run
Headless portability / linux-graphical (push) Waiting to run
Headless portability / linux-vulkan (push) Waiting to run
LiveEntityCollisionBuilder and LiveEntityDefaultPoseResolver move from AcDream.App.Physics to AcDream.Runtime.Physics with no behaviour change — diff-verified byte-identical shape math by both review lenses. The Build signature's App-record parameter is replaced by presentation-free primitives with identical guard semantics, INCLUDING the FinalPhysicsState read the contract had missed and the implementer surfaced rather than dropped. Visibility stays internal: Runtime's existing InternalsVisibleTo grants already cover every consumer, so the implementation's public widening is reverted per the architecture review's finding 11. The registration WIRING is deliberately WITHHELD. Both Opus lenses failed it, converging: a shadow registered at spawn freezes there (RuntimeRemotePhysicsUpdater is Runtime-homed but App-driven — nothing headless ticks it), so a walking NPC becomes a phantom obstacle at its spawn point while the real NPC still passes through the bot; three of five shadow-lifetime edges leaked (pickup leaves a permanent invisible collider, supersession orphans a duplicate, generation reset never unregisters and the K-ledger convergence oracle only checks retained shadows AFTER disposal clears them); and headless cannot resolve BSP collision assets at all, so doors and chests would still be walk-through. The frozen-shadow root was the SESSION LEAD's contract error (fact 3), not the implementer's. #330 stays OPEN, rewritten as the seven-point scope map the reviews produced — the honest overnight deliverable is that map, not a half-mechanism carrying new divergences. Suite 11,235 passed / 4 skipped / 0 failed (the withheld seam's two tests account for the delta from the implementation run's 11,237). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
5629e2cb12
commit
55b07f6a62
12 changed files with 255 additions and 35 deletions
|
|
@ -803,7 +803,62 @@ If the one-frame deletion is ever judged unacceptable, the lever is the
|
|||
|
||||
## #330 — The headless host registers no live-entity collision at all: a bot walks through every NPC and every server-spawned object
|
||||
|
||||
**Status:** OPEN
|
||||
**Status:** OPEN — **SCOPE MAPPED 2026-08-07 by a dual Opus review of a
|
||||
withheld implementation; the builder hoist landed, the wiring did not.**
|
||||
|
||||
An overnight implementation attempt wired spawn-time registration into the
|
||||
no-window route. Both review lenses failed it, converging (two reviewers
|
||||
converging = near-proof, per the project's own rule), and the findings ARE
|
||||
the issue's true scope — recorded here so the next attempt starts from the
|
||||
map instead of rediscovering it:
|
||||
|
||||
1. **A headless remote-motion tick does not exist.** `RuntimeRemotePhysicsUpdater`
|
||||
is Runtime-HOMED but App-DRIVEN (constructed only at
|
||||
`RemotePhysicsUpdater.cs:46`, ticked only from
|
||||
`LiveEntityAnimationScheduler.cs:351`), and `GetOrCreateRemoteMotion` has
|
||||
one production caller, in App. A shadow registered at spawn therefore
|
||||
FREEZES at the unsettled wire pose: a walking NPC becomes a phantom
|
||||
obstacle at its spawn point while the real NPC still passes through the
|
||||
bot — strictly worse than the honest gap. This is the load-bearing
|
||||
prerequisite.
|
||||
2. **Live collision-asset publication does not exist headless-side.** The
|
||||
headless `PhysicsDataCache` holds only the per-landblock static closure;
|
||||
there is no `IPreparedCollisionSource` on-demand pull
|
||||
(graphical: `LiveCollisionAssetPublisher`). Without it,
|
||||
`_physicsBspBounds` is null for live-entity parts, BSP dispatch never
|
||||
fires, and doors/chests/statues/portals get the wrong shape or none.
|
||||
3. **Degrade resolution:** the graphical route resolves collision part ids
|
||||
through `GfxObjDegradeResolver` slot-0 walking; raw `setup.Parts` is the
|
||||
wrong id for every humanoid part.
|
||||
4. **Shadow lifetime hangs off FIVE edges, not two:** wire delete, pickup
|
||||
(`TryApplyPickup` leaves a permanent invisible collider from a looted
|
||||
item), same-guid generation supersession (`RetireCanonicalOnly` path has
|
||||
no unregister → duplicate phantom), GENERATION RESET
|
||||
(`HeadlessGenerationResetHost.RetireEntityProjection` is an empty no-op
|
||||
and `ResetSessionPhysics` does not clear `ShadowObjects` — registrations
|
||||
leak across reconnects), and hidden/withdrawn suspension.
|
||||
5. **The K-ledger cannot see any of this:** `RuntimePhysicsOwnershipSnapshot.IsConverged`
|
||||
checks retained shadow count only AFTER disposal, and disposal clears the
|
||||
registry. Extending the convergence oracle to pre-disposal retained
|
||||
counts is part of this issue's test work, or every leak above ships green.
|
||||
6. **Ordering + retry:** registration must follow `ProjectSpawn` (a throw
|
||||
after `ApplyAcceptedSpawn` leaves a committed-but-unprojected entity),
|
||||
and a spawn arriving before the world frame publishes needs a retry pump
|
||||
— the withheld code silently dropped it for the incarnation's lifetime.
|
||||
7. **The appearance route EXISTS** (`OnAppearanceUpdated`) and must rebuild
|
||||
collision, as the graphical binding does.
|
||||
|
||||
**What DID land 2026-08-07:** the builder hoist —
|
||||
`LiveEntityCollisionBuilder` + `LiveEntityDefaultPoseResolver` moved to
|
||||
`AcDream.Runtime.Physics` (internal + existing IVT), `Build(...)`'s
|
||||
App-record parameter replaced by presentation-free primitives including the
|
||||
`FinalPhysicsState` the contract had missed. Both reviewers passed the hoist
|
||||
explicitly; the graphical host is diff-verified unchanged. The wiring
|
||||
attempt itself is preserved in the review transcripts, not in the tree.
|
||||
|
||||
**Original entry below.**
|
||||
|
||||
**Status (original):** OPEN
|
||||
**Severity:** HIGH for headless gameplay fidelity; zero impact on the graphical client.
|
||||
**Filed:** 2026-08-06, from the AP-22 deletion's blast-radius survey (§5 of
|
||||
[`docs/research/2026-08-06-ap22-contract.md`](research/2026-08-06-ap22-contract.md)).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue