mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2026-04-03 14:07:24 +02:00
- Added documentation for Story 1.6 outlining the requirements and acceptance criteria for migrating shared defs-backed resources to a dedicated host. - Updated sprint status to reflect the readiness of Story 1.6 for development. - Created epics document detailing the breakdown of the Fantasy-Map-Generator project, including functional and non-functional requirements. - Added implementation readiness report assessing the current state of documentation and readiness for the project. - Introduced end-to-end tests for scene bootstrap to ensure runtime hosts are created and reused correctly.
480 lines
22 KiB
Markdown
480 lines
22 KiB
Markdown
---
|
|
stepsCompleted:
|
|
- step-01-validate-prerequisites
|
|
- step-02-design-epics
|
|
- step-03-create-stories
|
|
- step-04-final-validation
|
|
inputDocuments:
|
|
- _bmad-output/planning-artifacts/prd-layered-map-dom-split.md
|
|
- _bmad-output/planning-artifacts/architecture-layered-map-dom-split.md
|
|
---
|
|
|
|
# Fantasy-Map-Generator - Epic Breakdown
|
|
|
|
## Overview
|
|
|
|
This document provides the complete epic and story breakdown for Fantasy-Map-Generator, decomposing the requirements from the PRD, UX Design if it exists, and Architecture requirements into implementable stories.
|
|
|
|
## Requirements Inventory
|
|
|
|
### Functional Requirements
|
|
|
|
FR1: Users can reorder layers in any sequence supported today, regardless of whether the layer is implemented in SVG or WebGL.
|
|
FR2: Visibility toggles behave exactly as they do now.
|
|
FR3: Editing and pointer interaction remain correct after layer splitting.
|
|
FR4: Shared styles, filters, masks, and text path resources remain available where needed.
|
|
FR5: Existing layer-based workflows continue to function without exposing rendering implementation details.
|
|
FR6: Export produces equivalent output to the current behavior for supported layers.
|
|
FR7: Legacy code paths that depend on svg, viewbox, or one selector scope have a compatibility path during migration.
|
|
|
|
### NonFunctional Requirements
|
|
|
|
NFR1: The architecture must support incremental migration rather than a flag-day rewrite.
|
|
NFR2: Test design and execution are out of scope for this implementation tranche and will be handled in a separate follow-up activity.
|
|
NFR3: Layer order changes must update all runtime surfaces atomically.
|
|
NFR4: Performance must not regress for existing SVG-only layers.
|
|
NFR5: The architecture must remain compatible with the existing global-variable runtime model.
|
|
|
|
### Additional Requirements
|
|
|
|
- The layer registry is the single source of truth and each layer must register id, kind, order, visible state, and surface.
|
|
- The runtime scene must use one independent surface per logical layer, including dedicated SVG shells for SVG layers and registered canvas surfaces for WebGL layers.
|
|
- Shared transform ownership moves from the old viewbox DOM element to scene state, while scale, viewX, viewY, graphWidth, and graphHeight remain authoritative globals.
|
|
- svg and viewbox must stop being architectural source-of-truth globals and instead be supported only through a temporary compatibility layer during migration.
|
|
- The compatibility layer must provide getLayerSvg(id), getLayerSurface(id), and queryMap(selector).
|
|
- Runtime shared defs resources must live in a dedicated defs host separate from layer surfaces.
|
|
- Filters, patterns, masks, symbols, markers, and text paths must use stable IDs and remain available across split surfaces.
|
|
- Export must use a separate assembly pipeline that rebuilds a unified SVG from registry order, layer outputs, and only the required defs resources.
|
|
- Runtime structure must allow arbitrary ordering of SVG and WebGL layers without grouped SVG buckets.
|
|
- Layer modules should own only their own drawing surface; scene owns shared runtime state; defs owns shared SVG resources.
|
|
- The migration should proceed in phases: foundation, initial split layers, mixed rendering, then export hardening.
|
|
- No starter template requirement was identified in the architecture document.
|
|
- No UX document was provided, so no UX-specific requirements were added in this step.
|
|
|
|
### FR Coverage Map
|
|
|
|
FR1: Epic 2 and Epic 3 - Reordering remains correct first for split SVG layers and then for mixed SVG and WebGL layers.
|
|
FR2: Epic 2 and Epic 3 - Visibility behavior remains unchanged for split layers and mixed rendering.
|
|
FR3: Epic 2 and Epic 3 - Pointer and editing workflows remain correct through the split-layer and mixed-render transitions.
|
|
FR4: Epic 1 and Epic 4 - Shared defs-backed resources are preserved in runtime and in unified export output.
|
|
FR5: Epic 1, Epic 2, and Epic 3 - Existing workflows continue to work while the runtime architecture changes underneath them.
|
|
FR6: Epic 4 - Export output remains equivalent for supported layers after the runtime moves to split surfaces.
|
|
FR7: Epic 1 - Legacy single-SVG callers keep a compatibility path during migration.
|
|
|
|
## Epic List
|
|
|
|
### Epic 1: Foundation for Layered Runtime
|
|
|
|
Establish the shared scene, defs, layer registry, layer lifecycle, and compatibility contracts so the runtime can migrate away from one canonical SVG root without breaking existing map behavior.
|
|
**FRs covered:** FR4, FR5, FR7
|
|
|
|
### Epic 2: First Split SVG Layers
|
|
|
|
Move approved low-risk SVG layers into standalone SVG shells while preserving visual behavior, layer controls, and editing interactions.
|
|
**FRs covered:** FR1, FR2, FR3, FR5
|
|
|
|
### Epic 3: Mixed SVG and WebGL Ordering
|
|
|
|
Register WebGL surfaces under the same ordering and visibility model so users can interleave SVG and WebGL layers through one control path.
|
|
**FRs covered:** FR1, FR2, FR3, FR5
|
|
|
|
### Epic 4: Unified Export Assembly
|
|
|
|
Assemble a unified SVG export from registry state and shared defs resources so supported layered maps export with equivalent output quality.
|
|
**FRs covered:** FR4, FR6
|
|
|
|
## Epic 1: Foundation for Layered Runtime
|
|
|
|
Establish the shared scene, defs, layer registry, layer lifecycle, and compatibility contracts so the runtime can migrate away from one canonical SVG root without breaking existing map behavior.
|
|
|
|
### Story 1.1: Bootstrap Scene Container and Defs Host
|
|
|
|
As a map maintainer,
|
|
I want runtime initialization to create a dedicated scene container and defs host,
|
|
So that split layer surfaces can share resources without depending on one map SVG root.
|
|
|
|
**Implements:** FR4, FR5; NFR1, NFR5.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
**Given** the current runtime starts from one canonical map host
|
|
**When** the layered runtime bootstrap runs
|
|
**Then** it creates or reuses a dedicated scene container for layer surfaces and a dedicated defs host outside individual layer surfaces
|
|
**And** the visible map loads without user-facing regressions at startup.
|
|
|
|
**Given** existing code expects the map to initialize once
|
|
**When** the new bootstrap path is enabled
|
|
**Then** the scene container and defs host are available through stable runtime references
|
|
**And** initialization does not require changing user-facing layer controls.
|
|
|
|
### Story 1.2: Add Scene Module for Shared Camera State
|
|
|
|
As a map maintainer,
|
|
I want a Scene module to own shared camera and viewport state,
|
|
So that all layer surfaces consume one authoritative transform contract.
|
|
|
|
**Implements:** FR5; NFR1, NFR5.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
**Given** shared globals such as scale, viewX, viewY, graphWidth, and graphHeight already exist
|
|
**When** the Scene module is introduced
|
|
**Then** it exposes a single runtime contract for camera and viewport state
|
|
**And** existing global values remain authoritative and usable during migration.
|
|
|
|
**Given** multiple surfaces will render the same map
|
|
**When** camera state changes
|
|
**Then** the Scene module provides one consistent state source for all registered surfaces
|
|
**And** no feature code needs to read transforms from DOM structure directly.
|
|
|
|
### Story 1.3: Add Layers Registry as the Ordering Source of Truth
|
|
|
|
As a map maintainer,
|
|
I want a centralized Layers registry,
|
|
So that visibility, order, and surface ownership are managed consistently instead of inferred from DOM position.
|
|
|
|
**Implements:** FR5; NFR1, NFR3, NFR5.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
**Given** logical map layers currently rely on DOM placement and ad hoc lookups
|
|
**When** a layer is registered
|
|
**Then** the registry stores its id, kind, order, visible state, and surface handle
|
|
**And** callers can query layer state without inferring it from DOM order.
|
|
|
|
**Given** runtime layer order changes
|
|
**When** reorder operations are applied through the registry
|
|
**Then** all registered layer surfaces receive the updated ordering atomically
|
|
**And** the registry remains the single source of truth for visibility and order.
|
|
|
|
### Story 1.4: Add Layer Surface Lifecycle Ownership
|
|
|
|
As a map maintainer,
|
|
I want a Layer abstraction to own each surface lifecycle,
|
|
So that individual layers can be created, mounted, updated, and disposed without leaking renderer-specific details.
|
|
|
|
**Implements:** FR5; NFR1, NFR5.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
**Given** the runtime needs one surface per logical layer
|
|
**When** a layer is instantiated
|
|
**Then** the Layer abstraction owns creation, mount, update, and teardown for that surface
|
|
**And** caller code interacts with the layer through a stable contract rather than direct DOM assumptions.
|
|
|
|
**Given** both SVG and WebGL layers will exist
|
|
**When** a surface is registered with the Layer abstraction
|
|
**Then** surface lifecycle handling works without exposing renderer-specific branching to feature modules
|
|
**And** layer modules remain responsible only for drawing their own surface.
|
|
|
|
### Story 1.5: Add Compatibility Lookups for Legacy Single-SVG Callers
|
|
|
|
As a map maintainer,
|
|
I want compatibility helpers for legacy single-SVG access patterns,
|
|
So that existing workflows keep working while code migrates to the new scene and layer contracts.
|
|
|
|
**Implements:** FR5, FR7; NFR1, NFR5.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
**Given** legacy code still expects svg, viewbox, or one shared selector scope
|
|
**When** compatibility helpers are introduced
|
|
**Then** the runtime provides getLayerSvg(id), getLayerSurface(id), and queryMap(selector)
|
|
**And** callers can continue to function during migration without depending on one canonical map SVG.
|
|
|
|
**Given** new code is added after the compatibility layer exists
|
|
**When** it needs layer or scene access
|
|
**Then** it can use the new layer and scene contracts directly
|
|
**And** the compatibility layer remains a migration bridge rather than the new source of truth.
|
|
|
|
### Story 1.6: Move Shared Defs Resources to the Dedicated Host
|
|
|
|
As a map maintainer,
|
|
I want shared defs-backed resources to be registered in one dedicated host,
|
|
So that split surfaces can keep using stable IDs for filters, masks, symbols, markers, patterns, and text paths.
|
|
|
|
**Implements:** FR4, FR5; NFR1, NFR5.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
**Given** runtime resources currently live under one shared SVG structure
|
|
**When** defs registration is migrated
|
|
**Then** shared resources are created under the dedicated defs host with stable identifiers
|
|
**And** layer surfaces can reference those resources without duplicating them per layer.
|
|
|
|
**Given** a split surface uses a filter, mask, symbol, marker, pattern, or text path
|
|
**When** the layer renders
|
|
**Then** the resource reference resolves from the dedicated defs host
|
|
**And** existing visual behavior remains unchanged for supported runtime features.
|
|
|
|
## Epic 2: First Split SVG Layers
|
|
|
|
Move approved low-risk SVG layers into standalone SVG shells while preserving visual behavior, layer controls, and editing interactions.
|
|
|
|
### Story 2.1: Create Reusable Standalone SVG Shell Mounting
|
|
|
|
As a map maintainer,
|
|
I want low-risk SVG layers to mount into dedicated SVG shells,
|
|
So that selected layers can leave the single-root SVG without changing their visible behavior.
|
|
|
|
**Implements:** FR5; NFR1, NFR5.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
**Given** a low-risk SVG layer is selected for migration
|
|
**When** its surface is created through the layered runtime
|
|
**Then** the layer mounts into its own dedicated SVG shell inside the scene container
|
|
**And** the shell can participate in registry-controlled ordering and visibility.
|
|
|
|
**Given** the shell mounting path is in place
|
|
**When** another approved low-risk SVG layer is migrated
|
|
**Then** the same mounting mechanism can be reused without introducing layer-specific bootstrap hacks
|
|
**And** the migration remains incremental.
|
|
|
|
### Story 2.2: Migrate a Representative Low-Risk SVG Layer to a Dedicated Shell
|
|
|
|
As a map maintainer,
|
|
I want one representative low-risk SVG layer migrated first,
|
|
So that the split-surface path is proven on a contained layer before broader rollout.
|
|
|
|
**Implements:** FR3, FR5; NFR1, NFR4.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
**Given** the standalone shell path exists
|
|
**When** the first approved low-risk SVG layer is migrated
|
|
**Then** it renders from its dedicated shell with unchanged visual output for supported behavior
|
|
**And** its feature workflow continues to operate through the new scene and layer contracts.
|
|
|
|
**Given** the representative layer is split out
|
|
**When** users interact with that layer through existing tools
|
|
**Then** pointer targeting and editing behavior remain correct
|
|
**And** the migration does not require unrelated layers to move at the same time.
|
|
|
|
### Story 2.3: Migrate Remaining Approved Low-Risk SVG Layers
|
|
|
|
As a map maintainer,
|
|
I want the remaining approved low-risk SVG layers moved through the same split-layer path,
|
|
So that the runtime can prove multi-layer SVG splitting before mixed rendering begins.
|
|
|
|
**Implements:** FR3, FR5; NFR1, NFR4.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
**Given** the representative migration pattern has been established
|
|
**When** additional approved low-risk SVG layers are migrated
|
|
**Then** each layer renders from its own SVG shell using the shared scene, layer, and defs contracts
|
|
**And** each migrated layer preserves its existing visible behavior for supported workflows.
|
|
|
|
**Given** more than one low-risk SVG layer has been split
|
|
**When** they coexist in the runtime
|
|
**Then** they can render independently without grouped SVG buckets
|
|
**And** layer modules remain responsible only for their own surfaces.
|
|
|
|
### Story 2.4: Drive Reorder and Visibility for Split SVG Layers from the Registry
|
|
|
|
As a map user,
|
|
I want reordered and toggled split SVG layers to behave exactly as before,
|
|
So that layer management remains familiar while the runtime architecture changes.
|
|
|
|
**Implements:** FR1, FR2, FR5; NFR3, NFR5.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
**Given** one or more low-risk SVG layers have been split into standalone shells
|
|
**When** a user reorders those layers through existing controls
|
|
**Then** the registry updates the shell ordering atomically
|
|
**And** the visible stacking order matches the updated control order.
|
|
|
|
**Given** a user toggles visibility for a split SVG layer
|
|
**When** the layer state changes
|
|
**Then** the registry applies the visible state to the correct shell
|
|
**And** toggle behavior matches existing user expectations.
|
|
|
|
### Story 2.5: Preserve Pointer and Editing Workflows for Split SVG Layers
|
|
|
|
As a map user,
|
|
I want editing and pointer interactions to remain correct on split SVG layers,
|
|
So that the architectural migration does not break existing map workflows.
|
|
|
|
**Implements:** FR3, FR5; NFR4, NFR5.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
**Given** a split SVG layer supports pointer or editing workflows today
|
|
**When** a user clicks, hovers, drags, or edits through the existing UI
|
|
**Then** events reach the correct standalone layer surface
|
|
**And** the workflow behaves the same way it did before the split.
|
|
|
|
**Given** multiple split SVG layers can overlap in the scene
|
|
**When** the active tool resolves pointer targets
|
|
**Then** targeting respects the registry-driven order and layer visibility state
|
|
**And** no workflow depends on a future mixed-render story to function.
|
|
|
|
## Epic 3: Mixed SVG and WebGL Ordering
|
|
|
|
Register WebGL surfaces under the same ordering and visibility model so users can interleave SVG and WebGL layers through one control path.
|
|
|
|
### Story 3.1: Register WebGL Surfaces in the Shared Layer Model
|
|
|
|
As a map maintainer,
|
|
I want WebGL surfaces registered in the same Layers model as SVG layers,
|
|
So that render technology no longer determines whether a layer can participate in the ordered scene.
|
|
|
|
**Implements:** FR1, FR5; NFR1, NFR5.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
**Given** the Layers registry already manages SVG layer surfaces
|
|
**When** a WebGL layer is registered
|
|
**Then** it receives the same core metadata contract of id, kind, order, visible state, and surface handle
|
|
**And** the registry can treat SVG and WebGL layers as peers in the same scene.
|
|
|
|
**Given** existing WebGL behavior already depends on shared scene context
|
|
**When** registration is moved into the shared layer model
|
|
**Then** WebGL layers keep access to the required scene and camera state
|
|
**And** they no longer rely on special ordering paths outside the registry.
|
|
|
|
### Story 3.2: Unify Mixed-Layer Ordering and Visibility Controls
|
|
|
|
As a map user,
|
|
I want one layer control path to reorder and toggle both SVG and WebGL layers,
|
|
So that I can manage the full layer stack without caring how any layer is rendered.
|
|
|
|
**Implements:** FR1, FR2, FR5; NFR3, NFR5.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
**Given** both SVG and WebGL layers are registered in the scene
|
|
**When** a user changes layer order through the existing controls
|
|
**Then** the registry applies the new order across both render technologies atomically
|
|
**And** the visible stack matches the requested mixed order.
|
|
|
|
**Given** a user toggles visibility for an SVG or WebGL layer
|
|
**When** the control state changes
|
|
**Then** the runtime updates the correct surface regardless of renderer type
|
|
**And** visibility behavior remains consistent across the mixed stack.
|
|
|
|
### Story 3.3: Keep Scene Transforms and Interaction Correct in Mixed Rendering
|
|
|
|
As a map user,
|
|
I want zoom, pan, and interactions to stay aligned across SVG and WebGL layers,
|
|
So that the map behaves as one coherent scene after mixed rendering is enabled.
|
|
|
|
**Implements:** FR3, FR5; NFR4, NFR5.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
**Given** the scene contains both SVG and WebGL surfaces
|
|
**When** camera state changes through zoom or pan
|
|
**Then** all registered surfaces consume the same scene transform state
|
|
**And** the map remains visually aligned across renderer boundaries.
|
|
|
|
**Given** a user interacts with mixed-render content through existing tools
|
|
**When** the runtime resolves those interactions
|
|
**Then** the correct layer surface handles the interaction in scene order
|
|
**And** mixed rendering does not degrade the expected behavior of existing workflows.
|
|
|
|
### Story 3.4: Preserve Atomic Updates and No-Regressions Guardrails in Mixed Mode
|
|
|
|
As a map maintainer,
|
|
I want mixed-layer updates applied through one controlled pipeline,
|
|
So that the runtime preserves atomic layer changes and avoids regressions for existing SVG-heavy maps.
|
|
|
|
**Implements:** FR1, FR2, FR5; NFR3, NFR4.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
**Given** layer order or visibility changes affect both SVG and WebGL surfaces
|
|
**When** the runtime applies an update
|
|
**Then** all affected surfaces transition through one coordinated update path
|
|
**And** partial mixed-stack states are not exposed to the user.
|
|
|
|
**Given** an existing SVG-heavy map uses no new mixed-render features
|
|
**When** it runs on the layered runtime
|
|
**Then** the runtime preserves current behavior for supported workflows
|
|
**And** the migration does not introduce avoidable performance regressions for SVG-only scenarios.
|
|
|
|
## Epic 4: Unified Export Assembly
|
|
|
|
Assemble a unified SVG export from registry state and shared defs resources so supported layered maps export with equivalent output quality.
|
|
|
|
### Story 4.1: Add Export Participation Metadata to the Layer Registry
|
|
|
|
As a map maintainer,
|
|
I want each registered layer to declare how it participates in export,
|
|
So that unified SVG assembly can rebuild export output from registry state instead of the live runtime DOM.
|
|
|
|
**Implements:** FR6; NFR1, NFR5.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
**Given** the export pipeline can no longer assume the runtime DOM is the final SVG document
|
|
**When** a layer is registered for export
|
|
**Then** the registry stores the metadata needed to include, order, or skip that layer during export assembly
|
|
**And** export logic reads registry state rather than scraping one runtime SVG root.
|
|
|
|
**Given** supported layers have different render technologies
|
|
**When** export participation metadata is evaluated
|
|
**Then** the assembler can determine which layers contribute to the final SVG output
|
|
**And** unsupported layers can be excluded intentionally rather than failing implicitly.
|
|
|
|
### Story 4.2: Assemble Unified SVG Export from Registry Order
|
|
|
|
As a map user,
|
|
I want export output assembled from the layered runtime state,
|
|
So that my exported map preserves supported layer order after the DOM is split into separate surfaces.
|
|
|
|
**Implements:** FR6; NFR1, NFR5.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
**Given** the runtime scene is composed of multiple registered surfaces
|
|
**When** a user exports the map
|
|
**Then** the export pipeline assembles one unified SVG document using registry order
|
|
**And** the supported exported layer stack matches the user-visible order.
|
|
|
|
**Given** the runtime no longer uses one canonical map SVG as its model
|
|
**When** export runs
|
|
**Then** the export pipeline treats the live DOM as an implementation detail rather than the export source of truth
|
|
**And** supported layers still produce equivalent SVG output.
|
|
|
|
### Story 4.3: Clone Only Required Defs Resources into Export
|
|
|
|
As a map user,
|
|
I want exported SVG files to include only the defs resources they actually use,
|
|
So that exported maps remain correct without dragging along unrelated runtime resources.
|
|
|
|
**Implements:** FR4, FR6; NFR1, NFR5.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
**Given** the runtime defs host may contain resources for many layers
|
|
**When** export assembly runs
|
|
**Then** the pipeline includes only defs resources referenced by the exported layers
|
|
**And** exported resources preserve the stable IDs required by those layers.
|
|
|
|
**Given** an exported layer references shared defs-backed assets
|
|
**When** the export document is opened independently of the runtime
|
|
**Then** those references resolve correctly within the assembled SVG
|
|
**And** unrelated defs content is not copied by default.
|
|
|
|
### Story 4.4: Preserve Text Paths, Masks, and Filtered Layers in Export
|
|
|
|
As a map user,
|
|
I want exported maps to preserve supported advanced SVG features,
|
|
So that split-surface runtime changes do not degrade final output quality.
|
|
|
|
**Implements:** FR4, FR6; NFR1, NFR5.
|
|
|
|
**Acceptance Criteria:**
|
|
|
|
**Given** supported exported layers use text paths, masks, filters, symbols, markers, or patterns
|
|
**When** export assembly completes
|
|
**Then** the unified SVG preserves those features with correct references and ordering
|
|
**And** output remains equivalent for supported layers.
|
|
|
|
**Given** advanced defs-backed features participate in export
|
|
**When** the assembler processes them
|
|
**Then** it clones the required resources and wiring needed for those features to render correctly outside the runtime
|
|
**And** export hardening remains isolated from runtime ordering logic.
|