373 Commits

Author SHA1 Message Date
Trey t
21c647d37e Merge branch 'main' of gitea.treytartt.com:admin/Sportstime 2026-04-16 14:34:48 -05:00
Trey t
a77a93b92d update profiles 2026-04-16 14:32:12 -05:00
Trey T
a6f538dfed Audit and fix 52 test correctness issues across 22 files
Systematic audit of 1,191 tests found tests written to pass rather than
verify correctness. Key fixes:

Infrastructure:
- TestClock: fixed timezone from .current to America/New_York (deterministic)
- TestFixtures: added 1.3x road routing factor to match production
- ItineraryTestHelpers: real per-city coordinates instead of hardcoded (40,-80)

Planning tests:
- Added missing Scenario E factory dispatch tests
- Tightened 12 loose assertions (>= 1 → == 8.0, > 0 → range checks)
- Fixed 4 no-op tests that accepted both success and failure
- Fixed wrong repeat-city invariant (was checking same-day, not different-day)
- Fixed tautological assertion in missing-stadium edge case

Services/Domain/Export tests:
- Replaced 4 placeholder tests (#expect(true)) with real assertions
- Fixed tautological assertions in POISearchServiceTests
- Fixed Chicago coordinate in RegionMapSelectorTests (-89 → -87.6553)
- Added sort order verification to ItineraryRowFlatteningTests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 23:00:46 -05:00
Trey T
9b622f8bbb Harden planning test suite with realistic fixtures and output sanity checks
Adds messy/realistic data factories to TestFixtures, new PlannerOutputSanityTests,
and updates all scenario planner tests with improved coverage and assertions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 13:38:41 -05:00
Trey t
188076717b Fix team-first future window selection 2026-04-03 15:31:52 -05:00
Trey t
0fa3db5401 Harden test harness and UI suite 2026-04-03 15:30:54 -05:00
Trey T
87b9971714 Fix FoundationModels crash, driving constraint, and disable card descriptions
- RouteDescriptionGenerator: reuse session, cap tokens at 60, greedy
  sampling, prewarm with prompt prefix, serial request queue with
  rate-limit retry and circuit breaker
- Disable AI/template descriptions on trip option cards
- GameDAGRouter: fix off-by-one in canTransition driving constraint
  (daysBetween+1) so multi-day cross-city routes aren't rejected
- CanonicalSyncService: wrap SyncStatusMonitor in #if DEBUG

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 12:42:21 -05:00
Trey T
aa6477b886 Fix launch crash — add production PostHog API key for Release builds
Replaces fatalError with hardcoded production key so analytics
initializes correctly in TestFlight/App Store builds.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 11:18:49 -05:00
Trey T
65fbb596a8 Fix Release build for App Store deployment — manual signing and #if DEBUG guard
- Switch Release config to manual signing (Apple Distribution, SportsTime Dist profile)
- Wrap SyncStatusMonitor.syncFailed call in #if DEBUG to fix Release compilation
- Add deploy instructions to CLAUDE.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 10:33:28 -05:00
akatreyt
741924f6fc Merge pull request #7 from akatreyt/improvement-plan/all-phases 2026-03-21 09:53:56 -05:00
Trey T
6cbcef47ae Add implementation code for all 4 improvement plan phases
Production changes:
- TravelEstimator: remove 300mi fallback, return nil on missing coords
- TripPlanningEngine: add warnings array, empty sports warning, inverted
  date range rejection, must-stop filter, segment validation gate
- GameDAGRouter: add routePreference parameter with preference-aware
  bucket ordering and sorting in selectDiverseRoutes()
- ScenarioA-E: pass routePreference through to GameDAGRouter
- ScenarioA: track games with missing stadium data
- ScenarioE: add region filtering for home games
- TravelSegment: add requiresOvernightStop and travelDays() helpers

Test changes:
- GameDAGRouterTests: +252 lines for route preference verification
- TripPlanningEngineTests: +153 lines for segment validation, date range,
  empty sports
- ScenarioEPlannerTests: +119 lines for region filter tests
- TravelEstimatorTests: remove obsolete fallback distance tests
- ItineraryBuilderTests: update nil-coords test expectation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 09:40:32 -05:00
Trey T
db6ab2f923 Implement 4-phase improvement plan with TDD verification + travel integrity tests
- Phase 1: Verify broken filter fixes (route preference, region filtering,
  must-stop, segment validation) — all already implemented, 8 TDD tests added
- Phase 2: Verify guard rails (no fallback distance, same-stadium gap,
  overnight rest, exclusion warnings) — all implemented, 12 TDD tests added
- Phase 3: Fix 2 timezone edge case tests (use fixed ET calendar), verify
  driving constraints, filter cascades, anchors, interactions — 5 tests added
- Phase 4: Add sortByRoutePreference() for post-planning re-sort, verify
  inverted date range rejection, empty sports warning, region boundaries — 8 tests
- Travel Integrity: 32 tests verifying N stops → N-1 segments invariant
  across all 5 scenario planners, ItineraryBuilder, isValid, and engine gate

New: sortByRoutePreference() on ItineraryOption (Direct/Scenic/Balanced)
Fixed: TimezoneEdgeCaseTests now timezone-independent

1199 tests, 0 failures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 09:37:19 -05:00
Trey t
ce734b6c63 fix: revert gameDate to local timezone and update DAG router test timing
The hardening pass incorrectly changed Game.gameDate to use UTC, which
broke timezone-dependent departure date calculations in ScenarioDPlanner.
Also widened the DAG router test's same-day game gap to account for the
new 3-hour game duration in canTransition.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 18:59:54 -06:00
Trey t
c94e373e33 fix: comprehensive codebase hardening — crashes, silent failures, performance, and security
Fixes ~95 issues from deep audit across 12 categories in 82 files:

- Crash prevention: double-resume in PhotoMetadataExtractor, force unwraps in
  DateRangePicker, array bounds checks in polls/achievements, ProGate hit-test
  bypass, Dictionary(uniqueKeysWithValues:) → uniquingKeysWith in 4 files
- Silent failure elimination: all 34 try? sites replaced with do/try/catch +
  logging (SavedTrip, TripDetailView, CanonicalSyncService, BootstrapService,
  CanonicalModels, CKModels, SportsTimeApp, and more)
- Performance: cached DateFormatters (7 files), O(1) team lookups via
  AppDataProvider, achievement definition dictionary, AnimatedBackground
  consolidated from 19 Tasks to 1, task cancellation in SharePreviewView
- Concurrency: UIKit drawing → MainActor.run, background fetch timeout guard,
  @MainActor on ThemeManager/AppearanceManager, SyncLogger read/write race fix
- Planning engine: game end time in travel feasibility, state-aware city
  normalization, exact city matching, DrivingConstraints parameter propagation
- IAP: unknown subscription states → expired, unverified transaction logging,
  entitlements updated before paywall dismiss, restore visible to all users
- Security: API key to Info.plist lookup, filename sanitization in PDF export,
  honest User-Agent, removed stale "Feels" analytics super properties
- Navigation: consolidated competing navigationDestination, boolean → value-based
- Testing: 8 sleep() → waitForExistence, duplicates extracted, Swift 6 compat
- Service bugs: infinite retry cap, duplicate achievement prevention, TOCTOU vote
  fix, PollVote.odg → voterId rename, deterministic placeholder IDs, parallel
  MKDirections, Sendable-safe POI struct

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 17:03:09 -06:00
Trey t
e046cb6b34 Fix custom item edit refresh and stabilize F069 UI test 2026-02-22 22:11:01 -06:00
Trey t
ec2bbb4764 Stabilize beta release with warning cleanup and edge-case fixes 2026-02-22 13:18:14 -06:00
Trey t
fddea81e36 fix: add contentShape to team picker rows for full-row tap targets
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 00:43:44 -06:00
Trey t
91c5eac22d fix: codebase audit fixes — safety, accessibility, and production hygiene
Address 16 issues from external audit:
- Move StoreKit transaction listener ownership to StoreManager singleton with proper deinit
- Remove noisy VoiceOver announcements, add missing accessibility on StatPill and BootstrapLoadingView
- Replace String @retroactive Identifiable with IdentifiableShareCode wrapper
- Add crash guard in AchievementEngine getContributingVisitIds + cache stadium lookups
- Pre-compute GamesHistoryViewModel filtered properties to avoid redundant SwiftUI recomputation
- Remove force-unwraps in ProgressMapView with safe guard-let fallback
- Add diff-based update gating in ItineraryTableViewWrapper to prevent unnecessary reloads
- Replace deprecated UIScreen.main with UIWindowScene lookup
- Add deinit task cancellation in ScheduleViewModel and SuggestedTripsGenerator
- Wrap ~234 unguarded print() calls across 27 files in #if DEBUG

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 00:07:53 -06:00
Trey t
826eadbc0f fix: ScenarioCPlanner endpoint merging and game validation
Eliminate redundant 0-mile travel segments when start/end city matches
the first/last game stop city, and fail early when no games exist at
endpoint cities within the selected date range.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 22:40:06 -06:00
Trey t
242634e03c Merge branch 'main' of github.com:akatreyt/sportstime 2026-02-21 20:45:32 -06:00
akatreyt
e948723c00 Merge pull request #6 from akatreyt/fix/issue-3 2026-02-21 18:06:04 -06:00
akatreyt
5689306895 Merge pull request #5 from akatreyt/fix/issue-2 2026-02-21 18:05:51 -06:00
akatreyt
9b7ac7d934 Merge pull request #4 from akatreyt/fix/issue-1 2026-02-21 18:05:39 -06:00
treyt
d98acd6a9a fix: resolve issue #3 - Iap coupon
Automated fix by Tony CI v3.
Closes #3

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-21 18:03:09 -06:00
treyt
ad3febf69b fix: resolve issue #2 - By router planning
Automated fix by Tony CI.
Closes #2

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-21 01:41:17 -06:00
Trey t
a4e9327b18 fix: restrict By Route wizard to stadium cities and filter sports by selected cities
LocationSearchSheet now shows only stadium cities (with sport badges) when
selecting start/end locations, preventing users from picking cities with no
stadiums. TripWizardViewModel filters available sports to the union of sports
at the selected cities, and clears invalid selections when locations change.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 22:47:46 -06:00
treyt
2a3fc8d5d7 fix: resolve issue #1 - Follow teams
Automated fix by Tony CI.
Closes #1

Co-Authored-By: Claude <noreply@anthropic.com>
2026-02-20 21:38:13 -06:00
Trey t
b062ced000 fix: improve text contrast for badges, category chips, and separators
- Change attraction category color from .yellow to orange variant for
  readable text in both light and dark mode (QuickAddItemSheet, POIDetailSheet)
- Fix "optional" badge to use textPrimary-based colors for strong contrast
- Bump paywall dashed separator from 0.4 to 0.6 opacity
- Fix SuggestedTripCard bullet separator from textMuted(0.5) to textSecondary

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 14:26:21 -06:00
Trey t
c52b70089e fix: move paywall sheet to stable scope and fix map button positions
Move .sheet(isPresented: $showPaywall) from subscription section to
top-level body so StoreManager state changes don't dismiss the sheet.
Reposition heart (16pt top/trailing) and map (16pt bottom/trailing,
above gradient) buttons on trip detail map.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 14:05:37 -06:00
Trey t
d1429071f6 redesign PaywallView with premium header, feature grid, and ticket separator
Replace the generic paywall header with a branded "SportsTime Pro / Your All-Access Pass"
hero section, 4 uniform feature cards (GeometryReader-sized squares), and a dashed ticket
perforation separator. Add "Show Paywall" debug button in Settings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 13:51:38 -06:00
Trey t
e2d449046b fix: add contentShape to all tappable rows so entire row area registers taps
Adds .contentShape(Rectangle()) or .contentShape(Capsule()) to 11 buttons,
NavigationLinks, and onTapGesture handlers across 8 files where only the
visible content (text/icons) was receiving taps instead of the full row.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 13:30:41 -06:00
Trey t
1b05f0ebaf fix: hide Creative Tools in release builds and improve Add Item keyboard behavior
Gate Icon Generator section behind #if DEBUG and group it with other debug
sections at the bottom of Settings. Remove auto-focus on description field,
dismiss keyboard on return key and on scroll.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 13:23:38 -06:00
Trey t
6aaa3dc073 Add F-082, F-099 UI tests and mark remaining tests RED in QA plan
Final batch: F-082 (create poll with 2+ saved trips) and F-099 (progress
percentage updates after stadium visit). Also marks 9 more impossible tests
RED (F-016, F-039, F-048, F-050, F-107, F-108, F-111, F-129, F-130).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 01:46:08 -06:00
Trey t
e6584d443d Add F-045, F-056, F-057 UI tests for planning errors and trip option filters
- F-045: Planning with conflicting constraints handles gracefully
- F-056: Pace filter (Packed/Moderate/Relaxed) selects correctly
- F-057: Cities filter limits trip results

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 01:28:05 -06:00
Trey t
4e6d8ff37f Add F-037, F-038, F-091 UI tests; mark F-016 red (no accessibility ID)
- F-037: Route preference cards (Direct/Scenic/Balanced) selectable
- F-038: Allow repeat cities toggle buttons work
- F-091: Date range filter sheet opens and applies correctly
- F-016: Marked RED - featured trip card buttons lack accessibility IDs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 01:16:25 -06:00
Trey t
ab1d7bc6b6 Add F-015, F-076, F-094 UI tests for home refresh, trip detail, diagnostics
- F-015: Featured trips refresh button works without crash
- F-076: Trip detail loads correctly with single-stop trip
- F-094: Schedule diagnostics sheet opens from filter menu

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 01:03:12 -06:00
Trey t
56c17e79a4 Mark 45 impossible/unreliable UI tests RED in QA test plan
Tests that require network control, StoreKit sandbox, CloudKit
operations, photo permissions, visual verification, or missing
accessibility IDs are marked RED as not automatable via XCUITest.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:55:09 -06:00
Trey t
4cb8d89fbd Add F-084, F-133, F-134 UI tests; mark F-131, F-132 red (toggle unreliable)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:52:07 -06:00
Trey t
be72367fb1 Add F-040, F-081, F-083 UI tests for review step and polls section
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:37:34 -06:00
Trey t
54be5cae3e Add F-030, F-031, F-032 UI tests for calendar date edge cases
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:30:48 -06:00
Trey t
61fd7f5209 Add F-041, F-047, F-051 UI tests for wizard and trip options
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:25:50 -06:00
Trey t
378f65f82c Add F-058, F-059, F-090 UI tests for trip options and schedule search
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:19:28 -06:00
Trey t
0f0e534214 Add F-018, F-060, F-062 UI tests and update QA test plan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:06:38 -06:00
Trey t
2d759274a8 Add F-068, F-069, F-070 UI tests for custom itinerary item lifecycle
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 23:49:29 -06:00
Trey t
8421b23f0c Add F-100, F-101, F-106 UI tests and page objects for Progress feature
Adds 3 new UI tests covering stadium visit manual entry, required field
validation, and games history navigation. Includes accessibility IDs on
StadiumVisitSheet/ProgressTabView and new page objects (StadiumVisitSheetScreen,
GamesHistoryScreen) in the test framework.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 23:02:52 -06:00
Trey t
f10bc4fe59 fix: crash on launch from BGTask handler @MainActor isolation violation
BGTaskScheduler.register(using: nil) invokes the handler on a background
queue, but the closure captured @MainActor-isolated self. Swift 6 runtime
enforces this with dispatch_assert_queue which crashed on Thread 4.

Fix: pass DispatchQueue.main as the handler queue so the callback runs
on the main queue, satisfying @MainActor isolation. Also fix expiration
handlers to capture a local Logger copy instead of accessing self.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 17:41:33 -06:00
Trey t
c976ae5cb3 Add POI category filters, delete item button, and fix itinerary persistence
- Expand POI categories from 5 to 7 (restaurant, bar, coffee, hotel, parking, attraction, entertainment)
- Add category filter chips with per-category API calls and caching
- Add delete button with confirmation dialog to Edit Item sheet
- Fix itinerary items not persisting: use LocalItineraryItem (SwiftData) as primary store with CloudKit sync as secondary, register model in schema

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 16:04:53 -06:00
Trey t
999b5a1190 Fix game times with UTC data, restructure schedule by date
- Update games_canonical.json to use ISO 8601 UTC timestamps (game_datetime_utc)
- Fix BootstrapService timezone-aware parsing for venue-local fallback
- Fix thread-unsafe shared DateFormatter in RichGame local time display
- Bump SchemaVersion to 4 to force re-bootstrap with correct UTC data
- Restructure schedule view: group by date instead of sport, with sport
  icons on each row and date section headers showing game counts
- Fix schedule row backgrounds using Theme.cardBackground instead of black
- Sort games by UTC time with local-time tiebreaker for same-instant games

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 11:43:39 -06:00
Trey t
e6c4b8e12b Add nearby POIs to Add-to-Day sheet and improve PlaceSearchSheet empty state
- Add mapItem field to POISearchService.POI for Apple Maps integration
- Merge description + location into single combined card in QuickAddItemSheet
- Auto-load nearby POIs when regionCoordinate is available, with detail sheet
- Create POIDetailSheet with map preview, metadata, and one-tap add-to-day
- Add poiAddedToDay/poiDetailViewed analytics events
- Add initial state to PlaceSearchSheet with search suggestions and flow layout

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 10:45:36 -06:00
Trey t
e7420061a5 fix: 22 audit fixes — concurrency, memory, performance, accessibility
- Move 7 Data(contentsOf:) calls off MainActor via Task.detached (BootstrapService)
- Batch-fetch N+1 queries in sync merge loops (CanonicalSyncService)
- Predicate-based gamesForTeam fetch instead of fetching all games (DataProvider)
- Proper Sendable on RouteInfo with nonisolated(unsafe) polyline (LocationService)
- [weak self] in BGTaskScheduler register closures (BackgroundSyncManager)
- Cache tripDays, routeWaypoints as @State with recompute (TripDetailView)
- Remove unused AnyCancellable, add Task lifecycle management (TripDetailView)
- Cache sportStadiums, recentVisits as stored properties (ProgressViewModel)
- Dynamic Type fonts replacing hardcoded sizes (OnboardingPaywallView)
- Accessibility labels/hints on stadium picker, date picker, map, stats,
  settings toggle, and day cards

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 09:23:29 -06:00