---
phase: 03-backing-track-finalization
type: execute
---

<objective>
Optimize performance, clean up diagnostic code, and perform comprehensive UAT to verify Phase 3 completion.

Purpose: Polish the player for production with performance optimizations, remove temporary diagnostic logging, and verify all functionality through comprehensive user acceptance testing.

Output: Production-ready backing track player with optimized performance, clean code, and verified functionality across all features and edge cases.
</objective>

<execution_context>
@./.claude/get-shit-done/workflows/execute-phase.md
@./.claude/get-shit-done/templates/summary.md
@./.claude/get-shit-done/references/checkpoints.md
</execution_context>

<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/02-backing-track-seek-controls/02-01-SUMMARY.md
@.planning/phases/03-backing-track-finalization/03-01-SUMMARY.md
@.planning/phases/03-backing-track-finalization/03-02-SUMMARY.md
@jam-ui/src/components/client/JKSessionBackingTrackPlayer.js

**Performance considerations:**
- 500ms polling runs continuously while playing (from Phase 1)
- Current implementation has diagnostic [BTP] logging (added in Phase 2)
- No optimization for inactive/hidden player
- No React performance optimizations (useMemo, useCallback)

**Phase 3 accomplishments so far:**
- Plan 03-01: Volume/loop controls finalized, UAT-003 resolved
- Plan 03-02: Error handling, loading states, edge cases covered

**Final tasks:**
- Performance optimization
- Clean up diagnostic code
- Comprehensive UAT verification
</context>

<tasks>

<task type="auto">
  <name>Task 1: Optimize polling and performance</name>
  <files>jam-ui/src/components/client/JKSessionBackingTrackPlayer.js</files>
  <action>Optimize performance and reduce unnecessary work:

**1. Conditional polling based on visibility:**

Add visibility detection:
```javascript
const [isVisible, setIsVisible] = useState(true);

useEffect(() => {
  const handleVisibilityChange = () => {
    setIsVisible(!document.hidden);
  };

  document.addEventListener('visibilitychange', handleVisibilityChange);
  return () => document.removeEventListener('visibilitychange', handleVisibilityChange);
}, []);
```

Modify polling interval condition (line 71):
```javascript
if (isPlaying && jamClient && isVisible) {
  // Poll at 500ms when visible
} else if (isPlaying && jamClient && !isVisible) {
  // Poll at 2000ms (2 seconds) when hidden - reduce frequency
}
```

**2. Optimize re-renders with React.memo for expensive computations:**

Add useMemo for derived values:
```javascript
const formattedCurrentTime = useMemo(() => formatTime(currentPositionMs), [currentPositionMs]);
const formattedDuration = useMemo(() => formatTime(durationMs), [durationMs]);
```

Use these memoized values in render instead of currentTime/duration states.

**3. Add useCallback for stable handler references:**

Wrap handlers that are passed as props or used in dependencies:
```javascript
const handlePlay = useCallback(async () => {
  // ... existing logic
}, [isPlaying, currentPositionMs, durationMs, jamClient]);

const handleSeek = useCallback(async (e) => {
  // ... existing logic
}, [jamClient]);

// Similar for other handlers
```

**4. Optimize slider updates:**

Throttle slider position updates during rapid changes:
- Current implementation updates state on every input event
- Add throttling to update at most every 100ms
- Use useRef to track last update time

**5. Clean up diagnostic logging:**

Remove or make conditional all [BTP] console.log statements added in Phase 2:
- Lines with `console.log('[BTP]` - either remove entirely or wrap in `if (DEBUG)` check
- Keep console.error for actual errors
- Consider adding a `const DEBUG = false;` flag at top of file

**6. Ensure proper cleanup:**

Verify all effects have cleanup:
- Polling interval: already has clearInterval cleanup
- Visibility listener: cleanup added above
- Any refs: ensure no memory leaks

**7. Lazy state updates:**

Avoid unnecessary state updates in polling:
```javascript
// Only update if value actually changed
if (validPosition !== currentPositionMs) {
  setCurrentPositionMs(validPosition);
}
```

**Pattern for optimization:**
```javascript
// Before: Always update
setState(newValue);

// After: Conditional update
if (newValue !== currentValue) {
  setState(newValue);
}
```</action>
  <verify>
- Player performs smoothly during playback (60fps UI)
- Polling reduces frequency when tab hidden (check Network tab)
- No unnecessary re-renders (React DevTools Profiler)
- Slider updates smoothly without lag
- Memory usage stable over time (no leaks)
- All [BTP] diagnostic logs removed or conditional
  </verify>
  <done>Performance optimized with visibility-aware polling, memoization, stable callbacks, clean diagnostic logging, no memory leaks</done>
</task>

<task type="checkpoint:human-verify" gate="blocking">
  <what-built>Complete backing track player with all Phase 3 enhancements</what-built>
  <how-to-verify>
**Comprehensive UAT Testing Checklist:**

**Setup:**
1. Start jam-ui: `cd jam-ui && npm run start`
2. Open browser to http://beta.jamkazam.local:4000
3. Join or create a session
4. Open browser console to check for errors

**A. Core Playback Controls:**
1. Click "Open > Backing Track", select audio file
   - [ ] Player opens successfully
   - [ ] Duration displays correctly (not NaN)
   - [ ] Time shows 0:00 initially
2. Click Play button
   - [ ] Audio plays
   - [ ] Time updates smoothly
   - [ ] Slider moves from left to right
   - [ ] No console errors
3. Click Pause button
   - [ ] Audio pauses
   - [ ] Time stops updating
   - [ ] Slider stops moving
4. Click Play again (resume)
   - [ ] Audio resumes from paused position
5. Click Stop button
   - [ ] Audio stops
   - [ ] Time resets to 0:00
   - [ ] Slider resets to left

**B. Seek Controls:**
6. Play audio, drag slider to middle while playing
   - [ ] Audio jumps to new position
   - [ ] Time display updates to match
   - [ ] Smooth transition
7. Pause audio, drag slider to different position
   - [ ] UAT-003 resolution verified (either works or documented as limitation)
   - [ ] Slider moves visually
   - [ ] Behavior matches Plan 03-01 resolution decision
8. Drag slider to end position
   - [ ] Resets to beginning when play clicked (UAT-004 fix from Phase 2)
   - [ ] No player freeze
9. Drag slider to start position (0:00)
   - [ ] Audio restarts from beginning

**C. Volume & Loop Controls (Plan 03-01):**
10. Adjust volume slider to 0%
    - [ ] Audio muted
11. Adjust volume slider to 50%
    - [ ] Audio volume at half level
12. Adjust volume slider to 100%
    - [ ] Audio at full volume
13. Enable loop checkbox
    - [ ] Checkbox checked
    - [ ] No console errors
14. Let track play to end with loop enabled
    - [ ] Track restarts automatically
15. Disable loop checkbox
    - [ ] Track stops at end (doesn't loop)

**D. Error Handling (Plan 03-02):**
16. Try loading invalid file (wrong format or non-existent)
    - [ ] Error message displayed to user
    - [ ] Message is clear and actionable
    - [ ] Controls disabled or "Retry"/"Close" options available
17. Simulate jamClient disconnection (if possible)
    - [ ] Error handling graceful
    - [ ] No uncaught exceptions
18. Try rapid-clicking play/pause buttons
    - [ ] No double-actions
    - [ ] Operations properly debounced
    - [ ] Loading indicators show during operations

**E. Loading States (Plan 03-02):**
19. Open backing track
    - [ ] Loading indicator while duration fetches
    - [ ] Play button disabled until ready
20. Perform operations (play/stop/seek)
    - [ ] Controls disabled during operation
    - [ ] Visual feedback (spinner or disabled state)
    - [ ] Smooth re-enable after operation

**F. Performance (Plan 03-03):**
21. Play track and switch to another browser tab
    - [ ] Audio continues playing
    - [ ] Check console for reduced polling frequency (optional)
22. Switch back to jam-ui tab
    - [ ] Slider position correct
    - [ ] Time display accurate
23. Let track play for several minutes
    - [ ] Smooth playback throughout
    - [ ] No lag or stuttering
    - [ ] Memory usage stable (check Task Manager)

**G. Edge Cases:**
24. Close player while track is playing
    - [ ] Track stops
    - [ ] Player closes cleanly
    - [ ] No console errors
25. Open player, don't play, just close
    - [ ] Closes cleanly
26. Seek multiple times rapidly
    - [ ] Handles gracefully
    - [ ] Final position correct

**H. Browser Console:**
27. Review browser console after all tests
    - [ ] No uncaught exceptions
    - [ ] No [BTP] diagnostic logs (or minimal if DEBUG enabled)
    - [ ] Only expected error logs (if any)

**I. Overall Quality:**
28. General assessment
    - [ ] UI responsive and smooth
    - [ ] No visual glitches
    - [ ] Professional appearance
    - [ ] Ready for production use

**Verification Status:**
Report any issues found or confirm "All tests passed - player ready for production"
  </how-to-verify>
  <resume-signal>Type "approved" if all tests pass, or describe any issues found that need fixing</resume-signal>
</task>

</tasks>

<verification>
Before declaring Phase 3 complete:
- [ ] Performance optimizations implemented and tested
- [ ] Diagnostic logging cleaned up
- [ ] Comprehensive UAT completed with all checks passed
- [ ] All three Plan 03 summaries created
- [ ] Phase 3 accomplishments documented in final summary
- [ ] Player ready for production use
</verification>

<success_criteria>

- Performance optimized (visibility-aware polling, memoization, no memory leaks)
- Diagnostic code removed or conditional
- Comprehensive UAT completed successfully
- All 28+ test cases passed
- No blocking issues found
- Player is production-ready
- All changes committed
- Phase 3 complete - ready for Phase 4 (JamTrack Research & Design)
</success_criteria>

<output>
After completion, create `.planning/phases/03-backing-track-finalization/03-03-SUMMARY.md`:

# Phase 3 Plan 3: Performance Optimization & Final UAT Summary

**Optimized performance and verified production readiness through comprehensive UAT**

## Accomplishments

- Implemented visibility-aware polling (reduces frequency when hidden)
- Added React performance optimizations (useMemo, useCallback)
- Cleaned up diagnostic logging from Phase 2
- Completed comprehensive UAT with 28+ test cases
- Verified all features working: playback, seek, volume, loop, error handling

## Files Created/Modified

- `jam-ui/src/components/client/JKSessionBackingTrackPlayer.js` - Performance optimizations, logging cleanup

## Decisions Made

- Polling frequency: 500ms visible, 2000ms hidden
- Diagnostic logging: [Removed entirely | Made conditional with DEBUG flag]
- Performance approach: [useMemo for derived values, useCallback for handlers]

## UAT Results

**Tests passed:** [X/28+]
**Issues found:** [List any issues, or "None"]
**Blocker issues:** [Any blockers, or "None"]
**Minor issues:** [Any minor issues, or "None"]

## Issues Encountered

[Any unexpected issues during optimization or UAT, or "None"]

## Phase 3 Complete

Backing Track player is now production-ready with:
- ✅ Full playback controls (play/pause/stop)
- ✅ Functional seek slider
- ✅ Volume and loop controls
- ✅ Comprehensive error handling
- ✅ Loading states and disabled UI during operations
- ✅ Edge case handling
- ✅ Performance optimizations
- ✅ Clean, maintainable code

Ready for Phase 4 (JamTrack Research & Design).
</output>
