docs: close #297-#299 with SHAs; session handoff

Marks #297 (9b1e6fc6), #298 (bc0077a5) and #299 (88348f67) DONE per the
issue-tracking rule, and adds a handoff covering what landed, what still needs
the user's eyes, and the route 4 decision waiting on them.

Three items are implemented and suite-green but NOT user-verified: collision
with PKLite players (including the equip/unequip case round 1 got wrong),
melee/bow on a PKLite player plus the auto-target guard, and combat-camera
tracking of a PKLite opponent.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-03 21:30:17 +02:00
parent bc0077a55f
commit b17f5cee49
2 changed files with 97 additions and 3 deletions

View file

@ -446,7 +446,7 @@ diff: `9966b531` touched none of `CollisionExemption`, `CombatTargetPolicy`,
`0f2d98c5`). `@pklite` made pre-existing behaviour reachable; it did not create
it. Do #297 FIRST — #298 depends on it.
- **#297OPEN — PublicWeenieBitfield is frozen at CreateObject, so a PK
- **#297DONE `9b1e6fc6` (2026-08-03) — PublicWeenieBitfield is frozen at CreateObject, so a PK
status change never reaches the client. HIGH.** User symptom: after `@pklite`,
the local player walks straight through other PKLite players.
ACE's only PK-change message is `GameMessagePublicUpdatePropertyInt` (0x02CE)
@ -483,7 +483,7 @@ it. Do #297 FIRST — #298 depends on it.
Note the vivid target indicator (`WorldSelectionQuery.cs:271-298`) reads the
spawn PWD bits directly and is stale by the same mechanism.
- **#298OPEN — melee/missile attack admission excludes players by
- **#298DONE `bc0077a5` (2026-08-03) — melee/missile attack admission excludes players by
construction. MEDIUM-HIGH. Blocked on #297.** User symptom: selecting a
PKLite player and attacking retargets to the nearest monster (auto-target on)
or does nothing (auto-target off, logging
@ -531,7 +531,7 @@ it. Do #297 FIRST — #298 depends on it.
lets the server arbitrate PK legality (retail
`ClientMagicSystem::ObjectCompatibleWithSpellTargetType` @0x00567230).
- **#299OPEN — CollisionExemption misses retail's mover-side
- **#299DONE `88348f67` (2026-08-03) — CollisionExemption misses retail's mover-side
IsImpenetrable branch, and its doc comment asserts the opposite. LOW.**
`CollisionExemption.cs:103` checks only the TARGET's `IsImpenetrable`, and the
class doc at `:33-39` claims "retail's pseudo-C only checks the target's

View file

@ -0,0 +1,94 @@
# Session handoff — 2026-08-03
Branch `claude/acdream-physics-divergence-5aa784`. `main` is still at `c7d5fc14`;
nothing here is merged. Complete Release suite green at **10,904 passed /
4 skipped / 0 failed** (session start: 10,844).
## What landed
| Commit | What |
|---|---|
| `9966b531` | **C4 route 2 — ForcePosition** through the canonical placement |
| `69ba9486` | Retail `@pklite` client command (`EnterPkLite` 0x028F) |
| `3ef61eb6` | Route 2 visual gate, rewritten with the real recipe |
| `d980456f` | Route 2 connected gate **user-accepted** |
| `e3b766d9` | Filed #297-#299 |
| `40f57213` | **Route 4 scoping — budget failed, stop and re-plan** |
| `88348f67` | **#299** mover-side `IsImpenetrable` exemption branch |
| `9b1e6fc6` | **#297** keep the PWD bitfield live so PK status reaches the client |
| `bc0077a5` | **#298** admit player targets to melee/missile attack and the camera |
## Needs your eyes (nothing below is user-verified)
Route 2 is accepted. These three are not:
1. **Collision with PKLite players** (#297). Both parties `@pklite`, walk into
each other — you should now collide instead of phasing through. Then have
them **equip or unequip something** and try again: that is the case round 1
got wrong, and the fix is specifically about surviving it.
2. **Melee/bow on a PKLite player** (#298). Select them, attack. Should work
now. Also confirm auto-target still refuses to acquire a player — pull a
monster with a PKLite player nearby and check auto-target picks the monster.
3. **The combat camera** (#298). With `ViewCombatTarget` on (default), attacking
a PKLite opponent should now track them. Retail gates the camera on the same
predicate as the attack; we were using the narrow one.
Recipe for getting into PK Lite is in
[`2026-08-03-c4-route-2-visual-gate.md`](2026-08-03-c4-route-2-visual-gate.md).
Remember PK Lite is a **one-way** character state.
## The decision waiting for you: route 4
I stopped rather than starting it. After route 2 I pinned a falsifiable budget —
*if route 4 also costs ~900 production lines, the bet is dead* — and scoping came
back at **1,500-2,500 lines** plus ~1,700 lines of test re-modelling.
The seam generalises fine; route 2 just was not a representative unit (1 entity
vs N, 1 disposition vs 4, 1 execution path vs 2, 2 duplicate authorities vs 6).
**Recommendation: split route 4 into 4a and 4b.** 4a = near/interpolate +
airborne no-op — the observable win, no park hazard. 4b = teleport/far/cellless,
where the parks, the service-window guard, N3 and #277 all live.
Full analysis, including four findings that change the campaign plan (route 4's
Create half is already done; AP-131 cannot be retired by route 4; #277's safety
bound breaks; N3 stops being latent) is in
[`2026-08-03-c4-route-4-scoping.md`](2026-08-03-c4-route-4-scoping.md).
## Open follow-ups filed this session
- **#300** — `Properties.Ints[134]` vs `PublicWeenieBitfield` mirror gap.
- **#301** — retail's `OnStatUpdated` also rewrites radar blip colour and radar
behaviour; acdream ignores both. #297 for the radar.
- **#302** — `PortalProjectionTests.ClipToRegion_FrameOwnedStore_ReusesExactResultArray`
is flaky, ~1 run in 6, a `GC.GetAllocatedBytesForCurrentThread` assertion.
**A green suite is not proof this is gone.**
- **#303** — `LiveEntityPvpBitfieldSync` is App-resident but touches only
Runtime-owned state.
- **#304** — `SelectionInteractionController.GetSelectedOrClosestCombatTarget`
has no production caller; one of #298's two widened call sites is dead code.
- **#305** — `HeadlessGameplayOperations` has #298's bug unpatched, so the
graphical and headless hosts now diverge.
Register rows added: **AP-134** (the replicated PWD-bitfield coherence
invariant). **TS-23**'s retirement narrative corrected — it claimed since July
that every mover-flags site read the mover's "real" PK bits; the bits existed but
their source was frozen, so that only became true at #297.
## Process notes worth keeping
- **Four implementation passes and five review rounds on route 2, and every
intermediate state was green** — 10,848, 10,853, 10,856, 10,858. The suite
caught none of the four real defects. Two of them were introduced *by* the
fixes for the other two.
- **Demanded regression tests found root causes that review missed.** #297's
"assert the flags survive an appearance rebuild" test is what exposed the
second snapshot store.
- **Three false claims reached documentation and were retracted before
commit** — a "retail fidelity gain" that was a fixture artifact, an
acceptance-coverage claim in the cutover plan, and an IA-19 citation covering
a divergence it does not reach. Each would have become the thing a future
session trusted.
- **Go to the bytes when the decompiler is ambiguous.** #299 turned on whether
`if (state_1 < 0)` was a 0x80 or 0x8000 test; decoding the PDB-paired binary
settled it (`test al,al; js`).