- Add 02-02-SUMMARY.md documenting pipeline regeneration
- Update STATE.md: Phase 2 complete, next is Phase 2.1
- Update ROADMAP.md: Mark Phase 2 as complete (2/2 plans)
- Performance: 5 plans, 37 min total, 7.4 min average
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Filter bundled JSON to core 4 sports only (152 → 122 stadiums)
- Exclude MLS stadiums (incomplete data, deferred to Phase 2.1)
- Filter aliases to match (200 → 165 aliases)
- All fields populated: no empty state, zero capacity, or null year
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Ran scrape_schedules.py --stadiums-update
- Ran canonicalize_stadiums.py for canonical IDs
- Core sports: MLB:30, NBA:30, NHL:32, NFL:30 (122 total)
- MLS stadiums also included from comprehensive scrape (30)
- Stadium aliases generated for historical name mappings
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added year_opened field to stadium data across all 4 sport modules:
- MLB: 30 ballparks (1912-2023)
- NBA: 30 arenas (1968-2024)
- NHL: 32 arenas (1968-2021)
- NFL: 30 stadiums (1924-2020)
Updated Stadium object creation in all modules to pass year_opened.
Stadium dataclass already supported the field.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 2: Stadium Foundation
- 2 plans created
- 5 total tasks defined
- Ready for execution
Plan 02-01: Audit & complete hardcoded stadium data
Plan 02-02: Regenerate canonical data and verify pipeline
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create 01-03-SUMMARY.md documenting NFL module and orchestrator refactor
- Update STATE.md: Phase 1 complete, ready for Phase 2
- Update ROADMAP.md: Mark Phase 1 as complete (3/3 plans)
- Phase 1 total duration: 23 min across 3 plans
Phase 1: Script Architecture complete. All 4 core sports (MLB, NBA, NHL, NFL)
now have dedicated modules with consistent patterns.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Extract NFL scrapers from monolithic scrape_schedules.py into dedicated
sport module following established pattern from nba.py/nhl.py:
- NFL_TEAMS: 32 teams with stadiums
- Game scrapers: ESPN API, Pro-Football-Reference, CBS Sports
- Stadium scrapers: ScoreBot, GeoJSON gist, hardcoded fallback
- NFL_GAME_SOURCES and NFL_STADIUM_SOURCES configurations
- get_nfl_season_string() for cross-calendar-year format (2025-26)
- scrape_nfl_games() convenience function with fallback
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- MLB_TEAMS dictionary with all 30 teams
- Game scrapers: Baseball-Reference, MLB Stats API, ESPN
- Stadium scrapers: MLBScoreBot, GeoJSON, hardcoded fallback
- MLB_GAME_SOURCES and MLB_STADIUM_SOURCES configurations
- scrape_mlb_games() convenience function
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fix data quality issues across MLB, NBA, NHL, NFL with correct game→team→stadium canonical linking.
Creates PROJECT.md with requirements and constraints.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add RegionMapSelector UI for geographic trip filtering (East/Central/West)
- Add RouteFilters module for allowRepeatCities preference
- Improve GameDAGRouter to preserve route length diversity
- Routes now grouped by city count before scoring
- Ensures 2-city trips appear alongside longer trips
- Increased beam width and max options for better coverage
- Add TripOptionsView filters (max cities slider, pace filter)
- Remove TravelStyle section from trip creation (replaced by region selector)
- Clean up debug logging from DataProvider and ScenarioAPlanner
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix same-day different-city validation in C2C routes (no more impossible
games like Detroit 7:30pm AND Milwaukee 8pm on the same day)
- Cap C2C trips at 14 days max with 3 middle stops, prefer shortest routes
- Add sport icon and name to game rows in trip itinerary
- Add horizontal scroll to route dots in suggested trip cards
- Allow swipe-to-dismiss on home sheet (trip planner still blocks)
- Generate travel segments for suggested trips
- Increase DAG route lookahead to 5 days for multi-day drives
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add local canonicalization pipeline (stadiums, teams, games) that generates
deterministic canonical IDs before CloudKit upload
- Fix CanonicalSyncService to use deterministic UUIDs from canonical IDs
instead of random UUIDs from CloudKit records
- Add SyncStadium/SyncTeam/SyncGame types to CloudKitService that preserve
canonical ID relationships during sync
- Add canonical ID field keys to CKModels for reading from CloudKit records
- Bundle canonical JSON files (stadiums_canonical, teams_canonical,
games_canonical, stadium_aliases) for consistent bootstrap data
- Update BootstrapService to prefer canonical format files over legacy format
This ensures all entities use consistent deterministic UUIDs derived from
their canonical IDs, preventing duplicate records when syncing CloudKit
data with bootstrapped local data.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add CKStadiumAlias model for CloudKit record mapping
- Add fetchStadiumAliases/fetchStadiumAliasChanges to CloudKitService
- Add syncStadiumAliases to CanonicalSyncService for delta sync
- Add subscribeToStadiumAliasUpdates for push notifications
- Update cloudkit_import.py with --stadium-aliases-only option
Data Architecture Updates:
- Remove obsolete provider files (CanonicalDataProvider, CloudKitDataProvider, StubDataProvider)
- AppDataProvider now reads exclusively from SwiftData
- Add background CloudKit sync on app startup (non-blocking)
- Document data architecture in CLAUDE.md
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add autocomplete suggestions for Home/Away team fields filtered by selected sport
- Apply themed background to StadiumVisitSheet and StadiumPickerSheet
- Add listRowBackground for consistent card styling in Form sections
- Fix data observation with @ObservedObject for AppDataProvider
- Clear team names when sport selection changes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Stadium Progress & Achievements:
- Add StadiumVisit and Achievement SwiftData models
- Create Progress tab with interactive map view
- Implement photo-based visit import with GPS/date matching
- Add achievement badges (count-based, regional, journey)
- Create shareable progress cards for social media
- Add canonical data infrastructure (stadium identities, team aliases)
- Implement score resolution from free APIs (MLB, NBA, NHL stats)
UI Improvements:
- Add ThemedSpinner and ThemedSpinnerCompact components
- Replace all ProgressView() with themed spinners throughout app
- Fix sport selection state not persisting when navigating away
Bug Fixes:
- Fix Coast to Coast trips showing only 1 city (validation issue)
- Fix stadium progress showing 0/0 (filtering issue)
- Remove "Stadium Quest" title from progress view
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Document Export layer (PDFGenerator, asset services)
- Add iOS 26 API notes (deprecated CLGeocoder, Swift 6 patterns)
- Add Documentation section pointing to docs/
- Expand Future Phases with market research findings (bucket list, group coordination, fan community)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Competitive analysis and feature recommendations for sports road trip planning,
including stadium bucket list tracking, AI planning, and group coordination.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove all print statements from planning engine, data providers, and PDF generation
- Fix deprecated CLGeocoder usage with MKLocalSearch for iOS 26
- Fix Swift 6 actor isolation by converting PDFGenerator/ExportService to @MainActor
- Add @retroactive to CLLocationCoordinate2D protocol conformances
- Fix unused variable warnings in GameDAGRouter and scenario planners
- Remove unreachable catch blocks in SettingsViewModel
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add MapSnapshotService for route maps and city maps using MKMapSnapshotter
- Add RemoteImageService for team logos and stadium photos with caching
- Add POISearchService for nearby attractions using MKLocalSearch
- Add PDFAssetPrefetcher to orchestrate parallel asset fetching
- Rewrite PDFGenerator with rich page layouts: cover, route overview,
day-by-day itinerary, city spotlights, and summary pages
- Add export progress overlay in TripDetailView with animated progress ring
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create EVChargingService using MapKit POI search for EV chargers
- Add ItineraryBuilder.enrichWithEVChargers() for post-planning enrichment
- Update TravelSection in TripDetailView with expandable charger list
- Add FeatureFlags.enableEVCharging toggle (default: false)
- Include EVChargingFeature.md documenting API overhead
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add themed background to all tab views (Schedule, Settings, My Trips)
- Remove navigation titles from all screens (tab bar provides context)
- Add empty state to My Trips view
- Remove max driving hours slider from trip planner (available in Settings)
- Replace save menu with heart button overlay on trip detail map
- Add ability to unsave trips by tapping heart again
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Generate 8 suggested trips on app launch (2 per region: East, Central, West, Cross-Country)
- Each region has single-sport and multi-sport trip options
- Region classification based on stadium longitude
- Animated loading state with shimmer placeholders
- Loading messages use Foundation Models when available, fallback otherwise
- Tap card to view trip details in sheet
- Refresh button to regenerate trips
- Fixed-height cards with aligned top/bottom layout
New files:
- Region.swift: Geographic region enum with longitude classification
- LoadingTextGenerator.swift: On-device AI loading messages
- SuggestedTripsGenerator.swift: Trip generation service
- SuggestedTripCard.swift: Carousel card component
- LoadingTripsView.swift: Animated loading state
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add initialSport parameter to TripCreationView
- Set selected sport when quick start button is tapped
- Auto-select that sport in trip planning view on appear
- Clear selection when sheet is dismissed
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Teal: Cool cyan and teal tones (default)
- Orbit: Bold navy and orange
- Retro: Classic columbia blue
- Clutch: Championship red and gold
- Monochrome: Clean grayscale aesthetic
- Sunset: Warm oranges and purples
- Midnight: Deep blues and gold
Features:
- Theme selection persisted via UserDefaults
- ThemeManager singleton for app-wide theme state
- All Theme colors now dynamically switch based on selection
- Settings UI shows color preview circles for each theme
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
TripOptionCard improvements:
- Replace horizontal route with vertical layout (start → end with arrow)
- Remove rank badges (1, 2, 3, etc.)
- Split stats into two rows: cities/miles and sports with game counts
- Clear selection when navigating back from detail view
Settings cleanup:
- Remove unused settings (preferred game time, playoff games, notifications)
- Convert remaining settings to sliders
Planning fixes:
- Fix multi-day driving calculation in canTransition
- Remove over-restrictive trip rejection in TravelEstimator
- Clear games cache when sport selection changes
UI polish:
- RoutePreviewStrip shows all cities (abbreviated)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Travel segment architecture:
- Remove departureTime/arrivalTime from TravelSegment (location-based, not date-based)
- Fix travel sections appearing after destination instead of between cities
- Fix missing travel segments when revisiting same city (consecutive grouping)
- Remove unwanted rest day at end of trip
Planning engine fixes:
- All three planners now group only consecutive games at same stadium
- Visiting A → B → A creates 3 stops with proper travel between
UI simplification:
- Remove redundant sort options (mostDriving/leastDriving, mostCities/leastCities)
- Remove unused "Find Other Sports Along Route" toggle (was dead code)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Theme:
- New teal/cyan/mint/pink/gold color palette replacing orange/cream
- Added Theme.swift, ViewModifiers.swift, AnimatedComponents.swift
Trip Creation:
- Removed Drive/Fly toggle (drive-only for now)
- Removed Lodging Type picker
- Renamed "Number of Stops" to "Number of Cities" with explanation
- Added explanation for "Find Other Sports Along Route"
- Removed staggered animation from trip options list
Bug Fix:
- Disabled AI route description generation (Foundation Models crashes
in iOS 26.2 Simulator due to NLLanguageRecognizer assertion failure)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Days are now headers with games as rows in that section
- Travel between days shown in standalone "Travel" sections
- Travel timing is flexible (user decides when to drive)
- Removed complex ItineraryDay bundling approach
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Replace O(2^n) GeographicRouteExplorer with O(n) GameDAGRouter using DAG + beam search
- Add geographic diversity to route selection (returns routes from distinct regions)
- Add trip options selector UI (TripOptionsView, TripOptionCard) to choose between routes
- Simplify itinerary display: separate games and travel segments by date
- Remove complex ItineraryDay bundling, query games/travel directly per day
- Update ScenarioA/B/C planners to use GameDAGRouter
- Add new test suites for planners and travel estimator
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Three-scenario planning engine (A: date range, B: selected games, C: directional routes)
- GeographicRouteExplorer with anchor game support for route exploration
- Shared ItineraryBuilder for travel segment calculation
- TravelEstimator for driving time/distance estimation
- SwiftUI views for trip creation and detail display
- CloudKit integration for schedule data
- Python scraping scripts for sports schedules
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>