---
phase: 09-trip-planner-modes-tdd
plan: 02
type: tdd
---
Test-driven validation of Scenario B (must-see games planning) filler game timing conflict prevention and impossible geographic combination detection.
Purpose: Ensure filler games don't conflict with anchored must-see games, and detect when selected games cannot be combined into a valid route. Tests define correctness - code must match.
Output: Working filler conflict prevention and impossible combination detection with passing TDD tests.
~/.claude/get-shit-done/workflows/execute-phase.md
./summary.md
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/09-trip-planner-modes-tdd/09-01-SUMMARY.md
@SportsTime/Planning/Engine/ScenarioBPlanner.swift
@SportsTimeTests/ScenarioBPlannerTests.swift
@SportsTimeTests/GameDAGRouterTests.swift
**Tech stack available:** Swift Testing framework, GameDAGRouter with anchor filtering, sliding window logic
**Established patterns:** Swift Testing @Test/@Suite, TDD RED-GREEN-REFACTOR, anchor game validation
**Constraining decisions:**
- Phase 08-01: GameDAGRouter validates anchor games appear in all routes
- Phase 08-02: Dynamic beam scaling prevents performance degradation
- Phase 09-01: Timezone boundary handling and same-day conflict detection patterns
**Issues being addressed:** None (new test coverage)
Feature 1: Filler game timing conflict prevention
SportsTimeTests/ScenarioBPlannerTests.swift
SportsTime/Planning/Engine/ScenarioBPlanner.swift
Test cases for filler games not conflicting with must-see games:
**Case 1: Filler game between two must-see games (feasible timing)**
- Must-see: LA Jan 5 1pm, SF Jan 7 7pm
- Filler available: San Jose Jan 6 7pm (between LA and SF, feasible)
- Expected: Filler included in route (LA → SJ → SF)
**Case 2: Filler game same-day as must-see (infeasible timing)**
- Must-see: LA Jan 5 7pm
- Filler available: Anaheim Jan 5 7pm (same time, different city)
- Expected: Filler excluded (cannot attend both at same time)
**Case 3: Filler game requires backtracking**
- Must-see: LA Jan 5 7pm, SF Jan 7 7pm (north-bound route)
- Filler available: San Diego Jan 6 7pm (south of LA, requires backtrack)
- Expected: Filler excluded or route reordered if feasible
**Case 4: Multiple filler options, only one feasible**
- Must-see: LA Jan 5 1pm, Phoenix Jan 7 7pm
- Filler A: SF Jan 6 7pm (300mi north, wrong direction)
- Filler B: Tucson Jan 6 7pm (100mi east toward Phoenix)
- Expected: Route includes Filler B, excludes Filler A
Anchors are fixed - filler games must not create conflicts or geographic inefficiency.
If tests fail:
1. ScenarioBPlanner may not be filtering filler games by geographic feasibility
2. GameDAGRouter may not be checking same-day timing conflicts for non-anchors
3. Sliding window logic may include infeasible date ranges
4. Fix ScenarioBPlanner's filler game selection logic
Do NOT weaken test assertions - fix the code to match expected behavior.
Feature 2: Impossible geographic combination detection
SportsTimeTests/ScenarioBPlannerTests.swift
SportsTime/Planning/Engine/ScenarioBPlanner.swift
Test cases for detecting impossible must-see game combinations:
**Case 1: Must-see games too far apart for date span**
- Must-see: LA Jan 5 7pm, New York Jan 6 7pm (2800 miles, 42hr drive)
- Date range: Jan 5-6 (24 hours available)
- Expected: .failure(.constraintsUnsatisfiable) - cannot drive 2800mi in 24hr
**Case 2: Must-see games in reverse chronological order geographically**
- Must-see: SF Jan 5, LA Jan 4 (SF is after LA chronologically but north)
- Expected: .failure(.dateRangeViolation) - SF game is before LA game but would require backtracking
**Case 3: Three must-see games forming triangle (inefficient)**
- Must-see: LA Jan 5, SF Jan 6, San Diego Jan 7
- Expected: Route attempts LA→SF→SD (but SD is south of LA) OR returns failure if too inefficient
**Case 4: Must-see games exceed driving constraints**
- Must-see: LA Jan 5 1pm, Phoenix Jan 5 7pm (380 miles, 6hr drive)
- Constraints: 1 driver, 4hr/day max
- Expected: .failure(.drivingExceedsLimit) - 6hr drive exceeds 4hr limit
**Case 5: Feasible must-see combination (sanity check)**
- Must-see: LA Jan 5 7pm, Anaheim Jan 7 7pm (30 miles)
- Expected: .success([...]) with both games in route
Tests verify ScenarioBPlanner detects impossible combinations early and returns explicit failures.
If tests fail:
1. ScenarioBPlanner may not validate geographic feasibility before routing
2. GameDAGRouter may not enforce driving constraints for anchor games
3. Failure reasons may not be specific enough (.constraintsUnsatisfiable vs .drivingExceedsLimit)
4. Fix ScenarioBPlanner's validation logic and failure reporting
Do NOT weaken test assertions - fix the code to match expected behavior.
All tests pass:
```bash
xcodebuild -project SportsTime.xcodeproj -scheme SportsTime \
-destination 'platform=iOS Simulator,name=iPhone 17,OS=26.2' \
-only-testing:SportsTimeTests/ScenarioBPlannerTests test
```
Specific tests to verify:
- Filler conflict tests: 4 new tests (between anchors, same-day, backtracking, multiple options)
- Impossible combination tests: 5 new tests (distance, reverse order, triangle, driving limit, feasible sanity)
- 9 new tests added to ScenarioBPlannerTests.swift
- All tests follow TDD pattern (RED → GREEN → REFACTOR)
- Each feature produces 2-3 commits (test, feat, optional refactor)
- No test assertions weakened
- All existing tests continue to pass
- Tests use existing helper patterns (makeStadium, makeGame, makeRequest)