Files
SportstimeAPI/.planning/phases/01-semantic-position-model/01-02-PLAN.md
Trey t a7d0e7f049 fix(01): revise plans based on checker feedback
- 01-01: Reframe must_haves.truths to user-observable behaviors
- 01-01: Remove unimplemented key_link (wiring happens in later phases)
- 01-02: Add test case for DATA-04 (custom items at any position)
- 01-02: Add must_haves.truths entry for custom item flexibility
- 01-02: Document LocalItineraryItem is standalone (no sibling models needed)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 13:47:12 -06:00

8.6 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, must_haves
phase plan type wave depends_on files_modified autonomous must_haves
01-semantic-position-model 02 execute 2
01-01
SportsTimeTests/SortOrderProviderTests.swift
SportsTimeTests/SemanticPositionPersistenceTests.swift
true
truths artifacts key_links
User can persist an item's position, reload, and find it in the same location
Moving travel segment to different day updates its day property
Inserting between two items gets sortOrder between their values (e.g., 1.0 and 2.0 -> 1.5)
Games remain fixed at their schedule-determined positions
Custom items can be placed at any sortOrder value (negative, zero, positive)
path provides min_lines
SportsTimeTests/SortOrderProviderTests.swift Unit tests for SortOrderProvider 80
path provides min_lines
SportsTimeTests/SemanticPositionPersistenceTests.swift Integration tests for position persistence 100
from to via pattern
SortOrderProviderTests SortOrderProvider Test imports and calls provider methods SortOrderProvider.
from to via pattern
SemanticPositionPersistenceTests LocalItineraryItem Creates and persists items via SwiftData LocalItineraryItem
Create comprehensive tests verifying the semantic position model works correctly.

Purpose: Prove that requirements DATA-01 through DATA-05 and PERS-01 through PERS-03 are satisfied. Tests must verify: sortOrder calculation correctness, midpoint insertion math, day derivation accuracy, and persistence survival across SwiftData reload.

Output: Two test files covering unit tests for SortOrderProvider and integration tests for persistence behavior.

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

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/01-semantic-position-model/01-RESEARCH.md @.planning/phases/01-semantic-position-model/01-01-SUMMARY.md

Source files

@SportsTime/Core/Models/Domain/SortOrderProvider.swift @SportsTime/Core/Models/Domain/ItineraryItem.swift @SportsTime/Core/Models/Local/SavedTrip.swift

Task 1: Create SortOrderProvider unit tests SportsTimeTests/SortOrderProviderTests.swift Create a new test file `SortOrderProviderTests.swift` with tests for all SortOrderProvider methods.

Test cases to include:

initialSortOrder tests:

  • test_initialSortOrder_midnight_returns100: 00:00 -> 100.0
  • test_initialSortOrder_noon_returns820: 12:00 -> 100 + 720 = 820.0
  • test_initialSortOrder_7pm_returns1240: 19:00 -> 100 + 1140 = 1240.0
  • test_initialSortOrder_1159pm_returns1539: 23:59 -> 100 + 1439 = 1539.0

sortOrderBetween tests:

  • test_sortOrderBetween_integers_returnsMidpoint: (1.0, 2.0) -> 1.5
  • test_sortOrderBetween_negativeAndPositive_returnsMidpoint: (-1.0, 1.0) -> 0.0
  • test_sortOrderBetween_fractionals_returnsMidpoint: (1.5, 1.75) -> 1.625

sortOrderBefore tests:

  • test_sortOrderBefore_positive_returnsLower: 1.0 -> 0.0
  • test_sortOrderBefore_negative_returnsLower: -1.0 -> -2.0

sortOrderAfter tests:

  • test_sortOrderAfter_positive_returnsHigher: 1.0 -> 2.0
  • test_sortOrderAfter_zero_returnsOne: 0.0 -> 1.0

needsNormalization tests:

  • test_needsNormalization_wellSpaced_returnsFalse: items with gaps > 1e-10
  • test_needsNormalization_tinyGap_returnsTrue: items with gap < 1e-10
  • test_needsNormalization_empty_returnsFalse: empty array
  • test_needsNormalization_singleItem_returnsFalse: one item

normalize tests:

  • test_normalize_reassignsIntegerSpacing: after normalize, sortOrders are 1.0, 2.0, 3.0...
  • test_normalize_preservesOrder: relative order unchanged after normalize

Use @testable import SportsTime at top. Tests compile and pass:

xcodebuild -project SportsTime.xcodeproj -scheme SportsTime -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.2' -only-testing:SportsTimeTests/SortOrderProviderTests test 2>&1 | grep -E "(Test Case|passed|failed)"
SortOrderProviderTests.swift exists with 16+ test cases, all tests pass Task 2: Create persistence integration tests SportsTimeTests/SemanticPositionPersistenceTests.swift Create a new test file `SemanticPositionPersistenceTests.swift` with integration tests for semantic position persistence.

These tests verify PERS-01, PERS-02, PERS-03, and DATA-04 requirements.

Test cases to include:

Position persistence (PERS-01):

  • test_itineraryItem_positionSurvivesEncodeDecode: Create ItineraryItem with specific day/sortOrder, encode to JSON, decode, verify day and sortOrder match exactly
  • test_localItineraryItem_positionSurvivesSwiftData: Create LocalItineraryItem, save to SwiftData ModelContext, fetch back, verify day and sortOrder match

Semantic-only state (PERS-02):

  • test_itineraryItem_allPositionPropertiesAreCodable: Verify ItineraryItem.day and .sortOrder are included in Codable output (not transient)

Midpoint insertion (PERS-03):

  • test_midpointInsertion_50Times_maintainsPrecision: Insert 50 times between adjacent items, verify all sortOrders are distinct
  • test_midpointInsertion_producesCorrectValue: Insert between sortOrder 1.0 and 2.0, verify result is 1.5

Day property updates (DATA-02, DATA-05):

  • test_travelItem_dayCanBeUpdated: Create travel item with day=1, update to day=3, verify day property changed
  • test_item_belongsToExactlyOneDay: Verify item.day is a single Int, not optional or array

Game immutability (DATA-03):

  • test_gameItem_sortOrderDerivedFromTime: Create game item for 7pm game, verify sortOrder is ~1240.0 (100 + 19*60)

Custom item flexibility (DATA-04):

  • test_customItem_canBePlacedAtAnyPosition: Create custom items with sortOrder values at negative (-5.0, before all games), between games (500.0), and after all games (2000.0). Verify all three persist correctly and can coexist on the same day sorted correctly.

Use in-memory SwiftData ModelContainer for tests. Note: LocalItineraryItem is standalone with no relationships - it can be registered alone:

let config = ModelConfiguration(isStoredInMemoryOnly: true)
let container = try ModelContainer(for: LocalItineraryItem.self, configurations: config)

Import XCTest, SwiftData, and @testable import SportsTime. Tests compile and pass:

xcodebuild -project SportsTime.xcodeproj -scheme SportsTime -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.2' -only-testing:SportsTimeTests/SemanticPositionPersistenceTests test 2>&1 | grep -E "(Test Case|passed|failed)"
SemanticPositionPersistenceTests.swift exists with 9+ test cases, all tests pass Task 3: Run full test suite to verify no regressions Run the complete test suite to verify: 1. All new tests pass 2. No existing tests broken by new code 3. Build and test cycle completes successfully

If any tests fail, investigate and fix before completing the plan.

xcodebuild -project SportsTime.xcodeproj -scheme SportsTime -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.2' test 2>&1 | tail -30

Look for "** TEST SUCCEEDED **" at the end. Full test suite passes with no failures, including all new and existing tests

1. SortOrderProviderTests.swift exists with 16+ test methods covering all SortOrderProvider functions 2. SemanticPositionPersistenceTests.swift exists with 9+ test methods covering persistence requirements 3. All tests pass when run individually and as part of full suite 4. Tests verify the success criteria from ROADMAP.md Phase 1: - Position survives reload (tested via encode/decode and SwiftData) - Travel day update works (tested via day property mutation) - Midpoint insertion works (tested via 50-iteration precision test) - Games use time-based sortOrder (tested via initialSortOrder) - Custom items can be placed anywhere (tested via negative/between/after positions)

<success_criteria>

  • 25+ new test cases across 2 test files
  • All tests pass
  • Tests directly verify Phase 1 requirements DATA-01 through DATA-05 and PERS-01 through PERS-03
  • No regression in existing tests </success_criteria>
After completion, create `.planning/phases/01-semantic-position-model/01-02-SUMMARY.md`