docs: roadmap N.0 shipped + realistic N.2-N.9 estimates + N.3 handoff

Roadmap updates after Phase N.1 ship:
- Marks N.0 (submodule + project refs setup) as ✓ SHIPPED with the
  c8782c9 commit reference
- Updates N.2-N.9 effort estimates with realistic post-N.1 numbers
  (originals were 1-2 days / 1 week / 2 weeks; realistic numbers
  factor in conformance-test discovery, ACME-vs-Chorizite delta
  hunts, and the visual-verification-then-revert cycle that ate
  most of N.1's calendar time)
- Adds a "Lessons from N.1" subsection so future N phases benefit
  from the rotation-bug-conformance-test pattern, the ACME divergence
  insight, and the "whackamole = stop" rule
- Updates total calendar estimate to 3-4 months / 10-12 engineering
  weeks for N.2-N.9 (was 2-3 months / 6-8 weeks)

New handoff doc at docs/research/2026-05-08-phase-n3-handoff.md
captures everything a fresh agent picking up N.3 (texture decoding)
needs: phase context, what to read first, suggested task decomposition,
watchouts (especially the ACME-divergence and conformance-test
lessons), and where to start.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Erik 2026-05-08 10:49:16 +02:00
parent ad8b931be7
commit 6010827b21
2 changed files with 192 additions and 11 deletions

View file

@ -0,0 +1,132 @@
# Phase N.3 handoff — texture decoding via WorldBuilder
**Use this whole document as the prompt** when handing off to a fresh
agent. Everything they need to pick up cold is below.
---
## Background you'll need
You're working in `acdream`, a from-scratch C# .NET 10 reimplementation
of Asheron's Call's retail client. The project's house rule (in
`CLAUDE.md`) is **the code is modern, the behavior is retail**.
acdream just shipped **Phase N.1** (commits `26cf2b8` through `ad8b931`),
the first sub-phase of a strategic migration to fork WorldBuilder
(`github.com/Chorizite/WorldBuilder`, MIT) and depend on its tested
rendering + dat-handling code instead of porting algorithms from retail
decomp ourselves.
**Read first:**
- `docs/architecture/worldbuilder-inventory.md` — the full taxonomy of
what WB has and what we keep porting ourselves
- `docs/superpowers/specs/2026-05-08-phase-n-worldbuilder-migration-design.md`
— the parent design doc for Phase N
- `CLAUDE.md` — especially the "Reference repos" section (now points at
WB as the rendering BASE) and the workflow rules
**Phase N.1 commit history (just shipped):** read
`git log --oneline c8782c9..ad8b931` to see how N.0 + N.1 were
structured. The pattern repeats for N.3.
## What N.3 is
Replace acdream's texture decoding pipeline with WorldBuilder's
`Chorizite.OpenGLSDLBackend.Lib.TextureHelpers`. WB handles INDEX16,
P8, BGRA, DXT, and alpha-channel decoding. Our existing implementations
of these are scattered across `src/AcDream.App/Rendering/TextureCache.cs`
and possibly `src/AcDream.Core/Meshing/` — find them with
`grep -rln "INDEX16\|P8 decode\|DXT\|BGRA" src/`.
## Acceptance criteria
- Build green (`dotnet build`)
- All existing tests green (the 8 pre-existing `DispatcherToMovementIntegrationTests`
failures don't count — they exist on main)
- New conformance tests added per format that's substituted (one xUnit
Theory per: INDEX16, P8, BGRA, DXT). Each compares a fixed input byte
array decoded by our path vs WB's path; assertions on output pixel array.
- Visual verification at Holtburg (or wherever) shows no texture
regressions: terrain texturing, mesh texturing, particle textures all
look the same.
- ISSUES.md updated with any known cosmetic deltas (the N.1 pattern —
if WB and retail disagree on something subtle, file it, don't try
to fix it inline).
## Tasks (suggested decomposition)
Follow the N.1 plan structure (`docs/superpowers/plans/2026-05-08-phase-n1-scenery-via-wb-helpers.md`)
as the template. Concretely:
1. **Audit our texture decode paths.** Grep, list every file/method that
decodes a texture. Map each to the WB equivalent in
`references/WorldBuilder/Chorizite.OpenGLSDLBackend/Lib/TextureHelpers.cs`
(read it end to end first).
2. **Per-format conformance test.** TDD style: write the test, run it
to fail, then plumb the substitution. Conformance test fixture inputs
should include real-dat byte sequences (read a known-good texture from
a dat, encode the bytes as a hex blob in the test).
3. **Substitution.** Replace each decode site with the WB call. Keep our
GL upload pathways — those are NOT WB's responsibility.
4. **Visual verification.** Launch the client at Holtburg, walk around,
look at a tree (mesh texture), the ground (atlas texture), particles
(the recent C.1 rain/clouds/aurora work), and a building (composite
texture). Compare against retail or against a screenshot before the
change.
5. **Delete legacy decoders** once visual verification passes.
6. **Update roadmap + ISSUES** as the final commit.
## Watchouts (lessons from N.1)
- **ACME has a downstream fork with extra filters** (`references/WorldBuilder-ACME-Edition/`).
WB's `TextureHelpers` may have ACME-specific patches not yet in upstream.
Compare both before assuming WB's version is canonical. We forked
upstream WB; ACME is reference-only.
- **Conformance tests are non-negotiable.** Phase N.1's rotation bug was
caught by the conformance test. Don't skip them. If a test fails, it's
a real divergence — investigate before "fixing" the test.
- **Whackamole stops the migration.** If 3+ visual regressions appear on
default-on, stop, file as ISSUES, ship. The migration goal is "use WB's
tested code"; pixel-perfect equivalence with our broken hand-ports is
not the goal.
- **`Setup.SortingSphere``Setup.CylSphere`.** The N.1 attempt at
`obj_within_block` over-suppressed because we used the wrong radius
source (sorting sphere too large). For texture decoding this likely
doesn't matter, but the general lesson is: read WB's full source
carefully before adapting; don't assume parallel methods do parallel
things.
- **Per-vertex road check — STOP signal.** If you find yourself reading
ACME for "what's missing" and considering a per-vertex filter, STOP.
N.1 tried this (commit `e279c46`), regressed visually, reverted in
`677a726`. ACME's filter set works as a coherent unit; pick-and-choose
fails. If the N.3 work uncovers a similar ACME-only filter, file it
in ISSUES and move on, don't port it inline.
## Where to start
1. `git pull` on main to get the latest (Phase N.1 just merged).
2. Create a new worktree for the work:
`git worktree add .claude/worktrees/<your-name> -b claude/<your-name>`.
3. Read the three "read first" docs above.
4. Run `dotnet build && dotnet test` to confirm clean baseline.
5. Read `references/WorldBuilder/Chorizite.OpenGLSDLBackend/Lib/TextureHelpers.cs`
end to end. Take notes on the public API surface.
6. Run the audit task (#1 in Tasks above). Output should be a markdown
table of "our function / file:line / WB equivalent / format covered."
7. Use `superpowers:writing-plans` to convert the audit into a concrete
per-format plan. Then use `superpowers:subagent-driven-development`
to execute it with fresh subagents per format.
## Useful greps
- `grep -rln "INDEX16\|IndexedSurface\|P8\|DXT\|BGRA\|TextureFormat" src/` — find decode paths
- `grep -rln "TextureCache" src/` — find our cache layer
- `grep -n "public static.*Decode\|public static.*Convert" references/WorldBuilder/Chorizite.OpenGLSDLBackend/Lib/TextureHelpers.cs` — WB's public API
## Open question to resolve early
Does `Chorizite.OpenGLSDLBackend.Lib.TextureHelpers` cover ALL the
formats we use, or does it have gaps? Audit our texture types against
WB's API in step 1. If WB is missing a format we need, the migration for
that format gets deferred (file in ISSUES; keep our decoder for it; note
in the roadmap).