diff --git a/docs/superpowers/plans/2026-05-21-phase-o-dat-path-unification.md b/docs/superpowers/plans/2026-05-21-phase-o-dat-path-unification.md new file mode 100644 index 0000000..6c3e626 --- /dev/null +++ b/docs/superpowers/plans/2026-05-21-phase-o-dat-path-unification.md @@ -0,0 +1,1052 @@ +# Phase O — DatPath Unification Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Extract the load-bearing WorldBuilder code we use into acdream's own source tree, route all dat reads through our `DatCollection`, and drop the two `` entries that pull in WB. End state: ONE dat reader in the process, ZERO references to `WorldBuilder.*` / `Chorizite.OpenGLSDLBackend.*` namespaces in our source. + +**Architecture:** Verbatim copy of ~33 WB files (~7.7K LOC) split across two layers — `src/AcDream.Core/Rendering/Wb/` for pure-CPU helpers (`TextureHelpers`, `SceneryHelpers`, `TerrainUtils`, `TerrainEntry`, `CellSplitDirection`); `src/AcDream.App/Rendering/Wb/` for everything that touches GL (`OpenGLGraphicsDevice`, `ManagedGL*`, `GLSLShader`, `GLHelpers`, `GLStateScope`, `ObjectMeshManager`, particle pipeline, render data structs). `ObjectMeshManager` refactored to take our `DatCollection` directly (with fallback to a thin adapter if the call-site count exceeds 20). Three `internal` types in Chorizite promoted to `public`. + +**Tech Stack:** C# .NET 10, Silk.NET.OpenGL, BCnEncoder.Net, Chorizite.DatReaderWriter (NuGet — stays). MIT attribution required for the extracted code per WB's license. + +**Spec:** [`docs/superpowers/specs/2026-05-21-phase-o-dat-path-unification-design.md`](../specs/2026-05-21-phase-o-dat-path-unification-design.md) +**Audit:** [`docs/research/2026-05-21-phase-o-t1-wb-audit.md`](../../research/2026-05-21-phase-o-t1-wb-audit.md) + +--- + +## File Structure + +### Created during this phase + +**`src/AcDream.Core/Rendering/Wb/` (new directory):** +- `TextureHelpers.cs` — pure pixel-format decoders (`Fill*` helpers for INDEX16/P8/A8/A8R8G8B8/R8G8B8/R5G6B5/A4R4G4B4/etc.). +- `SceneryHelpers.cs` — stateless scenery transformations (`Displace`, `RotateObj`, `ScaleObj`, `ObjAlign`, `CheckSlope`). +- `TerrainUtils.cs` — terrain math (`GetHeight`, `GetNormal`, `OnRoad`, `CalculateSplitDirection`). +- `TerrainEntry.cs` — packed per-vertex terrain struct (`[MemoryPackable]` attribute STRIPPED). +- `CellSplitDirection.cs` — `SWtoNE` / `SEtoNW` enum. + +**`src/AcDream.App/Rendering/Wb/` (existing directory, ~25 files added):** +- `OpenGLGraphicsDevice.cs` — Silk.NET wrapper, GL context, `ProcessGLQueue`. +- `GLSLShader.cs`, `GLHelpers.cs`, `GLStateScope.cs` — shader + state wrappers. +- `ManagedGLTexture.cs`, `ManagedGLTextureArray.cs`, `ManagedGLVertexBuffer.cs`, `ManagedGLIndexBuffer.cs`, `ManagedGLVertexArray.cs`, `ManagedGLFrameBuffer.cs`, `ManagedGLUniformBuffer.cs` — GL resource wrappers (7 files). +- `ObjectMeshManager.cs` — mesh extraction + GPU upload (REFACTORED to take `DatCollection`). +- `ObjectRenderBatch.cs`, `ObjectRenderData.cs` — render-data structs. +- `DebugRenderSettings.cs` — settings struct for `OpenGLGraphicsDevice` ctor. +- Particle batcher + emitter files (count + names confirmed during T4 closure walk). +- `GlobalMeshBuffer.cs`, modern render data structs (count + names confirmed during T4 closure walk). +- `EmbeddedResourceReader.cs`, `TextureFormatExtensions.cs`, `BufferUsageExtensions.cs` — three `internal` types promoted to `public`. + +**Repo root:** `NOTICE.md` updated (or created) with WB MIT attribution. + +### Modified during this phase + +- `src/AcDream.Core/AcDream.Core.csproj` — drop 2 `` lines. +- `src/AcDream.App/AcDream.App.csproj` — drop 2 `` lines. +- `src/AcDream.App/Rendering/Wb/WbMeshAdapter.cs` — drop `_wbDats` field/ctor/dispose; drop `[indoor-upload] NULL_RESULT` block (lines 192-263 currently); simplify ctor to pass `DatCollection` directly to `ObjectMeshManager`. +- `src/AcDream.App/Rendering/Wb/WbDrawDispatcher.cs` — update `using Chorizite.OpenGLSDLBackend.Lib;` → `using AcDream.App.Rendering.Wb;`. +- `src/AcDream.Core/World/WbSceneryAdapter.cs` — update `using WorldBuilder.Shared.Models;` → `using AcDream.Core.Rendering.Wb;`. +- `src/AcDream.Core/World/SceneryGenerator.cs` — update both `using` lines to new namespaces. +- `src/AcDream.Core/Textures/SurfaceDecoder.cs` — update `using Chorizite.OpenGLSDLBackend.Lib;` → `using AcDream.Core.Rendering.Wb;`. +- `tests/AcDream.Core.Tests/Textures/TextureDecodeConformanceTests.cs` — update `using` line. +- `tests/AcDream.Core.Tests/World/WbSceneryAdapterTests.cs` — doc-comment fix only. +- `tests/AcDream.Core.Tests/World/SceneryGeneratorTests.cs` — doc-comment fix only. +- `tests/AcDream.Core.Tests/Rendering/Wb/MeshExtractionConformanceTests.cs` — doc-comment fix only. +- `tests/AcDream.Core.Tests/Terrain/ClientReference.cs`, `ClientConformanceTests.cs` — doc-comment fix only. +- `CLAUDE.md` — rewrite the "WB integration cribs" section. +- `docs/architecture/worldbuilder-inventory.md` — update ownership notes. + +### Deleted during this phase + +- `tests/AcDream.Core.Tests/Terrain/SplitFormulaDivergenceTest.cs` — one-time data-collection test, job done at N.5b. + +--- + +## Task 1: Setup (was O-T2) + +**Files:** +- Create: `src/AcDream.Core/Rendering/Wb/` (directory only — no files yet) +- Create/Modify: `NOTICE.md` (repo root) + +The `src/AcDream.App/Rendering/Wb/` directory already exists. + +- [ ] **Step 1: Create the Core/Rendering/Wb directory** + +Run: +```powershell +New-Item -ItemType Directory -Force -Path "src/AcDream.Core/Rendering/Wb" +``` +Expected: directory created, no error. + +- [ ] **Step 2: Check whether NOTICE.md exists** + +Run: +```powershell +Test-Path "NOTICE.md" +``` +Expected: `True` or `False`. If `True`, read it before editing. If `False`, the next step creates it. + +- [ ] **Step 3: Create or append the WorldBuilder attribution section in NOTICE.md** + +Write to `NOTICE.md` (append if exists, create otherwise): + +```markdown +## WorldBuilder + +Portions of acdream's rendering and dat-handling code are copied from +WorldBuilder (https://github.com/Chorizite/WorldBuilder), MIT-licensed. +The extracted code lives under: + +- `src/AcDream.Core/Rendering/Wb/` — pure helpers (texture decode, + scenery transforms, terrain math). +- `src/AcDream.App/Rendering/Wb/` — GL infrastructure and mesh pipeline. + +Original copyright holders: Chorizite contributors (see WorldBuilder's +LICENSE file). Adapted by acdream maintainers to consume our +`DatCollection` directly (replacing WB's `DefaultDatReaderWriter`) and +to remove editor-only code paths. + +Original MIT license text: + +[Insert full MIT license body here from references/WorldBuilder/LICENSE — verify the file exists at that path and use its exact content] +``` + +If the user has a different `NOTICE.md` style, follow theirs; this is the minimum content. + +- [ ] **Step 4: Verify the MIT license body** + +Run: +```powershell +Test-Path "references/WorldBuilder/LICENSE" +Get-Content "references/WorldBuilder/LICENSE" -TotalCount 5 +``` +Expected: file exists; first few lines should be MIT license text. Copy the full LICENSE body into NOTICE.md, replacing the `[Insert ...]` placeholder. + +- [ ] **Step 5: Commit** + +```powershell +git add NOTICE.md +git add "src/AcDream.Core/Rendering/Wb/.gitkeep" # if needed to track empty dir +git commit -m @' +chore(O-T2): create Core/Rendering/Wb directory + NOTICE.md attribution + +Phase O setup: extracted-WB code home + MIT attribution per O-D5. +Spec: docs/superpowers/specs/2026-05-21-phase-o-dat-path-unification-design.md + +Co-Authored-By: Claude Opus 4.7 (1M context) +'@ +``` + +Note: `New-Item -ItemType Directory` doesn't track empty dirs in git. If T1 needs the directory to exist before later commits, write a placeholder file (e.g., `.gitkeep` or a tiny `README.md` describing the directory's purpose) and commit it. + +--- + +## Task 2: Extract pure stateless helpers to Core (was O-T5) + +Moved earlier in the plan from spec's T5 position because: (a) lowest-risk extraction (pure functions, no GL, no dat behavior change); (b) unblocks the namespace migrations in our own Core files; (c) catches any namespace-update gotchas before the load-bearing T4. + +**Files:** +- Create: `src/AcDream.Core/Rendering/Wb/TextureHelpers.cs` +- Create: `src/AcDream.Core/Rendering/Wb/SceneryHelpers.cs` +- Create: `src/AcDream.Core/Rendering/Wb/TerrainUtils.cs` +- Create: `src/AcDream.Core/Rendering/Wb/TerrainEntry.cs` +- Create: `src/AcDream.Core/Rendering/Wb/CellSplitDirection.cs` +- Modify: `src/AcDream.Core/World/SceneryGenerator.cs` (2 `using` lines) +- Modify: `src/AcDream.Core/World/WbSceneryAdapter.cs` (1 `using` line) +- Modify: `src/AcDream.Core/Textures/SurfaceDecoder.cs` (1 `using` line) +- Modify: `tests/AcDream.Core.Tests/Textures/TextureDecodeConformanceTests.cs` (1 `using` line) +- Modify: `tests/AcDream.Core.Tests/Terrain/SplitFormulaDivergenceTest.cs` — actually this gets DELETED at T7, but its imports still need to work between now and then OR the test is moved to deleted-list earlier. Decision: leave it broken-but-doesn't-affect-other-tests for now, delete cleanly at T7. + +- [ ] **Step 1: Read each of the 5 WB source files** + +Read: +- `references/WorldBuilder/Chorizite.OpenGLSDLBackend/Lib/TextureHelpers.cs` +- `references/WorldBuilder/Chorizite.OpenGLSDLBackend/Lib/SceneryHelpers.cs` +- `references/WorldBuilder/WorldBuilder.Shared/Modules/Landscape/Lib/TerrainUtils.cs` +- `references/WorldBuilder/WorldBuilder.Shared/Modules/Landscape/Models/TerrainEntry.cs` +- `references/WorldBuilder/WorldBuilder.Shared/Modules/Landscape/Models/CellSplitDirection.cs` + +(Note: the worktree's `references/WorldBuilder` submodule is empty. Use the main checkout at `/c/Users/erikn/source/repos/acdream/references/WorldBuilder/` if needed.) + +Confirm each file is what the audit expected. Note any unexpected dependencies (other WB types referenced beyond NuGet packages like Silk.NET, BCnEncoder.Net, MemoryPack, etc.). + +- [ ] **Step 2: Copy `TextureHelpers.cs` to Core** + +Copy `references/WorldBuilder/Chorizite.OpenGLSDLBackend/Lib/TextureHelpers.cs` to `src/AcDream.Core/Rendering/Wb/TextureHelpers.cs`. Then update the file: + +Change the namespace declaration line from: +```csharp +namespace Chorizite.OpenGLSDLBackend.Lib; +``` +to: +```csharp +namespace AcDream.Core.Rendering.Wb; +``` + +If TextureHelpers has any `using` statements pointing to other WB types, note them but DO NOT change yet — copy is verbatim except for the namespace. + +- [ ] **Step 3: Copy `SceneryHelpers.cs` to Core (same process)** + +Same as Step 2 for `SceneryHelpers.cs`. Update its namespace to `AcDream.Core.Rendering.Wb`. + +If `SceneryHelpers.cs` has a `using WorldBuilder.Shared.Modules.Landscape.Lib;` or similar for `TerrainUtils`, leave it — we'll update it at Step 6. + +- [ ] **Step 4: Copy `TerrainUtils.cs` to Core** + +Same. Update namespace from `WorldBuilder.Shared.Modules.Landscape.Lib` → `AcDream.Core.Rendering.Wb`. + +- [ ] **Step 5: Copy `TerrainEntry.cs` to Core + strip `[MemoryPackable]`** + +Copy. Update namespace. Then **strip the `[MemoryPackable]` attribute** + any `[MemoryPack...]` attributes on fields: + +```csharp +// BEFORE +[MemoryPackable] +public partial struct TerrainEntry { ... } + +// AFTER +public struct TerrainEntry { ... } +``` + +Drop the `partial` modifier as well if the only reason it's `partial` is the MemoryPack source generator (verify by checking whether any other file extends the type via a separate `partial`). + +Drop any `using MemoryPack;` line. + +- [ ] **Step 6: Copy `CellSplitDirection.cs` to Core** + +Enum. Update namespace. Nothing else. + +- [ ] **Step 7: Update internal cross-references in the new files** + +After all 5 files exist in `src/AcDream.Core/Rendering/Wb/`: + +If `SceneryHelpers.cs` had `using WorldBuilder.Shared.Modules.Landscape.Lib;` (for `TerrainUtils`), change to nothing — they're in the same namespace now. + +If `TerrainUtils.cs` had `using WorldBuilder.Shared.Modules.Landscape.Models;` (for `TerrainEntry` / `CellSplitDirection`), change to nothing — same namespace. + +Run: +``` +Grep pattern="using (WorldBuilder|Chorizite\.OpenGLSDLBackend)" path="src/AcDream.Core/Rendering/Wb" +``` +Expected: no matches. If any, that file's still pointing at the old namespace; fix. + +- [ ] **Step 8: Update our own Core source files' `using` lines** + +Three Core files import WB types directly: + +In `src/AcDream.Core/World/WbSceneryAdapter.cs:2`: +```csharp +// BEFORE +using WorldBuilder.Shared.Models; +// AFTER +using AcDream.Core.Rendering.Wb; +``` + +Wait — `WbSceneryAdapter.cs:2` actually says `using WorldBuilder.Shared.Models;` not `...Modules.Landscape.Models;`. Verify the actual `using` and update accordingly. The import is for `TerrainEntry`. After T2 step 6, `TerrainEntry` is in `AcDream.Core.Rendering.Wb`. + +In `src/AcDream.Core/World/SceneryGenerator.cs:2` and `:6`: +```csharp +// BEFORE +using Chorizite.OpenGLSDLBackend.Lib; +using WorldBuilder.Shared.Modules.Landscape.Lib; +// AFTER +using AcDream.Core.Rendering.Wb; +// (single using replaces both, since both target types now live in the new namespace) +``` + +In `src/AcDream.Core/Textures/SurfaceDecoder.cs:3`: +```csharp +// BEFORE +using Chorizite.OpenGLSDLBackend.Lib; +// AFTER +using AcDream.Core.Rendering.Wb; +``` + +- [ ] **Step 9: Update conformance test's `using`** + +In `tests/AcDream.Core.Tests/Textures/TextureDecodeConformanceTests.cs:1`: +```csharp +// BEFORE +using Chorizite.OpenGLSDLBackend.Lib; +// AFTER +using AcDream.Core.Rendering.Wb; +``` + +Leave `tests/AcDream.Core.Tests/Terrain/SplitFormulaDivergenceTest.cs` alone for now — it's deleted at T7. + +- [ ] **Step 10: Build solution; expect green (or only the SplitFormulaDivergenceTest broken)** + +Run: +``` +dotnet build +``` +Expected: green. The `SplitFormulaDivergenceTest.cs` still has its `using WbTerrainUtils = WorldBuilder.Shared.Modules.Landscape.Lib.TerrainUtils;` alias — but `WorldBuilder.Shared` is still project-referenced at this point, so it still compiles. If anything else fails, the namespace migration missed a file. Fix and rerun. + +- [ ] **Step 11: Run tests; expect green** + +Run: +``` +dotnet test --no-build +``` +Expected: green. Pay particular attention to `TextureDecodeConformanceTests` — those should still pass byte-for-byte after the namespace move. + +- [ ] **Step 12: Commit T5** + +```powershell +git add src/AcDream.Core/Rendering/Wb/ src/AcDream.Core/World/WbSceneryAdapter.cs src/AcDream.Core/World/SceneryGenerator.cs src/AcDream.Core/Textures/SurfaceDecoder.cs tests/AcDream.Core.Tests/Textures/TextureDecodeConformanceTests.cs +git commit -m @' +feat(O-T5): extract pure stateless helpers to AcDream.Core.Rendering.Wb + +Verbatim copy of 5 WorldBuilder files into src/AcDream.Core/Rendering/Wb/: +- TextureHelpers.cs (pixel-format decoders, Chorizite Lib) +- SceneryHelpers.cs (scenery transforms, Chorizite Lib) +- TerrainUtils.cs, TerrainEntry.cs, CellSplitDirection.cs (WB.Shared Landscape) + +Namespace migrated from WorldBuilder.* / Chorizite.OpenGLSDLBackend.Lib +to AcDream.Core.Rendering.Wb per O-D11. [MemoryPackable] stripped from +TerrainEntry per O-D10 (we don't serialize the struct). + +Updated 3 source files + 1 test file to import from the new namespace. + +Verbatim discipline (O-D1): only namespace + MemoryPack attribute changed. +All algorithm bodies byte-identical to upstream. + +Spec: docs/superpowers/specs/2026-05-21-phase-o-dat-path-unification-design.md + +Co-Authored-By: Claude Opus 4.7 (1M context) +'@ +``` + +--- + +## Task 3: Extract GL infrastructure to App (was O-T3) + +**Files:** +- Create: 11+ files under `src/AcDream.App/Rendering/Wb/` (exact count after closure walk) +- Modify: none yet (the existing App `Wb/` adapter files don't import GL infra directly — they go through Silk.NET — but `WbMeshAdapter.cs` constructs `OpenGLGraphicsDevice` which it currently imports from `Chorizite.OpenGLSDLBackend`. That single import will be updated at T4 when `ObjectMeshManager` arrives.) + +- [ ] **Step 1: Walk the GL-infra closure** + +Read `references/WorldBuilder/Chorizite.OpenGLSDLBackend/OpenGLGraphicsDevice.cs` first. List every WB type it references (look at field types, method parameters, constructor calls, `using` statements). + +Then read each referenced WB type. Continue until closure is closed. + +Expected closure (per audit): +- `OpenGLGraphicsDevice.cs` +- `GLSLShader.cs`, `GLHelpers.cs`, `GLStateScope.cs` (likely in `Lib/`) +- `ManagedGLTexture.cs`, `ManagedGLTextureArray.cs`, `ManagedGLVertexBuffer.cs`, `ManagedGLIndexBuffer.cs`, `ManagedGLVertexArray.cs`, `ManagedGLFrameBuffer.cs`, `ManagedGLUniformBuffer.cs` (root or `Lib/`) +- `EmbeddedResourceReader.cs`, `TextureFormatExtensions.cs`, `BufferUsageExtensions.cs` (3 internals to promote) +- `DebugRenderSettings.cs` (sometimes needed by `OpenGLGraphicsDevice` ctor) + +Write down the actual file list with paths. + +- [ ] **Step 2: Check for `SixLabors.ImageSharp` reachability** + +Run: +``` +Grep pattern="SixLabors\.ImageSharp" path="references/WorldBuilder/Chorizite.OpenGLSDLBackend" +``` +List every file in the closure that imports ImageSharp. + +If empty: document "ImageSharp not reachable" in the T3 commit message. Skip step 3. + +If non-empty: proceed to step 3. + +- [ ] **Step 3: Strip ImageSharp usage from the closure files (only if needed)** + +For each closure file that imports ImageSharp: +- Identify the call sites (typically PNG/JPG load helpers). +- Replace with our existing byte-handling or BCnEncoder calls. +- Remove the `using SixLabors.ImageSharp;` line. + +If a file's ImageSharp usage cannot be cleanly removed (e.g., it's the file's main purpose), then either: (a) drop the file from the extraction (verify it's not called by our closure), or (b) add `SixLabors.ImageSharp` as a `` to `AcDream.App.csproj` and keep the file. + +Document the decision in the T3 commit. + +- [ ] **Step 4: Copy each GL-infra file to `src/AcDream.App/Rendering/Wb/`** + +For each file in the closure list: +- Copy verbatim from WB source to `src/AcDream.App/Rendering/Wb/`. +- Update the namespace from `Chorizite.OpenGLSDLBackend` (or `.Lib`) to `AcDream.App.Rendering.Wb`. +- Update any `using Chorizite.OpenGLSDLBackend.Lib;` / `using Chorizite.OpenGLSDLBackend;` lines inside the copied files to point at the new namespace. +- For the 3 internal types (`EmbeddedResourceReader`, `TextureFormatExtensions`, `BufferUsageExtensions`): change `internal class` / `internal static class` / etc. to `public class` / `public static class`. + +Suggested copy order (each follows the same pattern): managed wrappers first (lowest deps), then helpers, then `OpenGLGraphicsDevice` last (depends on all the rest). + +- [ ] **Step 5: Build, iterate until green** + +Run: +``` +dotnet build +``` + +Common failures + fixes: +- "The type or namespace name 'X' could not be found" → `using` was missed; add `using AcDream.App.Rendering.Wb;`. OR a transitive WB type wasn't copied — copy it. +- "The type 'X' is defined in an assembly that is not referenced" → ImageSharp/MemoryPack/other NuGet — see step 3. +- "Inconsistent accessibility" → an internal type isn't yet promoted to public — promote it. + +Iterate until green. + +- [ ] **Step 6: Run tests; expect green (no test count change)** + +Run: +``` +dotnet test --no-build +``` + +Tests should pass; this task doesn't change behavior, only file location and namespace. + +- [ ] **Step 7: Commit T3** + +```powershell +git add src/AcDream.App/Rendering/Wb/ +git commit -m @' +feat(O-T3): extract GL infrastructure to AcDream.App.Rendering.Wb + +Verbatim copy of GL infra (~15 files) from +Chorizite.OpenGLSDLBackend into src/AcDream.App/Rendering/Wb/: +- OpenGLGraphicsDevice.cs, GLSLShader.cs, GLHelpers.cs, GLStateScope.cs +- ManagedGL{Texture,TextureArray,VertexBuffer,IndexBuffer, + VertexArray,FrameBuffer,UniformBuffer}.cs (7 files) +- DebugRenderSettings.cs + +Three internal types promoted to public per O-D9: +- EmbeddedResourceReader, TextureFormatExtensions, BufferUsageExtensions + +SixLabors.ImageSharp reachability: . + +Verbatim discipline (O-D1): namespace + access modifier changes only. +All algorithm bodies byte-identical to upstream. + +Build green; tests green (no count change). + +Spec: docs/superpowers/specs/2026-05-21-phase-o-dat-path-unification-design.md + +Co-Authored-By: Claude Opus 4.7 (1M context) +'@ +``` + +--- + +## Task 4: Extract mesh pipeline + dat refactor (was O-T4) + +The load-bearing task. Includes the `ObjectMeshManager` refactor or fallback to adapter, per O-D7. + +**Files:** +- Create: `src/AcDream.App/Rendering/Wb/ObjectMeshManager.cs` +- Create: `src/AcDream.App/Rendering/Wb/ObjectRenderBatch.cs` +- Create: `src/AcDream.App/Rendering/Wb/ObjectRenderData.cs` +- Create: ~5+ supporting files (particle batcher / emitter, global mesh buffer, modern render data — count + exact filenames during closure walk) +- Modify: `src/AcDream.App/Rendering/Wb/WbMeshAdapter.cs` (constructor + `using` updates; cleanup at T7) + +- [ ] **Step 1: Walk the mesh-pipeline closure** + +Read `references/WorldBuilder/Chorizite.OpenGLSDLBackend/Lib/ObjectMeshManager.cs` end-to-end. It's ~2K LOC; use Read with offsets if needed. List every WB type it references that ISN'T already in the GL-infra closure (T3) or stateless-helpers closure (T2). + +Expected new types in closure (per audit): +- `ObjectRenderBatch`, `ObjectRenderData` +- `GlobalMeshBuffer` (or similar; the single-VBO/IBO holder for modern rendering) +- `ParticleBatcher`, `ParticleEmitterRenderer` (referenced from mesh path) +- Modern render data structs (likely a couple of small files) + +Write the actual file list with paths. + +- [ ] **Step 2: Count the `_dats.X` call sites in `ObjectMeshManager.cs`** + +Run: +``` +Grep pattern="_dats\." path="references/WorldBuilder/Chorizite.OpenGLSDLBackend/Lib/ObjectMeshManager.cs" +``` +Count the matches. + +**Branch on count:** +- **≤ 20 sites**: take the refactor path (O-D7). Plan steps 3-7 cover this. +- **> 20 sites**: take the adapter fallback. Plan steps 3-7 are skipped; instead, plan steps A-D below (after step 7). + +Document the actual count in the T4 commit message regardless. + +- [ ] **Step 3: (refactor path) Copy mesh-pipeline files to App, namespace-update** + +Copy each closure file to `src/AcDream.App/Rendering/Wb/`. Update each file's namespace from `Chorizite.OpenGLSDLBackend.Lib` → `AcDream.App.Rendering.Wb`. Update any internal `using` lines. + +Do NOT yet modify `ObjectMeshManager`'s dat type — that's the next step. First, the verbatim copy + namespace. + +- [ ] **Step 4: (refactor path) Refactor `ObjectMeshManager` dat field type** + +In the newly-copied `src/AcDream.App/Rendering/Wb/ObjectMeshManager.cs`: + +a) Drop the import: +```csharp +// BEFORE +using WorldBuilder.Shared.Services; +``` +(plus any related; remove if present.) + +b) Add the import: +```csharp +using AcDream.Core; +// or wherever DatCollection lives — verify with: +// Grep pattern="^namespace.*DatCollection" path="src/AcDream.Core" +// or: +// Grep pattern="public.*class DatCollection\b" path="src/AcDream.Core" +``` + +c) Change the field declaration from: +```csharp +private readonly IDatReaderWriter _dats; +``` +to: +```csharp +private readonly DatCollection _dats; +``` + +d) Change the constructor parameter from `IDatReaderWriter dats` to `DatCollection dats`. + +e) Update each `_dats.X` call site. The most common shapes: +- `_dats.Portal.TryGet(id, out var x)` — verify DatCollection exposes `Portal.TryGet`. If yes, no change. If no, see step 5. +- `_dats.Cell.TryGet(id, out var x)` — verify the same. +- `_dats.HighRes.TryGet(...)` — same. +- `_dats.Language.TryGet(...)` — same. +- `_dats.ResolveId(id)` — drop the call site if it's diagnostic-only (per O-D12). If it's load-bearing, see step 5. + +For each call site, either: (a) leave it alone (DatCollection has the equivalent), (b) replace with DatCollection's API shape, or (c) escalate to step 5 (DatCollection needs a new method). + +- [ ] **Step 5: (refactor path) Add missing methods to DatCollection if needed** + +If step 4 surfaced a call shape DatCollection doesn't support, add the method to `src/AcDream.Core/Dats/DatCollection.cs` (or wherever DatCollection lives — find via grep). + +DO NOT add methods speculatively — only add what `ObjectMeshManager` actually calls. Document each added method in the T4 commit. + +- [ ] **Step 6: (refactor path) Update `WbMeshAdapter` to construct `ObjectMeshManager` with `DatCollection`** + +In `src/AcDream.App/Rendering/Wb/WbMeshAdapter.cs`: + +Update line 7-15 `using` lines: drop `using Chorizite.OpenGLSDLBackend;`, `using Chorizite.OpenGLSDLBackend.Lib;`, `using WorldBuilder.Shared.Models;`, `using WorldBuilder.Shared.Services;`. Add `using AcDream.App.Rendering.Wb;` (and `AcDream.Core.Rendering.Wb;` if needed for any of the now-Core types referenced). + +Update line 85-88 ObjectMeshManager construction. Today: +```csharp +_meshManager = new ObjectMeshManager( + _graphicsDevice, + _wbDats, + new ConsoleErrorLogger()); +``` + +Change to: +```csharp +_meshManager = new ObjectMeshManager( + _graphicsDevice, + dats, // the DatCollection passed to WbMeshAdapter's ctor + new ConsoleErrorLogger()); +``` + +Leave `_wbDats` field + its construction at line 79 + its disposal at line 346 in place for now — they're cleaned up at T7. + +Do NOT touch the `[indoor-upload] NULL_RESULT` block (lines 192-263) yet — also cleaned up at T7. + +- [ ] **Step 7: (refactor path) Build, iterate until green** + +Run: +``` +dotnet build +``` +Common failures: +- `_dats.X` call shape doesn't match DatCollection — fix per step 4/5. +- Missing `using` for a moved type — add. + +Iterate until green. + +- [ ] **Step A: (adapter fallback path, only if count > 20)** + +Create `src/AcDream.App/Rendering/Wb/DatCollectionAdapter.cs`: + +```csharp +using AcDream.Core; // or wherever DatCollection lives +using DatReaderWriter; +using DatReaderWriter.DBObjs; +// ... add interfaces / types needed to satisfy IDatReaderWriter + +namespace AcDream.App.Rendering.Wb; + +/// +/// Adapts our DatCollection to WB's IDatReaderWriter interface so +/// the extracted ObjectMeshManager can consume it without internal +/// refactoring. O-D7 fallback path — taken because ObjectMeshManager +/// has >20 _dats.X call sites and the refactor was deemed too invasive +/// for one ship-window. +/// +internal sealed class DatCollectionAdapter : IDatReaderWriter +{ + private readonly DatCollection _dats; + + public DatCollectionAdapter(DatCollection dats) + { + ArgumentNullException.ThrowIfNull(dats); + _dats = dats; + } + + // Implement each member of IDatReaderWriter by delegating to _dats. + // Members are determined by reading IDatReaderWriter.cs (which is + // also copied into this directory at this step, since we no longer + // have it via the WorldBuilder.Shared project reference). + // ... +} +``` + +You also need to copy `IDatReaderWriter.cs` from WB.Shared into `src/AcDream.App/Rendering/Wb/` (or define a slimmed-down version with only the members ObjectMeshManager uses). Document the choice. + +- [ ] **Step B: (adapter fallback) Wire the adapter in WbMeshAdapter** + +```csharp +// BEFORE (in WbMeshAdapter ctor) +_meshManager = new ObjectMeshManager(_graphicsDevice, _wbDats, ...); + +// AFTER +_meshManager = new ObjectMeshManager( + _graphicsDevice, + new DatCollectionAdapter(dats), + ...); +``` + +- [ ] **Step C: (adapter fallback) Build, iterate until green** + +Same as step 7 but with the adapter in place. + +- [ ] **Step D: (adapter fallback) Document the choice** + +Note in the T4 commit message that the adapter path was taken, with the actual call-site count and the rationale (e.g., "37 call sites; 22 use methods DatCollection doesn't currently expose, escalating to a separate refactor phase"). + +- [ ] **Step 8: (both paths) Run tests; expect green** + +Run: +``` +dotnet test --no-build +``` +Expected: green. No test count regression. + +- [ ] **Step 9: (both paths) Commit T4** + +```powershell +git add src/AcDream.App/Rendering/Wb/ +git add src/AcDream.Core/Dats/ # only if DatCollection grew methods at step 5 +git commit -m @' +feat(O-T4): extract mesh pipeline; dat-shim + +Verbatim copy of ObjectMeshManager + supports (~8 files, ~3.3K LOC) from +Chorizite.OpenGLSDLBackend.Lib into src/AcDream.App/Rendering/Wb/. + +ObjectMeshManager._dats call-site count: . +Path taken: OR . +Rationale: . + +DatCollection additions (if any): . + +WbMeshAdapter updated to construct ObjectMeshManager via the new path. +The _wbDats field + [indoor-upload] NULL_RESULT block stay in place for +now; cleaned up at T7. + +SixLabors.ImageSharp: . + +Verbatim discipline (O-D1): namespace + dat-surface only. Mesh extraction, +texture decode, particle pipeline byte-identical to upstream. + +Build green; tests green (no count change). + +Spec: docs/superpowers/specs/2026-05-21-phase-o-dat-path-unification-design.md + +Co-Authored-By: Claude Opus 4.7 (1M context) +'@ +``` + +--- + +## Task 5: Drop project references + cleanup (was O-T7) + +**Files:** +- Modify: `src/AcDream.App/AcDream.App.csproj` +- Modify: `src/AcDream.Core/AcDream.Core.csproj` +- Modify: `src/AcDream.App/Rendering/Wb/WbMeshAdapter.cs` +- Modify: `src/AcDream.App/Rendering/Wb/WbDrawDispatcher.cs` (`using` line) +- Modify: doc-comment-only files in tests/ (5-6 files, comment edits) +- Delete: `tests/AcDream.Core.Tests/Terrain/SplitFormulaDivergenceTest.cs` + +- [ ] **Step 1: Delete `_wbDats` field + construction from `WbMeshAdapter.cs`** + +Open `src/AcDream.App/Rendering/Wb/WbMeshAdapter.cs`. Delete: + +a) Line 34 (the field declaration): +```csharp +private readonly DefaultDatReaderWriter? _wbDats; +``` + +b) Line 79 (the construction): +```csharp +_wbDats = new DefaultDatReaderWriter(datDir); +``` + +c) Line 346 (the disposal in `Dispose()`): +```csharp +_wbDats?.Dispose(); +``` + +d) The `datDir` parameter — verify it's no longer used after `_wbDats` removal. If `OpenGLGraphicsDevice` ctor doesn't need it, remove `datDir` from `WbMeshAdapter`'s constructor signature + all call sites. If it's still needed for something else, keep it. + +- [ ] **Step 2: Delete the `[indoor-upload] NULL_RESULT` block** + +In `WbMeshAdapter.cs`, delete the block from line ~192 to line ~263 (the diagnostic block that uses `_wbDats.ResolveId(...)`). Also delete the `_pendingEnvCellRequests` field and its associated logic in `Tick()` (the `isPendingEnvCell` block at ~305-321). + +Result: `WbMeshAdapter.cs` shrinks substantially — should be down from 349 to ~250 LOC. + +- [ ] **Step 3: Update `WbMeshAdapter.cs` and `WbDrawDispatcher.cs` `using` lines** + +In `WbMeshAdapter.cs` (lines 7-15): +- Drop: `using Chorizite.OpenGLSDLBackend;`, `using Chorizite.OpenGLSDLBackend.Lib;`, `using WorldBuilder.Shared.Models;`, `using WorldBuilder.Shared.Services;`, `using DatReaderWriter;`, `using DatReaderWriter.DBObjs;` (verify whether the last two are still needed — they probably are for `GfxObj` references in `PopulateMetadata`). +- Add: `using AcDream.App.Rendering.Wb;` if not present. + +In `WbDrawDispatcher.cs` (line 9): +- Drop: `using Chorizite.OpenGLSDLBackend.Lib;` +- Add: `using AcDream.App.Rendering.Wb;` + +- [ ] **Step 4: Delete the `` lines in both csprojs** + +In `src/AcDream.App/AcDream.App.csproj`, delete lines 38-39 (the two `` entries to `WorldBuilder.Shared` and `Chorizite.OpenGLSDLBackend`). Also drop the comment immediately above them ("Phase N.4 Task 9: ...") since the reference rationale is now historical. + +In `src/AcDream.Core/AcDream.Core.csproj`, delete lines 27-28 (same two references). Also drop the multi-line comment immediately above ("Phase N: WorldBuilder is acdream's rendering + dat-handling base...") since the references are gone. + +- [ ] **Step 5: Delete `SplitFormulaDivergenceTest.cs`** + +```powershell +Remove-Item "tests/AcDream.Core.Tests/Terrain/SplitFormulaDivergenceTest.cs" +``` + +This was a one-time data-collection test; its job finished at N.5b ship. + +- [ ] **Step 6: Fix doc-only WB mentions in remaining test files** + +For each of these files, update comment-only references to WB to point at the extracted location instead. Files (per audit grep): +- `tests/AcDream.Core.Tests/World/WbSceneryAdapterTests.cs:10-17` — mentions `WorldBuilder.Shared.Models.TerrainEntry`. Update to `AcDream.Core.Rendering.Wb.TerrainEntry`. +- `tests/AcDream.Core.Tests/World/SceneryGeneratorTests.cs:9` — mentions WB helpers in comment. Update to refer to `AcDream.Core.Rendering.Wb`. +- `tests/AcDream.Core.Tests/Rendering/Wb/MeshExtractionConformanceTests.cs:12` — mentions `WB's ObjectMeshManager`. Either update to extracted name OR keep with a clarifying comment "(formerly WB; now ours, see Phase O)". +- `tests/AcDream.Core.Tests/Terrain/ClientReference.cs:11` and `ClientConformanceTests.cs:10` — both "Ported from WorldBuilder-ACME-Edition". These are historical attributions; leave them OR update phrasing. + +This is comment-edit work; no logic changes. + +- [ ] **Step 7: Build solution; expect green** + +Run: +``` +dotnet build +``` + +Expected: green. If a `using WorldBuilder.*` or `using Chorizite.OpenGLSDLBackend*` was missed, the build will fail with "namespace not found." Find it and update. + +Also expect: if any file still references `IDatReaderWriter` / `DefaultDatReaderWriter` directly, the build fails. Grep: +``` +Grep pattern="(IDatReaderWriter|DefaultDatReaderWriter)" path="src" +``` +Should return zero matches. + +- [ ] **Step 8: Run tests; expect green minus deleted test count** + +Run: +``` +dotnet test --no-build +``` + +Expected: green. The total test count drops by however many tests were in the deleted `SplitFormulaDivergenceTest.cs` (likely a single test or two — record the actual delta). + +- [ ] **Step 9: Verify the acceptance criteria for reference deletion** + +Run all three: +``` +Grep pattern="(WorldBuilder|Chorizite\.OpenGLSDLBackend)" path="src/AcDream.App/AcDream.App.csproj" +Grep pattern="(WorldBuilder|Chorizite\.OpenGLSDLBackend)" path="src/AcDream.Core/AcDream.Core.csproj" +Grep pattern="^using (WorldBuilder|Chorizite\.OpenGLSDLBackend)" path="src" +``` +Expected: all three return zero matches. + +``` +Grep pattern="DefaultDatReaderWriter" path="src" +``` +Expected: zero matches. + +If any return matches: something was missed in this task. Fix before commit. + +- [ ] **Step 10: Commit T7** + +```powershell +git add src/AcDream.App/Rendering/Wb/WbMeshAdapter.cs src/AcDream.App/Rendering/Wb/WbDrawDispatcher.cs src/AcDream.App/AcDream.App.csproj src/AcDream.Core/AcDream.Core.csproj tests/ +git rm tests/AcDream.Core.Tests/Terrain/SplitFormulaDivergenceTest.cs +git commit -m @' +feat(O-T7): drop WB project references; cleanup _wbDats + diagnostic block + +End of Phase O extraction: +- Dropped entries to WorldBuilder.Shared and + Chorizite.OpenGLSDLBackend from AcDream.App.csproj and + AcDream.Core.csproj. +- Deleted _wbDats field + ctor + dispose from WbMeshAdapter.cs. +- Deleted [indoor-upload] NULL_RESULT diagnostic block (lines 192-263); + the Phase 2 cell-resolution diagnostic served its purpose, and its + dependency on _wbDats.ResolveId goes away with this commit (per O-D12). +- Deleted SplitFormulaDivergenceTest.cs (one-time N.5b data-collection + test; job done). +- Updated comment-only WB mentions in 5 test files to point at the + extracted namespace. + +Verified acceptance criteria: +- Zero refs to WorldBuilder.* / Chorizite.OpenGLSDLBackend.* in any csproj. +- Zero "using WorldBuilder.*" / "using Chorizite.OpenGLSDLBackend*" in src/. +- DefaultDatReaderWriter referenced in zero places. + +Build green; tests green (count: - from deleted test, no regressions). + +Spec: docs/superpowers/specs/2026-05-21-phase-o-dat-path-unification-design.md + +Co-Authored-By: Claude Opus 4.7 (1M context) +'@ +``` + +--- + +## Task 6: Visual verification gate (was O-T8) + +**Goal:** Confirm that the extraction didn't regress rendering by side-by-side with main against retail in three scenes. + +**Files:** none modified; this is a runtime test. + +- [ ] **Step 1: Capture pre-extraction screenshots (do this BEFORE Task 2 if not already done)** + +If not already captured: pause this plan, switch back to `main` (or a commit at HEAD before Task 1), launch acdream at three scenes: +- Holtburg town (outdoor + scenery) +- An inn interior (EnvCell) +- A dungeon (portals) + +Save screenshots to `docs/research/phase-o-pre/holtburg-town.png`, `inn-interior.png`, `dungeon.png` (not committed; reference only). + +If you forgot to capture pre-screenshots before starting: you can either roll back to a pre-O commit (`git checkout ` on a scratch branch), or compare visually against the retail client side-by-side instead. + +- [ ] **Step 2: Launch acdream after Task 5 with the test character** + +Use the launch script from CLAUDE.md (PowerShell): + +```powershell +$env:ACDREAM_DAT_DIR = "$env:USERPROFILE\Documents\Asheron's Call" +$env:ACDREAM_LIVE = "1" +$env:ACDREAM_TEST_HOST = "127.0.0.1" +$env:ACDREAM_TEST_PORT = "9000" +$env:ACDREAM_TEST_USER = "testaccount" +$env:ACDREAM_TEST_PASS = "testpassword" +dotnet build # must be green first +dotnet run --project src\AcDream.App\AcDream.App.csproj --no-build -c Debug 2>&1 | + Tee-Object -FilePath "launch-O-verification.log" +``` + +Run in the background per CLAUDE.md guidance. + +- [ ] **Step 3: Visit the three scenes** + +In the running client: +1. **Holtburg town** — walk around, check terrain blending, scenery placement (trees/bushes), building exteriors. Compare with pre-O screenshot. +2. **Inn interior** — enter the inn at Holtburg, look at EnvCell geometry (walls, floor, fireplace), check that statics render correctly. +3. **Dungeon** — find any portal (Holtburg Town network portal works for spawn-based visuals; for a real dungeon, walk to a dungeon entrance). Check portal visibility, room geometry. + +User confirms each scene reads identical to pre-O. + +- [ ] **Step 4: Measure resident memory at radius=4 + 50 entities visible** + +In the running client: +- Set quality preset to Low (radius=4 — see CLAUDE.md "Quality Preset system"). +- Wait for streaming to settle. +- Open Task Manager (Windows) → Details tab → find `AcDream.App.exe` → Working Set (Memory). +- Record the value. + +Compare to a pre-O baseline (same scene, same settings, on `main` HEAD before Phase O). Expected delta: ≥50 MB reduction (validates that the second `DefaultDatReaderWriter` cache is actually gone). + +If <50 MB: investigate why. The dat-reader duplication should be ~50-100 MB per `WbMeshAdapter.cs:27` comment. + +- [ ] **Step 5: Close client gracefully and record findings** + +Use the graceful close from CLAUDE.md (WM_CLOSE) so ACE's session clears quickly. + +Write a brief verification note (in chat or in the T8 commit message): +- Three scenes: identical / different (describe difference). +- Memory delta: X MB reduction. +- User confirmation: yes / no. + +Do NOT proceed to Task 7 if any scene regressed or memory delta is <50 MB. + +- [ ] **Step 6: Tag the verification commit (or just push to next task)** + +No code change at T8 — but optionally record the verification artifacts: + +```powershell +git add docs/research/ # if you committed any post-O screenshots +git commit --allow-empty -m @' +chore(O-T8): visual verification passed + +Three scenes side-by-side against pre-O baseline: identical. +- Holtburg town (outdoor + scenery): OK +- Holtburg inn interior (EnvCell): OK +- (portals): OK + +Memory measurement at radius=4 + 50 entities visible: +- Pre-O: MB working set +- Post-O: MB working set +- Delta: MB reduction (>= 50 MB target) + +User confirmed identical rendering. + +Spec: docs/superpowers/specs/2026-05-21-phase-o-dat-path-unification-design.md + +Co-Authored-By: Claude Opus 4.7 (1M context) +'@ +``` + +--- + +## Task 7: Ship (was O-T9) + +**Files:** +- Modify: `CLAUDE.md` — rewrite "WB integration cribs" section. +- Modify: `docs/architecture/worldbuilder-inventory.md` — update ownership notes. +- Modify: `docs/plans/2026-04-11-roadmap.md` — move Phase O from "in flight" to "shipped". +- Modify: `docs/plans/2026-05-12-milestones.md` — note Phase O ship if appropriate. + +- [ ] **Step 1: Rewrite the "WB integration cribs" section in CLAUDE.md** + +Find the block in `CLAUDE.md` that starts with "**WorldBuilder is acdream's rendering + dat-handling base, integrated as of Phase N.4 ship (2026-05-08).**" and continues through the WB integration cribs (the bullet list of files and patterns). + +Replace it with text that reflects post-O reality: + +```markdown +**WorldBuilder code is extracted into acdream's source tree as of Phase +O ship (2026-XX-XX).** The pure helpers (texture decode, scenery +transforms, terrain math) live in `src/AcDream.Core/Rendering/Wb/`. +The GL-touching infrastructure and mesh pipeline live in +`src/AcDream.App/Rendering/Wb/`. There is no `` to +`WorldBuilder.Shared` or `Chorizite.OpenGLSDLBackend` in any csproj — +those projects remain in `references/WorldBuilder/` as read-references +only (grep against them when porting NEW pieces). + +ALL dat reads go through `DatCollection` (Phase O ship: ONE thing +touches the DATs). The previous `DefaultDatReaderWriter` second-reader +allocation in `WbMeshAdapter` is deleted. + +[update the file-path cribs below the header to point at the new +locations under `src/AcDream.{Core,App}/Rendering/Wb/`] +``` + +Preserve all of the substantive cribs about GL pipeline behavior, the +indirect-draw command struct, the surface-id rules, etc. — just retarget +the file paths and remove the "WB is a project reference" language. + +- [ ] **Step 2: Update `docs/architecture/worldbuilder-inventory.md`** + +Add a top-of-file banner indicating the inventory now describes "what we +extracted vs what we left in references/." Update the §1 status line. +The body inventory tables stay valuable (they describe the WB source we +might still grep). Add a column or section noting "Extracted into acdream +at Phase O" for each component that moved. + +- [ ] **Step 3: Update the roadmap** + +In `docs/plans/2026-04-11-roadmap.md`, find Phase O in the "active" / +"in flight" section. Move it to "shipped" with a one-line summary: + +``` +Phase O — DatPath Unification (2026-XX-XX, ): extracted +~33 WB files / ~7.7K LOC into src/AcDream.{Core,App}/Rendering/Wb/. +ObjectMeshManager refactored to take DatCollection (). Memory reduction MB. Reference: docs/superpowers/specs/2026-05-21-phase-o-dat-path-unification-design.md. +``` + +- [ ] **Step 4: Update milestones doc** + +In `docs/plans/2026-05-12-milestones.md`, locate the M1.5 block. Phase O +pre-empted M1.5 — add a brief writeup that O has shipped and M1.5 work +can resume from the 2026-05-20 baseline. + +- [ ] **Step 5: Build + test final** + +Run: +``` +dotnet build +dotnet test +``` +Expected: both green. + +- [ ] **Step 6: Final commit + Phase O ship marker** + +```powershell +git add CLAUDE.md docs/architecture/worldbuilder-inventory.md docs/plans/2026-04-11-roadmap.md docs/plans/2026-05-12-milestones.md +git commit -m @' +ship(O): Phase O — DatPath Unification — SHIPPED + +ONE thing touches the DATs. WB code lives in our repo: +- src/AcDream.Core/Rendering/Wb/ — pure helpers (5 files, ~782 LOC) +- src/AcDream.App/Rendering/Wb/ — GL infra + mesh pipeline (~25 files, ~7K LOC) + +Project references to WorldBuilder.Shared + Chorizite.OpenGLSDLBackend +dropped from AcDream.App.csproj and AcDream.Core.csproj. references/ +WorldBuilder remains in-tree as read-reference. + +DefaultDatReaderWriter removed; DatCollection is the only dat reader. +Working-set memory delta: MB reduction at radius=4 + 50 entities. + +Visual side-by-side passed: Holtburg town, inn interior, dungeon. + +Updates: +- CLAUDE.md: rewrote WB integration cribs to point at extracted locations. +- docs/architecture/worldbuilder-inventory.md: ownership now ours. +- Roadmap: moved Phase O to "shipped". +- Milestones: M1.5 resumes from 2026-05-20 baseline. + +Spec: docs/superpowers/specs/2026-05-21-phase-o-dat-path-unification-design.md + +Co-Authored-By: Claude Opus 4.7 (1M context) +'@ +``` + +- [ ] **Step 7: Merge to main** + +Per spec O-D6 (one ship-window). Open a PR (or fast-forward merge if the +worktree branch is clean) targeting main. Use `gh pr create` per +CLAUDE.md if a PR is desired; or: + +```powershell +git checkout main +git merge claude/serene-leakey-e6b8bc --ff-only +git push +``` + +Verify with: +``` +git status +git log -10 +``` + +--- + +## Self-review notes + +Plan reviewed against spec sections 4, 5, 6: + +**Spec coverage:** +- §4.1 (mesh pipeline) → Task 4. ✓ +- §4.2 (GL infra) → Task 3. ✓ +- §4.3 (stateless helpers) → Task 2. ✓ +- §4.4 (NOT extracted) → no task needed (these are explicitly skipped). +- §4.5 (drops) → Task 5. ✓ +- §5 task breakdown T2/T3/T4/T5/T7/T8/T9 → plan Tasks 1/3/4/2/5/6/7. ✓ +- §6 acceptance criteria → checked at Task 5 step 9 + Task 6 step 4 + Task 7. ✓ +- §7 risks → mitigations baked into task steps (T4 safety check at step 2; visual screenshots before Task 1 / Task 6 step 1). ✓ + +**Placeholder scan:** +- "[Insert full MIT license body here...]" in Task 1 step 3 — intentional, requires reading the actual LICENSE file at step 4. Acceptable since step 4 explicitly tells the executor to fetch the content. +- "exact filenames during closure walk" in Task 3 + Task 4 file-list — intentional honesty since the audit didn't persist the full per-file table. The closure-walk steps cover producing the exact list. +- "" in commit message templates — intentional; commit messages parameterize on findings (e.g., ImageSharp reachability) discovered during the task. + +**Type consistency:** +- `_dats` field name preserved across tasks. +- `DatCollection` class name verified — see Task 4 step 4b (executor confirms via grep). +- Namespace conventions: `AcDream.Core.Rendering.Wb` for Core helpers, `AcDream.App.Rendering.Wb` for App GL/mesh code. Consistent. + +**Scope check:** Single ship-window per spec O-D6. Plan is one cohesive unit; no decomposition needed. diff --git a/docs/superpowers/specs/2026-05-21-phase-o-dat-path-unification-design.md b/docs/superpowers/specs/2026-05-21-phase-o-dat-path-unification-design.md index b057fc0..8e196bf 100644 --- a/docs/superpowers/specs/2026-05-21-phase-o-dat-path-unification-design.md +++ b/docs/superpowers/specs/2026-05-21-phase-o-dat-path-unification-design.md @@ -126,9 +126,11 @@ One reader, one cache, one source of dat truth. ### 4.1 Mesh pipeline (T4 — the load-bearing extraction) +> **Layer placement:** mesh-pipeline files live under `src/AcDream.App/Rendering/Wb/` (NOT Core), because `ObjectMeshManager` and its supports use `Silk.NET.OpenGL` types directly (ManagedGL*, GLSLShader, etc.) and CLAUDE.md forbids Core depending on GL. + | WB source | New acdream home | Adaptation | |---|---|---| -| `Chorizite.OpenGLSDLBackend.Lib.ObjectMeshManager` | `src/AcDream.Core/Rendering/Wb/ObjectMeshManager.cs` | **Refactor**: replace `IDatReaderWriter` field/ctor-param with `DatCollection`. Update `_dats.X` call sites. Safety check at T4: if >20 sites, fall back to thin adapter. | +| `Chorizite.OpenGLSDLBackend.Lib.ObjectMeshManager` | `src/AcDream.App/Rendering/Wb/ObjectMeshManager.cs` | **Refactor**: replace `IDatReaderWriter` field/ctor-param with `DatCollection` (Core type — App can reference it). Update `_dats.X` call sites. Safety check at T4: if >20 sites, fall back to thin adapter. | | `Chorizite.OpenGLSDLBackend.Lib.ObjectRenderBatch` + `ObjectRenderData` | Same directory | Verbatim copy. | | Particle batcher + emitter (T4 supports) | Same | Verbatim copy. | | `Chorizite.OpenGLSDLBackend.Lib.DebugRenderSettings` | Same | Verbatim copy (constructor parameter type only). | @@ -136,14 +138,16 @@ One reader, one cache, one source of dat truth. ### 4.2 Texture pipeline + GL infrastructure (T3) +> **Layer split:** `TextureHelpers` is pure (no GL, no dat) → goes to Core. All other GL infra → App. + | WB source | New acdream home | Adaptation | |---|---|---| -| `Chorizite.OpenGLSDLBackend.Lib.TextureHelpers` | `src/AcDream.Core/Rendering/Wb/TextureHelpers.cs` | Verbatim. Pure functions — no dat dependency. | -| `Chorizite.OpenGLSDLBackend.OpenGLGraphicsDevice` | `src/AcDream.App/Rendering/Wb/OpenGLGraphicsDevice.cs` (stays in App because it talks to GL) | Verbatim. No dat dependency. | -| `ManagedGL{Texture,TextureArray,VertexBuffer,IndexBuffer,VertexArray,FrameBuffer,UniformBuffer}` | App `Wb/` directory | Verbatim. | -| `GLSLShader`, `GLHelpers`, `GLStateScope` | App `Wb/` directory | Verbatim. | -| `EmbeddedResourceReader` (internal → public) | Same | Promote `internal` → `public`. | -| `TextureFormatExtensions`, `BufferUsageExtensions` (internal → public) | Same | Promote `internal` → `public`. | +| `Chorizite.OpenGLSDLBackend.Lib.TextureHelpers` | `src/AcDream.Core/Rendering/Wb/TextureHelpers.cs` | Verbatim. Pure functions — no dat / no GL. | +| `Chorizite.OpenGLSDLBackend.OpenGLGraphicsDevice` | `src/AcDream.App/Rendering/Wb/OpenGLGraphicsDevice.cs` | Verbatim. Touches GL. | +| `ManagedGL{Texture,TextureArray,VertexBuffer,IndexBuffer,VertexArray,FrameBuffer,UniformBuffer}` | App `Wb/` directory | Verbatim. Touches GL. | +| `GLSLShader`, `GLHelpers`, `GLStateScope` | App `Wb/` directory | Verbatim. Touches GL. | +| `EmbeddedResourceReader` (internal → public) | App `Wb/` directory | Promote `internal` → `public`. | +| `TextureFormatExtensions`, `BufferUsageExtensions` (internal → public) | App `Wb/` directory | Promote `internal` → `public`. | ### 4.3 Stateless helpers (T5)