# Story 3.2: Scene Auto-Apply & ConfirmationBar **Status:** ready-for-dev **Epic:** 3 - Scene-Aware Camera Automation (Scene Presets) **Story Key:** 3-2-scene-auto-apply-and-confirmationbar **Created:** 2026-05-23 **Last Updated:** 2026-05-23 --- ## Story Header | Field | Value | |-------|-------| | **Epic** | 3 - Scene-Aware Camera Automation (Scene Presets) | | **Story ID** | 3.2 | | **Story Key** | 3-2-scene-auto-apply-and-confirmationbar | | **Title** | Scene Auto-Apply & ConfirmationBar | | **Status** | ready-for-dev | | **Priority** | High | | **Assigned Agent** | DEV (Amelia) | | **Created** | 2026-05-23 | --- ## ๐Ÿ“‹ Story Requirements ### User Story **As a** GM, **I want to** have Scene Presets automatically apply when I activate a Scene, with immediate strip-local feedback and a one-click Undo, **So that** camera layouts change seamlessly with scene transitions without manual intervention. ### Persona Alignment - **Primary:** Marcus (Veteran GM) - Needs seamless transitions between pre-configured scenes during play - **Primary:** Jake (Streamer) - Requires professional, automated scene transitions for broadcast production - **Secondary:** All GMs - Reduces cognitive load by eliminating repetitive manual setup ### Acceptance Criteria (BDD Format) #### AC-1: Auto-Apply on Scene Activation **Given** a Scene has a preset association configured **When** the GM activates that Scene (triggering `updateScene` hook) **Then** the associated preset applies after the configured pre-delay (0-5000ms) **And** all clients receive "Scene changed: camera layout updated" via `ui.notifications` #### AC-2: Configurable Pre-Delay **Given** a Scene has a pre-delay of N ms configured **When** that Scene activates **Then** the preset applies exactly N ms after the `updateScene` hook fires #### AC-3: ConfirmationBar Appearance **Given** auto-apply fires for a Scene **When** the Visibility Matrix update is broadcast **Then** the `ConfirmationBar` appears in `StripOverlayLayer` at `position: absolute; bottom: 0` showing "Preset applied โ€” N hidden, N visible" **And** an "Undo" button is present and primary affordance #### AC-4: One-Click Undo **Given** the "Undo" button is clicked **When** the click is processed **Then** the Visibility Matrix immediately reverts to the state before the preset was applied **And** all clients receive the reverted state #### AC-5: ConfirmationBar Auto-Dismiss **Given** the `ConfirmationBar` is visible and idle **When** 8 seconds elapse (or 4 seconds if โ‰ฅ2 presets applied within 60 seconds) **Then** the bar dismisses via `opacity` transition only (never `height` or `max-height` animation) #### AC-6: Instant-Replace Rule **Given** a second `ConfirmationBar` would appear while one is already visible **When** the second is triggered **Then** it instantly replaces the first with zero crossfade (instant-replace rule) #### AC-7: Per-Scene Disable **Given** auto-apply is disabled for a specific Scene **When** that Scene is activated **Then** no preset applies and no automation notification fires **And** the Director's Board manual override remains fully functional #### AC-8: Global Disable **Given** auto-apply is disabled globally in module settings **When** any Scene is activated **Then** no preset auto-applies regardless of Scene-level associations #### AC-9: Partial-Fail Amber Variant **Given** the partial-fail case (some participants unreachable) **When** the `ConfirmationBar` renders **Then** it uses the amber variant: "Preset applied โ€” N hidden, N visible (some updates pending)" ### Functional Requirements Covered - **FR-17:** Scene Preset auto-applies on FoundryVTT Scene activation via `updateScene` hook - **FR-18:** Scene Preset auto-apply can be disabled per-scene or globally via module settings ### Success Criteria - [ ] All 9 acceptance criteria pass manual testing - [ ] All unit tests pass (target: +25-30 new tests for ConfirmationBar + ScenePresetManager auto-apply) - [ ] `npm run lint` exits 0 (ESLint import boundaries enforced) - [ ] `npm run typecheck` exits 0 (strict JSDoc compliance) - [ ] Code review passes with no critical findings - [ ] Integration test: Scene activation โ†’ preset apply โ†’ ConfirmationBar โ†’ Undo flow verified end-to-end --- ## ๐ŸŽฏ Developer Context Section ### Epic Context **Epic 3: Scene-Aware Camera Automation (Scene Presets)** completes the Level 3 Progressive Enhancement: - **Story 3.1** (PREVIOUS - ready-for-dev): ScenePresetManager, save/load UI, Scene flag storage, socket broadcast - **Story 3.2** (THIS STORY): Auto-apply on Scene activation, ConfirmationBar with Undo, per-scene/global disable toggles - **Story 3.3** (NEXT - backlog): Preset import/export as JSON, merge/replace logic **This story delivers the automation magic** - the ability for GMs to set up camera layouts once and have them apply automatically during sessions. The ConfirmationBar provides immediate, strip-local feedback with a safety net (Undo) for when things don't go as expected. ### Cross-Epic Dependencies | Dependency | Source | Status | Used In This Story | |------------|--------|--------|-------------------| | ScenePresetManager | Story 3.1 | ready-for-dev | โœ… Extended with auto-apply logic | | Scene flag storage | Story 3.1 | ready-for-dev | โœ… Read preset associations | | StateStore.setMatrix() | Story 1.4 | done | โœ… Apply preset matrix | | SocketHandler broadcast | Story 1.3 | done | โœ… Broadcast preset apply | | NotificationBus | Story 2.1 | done | โœ… Optional fallback notification | | DirectorsBoard | Story 2.2 | done | โœ… Manual override always available | | ConfirmationBar UX patterns | UX-DR12 | Specified | โœ… Full implementation | ### Previous Story Intelligence (Story 3.1) **Critical Learnings from 3-1-save-and-load-scene-presets:** 1. **Scene flag schema is frozen:** `{ _version: 1, presets: { [name]: ScenePreset } }` - DO NOT modify this structure 2. **ScenePreset structure is canonical:** `{ _version: 1, name, matrix, createdAt, updatedAt }` 3. **Socket events already defined in contracts:** `scrying-pool.preset.apply` and `scrying-pool.preset.applied` 4. **Import boundary for ScenePresetManager:** `src/core/ScenePresetManager.js` may ONLY import from `src/contracts/` and `src/utils/` 5. **World settings for global config:** Use `scrying-pool.autoApplyEnabled` (boolean, default: true) 6. **Test pattern:** Fake timers for pre-delay testing; frozen fixtures for preset structures **Files Created in 3.1 (DO NOT RECREATE):** - `src/core/ScenePresetManager.js` - Extend this, don't replace it - `src/ui/gm/PresetSaveDialog.js` - Already exists - `src/ui/gm/PresetLoadDialog.js` - Already exists - `src/contracts/scene-preset.js` - Already exists, has validators **Patterns Established in 3.1:** - Scene flag access via `adapter.scenes.current().getFlag()` and `.setFlag()` - Matrix serialization/deserialization in ScenePresetManager - Error handling: clear user-facing messages, no stack traces ### Git Intelligence **Recent commits in Epic 3:** - `3-1-save-and-load-scene-presets.md` created 2026-05-23 09:51 - Full ScenePresetManager spec - Architecture established for Scene flag storage with versioning - Socket contract for preset events pre-defined **Actionable Insights:** - The preset storage mechanism is solid and tested - Socket infrastructure for preset apply is ready but not wired to Scene hooks - Need to add `updateScene` hook registration in module.js - ConfirmationBar is NEW - no existing implementation to build on --- ## ๐Ÿ—๏ธ Technical Requirements ### Core Components to Create/Extend | Component | File | Action | Purpose | |-----------|------|--------|---------| | ScenePresetManager | `src/core/ScenePresetManager.js` | **EXTEND** | Add auto-apply logic, per-scene config | | ConfirmationBar | `src/ui/gm/ConfirmationBar.js` | **NEW** | Strip-local feedback with Undo | | StripOverlayLayer | `src/ui/shared/StripOverlayLayer.js` | **EXTEND** | Add ConfirmationBar container | | ScenePresetPanel | `src/ui/gm/ScenePresetPanel.js` | **NEW** | Per-scene auto-apply toggle UI | ### Data Flow - Auto-Apply Sequence ``` Hooks.on('updateScene', scene) โ†“ ScenePresetManager.onSceneActivate(scene) โ†“ [Check: auto-apply enabled globally?] โ†“ [Check: scene has preset association?] โ†“ [Check: scene has auto-apply enabled?] โ†“ [Wait: configured pre-delay (0-5000ms)] โ†“ ScenePresetManager.applyPreset(presetName) โ†“ VisibilityManager.applyMatrix(preset.matrix) โ†“ StateStore.setMatrix(preset.matrix) โ†“ SocketHandler.emit('scrying-pool.preset.apply', payload) โ†“ [Broadcast to all clients] โ†“ Hooks.callAll('scrying-pool:presetApplied', { presetName, sceneId, matrix }) โ†“ ConfirmationBar.show({ presetName, hiddenCount, visibleCount, partialFail }) โ†“ [8s or 4s timer starts] โ†“ (User clicks Undo) ConfirmationBar.onUndo() โ†’ StateStore.setMatrix(previousMatrix) ``` ### New/Extended Socket Messages **Already defined in `src/contracts/socket-message.js` (from Story 3.1):** - `PRESET_APPLY: "scrying-pool.preset.apply"` - Intent (GM only) - `PRESET_APPLIED: "scrying-pool.preset.applied"` - Authoritative echo **New for this story:** - Payload extension for `PRESET_APPLY`: Add `{ sceneId, preDelay, autoApplied: true }` - New hook: `scrying-pool:presetApplied` for ConfirmationBar subscription ### World Settings (New) | Setting Key | Type | Default | Scope | Description | |-------------|------|---------|-------|-------------| | `scrying-pool.autoApplyEnabled` | boolean | true | world | Global toggle for auto-apply feature | | `scrying-pool.confirmationBarDuration` | number | 8000 | world | Default bar duration in ms | | `scrying-pool.shortConfirmationBarDuration` | number | 4000 | world | Short duration when โ‰ฅ2 presets in 60s | **Note:** Per-scene auto-apply toggle stored in Scene flag alongside preset association. ### Scene Flag Structure Extension **Existing (from Story 3.1):** ```javascript { _version: 1, presets: { [name: string]: ScenePreset } } ``` **Extended for Story 3.2:** ```javascript { _version: 1, presets: { [name: string]: ScenePreset }, autoApply: { enabled: boolean, // Per-scene toggle presetName: string, // Which preset to auto-apply preDelay: number // 0-5000 ms delay } } ``` **Migration:** If `autoApply` field missing, defaults to `{ enabled: false, presetName: null, preDelay: 0 }` --- ## ๐Ÿ›๏ธ Architecture Compliance ### Import Boundary Rules (HARD - ESLint Enforced) **NEW FILES:** ``` src/ui/gm/ConfirmationBar.js โ†’ may import: src/core/, src/contracts/, src/utils/ ONLY โŒ FORBIDDEN: src/foundry/, src/ui/gm/PresetSaveDialog.js, etc. src/ui/gm/ScenePresetPanel.js โ†’ may import: src/core/, src/contracts/, src/utils/ ONLY โŒ FORBIDDEN: src/notifications/, direct game.* access ``` **EXTENDED FILES:** ``` src/core/ScenePresetManager.js (EXTEND from Story 3.1) โ†’ EXISTING: may import src/contracts/, src/utils/ ONLY โ†’ NEW: may ALSO import src/core/VisibilityManager.js (for applyMatrix) โŒ STILL FORBIDDEN: src/foundry/, src/ui/, direct game.* src/ui/shared/StripOverlayLayer.js (EXTEND from Story 1.5) โ†’ EXISTING: may import src/core/, src/contracts/, src/utils/ โ†’ NEW: may import src/ui/gm/ConfirmationBar.js ``` ### Constructor Pattern (Side-Effect-Free) **ConfirmationBar:** ```javascript // โœ… CORRECT export class ConfirmationBar { constructor(adapter, visibilityManager, socketHandler) { this._adapter = adapter; this._visibilityManager = visibilityManager; this._socketHandler = socketHandler; this._previousMatrix = null; } init() { // Lifecycle registration here, NOT in constructor this._adapter.hooks.on('scrying-pool:presetApplied', (payload) => this._onPresetApplied(payload)); } teardown() { this._adapter.hooks.off('scrying-pool:presetApplied', this._onPresetApplied); } } ``` **ScenePresetManager Extension:** ```javascript // EXTEND existing class from Story 3.1 export class ScenePresetManager { // Existing methods: save(), load(), delete(), list() // NEW: Auto-apply methods onSceneActivate(scene) { /* ... */ } applyPreset(presetName, options = { autoApplied: false }) { /* ... */ } configureAutoApply(scene, { enabled, presetName, preDelay }) { /* ... */ } } ``` ### Dependency Injection **All new components follow FoundryAdapter pattern:** - `ConfirmationBar` receives `adapter` via constructor - `ScenePresetPanel` receives `adapter` via constructor - NO direct `game.*` access in any new file - All Foundry API calls go through `adapter.scenes`, `adapter.hooks`, etc. ### Hook Registration Order **Critical:** Module.js wiring order for Story 3.2 components: ```javascript // In module.js, inside Hooks.once('ready', () => { ... }) // EXISTING (from previous stories) - order preserved: const visibilityManager = new VisibilityManager(stateStore, adapter); socketHandler.setReady(visibilityManager); const notificationBus = new NotificationBus(adapter); const roleRenderer = new RoleRenderer(visibilityManager, adapter); const rosterStrip = new RosterStrip(visibilityManager, roleRenderer); // NEW for Story 3.2: const scenePresetManager = new ScenePresetManager( stateStore, adapter, visibilityManager, // NEW: for applyMatrix socketHandler // NEW: for preset broadcast ); // Register updateScene hook for auto-apply adapter.hooks.on('updateScene', (scene) => { scenePresetManager.onSceneActivate(scene); }); // NEW: StripOverlayLayer gets ConfirmationBar support const stripOverlayLayer = new StripOverlayLayer(adapter); const confirmationBar = new ConfirmationBar( adapter, visibilityManager, socketHandler, stripOverlayLayer ); confirmationBar.init(); // If GM, register DirectorsBoard with extended preset panel if (adapter.users.isGM()) { const directorsBoard = new DirectorsBoard(visibilityManager, socketHandler, adapter); // DirectorsBoard now includes ScenePresetPanel as embedded component } ``` --- ## ๐Ÿ“ File Structure Requirements ### Files to CREATE | File | Location | Purpose | AC Blocking | |------|----------|---------|-------------| | `ConfirmationBar.js` | `src/ui/gm/ConfirmationBar.js` | Strip-local feedback component | โœ… | | `ConfirmationBar.test.js` | `tests/unit/ui/gm/ConfirmationBar.test.js` | Unit tests | โœ… | | `ScenePresetPanel.js` | `src/ui/gm/ScenePresetPanel.js` | Per-scene auto-apply config UI | โœ… | | `ScenePresetPanel.test.js` | `tests/unit/ui/gm/ScenePresetPanel.test.js` | Unit tests | โœ… | | `_confirmation-bar.less` | `styles/components/_confirmation-bar.less` | ConfirmationBar styles | โœ… | | `confirmation-bar.hbs` | `templates/confirmation-bar.hbs` | Handlebars template | โœ… | ### Files to EXTEND | File | Changes | From Story | |------|---------|------------| | `ScenePresetManager.js` | Add auto-apply methods | 3.1 | | `module.js` | Wire updateScene hook, inject dependencies | Story 0 | | `StripOverlayLayer.js` | Add ConfirmationBar rendering | 1.5 | | `DirectorsBoard.js` | Integrate ScenePresetPanel | 2.2 | ### File Boundaries **ConfirmationBar owns:** - Display logic for preset apply feedback - Undo button click handler - Auto-dismiss timer management - Instant-replace logic for consecutive bar displays **ScenePresetManager owns (NEW):** - Auto-apply configuration per-scene - Pre-delay timer management - Scene activation detection - Preset application trigger **ScenePresetPanel owns:** - Per-scene auto-apply toggle UI - Pre-delay configuration (0-5000ms slider) - Preset selection for auto-apply --- ## ๐Ÿงช Testing Requirements ### Unit Test Coverage Targets | Component | Test File | Coverage Target | |-----------|-----------|-----------------| | ConfirmationBar | `ConfirmationBar.test.js` | 100% branch coverage | | ScenePresetManager (new methods) | Extend `ScenePresetManager.test.js` | +25 new tests | | ScenePresetPanel | `ScenePresetPanel.test.js` | 100% statement coverage | ### Test Scenarios (MUST INCLUDE) **ConfirmationBar:** ```javascript // Fake timers required for duration testing vi.useFakeTimers(); // Test 1: Shows on preset applied event // Test 2: Undo clicks revert to previous matrix // Test 3: Auto-dismisses after 8000ms // Test 4: Auto-dismisses after 4000ms when โ‰ฅ2 presets in 60s // Test 5: Instant-replace when new event during visible bar // Test 6: Shows amber variant on partial fail // Test 7: Clears timer on manual dismiss // Test 8: accessibility: focus trap, keyboard navigation ``` **ScenePresetManager (auto-apply):** ```javascript // Test 1: onSceneActivate does nothing when no preset association // Test 2: onSceneActivate applies preset after pre-delay // Test 3: onSceneActivate respects global disable // Test 4: onSceneActivate respects per-scene disable // Test 5: Pre-delay timer cleared on scene change // Test 6: applyPreset with autoApplied=true emits correct socket event // Test 7: configureAutoApply updates Scene flag correctly // Test 8: Migration: missing autoApply field gets defaults ``` **Integration Tests:** ```javascript // Test 1: Full flow: Scene activation โ†’ preset apply โ†’ ConfirmationBar โ†’ Undo // Test 2: Partial fail: Some participants offline โ†’ amber bar // Test 3: Global disable โ†’ no auto-apply on any scene // Test 4: Per-scene disable โ†’ no auto-apply on that scene only ``` ### Fixtures to Add/Update **New fixtures in `tests/fixtures/scene-preset.js`:** ```javascript export const SCENE_FLAG_WITH_AUTO_APPLY = Object.freeze({ _version: 1, presets: { /* ... */ }, autoApply: { enabled: true, presetName: 'combat', preDelay: 1000 } }); export const SCENE_FLAG_WITHOUT_AUTO_APPLY = Object.freeze({ _version: 1, presets: { /* ... */ } // autoApply missing - should default to disabled }); export const SCENE_FLAG_DISABLED_AUTO_APPLY = Object.freeze({ _version: 1, presets: { /* ... */ }, autoApply: { enabled: false, presetName: null, preDelay: 0 } }); ``` --- ## ๐ŸŽจ UX Design Requirements ### ConfirmationBar Specification (UX-DR12) **Location:** `StripOverlayLayer` at `position: absolute; bottom: 0` **Visual:** - Background: `--sp-surface` (semantic token) - Text: `--sp-text-primary` - Border: 1px solid `--sp-border` - Padding: 12px 16px - Border-radius: 4px - Box-shadow: `0 2px 8px rgba(0,0,0,0.3)` **Content:** - Message: "Preset applied โ€” N hidden, N visible" - Undo button: Primary CTA, left side - Duration indicator: Optional subtle progress bar **Variants:** - **Default:** Green accent for success - **Amber:** Orange accent when partial fail ("some updates pending") **Animations:** - In: Slide up from bottom + fade (200ms ease-out) - Out: Slide down to bottom + fade (200ms ease-in) - **CRITICAL:** Only `opacity` transitions for height changes - NEVER `height` or `max-height` animation - Gated under `@media (prefers-reduced-motion: no-preference)` **Behavior:** - Auto-dismiss: 8000ms default, 4000ms if โ‰ฅ2 presets applied within 60000ms window - Instant-replace: New bar replaces existing with 0ms crossfade - Click Undo: Reverts matrix, dismisses bar immediately - Click outside: No dismiss (bar is in StripOverlayLayer, which has pointer-events: none on parent) - Click on bar: No action (bar is informational, only Undo is interactive) **Accessibility:** - `role="status"` on bar container - `aria-live="polite"` for message updates - `aria-label="Preset [name] applied. Undo available."` on bar - Undo button: `role="button"`, `aria-label="Undo preset apply"` - Focus: Undo button receives focus when bar appears - Keyboard: Space/Enter on Undo button triggers revert ### ScenePresetPanel Specification **Location:** Embedded in DirectorsBoard as collapsible drawer/tab **Controls:** - Toggle: "Auto-apply preset on scene activation" (checkbox) - Preset selector: Dropdown of available presets for this scene - Pre-delay: Slider 0-5000ms with value display - Global settings link: "Configure global auto-apply settings" **Accessibility:** - All interactive elements keyboard-navigable - ARIA labels on all controls - Focus trap within panel --- ## ๐Ÿ”’ Security & Performance Requirements ### Security - **No data transmission:** Scene flag data stays in FoundryVTT world - **Permission check:** Only GM can configure auto-apply settings - **Validation:** All Scene flag inputs validated before saving - **Sanitization:** Preset names sanitized (no HTML, max length 100 chars) ### Performance - **Pre-delay max:** 5000ms - enforced at validation level - **Timer cleanup:** All timers cleared on module teardown - **Debounce:** If multiple scene activations in quick succession, only last one processed - **Memory:** ConfirmationBar holds previous matrix reference only while visible - **No blocking:** All operations async; no synchronous waits --- ## ๐Ÿ“‚ Project Structure Notes ### Alignment with Unified Structure All new files follow the established pattern: - `src/ui/gm/` - GM-only UI components - `src/core/` - Pure logic, testable - `styles/components/` - Component-specific LESS - `templates/` - Handlebars templates - `tests/unit/{mirror-path}/` - One spec per source file ### Detected Conflicts / Variances **None detected.** The architecture established in Stories 0, 1.x, and 2.x fully supports this implementation. ### Previous Work Patterns to Follow 1. **Constructor injection** (from Story 1.3): All Foundry deps via FoundryAdapter 2. **Import boundaries** (from Story 0): ESLint `no-restricted-paths` enforced 3. **Test patterns** (from Story 1.3): Fake timers, frozen fixtures, canonical mocks 4. **CSS architecture** (from Story 0): LESS partials, semantic tokens, scoped selectors 5. **Socket patterns** (from Story 1.3): Intent/echo cycle, PendingOp lifecycle --- ## ๐Ÿ”— References ### Source Documents | Reference | Path | Section | |-----------|------|---------| | Story 3.2 ACs | `_bmad-output/planning-artifacts/epics.md` | Story 3.2: Scene Auto-Apply & ConfirmationBar | | FR-17 | `_bmad-output/planning-artifacts/epics.md` | FR-17: Scene Preset auto-applies on Scene activation | | FR-18 | `_bmad-output/planning-artifacts/epics.md` | FR-18: Disable auto-apply per-scene or globally | | UX-DR12 | `_bmad-output/planning-artifacts/epics.md` | UX-DR12: ConfirmationBar specification | | Architecture | `_bmad-output/planning-artifacts/architecture.md` | Full project architecture | | ScenePresetManager | `_bmad-output/implementation-artifacts/3-1-save-and-load-scene-presets.md` | Story 3.1 implementation | | Socket contracts | `src/contracts/socket-message.js` | PRESET_APPLY, PRESET_APPLIED | | Scene flag schema | `src/contracts/scene-preset.js` | Versioned wrapper pattern | ### Previous Story Files (Critical Context) | Story | File | Relevance | |-------|------|-----------| | 3.1 | `3-1-save-and-load-scene-presets.md` | **MUST READ** - ScenePresetManager foundation | | 2.3 | `2-3-directors-board-bulk-actions-spotlight-and-keyboard-shortcuts.md` | Bulk action patterns, Undo concept | | 1.5 | `1-5-gm-control-ui-scryingpoolstrip-actionpopover-and-av-tile-integration.md` | StripOverlayLayer patterns | | 1.4 | `1-4-core-logic-scryingpoolcontroller-and-visibilitymanager.md` | Matrix application, state management | --- ## ๐Ÿค– Dev Agent Record ### Agent Model Used DEV (Amelia) - Senior software engineer for story execution ### Debug Log References **Critical debugging checkpoints:** 1. `Hooks.on('updateScene')` registration - verify in module.js 2. Scene flag read/write - verify via `adapter.scenes.current().getFlag()` 3. ConfirmationBar timer management - verify `clearTimeout` in all code paths 4. Undo matrix storage - verify previous matrix captured before apply 5. Socket payload validation - verify `src/contracts/scene-preset.js` validators ### Completion Notes List **Before marking done, verify:** - [ ] ConfirmationBar appears and disappears correctly - [ ] Undo works and reverts to exact previous state - [ ] Auto-apply respects both global and per-scene settings - [ ] Pre-delay is configurable and accurate - [ ] Partial fail shows amber variant - [ ] Instant-replace works for consecutive bars - [ ] All timers cleaned up on module teardown - [ ] No memory leaks from event listeners - [ ] Accessibility: keyboard nav, ARIA labels, focus management - [ ] All ESLint import boundaries pass ### File List **NEW FILES (7):** 1. `src/ui/gm/ConfirmationBar.js` 2. `src/ui/gm/ScenePresetPanel.js` 3. `tests/unit/ui/gm/ConfirmationBar.test.js` 4. `tests/unit/ui/gm/ScenePresetPanel.test.js` 5. `styles/components/_confirmation-bar.less` 6. `templates/confirmation-bar.hbs` 7. `tests/fixtures/scene-preset.js` (updated with auto-apply fixtures) **MODIFIED FILES (4):** 1. `src/core/ScenePresetManager.js` (extend with auto-apply) 2. `module.js` (wire updateScene hook, inject new dependencies) 3. `src/ui/shared/StripOverlayLayer.js` (add ConfirmationBar support) 4. `src/ui/gm/DirectorsBoard.js` (integrate ScenePresetPanel) **CONTRACT FILES (verify, don't modify):** - `src/contracts/socket-message.js` (already has preset events) - `src/contracts/scene-preset.js` (already has validators) --- ## โœ… Story Completion Status **Status:** ready-for-dev **Ultimate context engine analysis completed** - comprehensive developer guide created with: - Complete epic and cross-story context - Exhaustive architecture compliance requirements - Previous story intelligence and patterns - Git history insights - Specific file structure and boundaries - Testing requirements and fixtures - UX design specifications - Security and performance constraints - Actionable dev agent guardrails **The developer now has everything needed for flawless implementation!** --- *Generated for {project_name} by BMad Method Story Context Engine* *Agent: DEV (Amelia)* *Date: 2026-05-23*