Jelajahi Sumber

chore: stop tracking .planning directory

Files were tracked before .gitignore entry was added.
Removing from index only - files remain locally.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
tuanchris 1 Minggu lalu
induk
melakukan
e0016f52b7

+ 0 - 110
.planning/REQUIREMENTS.md

@@ -1,110 +0,0 @@
-# Requirements — v3 Touch App CPU Optimization
-
-**Goal:** Reduce idle CPU usage from 100%+ to under 20% on Raspberry Pi 3B+, Pi 4, and Pi 5.
-
-**Verification method:** Run touch app idle for 60 seconds, measure CPU with `htop` or `top`.
-
----
-
-## v3 Requirements (In Scope)
-
-### Category: QML Logging Cleanup
-
-- [x] **REQ-LOG-01**: Remove console.log from onPositionChanged handler in main.qml ✅
-  - Keep `backend.resetActivityTimer()` call
-  - Delete only the logging statement
-
-- [x] **REQ-LOG-02**: Remove console.log from onPressed handler in main.qml ✅
-  - Keep `backend.resetActivityTimer()` call
-
-- [x] **REQ-LOG-03**: Remove console.log from onClicked handler in main.qml ✅
-  - Keep `backend.resetActivityTimer()` call
-
-- [x] **REQ-LOG-04**: Remove all debug console.log from ConnectionStatus.qml ✅
-  - Lines with "ConnectionStatus:" prefix
-
-- [x] **REQ-LOG-05**: Remove all debug console.log from ExecutionPage.qml ✅
-  - Lines with "ExecutionPage:" prefix and image status logs
-
-- [x] **REQ-LOG-06**: Audit and remove debug logs from other QML files ✅
-  - ModernPatternListPage.qml
-  - PatternDetailPage.qml
-  - TableControlPage.qml
-  - LedControlPage.qml
-  - ModernPlaylistPage.qml
-
-### Category: Timer Optimization
-
-- [x] **REQ-TIMER-01**: Convert screen timeout from polling to event-driven ✅
-  - Current: 1-second QTimer checking `_check_screen_timeout()` continuously
-  - Target: Only schedule timeout check after activity detected
-  - Location: backend.py:140-152
-
-- [ ] **REQ-TIMER-02**: Ensure screen timeout still works correctly after refactor ⏳
-  - Screen should turn off after configured timeout period
-  - Touch should wake screen
-  - No regression in functionality
-  - **Status:** Needs hardware testing on Pi
-
-### Category: WebSocket Optimization
-
-- [x] **REQ-WS-01**: Reduce redundant signal emissions in `_on_ws_message` ✅
-  - Only emit signals when values actually change
-  - Location: backend.py:310-364
-
-- [x] **REQ-WS-02**: Remove or reduce print statements in WebSocket handler ✅
-  - Keep error logging, remove routine status logging
-
-### Category: Preview Cache Optimization
-
-- [x] **REQ-CACHE-01**: Cache pattern preview paths after first lookup ✅
-  - Add dictionary to store `filename → preview_path` mappings
-  - Location: backend.py `_find_pattern_preview()` method
-
-- [x] **REQ-CACHE-02**: Invalidate cache appropriately ✅
-  - Clear cache when patterns are refreshed
-  - Don't cache negative results (missing previews)
-
-### Category: Verification (Hardware Required)
-
-- [ ] **REQ-VERIFY-01**: Measure idle CPU on Pi 3B+ < 20% ⏳
-  - App running, no user interaction, for 60 seconds
-
-- [ ] **REQ-VERIFY-02**: Measure idle CPU on Pi 4 < 20% ⏳
-  - App running, no user interaction, for 60 seconds
-
-- [ ] **REQ-VERIFY-03**: Measure idle CPU on Pi 5 < 20% ⏳
-  - App running, no user interaction, for 60 seconds
-
-- [ ] **REQ-VERIFY-04**: Verify no UI lag during normal operation ⏳
-  - Scrolling pattern list remains smooth
-  - Touch response remains immediate
-
----
-
-## v4 / Future (Out of Scope)
-
-- Debug flag system for conditional logging
-- Performance test automation
-- CPU monitoring dashboard in app
-- Memory optimization
-- Startup time optimization
-
----
-
-## Summary
-
-| Category | v3 Count | Complete | Pending |
-|----------|----------|----------|---------|
-| QML Logging | 6 | 6 | 0 |
-| Timer Optimization | 2 | 1 | 1 |
-| WebSocket Optimization | 2 | 2 | 0 |
-| Preview Cache | 2 | 2 | 0 |
-| Verification | 4 | 0 | 4 |
-| **Total** | **16** | **11** | **5** |
-
-**Note:** 5 pending requirements need hardware verification on Raspberry Pi.
-
----
-
-*Updated: 2026-01-25*

+ 0 - 67
.planning/ROADMAP.md

@@ -1,67 +0,0 @@
-# Roadmap — v3 Touch App CPU Optimization
-
-**Milestone goal:** Reduce idle CPU usage from 100%+ to under 20% on Pi 3B+, Pi 4, and Pi 5.
-
----
-
-## Phase 1: CPU Optimization ✅ COMPLETE
-
-**Goal:** Eliminate all identified CPU hotspots and verify performance targets.
-
-**Requirements covered:**
-- REQ-LOG-01 through REQ-LOG-06 (QML logging cleanup)
-- REQ-TIMER-01, REQ-TIMER-02 (Timer optimization)
-- REQ-WS-01, REQ-WS-02 (WebSocket optimization)
-- REQ-CACHE-01, REQ-CACHE-02 (Preview cache)
-- REQ-VERIFY-01 through REQ-VERIFY-04 (Verification)
-
-**Success criteria:**
-- [x] No console.log in main.qml mouse/touch handlers
-- [x] No debug console.log in QML component files
-- [x] Screen timeout uses event-driven scheduling (not 1-sec polling)
-- [x] WebSocket handler only emits signals on actual value changes
-- [x] Pattern preview paths are cached after first lookup
-- [ ] Idle CPU < 20% measured on Pi (requires hardware testing)
-- [ ] UI remains responsive (requires hardware testing)
-
-**Completed:** 2026-01-25
-
----
-
-## Requirement Coverage
-
-| Requirement | Phase | Status |
-|-------------|-------|--------|
-| REQ-LOG-01 | 1 | ✅ Complete |
-| REQ-LOG-02 | 1 | ✅ Complete |
-| REQ-LOG-03 | 1 | ✅ Complete |
-| REQ-LOG-04 | 1 | ✅ Complete |
-| REQ-LOG-05 | 1 | ✅ Complete |
-| REQ-LOG-06 | 1 | ✅ Complete |
-| REQ-TIMER-01 | 1 | ✅ Complete |
-| REQ-TIMER-02 | 1 | ⏳ Needs Pi test |
-| REQ-WS-01 | 1 | ✅ Complete |
-| REQ-WS-02 | 1 | ✅ Complete |
-| REQ-CACHE-01 | 1 | ✅ Complete |
-| REQ-CACHE-02 | 1 | ✅ Complete |
-| REQ-VERIFY-01 | 1 | ⏳ Needs Pi test |
-| REQ-VERIFY-02 | 1 | ⏳ Needs Pi test |
-| REQ-VERIFY-03 | 1 | ⏳ Needs Pi test |
-| REQ-VERIFY-04 | 1 | ⏳ Needs Pi test |
-
-**Coverage:** 16/16 requirements addressed
-**Code complete:** 12/16 (75%)
-**Hardware verification pending:** 4/16 (25%)
-
----
-
-## Completed Milestones
-
-| Version | Name | Completed | Archive |
-|---------|------|-----------|---------|
-| v1 | Backend Testing | 2026-01-24 | [v1-backend-testing.md](milestones/v1-backend-testing.md) |
-| v2 | Frontend Testing | 2026-01-25 | [v2-frontend-testing.md](milestones/v2-frontend-testing.md) |
-
----
-
-*Updated: 2026-01-25*

+ 0 - 71
.planning/STATE.md

@@ -1,71 +0,0 @@
-# Project State
-
-## Current Position
-
-Milestone: v3 Touch App CPU Optimization
-Phase: 1 — CPU Optimization ✅ COMPLETE
-Plan: All plans executed
-Status: Phase complete, awaiting hardware verification
-Last activity: 2026-01-25 — Phase 1 executed and verified
-
-Progress: Phase 1 of 1 complete
-
-## Completed Milestones
-
-| Version | Name | Completed | Archive |
-|---------|------|-----------|---------|
-| v1 | Backend Testing | 2026-01-24 | [v1-backend-testing.md](milestones/v1-backend-testing.md) |
-| v2 | Frontend Testing | 2026-01-25 | [v2-frontend-testing.md](milestones/v2-frontend-testing.md) |
-
-## Accumulated Decisions
-
-| Decision | Context | Date |
-|----------|---------|------|
-| pytest + pytest-asyncio | Test framework selection for async FastAPI testing | 2026-01-24 |
-| httpx for API testing | Standard FastAPI testing approach with ASGITransport | 2026-01-24 |
-| CI=true env var | Hardware test auto-skip mechanism | 2026-01-24 |
-| relative_files = true | Coverage config for CI compatibility | 2026-01-24 |
-| Vitest + RTL | Frontend component testing framework | 2026-01-24 |
-| Playwright | E2E browser automation | 2026-01-24 |
-| MSW | API mocking at network level | 2026-01-24 |
-| Extend existing CI | Run frontend tests in same workflow as backend | 2026-01-24 |
-| vitest globals | Enable describe/it/expect without imports | 2026-01-24 |
-| MSW onUnhandledRequest: warn | Changed from error due to WebSocket conflicts | 2026-01-25 |
-| Chromium only (initial) | Faster CI, can add browsers later | 2026-01-24 |
-| Observable behavior testing | Focus on what renders, clicks, API calls not implementation | 2026-01-25 |
-| apiCallLog for API verification | Track API calls in MSW handlers for integration test assertions | 2026-01-25 |
-| Button finding via textContent | More reliable than getByRole for buttons with similar names | 2026-01-25 |
-| WebSocket mocking via routeWebSocket | Required to bypass blocking "Connecting to Backend" overlay | 2026-01-25 |
-| Dedicated port 5174 for E2E | Avoids conflict with other dev servers on 5173 | 2026-01-25 |
-| Remove debug logs (not flag) | Decided to remove all debug console.log rather than add conditional flag | 2026-01-25 |
-| Event-driven screen timeout | Replace 1-sec polling with event-driven timeout scheduling | 2026-01-25 |
-| Single-shot QTimer | Screen timeout timer fires once after inactivity period | 2026-01-25 |
-| Preview cache dictionary | Cache pattern preview paths to avoid repeated filesystem lookups | 2026-01-25 |
-
-## Blockers/Concerns
-
-**Hardware verification pending:** Need to test on actual Raspberry Pi to confirm CPU < 20%
-
-## Session Continuity
-
-Last session: 2026-01-25
-Stopped at: Phase 1 complete, ready for milestone audit
-Resume file: None
-
-## v3 Phase 1 Summary
-
-**Commits:** 6
-- `e3b1f2a` - Remove MouseArea console.log spam
-- `455ed5c` - Remove remaining debug logs from main.qml
-- `bf3729e` - Remove debug logs from ConnectionStatus.qml
-- `e1b5994` - Remove debug logs from ExecutionPage.qml
-- `e2e0c82` - Remove debug logs from remaining QML files
-- `bd48ed4` - Optimize timer, WebSocket, and preview cache
-
-**Files modified:** 8
-- main.qml, ConnectionStatus.qml, ExecutionPage.qml
-- TableControlPage.qml, ModernPlaylistPage.qml
-- ThemeManager.qml, BottomNavTab.qml
-- backend.py
-
-**Verification:** 6/6 must-haves passed (code inspection)

+ 0 - 299
.planning/phases/01-cpu-optimization/01-cpu-optimization-PLAN.md

@@ -1,299 +0,0 @@
-# Phase 1: CPU Optimization — Execution Plan
-
-```yaml
----
-phase: 01-cpu-optimization
-plan: 01
-name: cpu-optimization
-wave: 1
-autonomous: true
-scope: small
-estimated_tasks: 6
-requirements: REQ-LOG-01, REQ-LOG-02, REQ-LOG-03, REQ-LOG-04, REQ-LOG-05, REQ-LOG-06, REQ-TIMER-01, REQ-TIMER-02, REQ-WS-01, REQ-WS-02, REQ-CACHE-01, REQ-CACHE-02
-must_haves:
-  truths:
-    - No console.log in main.qml MouseArea handlers (onPressed, onPositionChanged, onClicked)
-    - No debug console.log in ConnectionStatus.qml
-    - No debug console.log in ExecutionPage.qml
-    - Screen timeout uses event-driven scheduling (no 1-second continuous timer)
-    - WebSocket handler only emits signals when values change
-    - Pattern preview paths are cached in a dictionary
-  artifacts:
-    - dune-weaver-touch/qml/main.qml (modified)
-    - dune-weaver-touch/qml/components/ConnectionStatus.qml (modified)
-    - dune-weaver-touch/qml/pages/ExecutionPage.qml (modified)
-    - dune-weaver-touch/backend.py (modified)
----
-```
-
-## Objective
-
-Eliminate CPU hotspots in the dune-weaver-touch Qt6 application to reduce idle CPU usage from 100%+ to under 20%.
-
-## Context
-
-### Files to Modify
-
-| File | Changes | Requirements |
-|------|---------|--------------|
-| `dune-weaver-touch/qml/main.qml` | Remove console.log from MouseArea handlers + navigation logs | REQ-LOG-01, REQ-LOG-02, REQ-LOG-03 |
-| `dune-weaver-touch/qml/components/ConnectionStatus.qml` | Remove all debug console.log | REQ-LOG-04 |
-| `dune-weaver-touch/qml/pages/ExecutionPage.qml` | Remove debug console.log (keep functional code) | REQ-LOG-05 |
-| `dune-weaver-touch/qml/pages/TableControlPage.qml` | Remove debug console.log | REQ-LOG-06 |
-| `dune-weaver-touch/qml/pages/ModernPlaylistPage.qml` | Remove debug console.log | REQ-LOG-06 |
-| `dune-weaver-touch/qml/components/ThemeManager.qml` | Remove debug console.log | REQ-LOG-06 |
-| `dune-weaver-touch/qml/components/BottomNavTab.qml` | Remove debug console.log | REQ-LOG-06 |
-| `dune-weaver-touch/backend.py` | Timer optimization, WebSocket optimization, preview cache | REQ-TIMER-01, REQ-TIMER-02, REQ-WS-01, REQ-WS-02, REQ-CACHE-01, REQ-CACHE-02 |
-
-### Key Decisions (from STATE.md)
-
-- Remove debug logs completely (not conditional flag)
-- Event-driven screen timeout (not polling)
-
----
-
-## Tasks
-
-### Task 1: Remove console.log from main.qml MouseArea handlers
-
-**Goal:** Eliminate the highest-impact CPU issue - logging on every pixel of touch movement.
-
-**Files:** `dune-weaver-touch/qml/main.qml`
-
-**Changes:**
-1. Lines 97-110: Remove console.log from onPressed, onPositionChanged, onClicked
-   - Keep `backend.resetActivityTimer()` calls
-   - Delete only the console.log statements
-
-**Before:**
-```qml
-onPressed: {
-    console.log("🖥️ QML: Touch/press detected - resetting activity timer")
-    backend.resetActivityTimer()
-}
-
-onPositionChanged: {
-    console.log("🖥️ QML: Mouse movement detected - resetting activity timer")
-    backend.resetActivityTimer()
-}
-
-onClicked: {
-    console.log("🖥️ QML: Click detected - resetting activity timer")
-    backend.resetActivityTimer()
-}
-```
-
-**After:**
-```qml
-onPressed: {
-    backend.resetActivityTimer()
-}
-
-onPositionChanged: {
-    backend.resetActivityTimer()
-}
-
-onClicked: {
-    backend.resetActivityTimer()
-}
-```
-
-**Commit:** `perf(01-01): remove MouseArea console.log spam in main.qml`
-
----
-
-### Task 2: Remove other debug console.log from main.qml
-
-**Goal:** Remove remaining debug logs from main.qml.
-
-**Files:** `dune-weaver-touch/qml/main.qml`
-
-**Changes:** Remove console.log from:
-- Line 28: `onCurrentPageIndexChanged`
-- Lines 33-34, 38, 43: `onShouldNavigateToExecutionChanged`
-- Lines 53-54, 60: `onExecutionStarted`
-- Line 75: `onScreenStateChanged`
-- Lines 79, 81, 84: `onBackendConnectionChanged`
-- Line 137: `onRetryConnection`
-- Line 157: `Component.onCompleted` in StackLayout
-- Line 217: `onTabClicked`
-
-**Commit:** `perf(01-01): remove remaining debug logs from main.qml`
-
----
-
-### Task 3: Remove debug console.log from ConnectionStatus.qml
-
-**Goal:** Eliminate logs that fire on every property access.
-
-**Files:** `dune-weaver-touch/qml/components/ConnectionStatus.qml`
-
-**Changes:** Remove all console.log statements (lines 15, 20, 34, 41, 43, 48, 50).
-
-The color binding should be simplified to:
-```qml
-color: {
-    if (!backend) return "#FF5722"
-    return backend.serialConnected ? "#4CAF50" : "#FF5722"
-}
-```
-
-Remove `onSerialConnectionChanged`, `Component.onCompleted`, and `onBackendChanged` debug handlers entirely (the color binding auto-updates).
-
-**Commit:** `perf(01-01): remove debug logs from ConnectionStatus.qml`
-
----
-
-### Task 4: Remove debug console.log from ExecutionPage.qml
-
-**Goal:** Remove verbose debug logging from execution page.
-
-**Files:** `dune-weaver-touch/qml/pages/ExecutionPage.qml`
-
-**Changes:** Remove console.log from:
-- Lines 17-21: `onBackendChanged`
-- Lines 25-28: `Component.onCompleted`
-- Lines 36, 40-42: `onSerialConnectionChanged`, `onConnectionChanged`
-- Lines 47-49: `onExecutionStarted` (keep the property assignments)
-- Lines 128, 130: Image source binding
-- Lines 138-145: `onStatusChanged`
-- Line 149: `onSourceChanged`
-
-Keep the functional code, only remove logging.
-
-**Commit:** `perf(01-01): remove debug logs from ExecutionPage.qml`
-
----
-
-### Task 5: Remove debug console.log from other QML files
-
-**Goal:** Clean up remaining QML files.
-
-**Files:**
-- `dune-weaver-touch/qml/pages/TableControlPage.qml` (lines 21, 26, 31, 39)
-- `dune-weaver-touch/qml/pages/ModernPlaylistPage.qml` (lines 35, 43-44, 461, 470, 472, 475, 501, 564, 583, 1009, 1028, 1047, 1066)
-- `dune-weaver-touch/qml/components/ThemeManager.qml` (line 70)
-- `dune-weaver-touch/qml/components/BottomNavTab.qml` (lines 35, 45)
-
-**Commit:** `perf(01-01): remove debug logs from remaining QML files`
-
----
-
-### Task 6: Optimize backend.py - Timer, WebSocket, and Cache
-
-**Goal:** Fix the three backend CPU issues.
-
-**Files:** `dune-weaver-touch/backend.py`
-
-**Changes:**
-
-#### 6a: Event-driven screen timeout (REQ-TIMER-01, REQ-TIMER-02)
-
-Replace continuous 1-second polling with event-driven scheduling.
-
-**Current (lines 140-142):**
-```python
-self._screen_timer = QTimer()
-self._screen_timer.timeout.connect(self._check_screen_timeout)
-self._screen_timer.start(1000)  # Check every second
-```
-
-**New approach:**
-```python
-self._screen_timer = QTimer()
-self._screen_timer.timeout.connect(self._screen_timeout_triggered)
-self._screen_timer.setSingleShot(True)  # Only fires once
-# Timer started in _reset_activity_timer() when activity detected
-```
-
-Update `_reset_activity_timer()` to:
-1. Stop any existing timer
-2. If screen timeout > 0, start a new single-shot timer for the timeout duration
-
-Update `_check_screen_timeout()` → rename to `_screen_timeout_triggered()`:
-- Simply turn off the screen (no time checking needed, timer already waited)
-
-#### 6b: WebSocket signal optimization (REQ-WS-01, REQ-WS-02)
-
-In `_on_ws_message()` (lines 310-364):
-- Remove print statements (keep only error logging)
-- Already checks for changes before emitting most signals - verify and keep this pattern
-
-Remove prints from:
-- Line 319: Pattern change logging
-- Line 322: Preview path logging
-- Line 332: Pause state logging
-- Line 339: Serial connection logging
-- Line 354: Speed change logging
-
-#### 6c: Preview path caching (REQ-CACHE-01, REQ-CACHE-02)
-
-Add a cache dictionary in `__init__`:
-```python
-self._preview_cache = {}  # filename -> preview_path
-```
-
-Modify `_find_pattern_preview()`:
-```python
-def _find_pattern_preview(self, fileName):
-    # Check cache first
-    if fileName in self._preview_cache:
-        return self._preview_cache[fileName]
-
-    # ... existing lookup logic ...
-
-    # Cache the result (only positive results)
-    if preview_path:
-        self._preview_cache[fileName] = preview_path
-
-    return preview_path
-```
-
-Add cache invalidation - add a method and call it when patterns might change:
-```python
-def _clear_preview_cache(self):
-    self._preview_cache = {}
-```
-
-**Commit:** `perf(01-01): optimize timer, WebSocket, and preview cache in backend.py`
-
----
-
-## Verification
-
-After all tasks complete:
-
-1. **Code verification:**
-   - `grep -r "console.log" dune-weaver-touch/qml/` should return minimal results (only intentional user-facing logs if any)
-   - `grep "_screen_timer.start(1000)" dune-weaver-touch/backend.py` should return nothing
-   - `grep "_preview_cache" dune-weaver-touch/backend.py` should find cache usage
-
-2. **Functional verification (requires Pi):**
-   - App starts without errors
-   - Screen timeout still works (screen turns off after configured time)
-   - Touch wakes screen
-   - Pattern execution works
-   - UI is responsive
-
-3. **Performance verification (requires Pi):**
-   - Run `htop` or `top` while app is idle for 60 seconds
-   - CPU usage should be < 20%
-
----
-
-## Success Criteria
-
-- [ ] No console.log in main.qml MouseArea handlers
-- [ ] No debug console.log in QML component files
-- [ ] Screen timeout uses single-shot timer (event-driven)
-- [ ] WebSocket handler has no routine print statements
-- [ ] Preview paths are cached after first lookup
-- [ ] All changes committed with atomic commits
-
----
-
-## Output
-
-- Modified files in `dune-weaver-touch/`
-- 6 commits following the pattern `{type}(01-01): {description}`
-- SUMMARY.md created after execution

+ 0 - 116
.planning/phases/01-cpu-optimization/01-cpu-optimization-SUMMARY.md

@@ -1,116 +0,0 @@
-# Phase 1: CPU Optimization Summary
-
-```yaml
----
-phase: 01-cpu-optimization
-plan: 01
-subsystem: dune-weaver-touch
-tags: [performance, qml, python, cpu-optimization]
-dependency-graph:
-  requires: []
-  provides: [optimized-touch-app]
-  affects: []
-tech-stack:
-  added: []
-  patterns: [event-driven-timeout, preview-caching]
-key-files:
-  created: []
-  modified:
-    - dune-weaver-touch/qml/main.qml
-    - dune-weaver-touch/qml/components/ConnectionStatus.qml
-    - dune-weaver-touch/qml/components/ThemeManager.qml
-    - dune-weaver-touch/qml/components/BottomNavTab.qml
-    - dune-weaver-touch/qml/pages/ExecutionPage.qml
-    - dune-weaver-touch/qml/pages/TableControlPage.qml
-    - dune-weaver-touch/qml/pages/ModernPlaylistPage.qml
-    - dune-weaver-touch/backend.py
-decisions: []
-metrics:
-  duration: ~15 minutes
-  completed: 2026-01-25
----
-```
-
-## One-Liner
-
-Remove all QML console.log statements and optimize backend with event-driven screen timeout and preview path caching for reduced CPU usage.
-
-## What Was Delivered
-
-### QML Console.log Removal
-
-All debug console.log statements were removed from QML files:
-
-1. **main.qml** - Removed 15+ console.log calls including:
-   - MouseArea handlers (onPressed, onPositionChanged, onClicked) - the highest impact
-   - Navigation handlers (onCurrentPageIndexChanged, onShouldNavigateToExecutionChanged)
-   - Signal handlers (onExecutionStarted, onScreenStateChanged, onBackendConnectionChanged)
-   - Component lifecycle (StackLayout.onCompleted, onTabClicked, onRetryConnection)
-
-2. **ConnectionStatus.qml** - Removed all debug logging and simplified color binding
-
-3. **ExecutionPage.qml** - Removed 12+ console.log calls from:
-   - Backend connection handlers
-   - Image source bindings
-   - Signal handlers
-
-4. **TableControlPage.qml** - Removed logs from signal handlers
-
-5. **ModernPlaylistPage.qml** - Removed logs from:
-   - Playlist loading
-   - Execution handlers
-   - Settings radio buttons
-
-6. **ThemeManager.qml** - Removed dark mode toggle logging
-
-7. **BottomNavTab.qml** - Removed icon mapping debug logs
-
-### Backend Optimizations
-
-1. **Event-driven screen timeout** (REQ-TIMER-01, REQ-TIMER-02):
-   - Replaced continuous 1-second polling timer with single-shot event-driven timer
-   - Timer now fires once after the full timeout duration
-   - `_reset_activity_timer()` restarts timer with full timeout on each activity
-   - Eliminates ~1 timer callback per second when idle
-
-2. **WebSocket signal optimization** (REQ-WS-01, REQ-WS-02):
-   - Removed print statements from all WebSocket message handling
-   - Pattern change, pause state, serial connection, and speed change handlers are now silent
-   - Signals still only emit when values actually change (existing optimization preserved)
-
-3. **Preview path caching** (REQ-CACHE-01, REQ-CACHE-02):
-   - Added `_preview_cache` dictionary to store filename -> preview_path mappings
-   - Cache lookup before filesystem search in `_find_pattern_preview()`
-   - Positive results cached after successful lookup
-   - Added `_clear_preview_cache()` method for cache invalidation
-
-## Commits
-
-| Hash | Description |
-|------|-------------|
-| e3b1f2a | Remove MouseArea console.log spam in main.qml |
-| 455ed5c | Remove remaining debug logs from main.qml |
-| bf3729e | Remove debug logs from ConnectionStatus.qml |
-| e1b5994 | Remove debug logs from ExecutionPage.qml |
-| e2e0c82 | Remove debug logs from remaining QML files |
-| bd48ed4 | Optimize timer, WebSocket, and preview cache in backend.py |
-
-## Verification Results
-
-All verification checks passed:
-
-1. `grep -r "console.log" dune-weaver-touch/qml/` - **No matches** (all QML logs removed)
-2. `grep "_screen_timer.start(1000)" dune-weaver-touch/backend.py` - **No matches** (polling removed)
-3. `grep "_preview_cache" dune-weaver-touch/backend.py` - **Found 7 matches** (cache implemented)
-
-## Deviations from Plan
-
-None - plan executed exactly as written.
-
-## Next Phase Readiness
-
-The touch application is now optimized. Functional testing on Raspberry Pi hardware will verify:
-- CPU usage reduction from 100%+ to < 20% when idle
-- Screen timeout still functions correctly (turns off after configured time)
-- Touch wakes screen properly
-- Pattern execution and UI responsiveness unaffected

+ 0 - 128
.planning/phases/01-cpu-optimization/01-cpu-optimization-VERIFICATION.md

@@ -1,128 +0,0 @@
----
-phase: 01-cpu-optimization
-verified: 2026-01-25T23:15:00Z
-status: passed
-score: 6/6 must-haves verified
----
-
-# Phase 1: CPU Optimization Verification Report
-
-**Phase Goal:** Eliminate all identified CPU hotspots and verify performance targets.
-**Verified:** 2026-01-25T23:15:00Z
-**Status:** passed
-**Re-verification:** No - initial verification
-
-## Goal Achievement
-
-### Observable Truths
-
-| # | Truth | Status | Evidence |
-|---|-------|--------|----------|
-| 1 | No console.log in main.qml MouseArea handlers | ✓ VERIFIED | Lines 86-96: `onPressed`, `onPositionChanged`, `onClicked` only call `backend.resetActivityTimer()` |
-| 2 | No debug console.log in ConnectionStatus.qml | ✓ VERIFIED | File is 25 lines total with no console.log statements |
-| 3 | No debug console.log in ExecutionPage.qml | ✓ VERIFIED | File is 422 lines with no console.log statements |
-| 4 | Screen timeout uses event-driven scheduling | ✓ VERIFIED | Line 144: `setSingleShot(True)`, no 1-second polling timer |
-| 5 | WebSocket handler only emits signals when values change | ✓ VERIFIED | `_on_ws_message()` (lines 315-364) has no print statements, emits only on value change |
-| 6 | Pattern preview paths are cached in a dictionary | ✓ VERIFIED | `_preview_cache` dict at line 108, cache lookup at lines 431-432 |
-
-**Score:** 6/6 truths verified
-
-### Required Artifacts
-
-| Artifact | Expected | Status | Details |
-|----------|----------|--------|---------|
-| `dune-weaver-touch/qml/main.qml` | No console.log in MouseArea handlers | ✓ VERIFIED | Lines 86-96 clean |
-| `dune-weaver-touch/qml/components/ConnectionStatus.qml` | No debug console.log | ✓ VERIFIED | 25 lines, no console.log |
-| `dune-weaver-touch/qml/pages/ExecutionPage.qml` | No debug console.log | ✓ VERIFIED | 422 lines, no console.log |
-| `dune-weaver-touch/backend.py` | Event-driven timer + cache | ✓ VERIFIED | setSingleShot(True), _preview_cache implemented |
-
-### Key Link Verification
-
-| From | To | Via | Status | Details |
-|------|-----|-----|--------|---------|
-| main.qml MouseArea | backend.resetActivityTimer() | Direct call | ✓ WIRED | Lines 87, 91, 95 |
-| backend._screen_timer | _screen_timeout_triggered | timeout.connect | ✓ WIRED | Line 145 |
-| _find_pattern_preview | _preview_cache | Dictionary lookup | ✓ WIRED | Lines 431-432, 462, 474 |
-
-### Requirements Coverage
-
-| Requirement | Status | Notes |
-|-------------|--------|-------|
-| REQ-LOG-01 through REQ-LOG-06 | ✓ SATISFIED | All QML console.log removed |
-| REQ-TIMER-01, REQ-TIMER-02 | ✓ SATISFIED | Event-driven single-shot timer implemented |
-| REQ-WS-01, REQ-WS-02 | ✓ SATISFIED | No prints in `_on_ws_message()`, signals emit on change only |
-| REQ-CACHE-01, REQ-CACHE-02 | ✓ SATISFIED | Preview cache dictionary implemented with clear method |
-
-### Anti-Patterns Found
-
-| File | Line | Pattern | Severity | Impact |
-|------|------|---------|----------|--------|
-| backend.py | Various | print statements | ℹ️ Info | These are operational logs (not in hot paths) |
-
-**Note:** The backend.py file still contains print statements, but these are:
-- Connection/disconnection status messages
-- API call logging for debugging
-- Error messages
-
-These are NOT in the hot path (`_on_ws_message`) and do not impact CPU performance since they fire rarely (on user actions or connection events, not continuously).
-
-### Human Verification Required
-
-### 1. CPU Usage Test
-**Test:** Run the touch app on a Raspberry Pi for 60 seconds while idle, monitor with `htop` or `top`
-**Expected:** CPU usage under 20%
-**Why human:** Requires physical hardware and runtime measurement
-
-### 2. Screen Timeout Functionality
-**Test:** Set a 30-second screen timeout, wait without touching the screen
-**Expected:** Screen turns off after 30 seconds
-**Why human:** Requires hardware screen control verification
-
-### 3. Touch Wake Functionality
-**Test:** After screen turns off, touch the screen
-**Expected:** Screen wakes up immediately
-**Why human:** Requires physical touch input verification
-
-### 4. UI Responsiveness
-**Test:** Scroll through pattern list, interact with controls
-**Expected:** No lag or stuttering
-**Why human:** Subjective feel assessment
-
-## Verification Commands Used
-
-```bash
-# Check for console.log in QML (result: 0 matches)
-grep -r "console.log" dune-weaver-touch/qml/ | wc -l
-# Result: 0
-
-# Check screen timer is single-shot (result: found)
-grep "setSingleShot(True)" dune-weaver-touch/backend.py
-# Result: Line 131 (reconnect timer), Line 144 (screen timer)
-
-# Check 1-second polling removed (result: no matches)
-grep "_screen_timer.start(1000)" dune-weaver-touch/backend.py
-# Result: No matches
-
-# Check preview cache exists (result: 7 matches)
-grep "_preview_cache" dune-weaver-touch/backend.py
-# Result: Lines 108, 431, 432, 462, 474, 481, 483
-```
-
-## Conclusion
-
-All 6 must-have truths have been verified in the actual codebase:
-
-1. **QML Logging Cleanup** - Complete. Zero console.log statements in QML files.
-2. **Event-Driven Timer** - Complete. Screen timer uses `setSingleShot(True)` instead of continuous polling.
-3. **WebSocket Optimization** - Complete. No print statements in message handler, signals only emit on value change.
-4. **Preview Caching** - Complete. Dictionary cache with lookup-before-search and cache invalidation method.
-
-The phase goal of eliminating CPU hotspots has been achieved at the code level. Human verification is required for:
-- Runtime CPU measurement on Pi hardware
-- Screen timeout/wake functionality
-- UI responsiveness testing
-
----
-
-*Verified: 2026-01-25T23:15:00Z*
-*Verifier: Claude (gsd-verifier)*

+ 0 - 133
.planning/phases/01-test-infrastructure/01-VERIFICATION.md

@@ -1,133 +0,0 @@
----
-phase: 01-test-infrastructure
-verified: 2026-01-24T18:50:00Z
-status: passed
-score: 4/4 must-haves verified
----
-
-# Phase 01: Test Infrastructure Verification Report
-
-**Phase Goal:** Set up Vitest, Playwright, and MSW so tests can be written
-**Verified:** 2026-01-24T18:50:00Z
-**Status:** passed
-**Re-verification:** No -- initial verification
-
-## Goal Achievement
-
-### Observable Truths
-
-| # | Truth | Status | Evidence |
-|---|-------|--------|----------|
-| 1 | `npm test` runs Vitest and exits cleanly | VERIFIED | 2 tests pass in 751ms, exit code 0 |
-| 2 | `npm run test:e2e` runs Playwright and exits cleanly | VERIFIED | Lists 1 test in 1 file, no config errors |
-| 3 | MSW handlers can intercept `/api/*` requests in tests | VERIFIED | handlers.ts defines `/api/patterns` and `/api/status`, wired via setup.ts |
-| 4 | Directory structure exists | VERIFIED | All required directories present |
-
-**Score:** 4/4 truths verified
-
-### Required Artifacts
-
-| Artifact | Expected | Status | Details |
-|----------|----------|--------|---------|
-| `frontend/vitest.config.ts` | Vitest configuration | EXISTS + SUBSTANTIVE | 21 lines, jsdom env, globals, coverage config |
-| `frontend/playwright.config.ts` | Playwright configuration | EXISTS + SUBSTANTIVE | 25 lines, chromium project, webServer config |
-| `frontend/src/test/setup.ts` | Test setup with MSW | EXISTS + SUBSTANTIVE + WIRED | 16 lines, imports MSW server, beforeAll/afterEach/afterAll hooks |
-| `frontend/src/test/mocks/handlers.ts` | MSW handlers | EXISTS + SUBSTANTIVE | 47 lines, 6 API endpoint handlers including `/api/*` |
-| `frontend/src/test/mocks/server.ts` | MSW server | EXISTS + WIRED | 4 lines, setupServer with handlers |
-| `frontend/src/__tests__/sample.test.tsx` | Sample component test | EXISTS + SUBSTANTIVE | 20 lines, 2 passing tests |
-| `frontend/e2e/sample.spec.ts` | Sample E2E test | EXISTS + SUBSTANTIVE | 9 lines, 1 test case |
-| `frontend/package.json` | Test scripts | VERIFIED | Has test, test:watch, test:ui, test:coverage, test:e2e, test:e2e:ui |
-
-### Key Link Verification
-
-| From | To | Via | Status | Details |
-|------|----|-----|--------|---------|
-| `vitest.config.ts` | `vite.config` | mergeConfig import | WIRED | Shares path aliases and config |
-| `setup.ts` | `mocks/server.ts` | import statement | WIRED | Server started in beforeAll |
-| `server.ts` | `handlers.ts` | import statement | WIRED | Handlers spread into setupServer |
-| `package.json` scripts | configs | CLI invocation | WIRED | `npm test` runs vitest, `npm run test:e2e` runs playwright |
-| `tsconfig.app.json` | vitest/globals | types array | WIRED | TypeScript recognizes test globals |
-
-### Requirements Coverage
-
-| Requirement | Status | Notes |
-|-------------|--------|-------|
-| INF-1: Vitest configured with jsdom and RTL | SATISFIED | vitest.config.ts has jsdom env, RTL installed |
-| INF-2: Playwright with Chrome configuration | SATISFIED | playwright.config.ts has chromium project |
-| INF-3: MSW configured for API mocking | SATISFIED | handlers.ts + server.ts + setup.ts integration |
-| INF-4: Test directory structure | SATISFIED | `src/__tests__/`, `e2e/`, `src/test/mocks/` exist |
-
-### Anti-Patterns Found
-
-| File | Line | Pattern | Severity | Impact |
-|------|------|---------|----------|--------|
-| (none) | - | - | - | - |
-
-No stub patterns, TODOs, or empty implementations found in test infrastructure files.
-
-### Human Verification Required
-
-None required. All must-haves can be verified programmatically.
-
-### Verification Commands Executed
-
-```bash
-# 1. npm test - Vitest execution
-$ cd frontend && npm test
- RUN  v3.2.4
- ✓ src/__tests__/sample.test.tsx (2 tests) 42ms
- Test Files  1 passed (1)
-      Tests  2 passed (2)
-   Duration  751ms
-
-# 2. npm run test:e2e --list - Playwright verification
-$ cd frontend && npm run test:e2e -- --list
-Listing tests:
-  [chromium] › sample.spec.ts:4:3 › Test Infrastructure › app loads successfully
-Total: 1 test in 1 file
-
-# 3. npm run test:coverage - Coverage verification
-$ cd frontend && npm run test:coverage
- Coverage enabled with v8
- ✓ src/__tests__/sample.test.tsx (2 tests) 46ms
- Coverage report from v8 generated
-
-# 4. Directory structure verification
-$ ls frontend/src/__tests__/
-sample.test.tsx
-$ ls frontend/e2e/
-sample.spec.ts
-$ ls frontend/src/test/mocks/
-handlers.ts  server.ts
-```
-
-### Dependencies Installed
-
-All required devDependencies verified in package.json:
-- `vitest@^3.2.4`
-- `@vitest/ui@^3.2.4`
-- `@vitest/coverage-v8@^3.2.4`
-- `jsdom@^27.0.1`
-- `@testing-library/react@^16.3.2`
-- `@testing-library/jest-dom@^6.9.1`
-- `@testing-library/user-event@^14.6.1`
-- `@playwright/test@^1.58.0`
-- `msw@^2.12.7`
-
----
-
-## Summary
-
-Phase 01 test infrastructure is fully operational. All four must-haves are verified:
-
-1. **Vitest works:** `npm test` runs 2 sample tests and exits with code 0
-2. **Playwright works:** `npm run test:e2e` lists tests without configuration errors
-3. **MSW works:** Handlers defined for `/api/*` endpoints, wired into test setup with proper lifecycle hooks
-4. **Directory structure exists:** All required directories and files present
-
-The infrastructure is ready for Phase 02 (Component Tests).
-
----
-
-_Verified: 2026-01-24T18:50:00Z_
-_Verifier: Claude (gsd-verifier)_

+ 0 - 172
.planning/phases/02-component-tests/02-01-SUMMARY.md

@@ -1,172 +0,0 @@
-# Phase 02 Plan 01: Critical Page Component Tests Summary
-
-```yaml
-phase: 02-component-tests
-plan: 01
-subsystem: frontend-testing
-tags: [vitest, react-testing-library, msw, component-tests]
-dependency-graph:
-  requires: [01-test-infrastructure]
-  provides: [component-tests, msw-handlers, test-utilities]
-  affects: [03-integration-tests, 04-e2e-ci]
-tech-stack:
-  added: []
-  patterns: [render-with-providers, mock-data-generators, browser-api-mocks]
-key-files:
-  created:
-    - frontend/src/test/utils.tsx
-    - frontend/src/test/mocks/websocket.ts
-    - frontend/src/test/mocks/browser.ts
-    - frontend/src/__tests__/pages/BrowsePage.test.tsx
-    - frontend/src/__tests__/pages/PlaylistsPage.test.tsx
-    - frontend/src/__tests__/pages/TableControlPage.test.tsx
-    - frontend/src/__tests__/components/NowPlayingBar.test.tsx
-  modified:
-    - frontend/src/test/mocks/handlers.ts
-    - frontend/src/test/setup.ts
-decisions:
-  - id: warn-unhandled-requests
-    description: Use 'warn' instead of 'error' for MSW unhandled requests due to WebSocket conflicts
-    context: MSW 2.x WebSocket interception conflicts with our mock WebSocket class
-  - id: simplified-nowplayingbar-tests
-    description: Simplified NowPlayingBar tests to focus on props and visibility
-    context: WebSocket-dependent functionality is difficult to test without complex mocking
-  - id: focus-on-observable-behavior
-    description: Tests focus on observable behavior (rendering, clicks, API calls) not implementation
-    context: Large components (1000+ lines) have many features; testing critical paths only
-metrics:
-  duration: ~8 minutes
-  completed: 2026-01-25
-```
-
-## One-liner
-
-Added 42 component tests across 4 critical pages with MSW handlers for 50+ endpoints, browser API mocks, and test utilities.
-
-## What Was Built
-
-### Test Utilities Module (`frontend/src/test/utils.tsx`)
-- `renderWithProviders()` - wraps components with BrowserRouter
-- `createMockPatterns()` - generates test pattern metadata
-- `createMockPlaylists()` - generates test playlist names
-- `createMockStatus()` - generates playback status data
-- `createMockPreview()` - generates preview image data
-- Re-exports from `@testing-library/react` and `userEvent`
-
-### Expanded MSW Handlers (`frontend/src/test/mocks/handlers.ts`)
-- **Pattern endpoints (10):** list, metadata, preview_batch, coordinates, run, delete, upload, history
-- **Playlist endpoints (10):** list_all, get, create, modify, rename, delete, run, reorder, add_to_playlist, add_to_queue
-- **Playback endpoints (6):** pause, resume, stop, force_stop, skip, set_speed
-- **Table control endpoints (5):** send_home, soft_reset, move_to_center, move_to_perimeter, send_coordinate
-- **Status endpoints (2):** serial_status, list_serial_ports
-- **Debug endpoints (3):** debug-serial open/close/send
-- Mutable `mockData` store with `resetMockData()` for test isolation
-
-### Browser API Mocks (`frontend/src/test/mocks/browser.ts`)
-- `MockIntersectionObserver` - immediately triggers as visible
-- `MockResizeObserver` - no-op implementation
-- `createMockMatchMedia()` - configurable media query mock
-- Canvas 2D context mock with all drawing methods
-- localStorage mock with getItem/setItem/removeItem/clear
-
-### WebSocket Mock (`frontend/src/test/mocks/websocket.ts`)
-- `MockWebSocket` class with CONNECTING/OPEN/CLOSED states
-- `simulateMessage()` and `simulateError()` helpers
-- Instance tracking via `MockWebSocket.instances[]`
-- `getLastWebSocket()` utility for test access
-
-### Component Tests
-
-**BrowsePage (10 tests):**
-- Pattern listing renders from API
-- Page title displayed
-- Empty pattern list handling
-- API error graceful handling
-- Pattern selection opens sheet
-- Search filters patterns by name
-- Clearing search shows all patterns
-- No results shows clear filters button
-- Pattern cards are clickable
-
-**PlaylistsPage (10 tests):**
-- Playlist names render from API
-- Page title and description displayed
-- Playlist count shown
-- Empty playlist list handling
-- Clicking playlist loads patterns
-- Create button opens modal
-- Create playlist calls API
-- Edit button opens rename modal
-- Delete buttons present for playlists
-- Run playlist triggers API
-
-**TableControlPage (13 tests):**
-- Page title and description rendered
-- Primary action buttons (Home/Stop/Reset)
-- Position control buttons (Center/Perimeter)
-- Speed control section with input
-- Home button calls send_home API
-- Stop button calls stop_execution API
-- Reset button triggers dialog
-- Reset dialog accessible via aria attributes
-- Move to center/perimeter buttons call APIs
-- Speed input submits on Set click
-- Speed input submits on Enter key
-- Speed badge displays current speed
-
-**NowPlayingBar (7 tests):**
-- Renders when visible
-- Does not render when isVisible=false
-- onClose callback handling
-- Accepts logsDrawerHeight prop
-- Accepts openExpanded prop
-- Accepts isLogsOpen prop
-- Renders with all props without crashing
-
-## Coverage Results
-
-| Component | Line Coverage |
-|-----------|---------------|
-| BrowsePage.tsx | 50.91% |
-| PlaylistsPage.tsx | 81.35% |
-| TableControlPage.tsx | 67.65% |
-| NowPlayingBar.tsx | (visibility tests only) |
-
-## Decisions Made
-
-### 1. MSW onUnhandledRequest: 'warn'
-Changed from 'error' to 'warn' because MSW 2.x automatically intercepts WebSocket connections, conflicting with our mock WebSocket class. The warnings are logged but tests pass.
-
-### 2. Simplified NowPlayingBar Tests
-The NowPlayingBar relies heavily on WebSocket for real-time status updates. Testing the WebSocket interaction requires complex mocking (injecting mock before component creates connection). Focus on props handling and visibility for this phase; WebSocket-dependent tests can be added in integration tests.
-
-### 3. Observable Behavior Testing
-Tests focus on:
-- What renders on screen
-- What happens when users click/type
-- What API calls are made
-Not tested: internal state, implementation details, private functions.
-
-## Deviations from Plan
-
-None - plan executed exactly as written.
-
-## Git Commits
-
-| Commit | Description |
-|--------|-------------|
-| f8f76bc | feat(02-01): add test utilities and expanded MSW handlers |
-| 93e1413 | test(02-01): add component tests for critical pages |
-
-## Next Phase Readiness
-
-### Prerequisites Met
-- [x] Test utilities available for consistent rendering
-- [x] MSW handlers cover all API endpoints
-- [x] Browser mocks handle jsdom limitations
-- [x] 42 tests passing with stable results
-
-### For Phase 03 (Integration Tests)
-- WebSocket status updates need proper injection mechanism
-- Consider using MSW's WebSocket support in future versions
-- Multi-component integration may need additional providers

+ 0 - 103
.planning/phases/03-integration-tests/03-01-SUMMARY.md

@@ -1,103 +0,0 @@
-# Phase 03 Plan 01: Multi-Component User Flow Tests Summary
-
-**One-liner:** Integration tests validating pattern browsing, playlist management, and playback control flows with API call verification via MSW apiCallLog tracking.
-
-## Completed Work
-
-### Tasks Completed
-
-| Task | Description | Commit | Files |
-|------|-------------|--------|-------|
-| 1.1-1.3 | Integration test infrastructure | beec9a9 | utils.tsx, handlers.ts, setup.ts |
-| 2.1 | Pattern flow integration tests | 286e40d | patternFlow.test.tsx |
-| 3.1 | Playlist flow integration tests | 313e479 | playlistFlow.test.tsx, handlers.ts |
-| 4.1 | Playback flow integration tests | bdf0f47 | playbackFlow.test.tsx |
-| 5.1-5.2 | Test verification and coverage | (this summary) | - |
-
-### Test Counts
-
-| Category | Tests |
-|----------|-------|
-| Pattern flow (INT-1) | 6 |
-| Playlist flow (INT-2) | 8 |
-| Playback flow (INT-3) | 8 |
-| **Total integration tests** | **22** |
-| Component tests (Phase 02) | 42 |
-| **Total tests** | **64** |
-
-### Key Files Created/Modified
-
-**Created:**
-- `frontend/src/__tests__/integration/patternFlow.test.tsx` - Browse -> select -> run flow tests
-- `frontend/src/__tests__/integration/playlistFlow.test.tsx` - Create -> view -> run playlist tests
-- `frontend/src/__tests__/integration/playbackFlow.test.tsx` - Playback lifecycle tests
-
-**Modified:**
-- `frontend/src/test/utils.tsx` - Added renderApp() helper for integration tests
-- `frontend/src/test/mocks/handlers.ts` - Added apiCallLog tracking and logApiCall helper
-- `frontend/src/test/setup.ts` - Added resetApiCallLog to beforeEach
-
-## Technical Decisions
-
-| Decision | Rationale |
-|----------|-----------|
-| apiCallLog array for tracking | Simple mutable array enables verification of API call sequences without complex mocking |
-| logApiCall() on key handlers | Selective logging on important endpoints (run, playlist, playback control) keeps logs focused |
-| Button finding via textContent | More reliable than getByRole name matching due to multiple buttons with similar names |
-| localStorage.clear() in beforeEach | Ensures test isolation for components that persist state |
-
-## Deviations from Plan
-
-### Auto-fixed Issues
-
-**1. [Rule 3 - Blocking] Fixed preview_thr_batch handler**
-- **Found during:** Task 3.1
-- **Issue:** Handler expected `files` but app sends `file_names`
-- **Fix:** Updated handler to accept both: `body.files || body.file_names || []`
-- **Files modified:** handlers.ts
-- **Commit:** 313e479
-
-**2. [Rule 1 - Bug] Added playlist_name to stop_execution reset**
-- **Found during:** Task 4.1
-- **Issue:** stop_execution handler didn't reset playlist_name to null
-- **Fix:** Added `mockData.status.playlist_name = null` to stop_execution handler
-- **Files modified:** handlers.ts
-- **Commit:** beec9a9
-
-## Coverage Summary
-
-```
-Pages tested:
-- BrowsePage.tsx: 53% statements covered
-- PlaylistsPage.tsx: 84% statements covered
-- TableControlPage.tsx: 68% statements covered
-
-Overall: 64 tests passing
-```
-
-## Requirements Addressed
-
-- [x] **INT-1:** Pattern flow - browse -> select -> trigger run -> verify API call
-- [x] **INT-2:** Playlist flow - create -> add patterns -> run -> verify API calls
-- [x] **INT-3:** Playback flow - start -> pause/resume -> stop -> verify state transitions
-
-## Next Phase Readiness
-
-Phase 03 is complete. Ready for Phase 04: E2E & CI.
-
-**Dependencies for Phase 04:**
-- MSW handlers with apiCallLog tracking (available)
-- Test infrastructure with full app rendering (renderApp available)
-- All integration tests passing (verified)
-
-## Metrics
-
-| Metric | Value |
-|--------|-------|
-| Start time | 2026-01-25T01:26:11Z |
-| End time | 2026-01-25T01:31:52Z |
-| Duration | ~6 minutes |
-| Tasks completed | 5/5 |
-| Tests added | 22 |
-| Files created | 3 |
-| Files modified | 3 |

+ 0 - 131
.planning/phases/04-e2e-ci/04-01-SUMMARY.md

@@ -1,131 +0,0 @@
-# Phase 04 Plan 01: E2E Tests and GitHub Actions Integration Summary
-
-**One-liner:** Playwright E2E tests with WebSocket mocking for critical user journeys, plus GitHub Actions CI integration for frontend tests.
-
-## Completed Work
-
-### Tasks Completed
-
-| Task | Description | Commit | Files |
-|------|-------------|--------|-------|
-| 1.1 | Playwright API mock utilities | ddc463c | e2e/mocks/api.ts |
-| 2.1 | Pattern flow E2E tests | dd4baaf | e2e/pattern-flow.spec.ts |
-| 2.2 | Playlist flow E2E tests | 647cb08 | e2e/playlist-flow.spec.ts |
-| 2.3 | Table control E2E tests | 8406243 | e2e/table-control.spec.ts |
-| 3.1 | Update sample spec | 449034a | e2e/sample.spec.ts |
-| 4.1 | Extend CI workflow | 9207135 | .github/workflows/test.yml |
-| 5.1-5.2 | Test fixes and verification | fa94d6a | api.ts, playwright.config.ts, tests |
-
-### Test Counts
-
-| Category | Tests |
-|----------|-------|
-| App infrastructure (sample.spec.ts) | 3 |
-| Pattern flow (pattern-flow.spec.ts) | 4 |
-| Playlist flow (playlist-flow.spec.ts) | 3 |
-| Table control (table-control.spec.ts) | 3 |
-| **Total E2E tests** | **13** |
-| Component tests (Phase 02) | 42 |
-| Integration tests (Phase 03) | 22 |
-| **Total frontend tests** | **77** |
-
-### Key Files Created/Modified
-
-**Created:**
-- `frontend/e2e/mocks/api.ts` - Playwright route mocking with WebSocket support
-- `frontend/e2e/pattern-flow.spec.ts` - Pattern browsing and execution E2E tests
-- `frontend/e2e/playlist-flow.spec.ts` - Playlist viewing and execution E2E tests
-- `frontend/e2e/table-control.spec.ts` - Table control page E2E tests
-
-**Modified:**
-- `frontend/e2e/sample.spec.ts` - Updated with meaningful infrastructure tests
-- `frontend/playwright.config.ts` - Added dedicated E2E port (5174) to avoid conflicts
-- `.github/workflows/test.yml` - Added frontend-test and frontend-e2e jobs
-
-## Technical Decisions
-
-| Decision | Rationale |
-|----------|-----------|
-| WebSocket mocking via routeWebSocket() | Required to bypass blocking "Connecting to Backend" overlay |
-| Dedicated port 5174 for E2E | Avoids conflict with other dev servers running on 5173 |
-| Playwright route interception | More reliable than MSW for E2E (MSW requires service worker in browser) |
-| Button locators by title/exact name | Avoids strict mode violations with multiple similar buttons |
-
-## Deviations from Plan
-
-### Auto-fixed Issues
-
-**1. [Rule 3 - Blocking] WebSocket connection blocks UI**
-- **Found during:** Task 5.1 verification
-- **Issue:** App shows blocking overlay until WebSocket /ws/status connects
-- **Fix:** Added `page.routeWebSocket()` mocking for all WebSocket endpoints
-- **Files modified:** e2e/mocks/api.ts
-- **Commit:** fa94d6a
-
-**2. [Rule 3 - Blocking] Port conflict with other dev server**
-- **Found during:** Task 5.1 verification
-- **Issue:** Port 5173 already in use by another project (Image2Dune)
-- **Fix:** Changed Playwright config to use dedicated port 5174
-- **Files modified:** playwright.config.ts
-- **Commit:** fa94d6a
-
-**3. [Rule 1 - Bug] Run playlist API field name mismatch**
-- **Found during:** Task 5.1 verification
-- **Issue:** Mock expected `name` but actual API sends `playlist_name`
-- **Fix:** Updated mock to accept both field names
-- **Files modified:** e2e/mocks/api.ts
-- **Commit:** fa94d6a
-
-## Requirements Addressed
-
-- [x] **E2E-1:** Critical user journey - browse -> play pattern -> verify UI updates
-- [x] **INF-5:** GitHub Actions workflow extended to run frontend tests alongside backend
-- [x] 3+ E2E tests (milestone target: 3+, actual: 13)
-- [x] CI: `npm test` runs Vitest tests in GitHub Actions
-- [x] CI: `npm run test:e2e` runs Playwright tests in GitHub Actions
-- [x] CI: Frontend tests configured with appropriate timeout (< 10 minutes)
-
-## CI Workflow Summary
-
-The `.github/workflows/test.yml` now includes:
-
-| Job | Description | Timeout |
-|-----|-------------|---------|
-| test | Backend Python tests with pytest | default |
-| lint | Backend Python linting with Ruff | default |
-| frontend-test | Vitest unit/integration tests | default |
-| frontend-e2e | Playwright E2E tests (Chromium) | 10 minutes |
-
-Features:
-- Node.js 20 with npm caching
-- Playwright browsers installed in CI
-- Report artifacts uploaded on failure
-- Triggered on push to main/feature/*, PRs to main
-- Includes `frontend/**` in path triggers
-
-## Next Phase Readiness
-
-Phase 04 is complete. This completes the v2-frontend-testing milestone.
-
-**Milestone Summary:**
-- Phase 01: Test infrastructure (Vitest, RTL, MSW, Playwright)
-- Phase 02: Component tests (42 tests)
-- Phase 03: Integration tests (22 tests)
-- Phase 04: E2E tests and CI (13 E2E tests, CI workflow)
-
-**Total Test Coverage:**
-- Backend: 17 tests (from v1)
-- Frontend: 77 tests (64 Vitest + 13 Playwright)
-- **Grand total: 94 tests**
-
-## Metrics
-
-| Metric | Value |
-|--------|-------|
-| Start time | 2026-01-25T14:43:03Z |
-| End time | 2026-01-25T14:52:00Z |
-| Duration | ~9 minutes |
-| Tasks completed | 7/7 |
-| E2E tests added | 13 |
-| Files created | 5 |
-| Files modified | 3 |