docs: reconcile project status and navigation

Add a canonical documentation map, modernize the public README, and align milestone, roadmap, architecture, issue, divergence, and session guidance with the July 20 baseline. Correct the far-teleport residual to issue #153, close visually accepted indicator and terrain-tiling work, record the remaining detail-overlay and build-warning debt, and deprecate the duplicate legacy bug ledger.

Co-authored-by: OpenAI Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-20 13:00:41 +02:00
parent a755b764bf
commit 6c3bd4ce4b
11 changed files with 429 additions and 155 deletions

View file

@ -90,8 +90,8 @@ where ImGui cannot reach the 3D scene. Plugin gameplay UI uses the BCL-only
`AcDream.Plugin.Abstractions.IUiRegistry.AddMarkupPanel` contract; plugins
never import App or ImGui namespaces. Full design:
[`docs/plans/2026-04-24-ui-framework.md`](docs/plans/2026-04-24-ui-framework.md).
Memory cribs: `memory/project_chat_pipeline.md` (chat pipeline as of
Phase I), `memory/project_input_pipeline.md` (input pipeline as of
Memory cribs: `claude-memory/project_chat_pipeline.md` (chat pipeline as of
Phase I), `claude-memory/project_input_pipeline.md` (input pipeline as of
Phase K).
**Input pipeline:** `src/AcDream.UI.Abstractions/Input/` (action enum,
@ -112,14 +112,18 @@ movement queries.
component/target gates, live enchantment wire, Magic-scoped input, spell bar, spellbook, component
book, effect indicators, shared main-panel switching, and positive/negative effects UI are implemented over the Step-9 projectile/DAT-effect
foundation. The 2026-07-20 R6 complete-root-Frame/object-workset cutover is automated-test complete;
three independent conformance/architecture/adversarial re-reviews are clean, the Release build has
zero warnings, and the full suite is 6,452 passed / 5 skipped. Its unattended seven-destination
three independent conformance/architecture/adversarial re-reviews are clean, the Release build succeeds
(the clean documentation audit exposes 17 pre-existing test-project warnings, #228), and the full suite
is 6,452 passed / 5 skipped. Its unattended seven-destination
connected input/portal/performance rebaseline also passes without an interactive desktop. Remaining
ownership cleanup and registered TS-50/TS-51 timing residuals stay carried. **Next:** connected R6
locomotion/collision/projectile/teleport visual gate, then the final two-client
portal-out/materialization observer gate. **Carried:** #145-residual, #116, R6 residuals, Track MP0.
portal-out/materialization observer gate. **Carried:** #153, #116, R6 residuals, and the deferred
Modern Pipeline track (MP1b+).
Start magic work at `claude-memory/project_magic_ui_and_casting.md`; detailed state is below.
Documentation entry point: [`docs/README.md`](docs/README.md).
For canonical state, read in this order:
- [`docs/plans/2026-05-12-milestones.md`](docs/plans/2026-05-12-milestones.md) — milestone targets + freeze list per milestone
- [`docs/plans/2026-04-11-roadmap.md`](docs/plans/2026-04-11-roadmap.md) — what's shipped, what's in flight, what's next
@ -141,7 +145,7 @@ For engineering reference (read on demand, not at session start):
The memory dir also holds `feedback_*.md` lessons-learned (cross-cutting
patterns the project has agreed on) and `project_*.md` per-subsystem
cribs (chat pipeline, input pipeline, interaction pipeline, etc.).
See `memory/MEMORY.md` for the index.
See `claude-memory/MEMORY.md` for the index.
## Code Structure Rules

View file

@ -88,8 +88,8 @@ where ImGui cannot reach the 3D scene. Plugin gameplay UI uses the BCL-only
`AcDream.Plugin.Abstractions.IUiRegistry.AddMarkupPanel` contract; plugins
never import App or ImGui namespaces. Full design:
[`docs/plans/2026-04-24-ui-framework.md`](docs/plans/2026-04-24-ui-framework.md).
Memory cribs: `memory/project_chat_pipeline.md` (chat pipeline as of
Phase I), `memory/project_input_pipeline.md` (input pipeline as of
Memory cribs: `claude-memory/project_chat_pipeline.md` (chat pipeline as of
Phase I), `claude-memory/project_input_pipeline.md` (input pipeline as of
Phase K).
**Input pipeline:** `src/AcDream.UI.Abstractions/Input/` (action enum,
@ -110,14 +110,18 @@ movement queries.
component/target gates, live enchantment wire, Magic-scoped input, spell bar, spellbook, component
book, effect indicators, shared main-panel switching, and positive/negative effects UI are implemented over the Step-9 projectile/DAT-effect
foundation. The 2026-07-20 R6 complete-root-Frame/object-workset cutover is automated-test complete;
three independent conformance/architecture/adversarial re-reviews are clean, the Release build has
zero warnings, and the full suite is 6,452 passed / 5 skipped. Its unattended seven-destination
three independent conformance/architecture/adversarial re-reviews are clean, the Release build succeeds
(the clean documentation audit exposes 17 pre-existing test-project warnings, #228), and the full suite
is 6,452 passed / 5 skipped. Its unattended seven-destination
connected input/portal/performance rebaseline also passes without an interactive desktop. Remaining
ownership cleanup and registered TS-50/TS-51 timing residuals stay carried. **Next:** connected R6
locomotion/collision/projectile/teleport visual gate, then the final two-client
portal-out/materialization observer gate. **Carried:** #145-residual, #116, R6 residuals, Track MP0.
portal-out/materialization observer gate. **Carried:** #153, #116, R6 residuals, and the deferred
Modern Pipeline track (MP1b+).
Start magic work at `claude-memory/project_magic_ui_and_casting.md`; detailed state is below.
Documentation entry point: [`docs/README.md`](docs/README.md).
For canonical state, read in this order:
- [`docs/plans/2026-05-12-milestones.md`](docs/plans/2026-05-12-milestones.md) — milestone targets + freeze list per milestone
- [`docs/plans/2026-04-11-roadmap.md`](docs/plans/2026-04-11-roadmap.md) — what's shipped, what's in flight, what's next
@ -139,7 +143,7 @@ For engineering reference (read on demand, not at session start):
The memory dir also holds `feedback_*.md` lessons-learned (cross-cutting
patterns the project has agreed on) and `project_*.md` per-subsystem
cribs (chat pipeline, input pipeline, interaction pipeline, etc.).
See `memory/MEMORY.md` for the index.
See `claude-memory/MEMORY.md` for the index.
## Code Structure Rules

125
README.md
View file

@ -5,54 +5,64 @@ A modern open-source C# / .NET 10 Asheron's Call client.
Faithful port of the retail client's behaviour to Silk.NET with a modern,
plugin-friendly architecture. The code is modern; the behaviour is retail.
**Status:** playable pre-alpha. You can log in to an ACE server, walk and
run through Dereth, see other players animate correctly, watch the
day-night cycle, hear ambient audio, and take weapons out. Many systems
are still stubbed or in-progress — see roadmap.
**Status:** playable pre-alpha; M3 ("Cast a spell") is active. The connected
client supports the complete M2 combat/loot/inventory loop plus retained
spellbook, component-book, favorite-spell, enchantment, portal-space, radar,
chat, character, and inventory UI. Current work is verification and retail
conformance, not a first-playable bring-up.
Start at the [documentation map](docs/README.md) for the current milestone,
roadmap, tactical issues, architecture, retail-divergence register, research,
and durable memory.
## Stack
- **Language:** C# .NET 10
- **Graphics:** [Silk.NET](https://github.com/dotnet/Silk.NET) (OpenGL 4.3)
- **Graphics:** [Silk.NET](https://github.com/dotnet/Silk.NET) (OpenGL 4.3
context; `GL_ARB_bindless_texture` and `GL_ARB_shader_draw_parameters` are
mandatory)
- **Audio:** OpenAL via Silk.NET
- **Dat parsing:** [Chorizite.DatReaderWriter](https://github.com/Chorizite/DatReaderWriter)
- **Networking:** Custom UDP + ISAAC cipher + game-message layer, wire-compatible
with ACEmulator server
## What works
## What works today
- Connecting to a local ACEmulator (ACE) server on `127.0.0.1:9000`
- Character selection and login
- Rendering Dereth terrain with retail-correct texture blending,
per-vertex lighting, and road overlays
- Static scenery (buildings, trees, scenery objects) via EnvCell walker
- Animated characters (own + remote) with walk / run / strafe / jump /
turn / attack motions sourced from the retail motion tables
- Network sync with remote players — you can watch other characters
animate correctly, including speeds and directional motion
- Day-night cycle driven from the retail Region dat (0x13000000) —
correct DayGroup picking via the retail LCG, correct keyframe
interpolation, correct per-keyframe sky-object replace
- Weather (rain/snow particles synced from the server via the retail
DayGroup name)
- Sky dome, stars, moon, clouds, sun — each rendered from the retail
Region's SkyObjects with texture scrolling and alpha fade
- Plugin host with live event replay-on-subscribe
- ACE login, character selection, world entry, chat, client commands, and
graceful logout.
- Outdoor, building, cellar, and dungeon streaming with portal-space travel,
terrain/scenery/EnvCell rendering, collision, lighting, sky, fog, audio, and
day/night presentation.
- Local and observed player/NPC/monster movement, animation, selection, radar,
combat stances, melee and missile presentation, death, corpses, chests, and
looting.
- Inventory bags, stack splitting, paperdoll/equipment, weapon switching,
quick bars, item use, giving items to NPCs, and server-authoritative item
movement.
- Retained retail-style gameplay UI for vitals, chat, toolbar, inventory,
character/skills, spellbook/components, helpful/harmful effects, combat and
spell bars, radar/compass, indicator pages, and confirmation dialogs.
- Spell catalog, learned/favorite spells, component preflight, connected casts,
enchantments, DAT-driven missiles/effects, recall, Hidden/UnHide, and portal
materialization presentation.
- Plugin host, shared input/command abstractions, and permanent ImGui developer
tools behind `ACDREAM_DEVTOOLS=1`.
## What's stubbed or in-progress
## Active gaps
- Indoor transitions (building interiors) — disabled, Phase B.3 pending
- Combat — animation works, damage math not wired
- Lightning visual — the retail PhysicsScript-driven flash is researched
but not wired (see `docs/research/2026-04-23-lightning-real.md`)
- TimeSync drift — we only sync calendar on login, not periodically,
so acdream's in-game clock gradually drifts from retail's
- Landscape draw distance — currently `ACDREAM_STREAM_RADIUS=2` (~400m)
vs retail's several kilometres
- R6's complete object-frame update path still needs the next local visual
comparison; the final M3 gate is a two-client portal-out/materialization
observer comparison.
- Issue `#225` still needs the lifestone/particle alpha-order visual check,
although its connected lifetime/performance gates pass.
- Narrow behavior debt remains in issue `#153` (an unstreamed far-teleport
edge case), issue `#116` (slide feel), and registered TS-50/TS-51 effect
timing.
- Many later retail systems remain roadmap work: advanced social/vendor/trade/
crafting UI, full weather/lightning parity, deeper combat/stat systems,
graphical Linux, and a true headless multi-session bot host.
See `docs/plans/2026-04-11-roadmap.md` for the ordered phase list.
See `docs/ISSUES.md` for the rolling list of known bugs + small deferred
features (tactical, bug-level; the roadmap is strategic, phase-level).
See [docs/README.md](docs/README.md) for document authority and current links.
## Building + running
@ -74,7 +84,8 @@ $env:ACDREAM_TEST_HOST = "127.0.0.1"
$env:ACDREAM_TEST_PORT = "9000"
$env:ACDREAM_TEST_USER = "testaccount"
$env:ACDREAM_TEST_PASS = "testpassword"
dotnet run --project src\AcDream.App\AcDream.App.csproj -c Debug
$env:ACDREAM_RETAIL_UI = "1"
dotnet run --project src\AcDream.App\AcDream.App.csproj -c Release
```
Offline CLI dat inspector (no server needed):
@ -89,8 +100,11 @@ dotnet run --project src/AcDream.Cli -- "C:\path\to\Asheron's Call"
|---|---|
| `ACDREAM_DUMP_SKY=1` | Per-second dump of the interpolated `SkyKeyframe` values + per-SkyObject draw info + texture alpha histograms |
| `ACDREAM_DUMP_MOTION=1` | Dump every inbound `UpdateMotion` + resulting `SetCycle` |
| `ACDREAM_STREAM_RADIUS=N` | Tune landblock visible-window radius (default 2 = 5×5) |
| `ACDREAM_STREAM_RADIUS=N` | Legacy override for the configured two-tier streaming radii |
| `ACDREAM_NO_AUDIO=1` | Suppress OpenAL init |
| `ACDREAM_RETAIL_UI=1` | Enable retained retail gameplay UI |
| `ACDREAM_DEVTOOLS=1` | Enable ImGui developer tools |
| `ACDREAM_UNCAPPED_RENDER=1` | Disable normal presentation pacing for throughput measurement |
| `ACDREAM_DAY_GROUP=N` | Force a specific DayGroup index for A/B-testing weather presets |
| `ACDREAM_RUN_SKILL=N` / `ACDREAM_JUMP_SKILL=N` | Client-side run/jump skill (default 200) |
@ -98,16 +112,20 @@ dotnet run --project src/AcDream.Cli -- "C:\path\to\Asheron's Call"
```
src/
AcDream.App/ rendering + audio + main loop (Silk.NET)
AcDream.Core/ game state, meshing, physics, sky, weather, lighting
AcDream.App/ window, retained UI, rendering, audio, runtime wiring
AcDream.Content/ GL-free DAT mesh/texture extraction
AcDream.Core/ game state, physics, movement, world, gameplay logic
AcDream.Core.Net/ UDP + ISAAC + game-message layer
AcDream.UI.Abstractions/ shared UI/input ViewModels, commands, contracts
AcDream.UI.ImGui/ permanent developer-tool renderer
AcDream.Cli/ offline dat-inspector console app
AcDream.Bake/ offline content bake tooling
AcDream.Plugin.Abstractions/ plugin host interfaces
AcDream.Plugins.Smoke/ example plugin
tests/
AcDream.Core.Tests/ xUnit tests (742 passing)
AcDream.Core.Net.Tests/ network-layer tests
AcDream.*.Tests/ layer-matched xUnit projects (6,452 passing,
5 intentional skips at the 2026-07-20 baseline)
tools/
RetailTimeProbe/ Win32 P/Invoke ReadProcessMemory probe of
@ -122,7 +140,8 @@ references/ vendored read-only reference code — ACE,
Gitignored.
docs/
architecture/ single-source-of-truth architecture doc
README.md documentation map + authority order
architecture/ architecture, structure, divergence, WB inventory
plans/ phase roadmaps + per-phase specs
research/ decompile-derived research, per-phase
findings, deep-dive agent reports
@ -131,18 +150,20 @@ docs/
## Development workflow
All AC-specific behaviour is ported from the decompiled retail client
(`docs/research/decompiled/`). The workflow is:
All AC-specific behaviour is ported from the named retail client oracle
(`docs/research/named-retail/`). The workflow is:
1. **Decompile first.** Find the matching function in the decompiled
client.
2. **Cross-reference.** Check against ACE's C# port and ACViewer /
1. **Grep named retail first.** Find the matching `class::method` in the
Sept 2013 named pseudo-C and headers.
2. **Decompile only as fallback.** Use the older Ghidra chunks when the named
oracle lacks the function.
3. **Cross-reference.** Check against ACE's C# port and ACViewer /
WorldBuilder.
3. **Write pseudocode.** Translate C to readable pseudocode first.
4. **Port faithfully.** Translate line-by-line, preserving variable
4. **Write pseudocode.** Translate C to readable pseudocode first.
5. **Port faithfully.** Translate line-by-line, preserving variable
names and control flow.
5. **Conformance test.** Add tests using golden values from retail.
6. **Integrate surgically.** Minimise churn in the surrounding pipeline.
6. **Conformance test.** Add tests using golden values from retail.
7. **Integrate surgically.** Minimise churn in the surrounding pipeline.
Guessing at AC-specific algorithms is explicitly forbidden — see
`CLAUDE.md` for the full workflow rationale and the list of failure
@ -150,7 +171,7 @@ modes we've paid for in the past.
## Reference repos
We cross-reference five external projects for every retail behaviour:
We cross-reference six external projects for retail behavior:
- **ACE** (ACEmulator) — authoritative server-side protocol
- **ACViewer** — MonoGame dat viewer; good for character appearance

View file

@ -15,10 +15,33 @@ What does NOT go here:
## Conventions
- Sequential integer IDs (`#1`, `#2`, …). Commits that close an issue reference the ID in the message (e.g. `fix #3: periodic TimeSync parsing`).
- `Status` is `OPEN`, `IN-PROGRESS`, or `DONE`. DONE items move to the **Recently closed** section at the bottom with closed-date + commit SHA.
- `Status` is `OPEN`, `IN-PROGRESS`, or `DONE`. The status inside each issue is
authoritative. This long-lived file still has completed items interleaved
with open history; physical placement under an older heading is not status.
- New DONE items should move to **Recently closed** when practical. Do not do a
mechanical move of old blocks merely to tidy the file; preserve their
research context until a deliberate archive split.
- Every session: scan OPEN issues at start; promote/close anything we touched during the session before ending.
- Promoting to a Phase: mark as `DONE (promoted to Phase X)` + commit SHA where the Phase entry landed.
## Current queue — 2026-07-20
- **Next visual gate:** R6 locomotion/collision/projectile/teleport comparison
after the complete-root-Frame/object-workset cutover.
- **M3 closing gate:** `#218`, final two-client portal-out/materialization and
indoor observer comparison.
- **Separate rendering gate:** `#225`, lifestone/particle alpha ordering. Its
connected performance, lifetime, and unattended portal routes pass.
- **Carried behavior debt:** `#153` far-teleport unstreamed-edge arrival and
`#116` slide response. TS-50/TS-51 are tracked in the divergence register.
- **Deferred visual fidelity:** `#226` retail landscape detail overlay.
- **Build hygiene:** `#228` records 17 clean-Release test-project warnings;
production compilation and all tests pass.
The [documentation map](README.md) defines how this tactical ledger relates to
the milestone, roadmap, architecture, divergence register, research, and
memory.
## Template
Copy this block when adding a new issue:
@ -44,6 +67,80 @@ Copy this block when adding a new issue:
---
## #228 — Clean Release build emits 17 test-project warnings
**Status:** OPEN
**Severity:** LOW
**Filed:** 2026-07-20
**Component:** tests / build hygiene
**Description:** A fresh `dotnet build AcDream.slnx -c Release --no-restore`
succeeds with zero errors but emits 17 warnings from
`tests/AcDream.Core.Tests`. Earlier current-state prose claimed “zero warnings”
after an incremental gate in which those projects did not recompile.
**Root cause / status:** The warnings are existing nullable-flow (`CS8600`,
`CS8602`, `CS8625`), never-assigned test fixture fields (`CS0649`), and xUnit
analyzer findings (`xUnit1025`, `xUnit1031`, `xUnit2013`, `xUnit2017`). One
duplicate `InlineData` also causes xUnit to skip a duplicate test-case ID during
discovery; the intended unique cases still pass. This is test hygiene, not a
production runtime failure.
**Files:** `tests/AcDream.Core.Tests/Conformance/DatConcurrencyStressTests.cs`;
`tests/AcDream.Core.Tests/Physics/Motion/RemoteChaseEndToEndHarnessTests.cs`;
`tests/AcDream.Core.Tests/Physics/CellGraphMembershipTests.cs`;
`tests/AcDream.Core.Tests/Physics/DoorSetupGfxObjInspectionTests.cs`;
`tests/AcDream.Core.Tests/Physics/MotionInterpreterDoMotionFamilyTests.cs`;
`tests/AcDream.Core.Tests/Rendering/Wb/AcSurfaceMetadataTableTests.cs`;
`tests/AcDream.Core.Tests/Physics/MotionInterpreterTests.cs`;
`tests/AcDream.Core.Tests/Physics/CellArrayTests.cs`;
`tests/AcDream.Core.Tests/Streaming/StreamingControllerTwoTierTests.cs`.
**Acceptance:** A non-incremental Release solution build reports zero warnings
and zero errors without suppressing analyzers or weakening nullable checking;
the full 6,452-pass / 5-skip suite remains green.
---
## #226 — Retail landscape detail-texture overlay is not rendered
**Status:** OPEN — deferred visual fidelity; the user-visible tiling regression
in #155 is fixed
**Severity:** LOW
**Filed:** 2026-07-20
**Component:** rendering / terrain material
**Description:** Retail can overlay a high-frequency landscape detail texture,
faded by viewer distance and gated by the Environment Detail Textures setting.
acdream now repeats every base/overlay/road surface at its authored
`TerrainTex.TexTiling`, which fixed the stretched/blurry symptom in #155, but
does not yet render this separate optional detail layer.
**Root cause / status:** The earlier #155 investigation conflated two retail
mechanisms. `bb5acab9` ported the behavior that produced the observed mismatch:
`TexMerge::CopyAndTile`/`Merge` pass each source's authored base tiling into the
terrain composition. The still-missing detail pass is a distinct
`LScape::GenerateDetailSurfaces`/`ACRender::landPolyDraw` path. The first
experimental detail-array implementation sampled the wrong neutral/data
contract and was reverted rather than shipping a darkened ground. TS-52 records
the current divergence.
**Files:** `src/AcDream.App/Rendering/TerrainAtlas.cs`;
`src/AcDream.App/Rendering/TerrainModernRenderer.cs`;
`src/AcDream.App/Rendering/Shaders/terrain_modern.frag`.
**Research:** `docs/research/2026-07-13-retail-terrain-texture-tiling-pseudocode.md`
covers the now-shipped base contract. The detail symbols cited above must be
distilled into a dedicated pseudocode note as the first #226 implementation
step; the reverted experiment remains available in git history.
**Acceptance:** With retail Environment Detail Textures enabled, close ground
shows the same high-frequency detail and distance fade without changing base
color/brightness. Disabling it produces the already-accepted authored base
tiling.
---
## #225 — Scene particles overpaint translucent world objects
**Status:** IN-PROGRESS — implementation/reviews and connected stress gate pass; final visual gate pending
@ -172,6 +269,16 @@ The run was performed over RDP, but software pacing was explicitly disabled and
`pace` remained zero, so these are engine-throughput measurements rather than
remote-display refresh measurements. The lifestone/particle visual gate remains.
The 2026-07-20 unattended R6 rebaseline repeated the seven-destination route
without an interactive desktop and exercised semantic turn, forward, charged
jump, and combat input through the production dispatcher. All seven portal
materializations, outbound movement gates, same-location memory/update checks,
fatal-log scan, and graceful WM_CLOSE teardown passed. Caul update p95 was
1.2 ms on the first visit and 1.1 ms on return; Sawato was 0.2/0.3 ms. This is
additional lifetime/correctness evidence, not a replacement for the translucent
lifestone visual check. See
`docs/research/2026-07-20-connected-r6-soak.md`.
**Files:** `src/AcDream.App/Rendering/RetailAlphaQueue.cs`;
`src/AcDream.App/Rendering/Wb/WbDrawDispatcher.cs`;
`src/AcDream.App/Rendering/ParticleRenderer.cs`;
@ -210,7 +317,7 @@ degrade FPS, and revisiting an expired region restores its objects.
## #224 — Gameplay indicator bar only implemented effect icons
**Status:** IN-PROGRESS
**Status:** DONE — 2026-07-17, user visually confirmed after detail-panel polish
**Severity:** MEDIUM
**Filed:** 2026-07-17
**Component:** retained UI / gameplay indicators / session telemetry
@ -249,6 +356,13 @@ selected spell name/description now reflows to the authored width and its own
`0x10000127` scrollbar works independently of the upper effect-list scrollbar.
Vitae recovery XP also uses retail's grouped integer presentation.
**Resolution:** `52c529be`, `a96767ba`, `d1d60310`, `16c21e29`, and
`82789eea` ported the strip, shared pages, retail Vitae/Character Information,
button state, description wrapping, independent lower scrolling, and grouped
XP. The user accepted the resulting pages. Transport packet-loss averaging and
Mini Game gameplay remain explicitly tracked by AP-110 rather than keeping this
visible UI issue open.
**Files:** `src/AcDream.App/UI/Layout/IndicatorBarController.cs`;
`src/AcDream.App/UI/Layout/DatWidgetFactory.cs`;
`src/AcDream.Core.Net/WorldSession.cs`; `src/AcDream.App/UI/RetailUiRuntime.cs`.
@ -2618,42 +2732,42 @@ BCL-only.
**2026-07-09 triage:** investigated, verdict STILL_OPEN — a fix for this exact bug (`9444a328`, normalizing the panel root to (0,0) for off-screen FBO captures) exists but only on unmerged branches (`codex/mockup-stage` / `claude/peaceful-visvesvaraya-e0a196`); `StudioWindow.cs` on this branch still has no position-normalization code and the mechanism is unfixed here.
## #155 — Outdoor terrain textures look stretched + blurry vs retail (missing landscape DETAIL-texture overlay)
## #155 — Outdoor terrain textures looked stretched and blurry vs retail
**Status:** OPEN — **root cause VERIFIED (oracle-first); fix attempt implemented + REVERTED** (rendered the ground black). Ready for a focused fresh implementation pass.
**Severity:** MEDIUM (visible — outdoor ground reads soft/stretched everywhere vs retail's crisp ground; user side-by-side screenshots)
**Status:** DONE — 2026-07-13, `bb5acab9`, user visually confirmed
**Severity:** MEDIUM
**Filed:** 2026-06-25
**Component:** render — terrain texturing (WB-derived modern path: `TerrainAtlas` / `TerrainModernRenderer` / `terrain_modern.frag`)
**Component:** rendering / terrain texture composition
**Description (user-observed, 2026-06-25):** Outdoor terrain textures look stretched and less detailed than retail — a cobblestone road's stones look too big/blurry, grass is softer. Side-by-side: retail crisp, acdream smeared.
**Description:** Cobblestone, roads, and grass appeared enlarged and soft even
though the high-resolution source surfaces, mipmaps, and anisotropic filtering
were active.
**Root cause (VERIFIED — decomp + dat, not guessed):** acdream renders one base texture tiled **once per 24 m landcell** (`terrain_modern.frag:49` `const float TILE = 1.0;`, `vBaseUV` 0→1 per cell) and **ignores the dat's detail-texture fields entirely**. Retail overlays a high-frequency **landscape detail texture** on the base ground; that overlay is what keeps retail's ground crisp up close. Filtering is NOT the problem (the ground array already has mipmaps + `LinearMipmapLinear` + 16× anisotropy, `TerrainAtlas.cs:187-193`); resolution is NOT the problem (terrain is 512² in both Portal and HighRes).
**Corrected root cause / resolution:** The first investigation attributed the
whole symptom to retail's separate detail-texture overlay and incorrectly
claimed the base `TerrainTex.TexTiling` field did not exist. The later
named-retail/DAT audit disproved that claim. Retail
`TexMerge::CopyAndTile @ 0x00503580` and `TexMerge::Merge @ 0x005038C0` pass
each base, overlay, and road surface's authored `TexTiling` into composition.
acdream had hard-coded one repeat per 24-metre landcell. `bb5acab9` carries the
field through `TerrainAtlas`, uploads a layer-indexed table, and applies it in
the modern shader while leaving cell-scale alpha masks unchanged. The user
confirmed the outdoor textures now match the expected scale.
**Verified retail mechanism (decomp `docs/research/named-retail/acclient_2013_pseudo_c.txt`):**
- Dat fields on `DatReaderWriter.Types.TerrainTex` (confirmed via reflection on Chorizite.DatReaderWriter 2.1.7): `DetailTextureId` (`QualifiedDataId<SurfaceTexture>`, `.DataId`) + `DetailTexTiling` (`uint`). acdream currently reads neither (only `TextureId`).
- `ACRender::landPolyDraw` 0x006b6525 (lines 702299-702300): **detail UV = `curr_detail_tiling × baseUV`** (the detail texture tiles `detail_tiling×` relative to the base).
- `landPolyDraw` 0x006b6450-0x006b649c (lines 702263-702287): **distance fade** — detail alpha is FULL at camera depth `< 10`, lerps to 0 by depth `50`, gone beyond. (Detail only sharpens up close.)
- 0x0059cab4 / lines 425099-425112: blend = **`TEXOP_MODULATE`** (modern equivalent: MODULATE2X `base*detail*2`, neutral at gray 0.5).
- `TexMerge::GetDetailTiling` 0x00503a10 (line 263852); `LScape::GenerateDetailSurfaces`/`SetDetailTexturing` 0x00506b40 (line 268389). Gated by the `EnvironmentDetailTextures` graphics preference (`Render::m_RenderPrefs.EnvironmentDetailTextures`).
- **FAITHFULNESS NOTE:** retail uses a **single landscape detail-tiling SCALAR**`GetDetailTiling(region, 0)` reads `TerrainDesc[0].DetailTexTiling` (category 0 = landscape; default **2.0** @0x0081eca8), stored in global `Render::curr_detail_tiling` and applied to ALL terrain UVs. It is **NOT per-terrain-type**. Prefer the single scalar.
The optional high-frequency Environment Detail Textures pass is a different
retail mechanism. It remains deferred under #226/TS-52 and does not keep this
fixed user-visible regression open.
**⚠ DO-NOT-RETRY:** the first investigation agent **FABRICATED a base `TexTiling` field** — it does **NOT** exist on `TerrainTex` (only `DetailTexTiling`). Do not re-introduce a "read `TexTiling`, multiply the base UV" fix; the base tiling is not a per-type dat field. (Verify the actual base landcell UV scale in the decomp before touching `TILE`.)
**Files:** `src/AcDream.App/Rendering/TerrainAtlas.cs`;
`src/AcDream.App/Rendering/TerrainModernRenderer.cs`;
`src/AcDream.App/Rendering/TerrainTextureTilingTable.cs`;
`src/AcDream.App/Rendering/Shaders/terrain_modern.frag`.
**Fix attempt (implemented + REVERTED, this session):** built a parallel detail `GL_TEXTURE_2D_ARRAY` (per type from `DetailTextureId`) + `uDetailTiling[]` + the shader block `rgb *= mix(vec3(1.0), detail*2.0, fade)` with the 10→50 depth fade. It **compiled, linked, ran with no GL error** — but the ground rendered **black/dark up close**: the detail array sampled near-zero, so MODULATE2X collapsed `rgb` to 0. **The bindless handles were verified NOT swapped** (renderer correctly binds `(terrain, alpha, detail)`). The bug is in the detail-texture **DATA**: the no-detail gray fill (`NoDetailGray=128`) didn't land as neutral, OR `DetailTextureId` decodes dark/black, OR AC's detail textures are not 0.5-centered (so MODULATE2X darkens). Reverted via `git checkout` — terrain back to the working (blurry) state.
**Research:** `docs/research/2026-07-13-retail-terrain-texture-tiling-pseudocode.md`.
**NEXT (debugging steps for the fresh pass):**
1. **Dump the detail array content** — are the layers ~0.5 gray or ~0 black? (Throwaway: decode each `DetailTextureId` + print mean brightness.) This tells you gray-fill vs decode vs texture-content.
2. If the textures decode dark, AC detail textures may not be gray-centered → use plain MODULATE or re-center, not MODULATE2X. Confirm the actual blend visually.
3. Confirm `DetailTextureId``SurfaceTexture``RenderSurface` resolves (do the detail textures even exist for these terrain types? many may be 0 → must fall to the gray no-op).
4. Use retail's **single landscape scalar** (`TerrainDesc[0].DetailTexTiling`, default 2.0), not per-type (faithfulness note above).
5. Gate behind an `EnvironmentDetailTextures` equivalent.
6. **Secondary (separate, unconfirmed):** is the base `TILE=1.0` (once per cell) correct vs retail? Verify the landcell base UV scale in the decomp during the fix — it may also contribute to "stretched."
**Files (the reverted attempt, for reference):** `TerrainAtlas.cs` (detail array build + gray fill + `DetailTiling`), `terrain_modern.frag` (uDetail sampler + MODULATE2X + fade), `TerrainModernRenderer.cs` (bind detail handle + upload `uDetailTiling[]`).
**Milestone note:** freeze-override render-polish (off the M1.5 critical path); resume when prioritized. Detail-overlay is a real retail feature acdream lacks — register an AP row when it ships (or note it as a known divergence until then).
**Acceptance:** outdoor ground (cobblestone road + grass) reads crisp up close matching retail, detail fades cleanly past ~50 m, no overall color/brightness shift (modulate neutral); user side-by-side vs retail.
**Acceptance:** Authored grass, road, base, and overlay textures repeat at
retail scale without reducing source resolution or changing blend masks —
passed in the connected visual gate.
---
@ -2699,9 +2813,18 @@ BCL-only.
---
## #153Portals only work once per session (can't run in, run out, re-enter)
## #153Far teleport onto an unstreamed landblock edge can run away
**Status:** 🟡 PARTIALLY FIXED — REOPENED 2026-06-21 (a NARROWER residual). The cell-relative carried-anchor (Option B, Slices 13+7, `438bb68``403a338`) **fixes the cascade for a STREAMED-terrain arrival** (live-verified: `+Je` ran through ~10 far-town landblocks across 2 sessions, zero march). BUT a third live session found the cascade **RECURS when a teleport arrives onto a NOT-YET-STREAMED landblock NEAR AN EDGE.** Evidence (`launch5.log`): arrival `[snap] claim=0xC98C0028 pos=(113.666,190.259,22.010) branch=NO-LANDBLOCK (lbs=0) -> verbatim` (local Y=190.3, **1.7 m from the 192 boundary**) → cell marches `0xC98C(lbY 0x8C) → 0xC9FE(lbY 0xFE)` +2/tick while Z free-falls 22→19; the outbound wire then sends the marched cell `C9FE0031` with compensating garbage `localY=21684` → ACE `MOVEMENT SPEED` / `failed transition` → player stuck. Contrast same session: hub `0x00070133` VALIDATED→fine; far town `0x977B000C` arrived unstreamed but **mid-block** (Y=73.8) → Z free-fall only, NO march. **ROOT (hypothesis, NOT yet apparatus-confirmed):** outdoor teleport places immediately but the destination streams a few ticks later (`streaming: dungeon EXIT-expand -> (201,140)` logs just after placement); during that gap the resolve runs against an empty world, and at an edge the player crosses into the unstreamed neighbour where the carried anchor (which computes to `(0,0,0)` at the recentered center) gives no protection. Same root as the Z free-fall (`#135`/`#138` placed-but-unstreamed gap). **DO NOT guess-patch** (original #145 burned 5 attempts) — needs a capture + an anchor/guard diagnostic at the crossing FIRST. Likely fix shape: a streaming-gap HOLD (freeze the per-tick resolve — no march, no fall — until the player's landblock loads; the async equivalent of retail's synchronous load), which would fix both symptoms. Suites still green; `TeleportFarTownRunawayTests` covers the STREAMED case only. [Prior "fixed" banner was premature — 2 clean sessions wasn't enough for a streaming-timing bug.]
**Status:** IN-PROGRESS — the original repeat-portal failure and streamed-arrival
cascade are fixed; a narrower unstreamed-arrival-near-edge residual remains.
The cell-relative carried anchor (Option B, Slices 13+7,
`438bb68``403a338`) passed roughly ten streamed far-town transitions. The
recorded residual arrives within about 2 metres of a 192-metre landblock edge
before the neighbour is resident, then advances membership through unstreamed
cells while producing an inconsistent outbound cell/local-position pair. Keep
the capture-first/DO-NOT-RETRY constraints and detailed verified mechanism
below; this is the issue formerly misreferenced in living docs as
#145-residual.” Issue #145 is an unrelated completed UI Z-order bug.
**Status (historical):** REOPENED 2026-06-21 — RESIDUAL: a teleport to a FAR town triggers a per-frame **resolver runaway** (the 2026-06-20 source-drop fix holds for Holtburg↔dungeon, but far-town destinations regress). #138 (objects come back) is confirmed SEPARATE + fixed. Root cause under research (retail-decomp oracle workflow).
**Severity:** HIGH (blocks far-town portal travel; breaks collision after the teleport — user, 2026-06-21)
@ -3060,7 +3183,7 @@ Both are the **entity-lifecycle/render path across a teleport**, NOT the streami
**Acceptance:** portal out of the 0x0007 dungeon → full outdoor world streams (trees/scenery present), **server objects (doors/NPCs/portals) render**, **own avatar renders across repeated round-trips**, collision works, position tracks (no avatar-vs-camera desync).
**2026-07-10 gate — PASSED, #138 CLOSED:** the user confirmed the full dungeon round-trip end-to-end — ENTER + NAVIGATE (dungeon streams, renders, collides, navigable, doors work) AND the EXIT (portal OUT to the outdoor world, world streams, collision holds, position tracks). This completes the #138 acceptance and lands M1.5. **Separate follow-up still open:** `#145-residual` (the far-town teleport-OUT arrival cascade) is a narrow far-teleport streaming edge case tracked on its own; it is NOT a #138 or M1.5 blocker and stays open for capture-harness-first work if it recurs.
**2026-07-10 gate — PASSED, #138 CLOSED:** the user confirmed the full dungeon round-trip end-to-end — ENTER + NAVIGATE (dungeon streams, renders, collides, navigable, doors work) AND the EXIT (portal OUT to the outdoor world, world streams, collision holds, position tracks). This completes the #138 acceptance and lands M1.5. **Separate follow-up still open:** #153 (the far-town teleport-OUT arrival cascade) is a narrow far-teleport streaming edge case tracked on its own; it is NOT a #138 or M1.5 blocker and stays open for capture-harness-first work if it recurs.
---
@ -7468,7 +7591,7 @@ App 741+2skip / UI 425 / Net 385 green.
---
## #170 — Remote creature chase+attack renders wrong vs retail (glide, run not sustained)
## Historical closing summary for #170 — Remote creature chase+attack
**Status:** DONE (2026-07-04, user visual gate passed — "as close to retail now as
I can see"). Three-fix arc: `427332ac` deleted the per-frame
@ -8712,10 +8835,10 @@ The mechanism named as the suspect in #68 (`RemoteMoveToDriver`'s arrival handli
---
## #87 — Drop WB fork patch by switching to PrepareEnvCellGeomMeshDataAsync
## #227 — [DONE] Drop WB fork patch by switching to PrepareEnvCellGeomMeshDataAsync
**Status:** DONE (2026-07-09, investigated this session).
Superseded by Phase O (2026-05-21, dropped the `WorldBuilder.Shared`/`Chorizite.OpenGLSDLBackend` project references entirely — there's no more forked submodule to patch/revert) and Phase A8 (2026-05-28, shipped `EnvCellRenderer.cs` which already calls the narrow `PrepareEnvCellGeomMeshDataAsync(geomId, environmentId, cellStructure, surfaces)` entry point at `EnvCellRenderer.cs:355`, using the bit-32-tagged synthetic geom id the issue proposed). `ObjectMeshManager.cs`'s bounds/type dispatch now branches on resolution type before calling `TryGet<T>`, so the blind `TryGet<Setup>` bug is structurally gone. `EnvCellRenderer` remains the live production cell-rendering path under Phase U as of commit `6aabe0b5` (Jul 6 2026). Note: a second, unrelated, already-DONE issue also uses the heading `## #87` elsewhere in this file (a pre-existing numbering collision, left untouched).
Superseded by Phase O (2026-05-21, dropped the `WorldBuilder.Shared`/`Chorizite.OpenGLSDLBackend` project references entirely — there's no more forked submodule to patch/revert) and Phase A8 (2026-05-28, shipped `EnvCellRenderer.cs` which already calls the narrow `PrepareEnvCellGeomMeshDataAsync(geomId, environmentId, cellStructure, surfaces)` entry point at `EnvCellRenderer.cs:355`, using the bit-32-tagged synthetic geom id the issue proposed). `ObjectMeshManager.cs`'s bounds/type dispatch now branches on resolution type before calling `TryGet<T>`, so the blind `TryGet<Setup>` bug is structurally gone. `EnvCellRenderer` remains the live production cell-rendering path under Phase U as of commit `6aabe0b5` (Jul 6 2026). This historical item was renumbered from a duplicate `#87` heading to `#227` during the 2026-07-20 documentation audit; the original indoor-cell issue retains #87.
---

98
docs/README.md Normal file
View file

@ -0,0 +1,98 @@
# acdream documentation map
This page is the entry point for project documentation. It distinguishes
current sources of truth from implementation history so an old plan or issue
banner cannot silently override the current program state.
## Current snapshot — 2026-07-20
- **Active milestone:** M3, “Cast a spell.” The automated implementation and
connected single-client magic/portal presentation gates are complete.
- **Next visual gates:** the R6 locomotion/collision/projectile/teleport retail
comparison, then the final two-client portal-out/materialization observer
comparison (`#218`).
- **Separate visual verification:** the shared-alpha lifestone/particle result
in `#225`; its connected resource-lifetime and performance routes pass.
- **Carried behavior debt:** `#153` (far teleport onto an unstreamed edge),
`#116` (two narrowed slide-response cases), and divergence rows TS-50/TS-51.
- **Deferred engineering tracks:** Modern Pipeline MP1b+ and Linux/headless
automation (Track LH). Neither is part of the active M3 gate.
- **Divergence audit:** 178 active rows — IA 17, AD 37, AP 85, TS 34,
and UN 5 — plus the retained retired TS-37 history note.
- **Latest automated baseline:** Release build succeeds with 17 known
test-project warnings (`#228`); 6,452 tests passed and 5 intentionally
skipped. The unattended connected R6 route
completed seven portal materializations, production input exercises, and a
graceful close. See
[`research/2026-07-20-connected-r6-soak.md`](research/2026-07-20-connected-r6-soak.md).
## Sources of truth
Read these in this order when deciding what to do next:
1. [`plans/2026-05-12-milestones.md`](plans/2026-05-12-milestones.md) — the
active playable outcome, freeze boundaries, and visual gates.
2. [`plans/2026-04-11-roadmap.md`](plans/2026-04-11-roadmap.md) — strategic
phase ledger: shipped, active, deferred, and future work.
3. [`ISSUES.md`](ISSUES.md) — tactical defects and small follow-ups. The status
inside an issue is authoritative; physical order is not.
4. [`architecture/retail-divergence-register.md`](architecture/retail-divergence-register.md)
— every known place runtime behavior can differ from retail.
5. [`architecture/acdream-architecture.md`](architecture/acdream-architecture.md)
and [`architecture/code-structure.md`](architecture/code-structure.md) —
ownership, dependency, update-thread, and extraction rules.
6. [`architecture/worldbuilder-inventory.md`](architecture/worldbuilder-inventory.md)
— rendering/DAT code already owned in-tree versus mechanisms still ours to
port.
If these disagree, milestones control the current outcome, the roadmap controls
work ordering, the issue status controls the individual defect, and the
architecture documents control implementation shape. Reconcile the stale
document in the same change; do not leave both claims standing.
## Research and implementation records
- [`research/named-retail/`](research/named-retail/) is the primary retail
oracle: named pseudo-C, headers, symbols, and types from the Sept 2013 build.
- [`research/decompiled/`](research/decompiled/) is the older Ghidra fallback.
- [`research/`](research/) contains focused pseudocode, traces, fixtures, and
gate reports. A dated research note records evidence; it does not become a
new roadmap.
- [`superpowers/specs/`](superpowers/specs/) and
[`superpowers/plans/`](superpowers/plans/) are per-slice design and execution
records. Completed plans remain historical.
- [`audit/`](audit/) contains completion and conformance audits.
## Durable memory
- [`../claude-memory/MEMORY.md`](../claude-memory/MEMORY.md) indexes the live
subsystem memories and the render/physics digests. Read a domain digest
before changing that subsystem, especially its DO-NOT-RETRY table.
- [`../memory/`](../memory/) contains stable engineering references such as the
modern rendering pipeline, two-tier streaming, and toolchain notes.
Memory accelerates recall; it does not outrank the canonical documents above.
When current truth changes, update the relevant canonical document and distill
only the durable lesson into memory.
## Historical and deprecated documents
- [`bugs.md`](bugs.md) is the April 2026 bug snapshot. It is preserved for
archaeology and is not an active ledger.
- Dated plans and specs describe the decision at that time. Their completion
wording is historical unless the current milestone/roadmap explicitly links
the item as active.
- Old `R1→R8` architecture sequencing is superseded. Current execution comes
from the milestones and strategic roadmap.
## Documentation maintenance rules
- Update milestone, roadmap, issue, divergence, architecture, and memory claims
in the same commit when a shipped change affects them.
- Keep one issue ID per defect. Narrow an issue in place; do not reuse another
issue's number as a shorthand.
- Mark automated, connected, and visual gates separately. An automated pass is
not a visual acceptance, and an RDP throughput sample is not a local-display
visual comparison.
- Preserve research history, but remove stale “current/next” claims from living
documents once the state advances.

View file

@ -13,6 +13,11 @@ A modern C# .NET 10 Asheron's Call client that:
inheritance, interfaces, dependency injection) while matching retail
behavior exactly
**Current program status is intentionally not duplicated in this architecture
document.** Start at [`../README.md`](../README.md), then use the milestone and
roadmap linked there. This file governs ownership and dependency shape even
when the active gameplay milestone changes.
## Guiding Principle
**The code is modern. The behavior is retail.**
@ -790,12 +795,15 @@ and `docs/superpowers/specs/`.
Current movement/collision ownership:
- **B.3** is shipped MVP history: first collision resolver foundation.
- **L.1** owns animation/motion parity, including root-motion coupling.
- **L.2** owns movement and collision conformance:
- **L.1/R6** own animation/motion parity and the complete retail object-frame
update order over canonical `LiveEntityRuntime` records.
- **L.2** owns the remaining movement and collision conformance:
`docs/plans/2026-04-29-movement-collision-conformance.md`.
- **G.3** owns dungeon streaming and portal-space delivery after L.2e lands
trustworthy `cell_bsp`, `CELLARRAY`, adjacent-cell checks, and building
entry/exit boundaries.
- **G.3 is shipped**: dungeon streaming, portal-space presentation, collision,
lighting, doors, and the full round-trip gate landed. The separate far-
teleport unstreamed-edge residual is issue #153, not unfinished G.3.
- **M3** owns current connected magic/portal acceptance; Track LH is the future
presentation-independent Linux/headless extraction.
The GameEntity / thin GameWindow refactor remains a valid target architecture,
but it is not a prerequisite for L.2. Do not resurrect old R1-R8 phase numbers

View file

@ -4,7 +4,8 @@
"Code Structure Rules" section in `CLAUDE.md`.
**Purpose:** Describe the desired structural state of the App layer,
explain the rules we've adopted, and lay out the safe extraction
sequence from today's reality (one 15,288-line `GameWindow.cs`) to the
sequence from today's reality (one 14,557-line `GameWindow.cs` at the
2026-07-20 audit) to the
target (thin `GameWindow`, small focused collaborators).
**Companion to:** [`acdream-architecture.md`](acdream-architecture.md)
(the layered architecture) and
@ -20,7 +21,7 @@ layer is wire-compatible, the UI has a stable contract, plugins load.
The structural debt is concentrated in **one file**:
```
src/AcDream.App/Rendering/GameWindow.cs 15,288 lines
src/AcDream.App/Rendering/GameWindow.cs 14,557 lines (2026-07-20)
```
`GameWindow` is the single object that:
@ -341,7 +342,7 @@ Each step is **one PR-sized refactor**. Each must build clean, all
tests pass, and visual verification at Holtburg looks identical to
the previous step. Don't bundle two steps.
### Step 1 — `RuntimeOptions` (this PR)
### Step 1 — `RuntimeOptions` — SHIPPED (`eda936dc`)
**Scope:** Replace startup-time env var reads with a typed options
object built once in `Program.cs`.
@ -357,7 +358,7 @@ new `tests/AcDream.App.Tests/` project).
**Verification:** `dotnet build` + `dotnet test` green. Visual launch
verifies live mode + dat dir resolution still work.
### Step 2 — `LiveSessionController`
### Step 2 — `LiveSessionController` — SHIPPED (`0b25df53`)
**Scope:** Extract `TryStartLiveSession` + the WorldSession ownership +
the post-EnterWorld drain (`OnLiveStateUpdated`, `OnLiveEntityDeleted`,

View file

@ -214,7 +214,7 @@ AP-94..AP-112 for the confirmed retail-UI completion gaps.
| AP-117 | Outdoor particle `CLandCell::IsInView` state is reconstructed with the modern landscape renderer's per-cell frustum plus active doorway clip-plane/scissor-AABB tests; retail `LScape::landcell_check` uses `Render::get_clip_height` + `Render::block_check` on terrain-cell corner intervals | `src/AcDream.App/Rendering/TerrainModernRenderer.cs` (`CollectVisibleCells`) | The mandatory modern renderer batches terrain by landblock and has no retail `ViewIntervalType` product. Publishing cell visibility from the exact landscape draw slices preserves ownership/order and removes the former object-survivor dependency without adding a second view pipeline | At a terrain cell grazing a frustum or doorway boundary, the conservative AABB test may freeze or resume particles on a slightly different frame than retail; whole regions outside the active doorway slice are rejected, and authored distance, login/portal fail-closed behavior, and indoor PView cells remain exact | `LScape::landcell_check @ 0x005050A0`; `CLandCell::IsInView @ 0x00532CB0`; `CPhysicsObj::ShouldDrawParticles @ 0x0050FE60` |
| AP-118 | An AutoWield transaction begun in active combat preserves the ready mode implied by the requested weapon. After authoritative `WieldObject`, a mode that settled without a blocker transition clears immediately; local ACE's observed pre-wield transition plus `ready -> NonCombat`, or post-wield `NonCombat -> ready -> NonCombat`, causes one normal `ChangeCombatMode` request from the trailing notice. Explicit user combat input cancels settlement. Retail's client does not need this extra request against the retail server. | `src/AcDream.App/UI/AutoWieldController.cs`; production binding in `GameWindow.cs` | Local ACE queues a trailing NonCombat callback during primary-weapon replacement and rejects an earlier request while the shuffle is busy; responding to the authoritative notice that completes that exact sequence orders the ordinary request after it without suppressing any server state | A non-ACE server that emits a different intermediate sequence can retain the settlement until a later explicit combat request, replacement, or logout clears it; peace-mode equips send none | `CPlayerSystem::AutoWield @ 0x00560A60`; `ACCWeenieObject::ServerSaysMoveItem @ 0x0058DBB0`; ACE `Player_Inventory.TryShuffleStance` / `TryDequipObjectWithNetworking` |
## 4. Temporary stopgap (TS) — 34 active rows (TS-20 retired 2026-07-16 — the later named-retail audit disproved the proposed DrawingBSP polygon filter; TS-37 is a retired-row historical note, not an active count; TS-39 retired R5-V3 — sticky seams bound to the ported PositionManager/StickyManager, radii threaded; TS-45 retired 2026-07-07 — hand-rolled `SphereCollision` replaced by the faithful CSphere family port, fixing the player-vs-monster crowd wedge; TS-3 retired 2026-07-07 — `frames_stationary_fall` accounting ported in the #182 verbatim UpdateObjectInternal rebuild, fixing the airborne falling-animation wedge; TS-41 retired 2026-07-07 — SERVERVEL synth-velocity remote body-drive replaced by the retail interp catch-up + unconditional MovementManager::UseTime, the remote-creature de-overlap #184; TS-42 retired 2026-07-19 — semantic animation completion now precedes the ordered Target/Movement/PartArray/Position tail; TS-44 narrowed again 2026-07-19 — complete orientation joined interpolation, only during-stick enqueue suppression remains)
## 4. Temporary stopgap (TS) — 34 active rows + TS-37 historical note (TS-20 retired 2026-07-16 — the later named-retail audit disproved the proposed DrawingBSP polygon filter; TS-37 is a retired-row historical note, not an active count; TS-39 retired R5-V3 — sticky seams bound to the ported PositionManager/StickyManager, radii threaded; TS-45 retired 2026-07-07 — hand-rolled `SphereCollision` replaced by the faithful CSphere family port, fixing the player-vs-monster crowd wedge; TS-3 retired 2026-07-07 — `frames_stationary_fall` accounting ported in the #182 verbatim UpdateObjectInternal rebuild, fixing the airborne falling-animation wedge; TS-41 retired 2026-07-07 — SERVERVEL synth-velocity remote body-drive replaced by the retail interp catch-up + unconditional MovementManager::UseTime, the remote-creature de-overlap #184; TS-42 retired 2026-07-19 — semantic animation completion now precedes the ordered Target/Movement/PartArray/Position tail; TS-44 narrowed again 2026-07-19 — complete orientation joined interpolation, only during-stick enqueue suppression remains)
| # | Divergence | Where (file:line) | Why it is safe / justified | Risk if assumption breaks | Retail oracle |
|---|---|---|---|---|---|
@ -255,6 +255,7 @@ AP-94..AP-112 for the confirmed retail-UI completion gaps.
| TS-49 | Hidden-object availability is bridged through `TargetManager.NotifyVoyeurOfEventAndClear(ExitWorld)` because acdream has not ported retail's DetectionManager. Retail `CObjCell::hide_object` sends `LeftDetection` to detection voyeurs; acdream instead uses the existing non-Ok target update to tear down MoveTo/Sticky consumers and clear watched-role subscriptions while preserving the hidden object's own watcher role. | `src/AcDream.App/Rendering/EntityPhysicsHost.cs` (`NotifyHidden`); `src/AcDream.Core/Physics/Motion/TargetManager.cs` (`NotifyVoyeurOfEventAndClear`) | The current movement consumers already share TargetManager's status fan-out; the bridge prevents pursuit of an unavailable object without inventing a second partial detection database. | Plugins or future systems listening specifically for retail detection enter/leave events receive no `LeftDetection`; only movement/sticky target consumers observe the equivalent availability loss. | `CObjCell::hide_object @ 0x0052BE30`; retire by porting DetectionManager/CObjCell detection-voyeur delivery and routing Hidden through `LeftDetection` |
| TS-50 | `AnimationDone` executes semantically at each owner's retail `CPhysicsObj::process_hooks` boundary, but all other animation hooks are retained in `AnimationHookFrameQueue` until final root/part/equipped-child pose publication. Retail executes the complete hook stream before transition and the Target/Movement/PartArray/Position manager tail because its current CPartArray pose already exists in-place. Static owners correctly reach `process_hooks` only after their root, parts, and children are current. | `src/AcDream.App/Rendering/Vfx/AnimationHookFrameQueue.cs`; `src/AcDream.App/Rendering/RetailStaticAnimatingObjectScheduler.cs`; frame drain in `src/AcDream.App/Rendering/GameWindow.cs` | The modern renderer publishes immutable effect-pose snapshots after all root/child composition; deferred visual sinks avoid attaching particles/lights/audio to the previous pose. Semantic `AnimationDone` is split out and exact, so motion completion and manager behavior are not delayed. Pose-owner lifetime tokens prevent deferred hooks from crossing delete/local-ID reuse. | A non-AnimationDone hook with same-quantum semantic consequences (notably `CallPES`, default-script chaining, audio/particle creation relative to a transition) runs later than retail and can observe post-tail state or start one render frame late. | `CPhysicsObj::process_hooks @ 0x00511550`; `CPhysicsObj::UpdatePositionInternal @ 0x00512C30`; `CPhysicsObj::animate_static_object @ 0x00513DF0`; retire by publishing the current per-object/child pose before hook routing or splitting semantic and presentation sinks without changing authored hook order |
| TS-51 | Particle and PhysicsScript tails advance once per render frame after the complete ordinary/static object worksets. Retail advances each object's ParticleManager and ScriptManager inside every admitted `UpdateObjectInternal` quantum; `animate_static_object` also advances that static owner's managers using its whole admitted elapsed interval. | `src/AcDream.App/Rendering/GameWindow.cs` (`AdvanceLiveObjectRuntime` final `_particleSystem.Tick(dt)` / `_scriptRunner.Tick(...)`) | The current managers are shared presentation/runtime owners rather than per-object manager instances. R6 makes root motion, animation, object clocks, workset membership, and manager order faithful without pretending the shared tails have per-owner timing. Splitting ownership safely requires a later effect-lifetime slice. | A render fragment below retail's minimum object quantum can advance an effect while its owner waits; a catch-up frame advances an owner's root through several quanta but its effect tail only once; static default scripts/particles use render elapsed rather than `animate_static_object` elapsed/discard timing. | `CPhysicsObj::UpdateObjectInternal @ 0x005156B0`; `CPhysicsObj::animate_static_object @ 0x00513DF0`; retire by giving live/static owners incarnation-bound particle/script managers and ticking each manager in the owning object quantum |
| TS-52 | The terrain shader applies retail-authored base/overlay/road `TerrainTex.TexTiling` but omits the separate Environment Detail Textures pass and its viewer-distance fade (**#226**). | `src/AcDream.App/Rendering/TerrainAtlas.cs`; `src/AcDream.App/Rendering/TerrainModernRenderer.cs`; `src/AcDream.App/Rendering/Shaders/terrain_modern.frag` | `bb5acab9` fixed the user-visible stretched/blurry regression by porting the distinct base-tiling contract. An earlier experimental detail array darkened the whole ground because its source/neutral blend contract was wrong, so it was correctly reverted rather than guessed into production. | With retail's Environment Detail Textures preference enabled, close terrain lacks the extra high-frequency modulation/fade even though authored base texture scale is correct. | `LScape::GenerateDetailSurfaces` / `SetDetailTexturing @ 0x00506B40`; `ACRender::landPolyDraw @ 0x006B6450..0x006B6525`; issue #226 |
---

View file

@ -1,11 +1,18 @@
# acdream — known bugs
# acdream — historical bug snapshot (deprecated)
Track visual, gameplay, and protocol bugs here. Close by moving to
the "Fixed" section with the commit hash that resolved it.
> **Not an active issue tracker.** This file preserves the 2026-04-14 snapshot
> for archaeology. Several “open” entries below were superseded, narrowed, or
> fixed by later collision/rendering work. Do not update status here and do not
> use these BUG numbers for new work. The canonical tactical ledger is
> [`ISSUES.md`](ISSUES.md); current program navigation is in
> [`README.md`](README.md).
The text below is intentionally retained as historical evidence of what was
believed at the time.
---
## Open
## Historical open snapshot (not current)
### BUG-001: Wrong cloth textures on characters
- **Observed:** 2026-04-13
@ -53,7 +60,7 @@ the "Fixed" section with the commit hash that resolved it.
---
## Fixed
## Historical fixed snapshot
### BUG-002: Jump not visible from retail client
- **Fixed:** 5634e71 — Jump packet (opcode 0xF61B) now sent to server.

View file

@ -1,6 +1,6 @@
# acdream — strategic roadmap
**Status:** Living document. Updated 2026-07-20. **M3 active; automated implementation complete, visual gates pending.** M2's connected demo loop is complete. M3 now has the retail cast-intent/component/target lifecycle, exact live enchantment wire state, scoped Magic input, retained spell bar, spellbook, component book, positive/negative effects panels with authored rows and selected-spell details, the complete seven-control gameplay indicator strip and its Character Information/Link/Vitae detail pages, and shared `gmPanelUI` geometry/switching over the Step 9 projectile/PhysicsScript/particle/portal foundation. The remaining M3 work is the connected single-client magic-UI/casting gate and final two-client portal-out/materialization observer gate.
**Status:** Living document. Updated 2026-07-20. **M3 active; automated implementation and connected single-client magic/portal gates complete.** M2's connected demo loop is complete. M3 now has the retail cast-intent/component/target lifecycle, exact live enchantment wire state, scoped Magic input, retained spell bar, spellbook, component book, positive/negative effects panels with authored rows and selected-spell details, the complete seven-control gameplay indicator strip and its Character Information/Link/Vitae detail pages, and shared `gmPanelUI` geometry/switching over the Step 9 projectile/PhysicsScript/particle/portal foundation. The next gate is a local visual rebaseline of the new R6 object-frame path; the final M3 requirement is the two-client portal-out/materialization observer gate. Issue #225's lifestone/particle alpha comparison is a separate rendering visual gate.
**Purpose:** One source of truth for where the project is and where it's going. Every observed defect or missing feature has a named phase that owns it; when something looks wrong in-game, look here to find the phase that'll address it. Implementation details live in per-phase specs under `docs/superpowers/specs/`, not in this file.
---
@ -30,9 +30,13 @@ active enchantment, then recall through the DAT-driven portal presentation.
Connected-gate
correction now also pins type-12 spellbook tabs, retail zero text margins,
and `PassToChildren` Closed/Open chrome through real-DAT fixtures.
3. **Pending user visual gate:** connected projectile/self-buff casts plus the
complete retained magic UI interaction checklist.
4. **Pending user visual gate:** two-client portal-out/materialization observer
3. **Done (connected user gates):** projectile/self-buff casts, protection
effects, spellbook/component-book filtering and deletion, favorite spell
bar interaction, recall, portal-space presentation, and retained indicator
pages.
4. **Pending local visual gate:** locomotion, collision, projectile, and
teleport comparison after the R6 complete-root-Frame/object-workset cutover.
5. **Pending two-client visual gate:** portal-out/materialization observer
presentation before M3 closes, including #218's finished Hidden silhouette,
fully rendered destination reveal, and no indoor stop-time position snap.
@ -43,10 +47,10 @@ the active slice only when they block this demo or represent a severe regression
## Historical program: Phase W — Unified Cell Graph (UCG)
**[SUPERSEDED — G.3 dungeon work shipped; M1.5 next step = #138 round-trip
gate + #145-residual. See the shipped table + `docs/plans/2026-05-12-milestones.md`
M1.5 section for current status. This section's W1/W2a history below is kept
for record.]**
**[SUPERSEDED — G.3 shipped and M1.5 landed after the #138 round-trip gate.
Issue #153 is a separate far-teleport edge residual. See the shipped table +
`docs/plans/2026-05-12-milestones.md` M1.5 section for current status. This
section's W1/W2a history below is kept for record.]**
**Pivot (2026-06-02).** The render-pipeline reset stalled because the indoor "world from
below" is a cell-**membership** disagreement between the render-side `CellVisibility` and
@ -606,7 +610,7 @@ Research: R9 + R12 + R13.
- **✓ SHIPPED — G.1 — Sky + weather + day-night.** Deterministic client-side from Portal Year time. Sky dome geometry + keyframe gradients + rain/snow particles. See `r12-weather-daynight.md`. Full data + visual stack shipped: Region dat loader, keyframe interp, WeatherSystem with 5-kind PDF + transitions + storm flashes, WorldSession→WorldTimeService sync via ConnectRequest+TimeSync, SkyRenderer with sky-object arcs + UV scroll, rain/snow billboard renderer, F7/F10 debug cycle keys.
- **✓ SHIPPED — G.2 — Dynamic lighting.** 8-light D3D-style fixed pipeline. Hard-cutoff at Range, no attenuation inside. Cell ambient. Shader UBO per frame. See `r13-dynamic-lighting.md`. SceneLightingUbo std140 at binding=1 feeds terrain + mesh + mesh_instanced + sky shaders. LightingHookSink auto-registers Setup.Lights at entity stream-in, flips IsLit on SetLightHook, unregisters on landblock unload.
- **Indoor portal-based cell tracking (follow-up to Indoor walking Phase 1 / issue #87).** Replace `PhysicsDataCache.TryFindContainingCell` AABB containment with retail's `CObjMaint::HandleObjectEnterCell` portal traversal. When the player crosses a cell portal boundary, `CellId` propagates through the `CEnvCell` portal connectivity graph. Prerequisite for wall collision from outside (#85) and the remaining #84 threshold symptom. PDB symbols and `acclient.h` `CCellStructure` refs are in place (see #87). **Unblocks G.3.**
- **✓ SHIPPED — G.3 — Dungeon streaming + portal space.** `EnvCellStreamer`, portal-visibility BFS, `PlayerTeleport (0xF751)` handling with post-transition `LoginComplete`, and the retail DAT-authored portal-space CreatureMode viewport (Setup `0x02000306`, animation `0x030005AC`, exact camera/light/timing/view-plane transitions, forward-axis roll, direct portal→world viewport switch, projection warp, destination viewer reset, object/physics-before-network frame barrier, pre-network input movement/jump output, post-inbound AutonomousPosition, non-advancing spatial reconciliation, and retail `set_hidden` PartArray timeline teardown on both Hidden and UnHide; `/ls` and spell-recall corrective visual gates passed 2026-07-16, with non-blocking visual polish deferred). Dungeons render, stream, teleport-in, collide, light, and their doors work — see the shipped-table rows (G.3, G.3a, #137 collision, A7.L1 lighting) below and the M1.5 section of `docs/plans/2026-05-12-milestones.md` for current gate status (one recorded end-to-end dungeon round-trip user gate outstanding; live residual = far-town teleport-OUT arrival cascade, #145-residual REOPENED). See `r09-dungeon-portal-space.md` and `docs/research/2026-07-15-retail-portal-space-pseudocode.md`.
- **✓ SHIPPED — G.3 — Dungeon streaming + portal space.** `EnvCellStreamer`, portal-visibility BFS, `PlayerTeleport (0xF751)` handling with post-transition `LoginComplete`, and the retail DAT-authored portal-space CreatureMode viewport (Setup `0x02000306`, animation `0x030005AC`, exact camera/light/timing/view-plane transitions, forward-axis roll, direct portal→world viewport switch, projection warp, destination viewer reset, object/physics-before-network frame barrier, pre-network input movement/jump output, post-inbound AutonomousPosition, non-advancing spatial reconciliation, and retail `set_hidden` PartArray timeline teardown on both Hidden and UnHide; `/ls` and spell-recall corrective visual gates passed 2026-07-16, with non-blocking visual polish deferred). Dungeons render, stream, teleport, collide, light, and their doors work; the final end-to-end dungeon round-trip gate passed 2026-07-10. See the shipped-table rows (G.3, G.3a, #137 collision, A7.L1 lighting) and the M1.5 section of `docs/plans/2026-05-12-milestones.md`. The far-town unstreamed-edge arrival residual is tracked separately as #153. See `r09-dungeon-portal-space.md` and `docs/research/2026-07-15-retail-portal-space-pseudocode.md`.
**Acceptance:** walk outside at dusk, see the sky gradient + sun moving; enter a torch-lit dungeon via portal; leave back to daylight.
@ -647,7 +651,7 @@ the way retail + holtburger expect.
- Attacking a creature produces "You hit Drudge for 12 slashing damage (87%)" lines in chat.
- Accented character names round-trip through the wire correctly (CP1252).
**Memory crib:** `memory/project_chat_pipeline.md`.
**Memory crib:** `claude-memory/project_chat_pipeline.md`.
---
@ -704,7 +708,7 @@ with retail's MMB-hold mouse-look.
dormant — light up in Phase L when `CombatState.CurrentMode` is
wired (issue #L.3).
**Memory crib:** `memory/project_input_pipeline.md`.
**Memory crib:** `claude-memory/project_input_pipeline.md`.
---
@ -915,8 +919,9 @@ diagnostic scaffolding, not yet the final collision system.
InterpolationManager into the owned
PositionManager facade remains the final R6 ownership cleanup.
Final 2026-07-20 gate: three independent retail/architecture/adversarial
re-reviews are clean; Release build is warning-free; the repository suite is
6,452 passed / 5 skipped. The unattended connected Release rebaseline also
re-reviews are clean; Release builds successfully with 17 known test-project
warnings tracked by #228; the repository suite is 6,452 passed / 5 skipped.
The unattended connected Release rebaseline also
passes: seven portal materializations across Caul, Sawato, Rynthid,
Aerlinthe, Holtburg, and same-location revisits; production-dispatcher turn,
forward, charged-jump, and combat inputs; outbound movement evidence;
@ -1441,8 +1446,8 @@ OpenGL ceiling; revisit macOS only if a supported graphics backend is chosen.
## Cross-cutting work tracked in parallel
- **Test coverage.** Each phase lands with unit + integration tests in `tests/`. Current count: 98 Core + 96 Core.Net = 194. Keep the ratio as new phases land.
- **Memory files.** Project state under `memory/project_phase_*_state.md` is updated when a phase ships. `MEMORY.md` is the index.
- **Test coverage.** Each phase lands with layer-matched unit and integration tests in `tests/`. Current Release baseline: 6,452 passed / 5 intentional skips (2026-07-20).
- **Memory files.** Live subsystem state and digests are indexed by `claude-memory/MEMORY.md`; stable engineering references remain under `memory/`. Canonical program status stays in milestones/roadmap/issues.
- **`CLAUDE.md` discipline.** Check all four references (ACE, ACViewer, WorldBuilder, Chorizite) before committing to an approach. WorldBuilder is the closest stack match and should be checked first.
---
@ -1470,8 +1475,8 @@ OpenGL ceiling; revisit macOS only if a supported graphics backend is chosen.
| Character clothing missing / wrong | **5 FIXED** ✓ |
| Statue wrong color / wrong scale | **5 FIXED** ✓ |
| Holtburg sign half-buried | **5 FIXED** ✓ |
| Can't walk past the loaded 3×3 window | **A.1 FIXED** ✓ (5×5 default, `ACDREAM_STREAM_RADIUS` to tune) |
| Frame hitch crossing landblock boundary | **Phase A.3** (synchronous loader for now; async returns when DatCollection is thread-safe) |
| Can't walk past the loaded 3×3 window | **A.1/A.5 FIXED** ✓ (two-tier streaming, near 4 / far 12 by default; legacy override remains) |
| Frame hitch crossing landblock boundary | **A.3/A.5 async streaming SHIPPED**; residual content-load hitches are measured under Modern Pipeline MP1c |
| Walking around doesn't move me on the server | **Phase B.2/B.3 FIXED** ✓ for coarse server movement; fine retail collision parity is **Phase L.2** |
| Packet loss / out-of-order UDP causes stale or missing world updates | **Phase M.3** |
| Server asks for retransmit and client doesn't resend cached packets | **Phase M.3** |
@ -1482,22 +1487,22 @@ OpenGL ceiling; revisit macOS only if a supported graphics backend is chosen.
| Sliding along buildings / walls feels wrong | **Phase L.2c + L.2d** |
| Roof edge / cliff / precipice blocks or slides wrong | **Phase L.2c** |
| Crossing outdoor cell seams reports the wrong cell | **Phase L.2e** |
| Can't talk to NPCs | **Phase H.3** (emote scripts + dialogs) |
| Can't open a door | **Phase F** (object-use action) |
| Portals render as a rotating black disk | **Phase E.3** (particle system) |
| Chimneys have no smoke | **Phase E.3** |
| Houses have no fireplace fire | **Phase E.3** |
| Can't talk to NPCs | Basic select/use/give interaction works; full emote conversation/dialog systems remain **Phase H.3** |
| Can't open a door | **FIXED** ✓ — object-use, animation, fading hooks, and collision transitions shipped |
| Portals render as a rotating black disk | **FIXED** ✓ — DAT particles/effects and portal-space presentation shipped |
| Chimneys have no smoke | **Phase E.3 SHIPPED** |
| Houses have no fireplace fire | **Phase E.3/G.2 SHIPPED** |
| No fireplace / torch lighting | **Phase G.2** (shipped; Setup.Lights auto-register, 8-light cap with hard-cutoff) |
| Skin/hair color slightly off | **Phase C.3** |
| No chat window | **Phase H.1 / I.1-I.7 FIXED** ✓ |
| Chat? You can finally type and send messages | **I.4 FIXED** ✓ (shipped 2026-04-25) |
| Combat doesn't show in the chat log | **I.7 FIXED** ✓ |
| Accented character names show as `?` or garbled | **I.5 FIXED** ✓ (Windows-1252 codec) |
| No sound | **Phase E.2** |
| Dungeons / foundry interior missing | **Phase G.3 — SHIPPED** (render/stream/teleport-in/collide/light/doors all closed; M1.5 next step = #138 round-trip gate + #145-residual) |
| Can't fight monsters | **Phase F.3** (combat math + damage) |
| Can't cast spells | **Phase F.4** |
| No inventory panel | **Phase F.2 + F.5** |
| No sound | **Phase E.2 SHIPPED** ✓ (remaining unsupported codecs are TS-9) |
| Dungeons / foundry interior missing | **Phase G.3 — SHIPPED + M1.5 gate passed 2026-07-10** (render/stream/teleport/collision/light/doors closed; separate far-teleport edge residual = #153) |
| Can't fight monsters | **M2 LANDED 2026-07-15** ✓ — melee/missile, death, loot, inventory loop user-gated |
| Can't cast spells | **M3 connected single-client casting/effects gate passed** ✓; final two-client portal observer gate remains |
| No inventory panel | **D.5 / M2 SHIPPED + user-gated** ✓ — bags, stacks, paperdoll, equipment, drag/drop, loot |
| No character creation — must use ACE admin | **Phase H.4** |
| Sky is a flat color | **Phase G.1** (shipped; F7 cycles time, F10 cycles weather) |
| Can't join allegiance | **Phase H.2** |

View file

@ -15,11 +15,14 @@ new R6 object-update cutover has passed its unattended connected input/portal/
performance rebaseline; its locomotion/collision/projectile/teleport visual
gate remains for the next local viewing session before that observer gate.
Carried:
#145-residual, #116 slide-response, the remaining R6 ownership cleanup plus
#153 far-teleport residual, #116 slide-response, the remaining R6 ownership cleanup plus
registered TS-50/TS-51 timing residuals (the complete-root-Frame/object-workset
cutover is automated-test complete 2026-07-20; three independent re-reviews are
clean, Release builds with zero warnings, and 6,452 tests pass / 5 skip), and
Track MP0.
clean, Release builds with 17 known test-project warnings tracked by #228, and
6,452 tests pass / 5 skip), and
the deferred Modern Pipeline track (MP1b+). The separate #225 shared-alpha
implementation has passed connected lifetime/performance gates and awaits only
its lifestone/particle visual comparison.
---
@ -219,7 +222,7 @@ lighting (#79/#93/#80). The indoor-physics workarounds (#90 stickiness +
`TryFindIndoorWalkablePlane` synthesis) were removed by A6.P4 — no duct-tape
left. **Explicit caveats carried forward (NOT M1.5 blockers — tracked as
their own follow-ups):** the far-town teleport-OUT arrival cascade
(#145-residual, REOPENED — a narrow far-teleport streaming edge case,
(#153, REOPENED — a narrow far-teleport streaming edge case,
capture-harness-first) and #116 slide-response feel-debt. Next: **M2 —
"Kill a drudge."**
@ -238,10 +241,10 @@ multi-landblock dungeon LOD + `PlayerTeleport` handling), and it has since
blowup (RESOLVED), dungeon doors (#187/#188), and A7 dungeon lighting
(#79/#93/#80/#154, all CLOSED). M1.5's dungeon-demo scenario (enter via
portal, navigate 3-5 rooms, walls block, smooth transitions) is
functionally met; M1.5 now awaits ONE recorded end-to-end dungeon
round-trip user gate. The sole remaining live-code residual is the
far-town teleport-OUT arrival cascade (**#145-residual, REOPENED** — see
below).
functionally met. The final end-to-end dungeon round-trip gate passed on
2026-07-10 and landed M1.5. The separate live-code residual is the far-town
teleport-OUT arrival cascade (**#153, REOPENED** — see below); it is not a
dungeon-round-trip blocker.
**Building/cellar demo — DONE + user-gated.** The indoor world reads as
solid. Across the
@ -311,10 +314,9 @@ shipped: teleport-into-dungeon (G.3a hold-until-hydrate FSM,
#137 (`0efa7ed2`); the #95 portal-graph visibility blowup RESOLVED
(9.1M→~39k instances, `a40c38e8`); dungeon doors shipped (#187
`e2e285b8`, #188 `3284dd0a`); A7 dungeon lighting closed
(#79/#93/#80/#154, `44cced71`/`d275ed55`/`9ebb2060`). Remaining: one
recorded end-to-end dungeon round-trip user gate, plus the far-town
teleport-OUT arrival cascade residual (**#145-residual, REOPENED** —
capture-harness-first).
(#79/#93/#80/#154, `44cced71`/`d275ed55`/`9ebb2060`). The recorded end-to-end
dungeon round-trip passed on 2026-07-10. The far-town teleport-OUT arrival
cascade residual remains separate (**#153, REOPENED** — capture-harness-first).
**2026-07-15 portal presentation completion (single-client visual gate passed
2026-07-16; non-blocking polish deferred).** The
@ -482,7 +484,7 @@ the A6 physics/membership family + A6.P4 per-cell shadow architecture, A7
indoor/dungeon lighting, and **full Phase G.3 dungeon support** (streaming
collapse/expand, teleport in/out, dungeon collision/lighting/doors). No
rework until M7 polish. Exempt from the freeze as still-open bugs (rule 2's
"actively broken" clause): #145-residual (far-town teleport-OUT cascade) and
"actively broken" clause): #153 (far-town teleport-OUT cascade) and
#116 (slide-response) — these are tracked follow-ups, not frozen work.
**Estimated timeline:** 35 weeks calendar (1726 days focused work). Bigger