# Epic 2 Retrospective โ€” Relief Icons Layer Migration **Date:** 2026-03-12 **Facilitator:** Bob ๐Ÿƒ (Scrum Master) **Project Lead:** Azgaar **Epic:** 2 โ€” Relief Icons Layer Migration **Status at Retro:** 1/3 stories formally `done`; 2/3 in `review` (dev complete, code review pending) --- ## Team Participants | Agent | Role | | ---------- | ----------------------------------- | | Bob ๐Ÿƒ | Scrum Master (facilitating) | | Amelia ๐Ÿ’ป | Developer (Claude Sonnet 4.5 / 4.6) | | Quinn ๐Ÿงช | QA Engineer | | Winston ๐Ÿ—๏ธ | Architect | | Alice ๐Ÿ“Š | Product Owner | | Azgaar | Project Lead | --- ## Epic 2 Summary ### Delivery Metrics | Metric | Value | | ----------------------------------- | ----------------------------------------------------- | | Stories completed (formally `done`) | 1/3 | | Stories dev-complete (in `review`) | 2/3 โ€” 2-2, 2-3 | | Blockers encountered | **0** | | Production incidents | **0** | | Technical debt items | **1** โ€” T11 manual smoke test deferred from Story 2-2 | | Test coverage at epic end | **88.51%** (was 85.13% entering epic) | | Total tests at epic end | **43** (was 34 entering epic) | | Lint errors | **0** across all three stories | ### FRs Addressed | FR | Description | Status | | ---- | ---------------------------------------------------- | -------------------------------------------------------------------- | | FR12 | Instanced relief rendering in single GPU draw call | โœ… Story 2-2 | | FR13 | Position icons at SVG-space terrain cell coordinates | โœ… Story 2-2 | | FR14 | Scale icons by zoom level and user scale setting | โœ… Story 2-2 | | FR15 | Per-icon rotation from terrain dataset | โœ… Story 2-1 (verified: no rotation field; zero rotation is correct) | | FR16 | Configurable opacity | โœ… Story 2-2 | | FR17 | Re-render on terrain dataset change | โœ… Story 2-2 | | FR18 | WebGL2 detection and automatic SVG fallback | โœ… Stories 2-2, 2-3 | | FR19 | SVG fallback visual parity | โœ… Story 2-3 (structural verification) | | FR20 | No WebGL canvas intercepting pointer events | โœ… Epic 1 / Story 2-2 | | FR21 | Existing Layers panel controls unchanged | โœ… Story 2-2 | ### NFRs Addressed | NFR | Description | Status | | ------ | --------------------------------------------- | --------------------------------------------------------- | | NFR-B1 | Named Three.js imports only | โœ… Story 2-2 | | NFR-M5 | โ‰ฅ80% Vitest coverage | โœ… 88.51% | | NFR-C1 | WebGL2 sole gating check | โœ… Story 2-3 | | NFR-C4 | Hardware acceleration disabled = SVG fallback | โœ… Story 2-3 | | NFR-P1 | <16ms render (1,000 icons) | โš ๏ธ Implemented; browser measurement deferred to Story 3-1 | | NFR-P2 | <100ms render (10,000 icons) | โš ๏ธ Implemented; browser measurement deferred to Story 3-1 | --- ## Story-by-Story Analysis ### Story 2-1: Verify and Implement Per-Icon Rotation in buildSetMesh **Agent:** Claude Sonnet 4.5 **Status:** `done` **Pattern:** Investigation-first story โ€” verify before coding **What went well:** - Perfect execution of the investigate-first pattern. Hypothesis (`r.i` might be rotation) confirmed false in one pass. - Verification comment added to `buildSetMesh` creates a permanent, documented decision trail. - Zero code churn. AC2 was correctly identified as N/A without second-guessing. - `npm run lint` โ†’ `Checked 80 files in 98ms. No fixes applied.` โœ… **No struggles:** Clean from start to finish. **Key artifact:** FR15 verification comment in `buildSetMesh` documenting that `r.i` is a sequential index, not a rotation angle, and that both WebGL and SVG paths produce unrotated icons โ€” visual parity confirmed by shared code path. --- ### Story 2-2: Refactor draw-relief-icons.ts to Use Framework **Agent:** Claude Sonnet 4.6 **Status:** `review` (dev complete) **What went well:** - Biome import ordering auto-fix was handled correctly โ€” recognized as cosmetic-only, not flagged as a bug. - Discovery of GPU leak pattern: `buildReliefScene` traverses and disposes geometry _before_ `terrainGroup.clear()` โ€” not in the spec, found empirically, fixed correctly. Prevents silent GPU memory accumulation on repeated `drawRelief()` calls. - `preloadTextures()` moved into `setup()` callback โ€” arguably more correct than module-load-time preloading (textures load when the framework is ready, not at import). - Anisotropy line removal was clean โ€” explanatory comment documents the renderer ownership transfer. - All 34 existing framework tests pass unaffected โœ… **Struggles:** - None during implementation. One optional item (T11) was deferred. **Technical debt incurred:** - **T11 (medium priority, HIGH impact on Epic 3):** Browser smoke test โ€” load map, render relief icons, toggle layer, pan/zoom, measure render time. Deferred as "optional" in Story 2-2. This is the prerequisite for Story 3-1's benchmarking. **Key decisions:** - `lastBuiltIcons`/`lastBuiltSet` reset to `null` in `undrawRelief` โ€” prevents stale memoization after `group.clear()`. - `drawSvg(icons, parentEl)` called for both `type === "svg"` and `hasFallback === true` โ€” same code path, guaranteed visual parity. --- ### Story 2-3: WebGL2 Fallback Integration Verification **Agent:** Claude Sonnet 4.6 **Status:** `review` (dev complete) **What went well:** - No duplication of existing tests โ€” developer read the test file before writing new ones. All 9 new tests are genuinely novel. - Node env constraint correctly identified and handled: `vi.stubGlobal("requestAnimationFrame", vi.fn())` pattern discovered independently (same pattern used in Story 1.3). - Coverage increase from 85.13% โ†’ 88.51% (+3.38%) from fallback branch coverage. - AC4 visual parity verified structurally with sound reasoning: `drawSvg()` is unchanged; same code path = identical output. **Struggles:** - Initial `requestRender()` test attempted `vi.spyOn(globalThis, "requestAnimationFrame")` which fails in node env. Self-corrected to `vi.stubGlobal`. Good problem-solving. **Deferred (T5):** Integration test for `window.drawRelief()` SVG output when `hasFallback=true` โ€” skipped due to node env (`pack` globals, DOM requirements). Documented with clear rationale. **Final counts:** 43 tests total (+9 new), 88.51% statement coverage. --- ## Cross-Story Patterns ### โœ… Pattern 1 โ€” Investigation-before-implementation (All 3 stories) Every story began by reading existing code before writing new code: - Story 2-1: verified `r.i` before deciding whether to implement rotation - Story 2-2: confirmed `buildSetMesh` findings from 2-1 still held before proceeding - Story 2-3: read full test file before writing any new tests **Team verdict:** This is a strength. Official team practice going forward. ### โš ๏ธ Pattern 2 โ€” Node-only Vitest environment as recurring constraint (Stories 2-2, 2-3) Both stories deferred important verification because the unit test environment has no DOM, no `pack` globals, and no real WebGL context. Story 3-1 is a browser-only story โ€” this pattern will surface again. **Team verdict:** Known constraint, documented. Story 3-1 scope includes browser harness decision. ### โœ… Pattern 3 โ€” Transparent documentation of deferred work (Both deferring stories) Both deferrals (T11 in 2-2, T5 in 2-3) are clearly documented with explicit reasoning in completion notes. No hidden debt. **Team verdict:** Healthy habit. Explicit "deferred to story X" annotation should be formalized. --- ## Previous Epic Retrospective No Epic 1 retrospective exists. This is the first retrospective for the Fantasy-Map-Generator project. **Note:** Epic 1's retrospective status in sprint-status.yaml remains `optional`. If desired, a retro for Epic 1 can be run separately. --- ## Next Epic Preview: Epic 3 โ€” Quality & Bundle Integrity **Stories:** 3-1 Performance Benchmarking, 3-2 Bundle Size Audit (both `ready-for-dev`) ### Dependencies on Epic 2 | Epic 3 Story | Depends On | Status | | ---------------------------- | ------------------------------------------ | ------------------------- | | 3-1 Performance Benchmarking | Relief layer rendering in browser from 2-2 | โš ๏ธ T11 smoke test pending | | 3-1 Performance Benchmarking | `window.drawRelief()` callable | โœ… 2-2 complete | | 3-2 Bundle Size Audit | Named Three.js imports from 2-2 | โœ… 2-2 complete | | 3-2 Bundle Size Audit | `vite build` clean | โœ… lint passes | ### Key Insight Story 2-2's deferred T11 (browser smoke test) and Story 3-1's benchmarking overlap naturally. Story 3-1 should begin with the T11 verification items as pre-benchmark confirmation steps. ### Story 3-2 Independence Story 3-2 (Bundle Size Audit) has no dependency on Story 3-1 or on T11. It can begin immediately once Stories 2-2 and 2-3 code reviews are complete. --- ## Significant Discovery Assessment **No significant discoveries requiring Epic 3 plan changes.** The architecture is sound, the named import refactor (NFR-B1) is done, fallback is tested, and Epic 3's premise is validated. The only course-correction needed is scoping: Story 3-1 should explicitly include T11 smoke test items. --- ## Action Items ### Process Improvements | # | Action | Owner | Success Criteria | | --- | ----------------------------------------------------------------------------- | ---------------------- | ----------------------------------------------------------------- | | P1 | Update story template: deferred tasks must annotate "Deferred to: [story X]" | Bob ๐Ÿƒ (SM) | Template updated before creating Story 3-1 | | P2 | Document known node-env Vitest constraint in story template dev notes section | Paige ๐Ÿ“š (Tech Writer) | One-line note: "Vitest: no DOM, no `pack` globals, no real WebGL" | ### Technical Debt | # | Item | Owner | Priority | | --- | --------------------------------------------------------------------------------------------------- | --------- | ------------------------------------ | | D1 | T11 browser smoke test from Story 2-2 โ€” manual verification of icons render, layer toggle, pan/zoom | Amelia ๐Ÿ’ป | HIGH โ€” subsumed into Story 3-1 scope | ### Team Agreements 1. **Verify-before-implement** is official practice โ€” every story where implementation could be skipped must confirm first 2. **Deferred tasks** always annotate the receiving story ("Deferred to: Story X-Y") 3. **Node env constraint** is documented once in the story template โ€” not re-discovered per story --- ## Epic 3 Preparation Tasks ### Critical (block Epic 3 start) - [ ] Complete formal code review for Story 2-2 โ†’ mark `done` Owner: Azgaar (Project Lead) - [ ] Complete formal code review for Story 2-3 โ†’ mark `done` Owner: Azgaar (Project Lead) - [ ] Determine Story 3-1 browser test approach: Playwright (existing config at `playwright.config.ts`) vs. manual DevTools Owner: Quinn ๐Ÿงช (QA) ### Parallel (can start now) - [ ] Story 3-2 (Bundle Size Audit) โ€” no blocking dependencies Owner: Amelia ๐Ÿ’ป ### Story 3-1 Scope Enhancement (SM action when creating story) - [ ] Add T11 items from Story 2-2 to Story 3-1 as pre-benchmark verification steps Owner: Bob ๐Ÿƒ (SM โ€” add when creating Story 3-1) --- ## Critical Path 1. โ†’ Code review Stories 2-2 and 2-3 โ†’ `done` _(Azgaar)_ 2. โ†’ Create Story 3-1 with T11 items folded in _(Bob SM)_ 3. โ†’ Story 3-2 runs in parallel _(Amelia Dev)_ --- ## Readiness Assessment | Dimension | Status | Notes | | ---------------------- | ---------- | ------------------------------------------------------ | | Testing & Quality | โœ… Green | 43 tests, 88.51% coverage, lint clean | | Browser Verification | โš ๏ธ Pending | T11 smoke test โ€” folded into Story 3-1 | | Deployment | N/A | Development project | | Stakeholder Acceptance | โœ… | Single-developer project โ€” retrospective is acceptance | | Technical Health | ๐ŸŸข Clean | Named imports, GPU leak fixed, fallback tested | | Unresolved Blockers | None | Code review is a process gate, not a blocker | --- ## Key Takeaways 1. **Investigate-first discipline prevents phantom implementations.** FR15 rotation was verified absent rather than implemented speculatively โ€” saved real complexity. 2. **The node-only test environment is a known, documented constraint** โ€” not a surprise, not a failure. Epic 3 Story 3-1 is the natural home for browser-level verification. 3. **Unscoped quality improvements happen when stories are well-understood.** The GPU leak fix in `buildReliefScene` wasn't specced โ€” it was discovered and fixed correctly by an engaged developer. 4. **Transparent deferral documentation is the team's strongest quality habit.** Nothing was buried. --- ## Commitments - Action Items: **2** - Preparation Tasks: **3 critical, 2 parallel** - Critical Path Items: **2 code reviews** - Team Agreements: **3** --- ## Next Steps 1. Code review Stories 2-2 and 2-3 (Azgaar) 2. Create Story 3-1 with T11 items (Bob SM โ€” use `create-story`) 3. Story 3-2 ready to kick off in parallel 4. No Epic 3 plan changes required โ€” proceed when code reviews are done --- _Retrospective facilitated by Bob ๐Ÿƒ (Scrum Master) ยท Fantasy-Map-Generator Project ยท 2026-03-12_