# Handoff — two teleport-OUT issues (no-collision-after-death, char-missing-after-portal) — 2026-06-24 **Branch/worktree:** observed on `claude/thirsty-goldberg-51bb9b` (`C:\Users\erikn\source\repos\acdream\.claude\worktrees\thirsty-goldberg-51bb9b`). References / named-retail live in the MAIN repo `C:\Users\erikn\source\repos\acdream\`. > **These are NOT regressions from the dense-town FPS work.** That work (commits > `290e731` cell-object batching, `9f51a4d` cell-particle consolidation, `a9d06a6` > apparatus strip, `02578dd` docs) is **finalized + committed** and touched > **render files ONLY** — zero physics / collision / streaming / movement / > membership code (verified: `git show --name-only 290e731 9f51a4d a9d06a6`). Do > NOT suspect those commits. The only indirect link: higher FPS makes the same > few-tick transient render across more frames, so it's more *noticeable*; the > underlying bug predates the FPS work (and collision is FPS-independent — physics > ticks at a fixed rate). --- ## The two issues (user-observed, 2026-06-24) Both are on the **teleport-OUT-to-outdoor** path and are almost certainly the same known **placed-but-unstreamed streaming gap** (#135/#138 family). ISSUES §51 says a streaming-gap fix "would fix **both** symptoms." They're split into two prompts only so they can be tackled independently — whoever picks one should read both. ### Issue A — no collision after death → portaled to Holtburg - **Symptom:** after dying and being teleported to Holtburg, the player has **no collision** (falls through / clips). - **Root (known, NOT this session's work):** the *placed-but-unstreamed gap* — on a teleport the player is placed immediately, but the destination landblock streams in a few ticks later; during that gap the physics resolve runs against an **empty world** (no terrain/collision meshes loaded), so collision finds nothing. - **ISSUES refs:** [`docs/ISSUES.md:51`](../ISSUES.md) (the far-town runaway/march + Z free-fall, "same root as #135/#138 placed-but-unstreamed gap"), and [`docs/ISSUES.md:138`](../ISSUES.md) (acceptance: "the outdoor world fully streamed, **collision working**"). Whether the death lands in a dungeon-exit (#138 proper) or an outdoor respawn-to-lifestone, the placement→stream→resolve timing is the same. ### Issue B — char missing sometimes after portal to outside - **Symptom:** after portaling outside, the **character (and other entities) are missing for a moment**, then pop in. - **Root (known = #138):** teleport-OUT re-hydrates world entities with **fresh monotonic Ids** a few ticks after arrival (`GameWindow` ~`:3251`, `Id = _liveEntityIdCounter++`); during that gap they aren't in the draw set, so they appear late ("objects come back"). The player is one of them. - **ISSUES refs:** [`docs/ISSUES.md:265`](../ISSUES.md) (#138 — "Teleport OUT of a dungeon loads the outdoor world incompletely + position desync"), [`docs/ISSUES.md:299`](../ISSUES.md) (the fresh-Id re-hydration detail + the cache-invalidation side-finding). --- ## ⚠ This is the DELICATE area — read before touching 1. **DO NOT guess-patch.** The teleport/streaming runaway burned **~5 failed attempts** (#145). Build the apparatus FIRST (capture → replay), per `memory/feedback_apparatus_for_physics_bugs.md`. 2. **A "streaming HOLD" was tried and REVERTED.** Freezing the per-tick resolve until the landblock loads produced a ~10 s freeze; the user called it "shaky and bandaid" (`feedback_no_holds_for_slow_foundation` in memory). The real fix is **fix the foundation** — make the destination stream *with* placement (the async equivalent of retail's synchronous load), not a gate that masks a slow stream. 3. **Capture first.** Reproduce a real teleport and capture the placement→stream→resolve sequence before proposing anything. ## Where to start reading (in order) - `claude-memory/project_physics_collision_digest.md` — physics / collision / cell-membership SSOT + the DO-NOT-RETRY table. **START HERE.** - `docs/ISSUES.md` #135, #138, #107, #145 (the teleport/streaming family). - `memory/reference_two_tier_streaming.md` — the A.5 streaming architecture (Region → Controller → LandblockStreamer → GpuWorldState; near/far radii). - The teleport/placement + streaming code: grep `GameWindow` for the snap/placement path (`[snap]`, `EXIT-expand`, `_liveEntityIdCounter`), the streaming `dungeon EXIT-expand → (x,y)` logs, and `PlayerMovementController` / `PhysicsEngine` arrival resolve. ## Capture apparatus (already in the tree) - `ACDREAM_CAPTURE_RESOLVE=` — JSON-Lines of every player-side `PhysicsEngine.ResolveWithTransition` (inputs + body before/after + result). Run it across a death→Holtburg teleport to see the resolve running against the empty world during the gap. - `ACDREAM_PROBE_CELL=1` — one `[cell-transit]` line per player cell change (old→new, reason). Low volume; shows the post-teleport cell march. - `ACDREAM_PROBE_RESOLVE=1` — per-resolve line (input/target/output, grounded, contact-plane, responsible entity). Heavy. - Launch (PowerShell): user `notan` / `MittSnus81!`, local ACE `127.0.0.1:9000`. See CLAUDE.md "Running the client against the live server". ## Likely fix shape (hypothesis, NOT confirmed — capture first) Make the teleport destination's near landblocks **stream synchronously (or placement waits on the first stream tick)** so the arrival resolve never runs against an empty world, AND the entity re-hydration completes before/with the first drawn frame — rather than a per-tick HOLD. Both symptoms (no-collision, char-missing) collapse to "the world isn't there yet when we place + resolve + draw." Confirm the exact gap timing from a capture before committing to a shape.