docs(03): create phase 3 visual flattening plans
Phase 03: Visual Flattening - 2 plans in 2 waves - Plan 01: Create ItineraryFlattener utility, refactor reloadData() - Plan 02: Add determinism tests for flattening behavior - Ready for execution Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
183
.planning/phases/03-visual-flattening/03-02-PLAN.md
Normal file
183
.planning/phases/03-visual-flattening/03-02-PLAN.md
Normal file
@@ -0,0 +1,183 @@
|
||||
---
|
||||
phase: 03-visual-flattening
|
||||
plan: 02
|
||||
type: execute
|
||||
wave: 2
|
||||
depends_on: ["03-01"]
|
||||
files_modified:
|
||||
- SportsTimeTests/ItineraryFlattenerTests.swift
|
||||
autonomous: true
|
||||
|
||||
must_haves:
|
||||
truths:
|
||||
- "Same semantic state produces identical row order on repeated flattening"
|
||||
- "Item with sortOrder -1.0 appears before all games in that day"
|
||||
- "Reordering an item and re-flattening preserves the new order"
|
||||
artifacts:
|
||||
- path: "SportsTimeTests/ItineraryFlattenerTests.swift"
|
||||
provides: "Determinism and ordering tests"
|
||||
min_lines: 80
|
||||
key_links:
|
||||
- from: "ItineraryFlattenerTests"
|
||||
to: "ItineraryFlattener.flatten()"
|
||||
via: "test assertions"
|
||||
pattern: "ItineraryFlattener\\.flatten"
|
||||
---
|
||||
|
||||
<objective>
|
||||
Add tests verifying ItineraryFlattener produces deterministic, sortOrder-based output.
|
||||
|
||||
Purpose: Ensure the three success criteria from ROADMAP.md are verifiable through automated tests.
|
||||
|
||||
Output: New test file `ItineraryFlattenerTests.swift` with tests covering all success criteria.
|
||||
</objective>
|
||||
|
||||
<execution_context>
|
||||
@~/.claude/get-shit-done/workflows/execute-plan.md
|
||||
@~/.claude/get-shit-done/templates/summary.md
|
||||
</execution_context>
|
||||
|
||||
<context>
|
||||
@.planning/PROJECT.md
|
||||
@.planning/ROADMAP.md
|
||||
@.planning/STATE.md
|
||||
@.planning/phases/03-visual-flattening/03-RESEARCH.md
|
||||
@.planning/phases/03-visual-flattening/03-01-SUMMARY.md
|
||||
@SportsTime/Core/Models/Domain/ItineraryFlattener.swift
|
||||
@SportsTime/Core/Models/Domain/SortOrderProvider.swift
|
||||
@SportsTimeTests/ItineraryConstraintsTests.swift
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Create ItineraryFlattenerTests with determinism tests</name>
|
||||
<files>SportsTimeTests/ItineraryFlattenerTests.swift</files>
|
||||
<action>
|
||||
Create a new test file `ItineraryFlattenerTests.swift` using Swift Testing (`@Suite`, `@Test`).
|
||||
|
||||
Test suite structure:
|
||||
```swift
|
||||
import Testing
|
||||
@testable import SportsTime
|
||||
|
||||
@Suite("ItineraryFlattener")
|
||||
struct ItineraryFlattenerTests {
|
||||
// Test helper to create mock ItineraryDayData
|
||||
// Test helper to create mock RichGame
|
||||
// Test helper to create mock ItineraryItem
|
||||
}
|
||||
```
|
||||
|
||||
Required tests (map directly to ROADMAP success criteria):
|
||||
|
||||
1. **success_negativeSortOrderAppearsBeforeGames** (Success Criterion 1)
|
||||
- Create item with sortOrder = -1.0
|
||||
- Create games with sortOrder ~820 (noon game)
|
||||
- Flatten and verify custom item index < games index
|
||||
- Assert: "Item with sortOrder -1.0 appears before all games in that day's section"
|
||||
|
||||
2. **success_sameStateProducesIdenticalOrder** (Success Criterion 2)
|
||||
- Create fixed test data (2 days, games, travel, custom items)
|
||||
- Flatten twice
|
||||
- Compare resulting row IDs
|
||||
- Assert: arrays are identical (not just equal length)
|
||||
|
||||
3. **success_reorderPreservesNewOrder** (Success Criterion 3)
|
||||
- Create items with sortOrder 1.0, 2.0, 3.0
|
||||
- Simulate reorder: change item from 1.0 to 2.5
|
||||
- Flatten
|
||||
- Verify new order is [2.0, 2.5, 3.0] not [1.0, 2.0, 3.0]
|
||||
|
||||
Additional tests for comprehensive coverage:
|
||||
|
||||
4. **flatten_dayHeaderAlwaysFirst**
|
||||
- Verify first item for each day is `.dayHeader`
|
||||
|
||||
5. **flatten_sortsByDayThenSortOrder**
|
||||
- Items on day 1 appear before items on day 2
|
||||
- Within each day, items sorted by sortOrder
|
||||
|
||||
6. **flatten_gamesGetSortOrderFromTime**
|
||||
- Game at 8:00 PM (sortOrder ~1180) appears after item with sortOrder 500
|
||||
- Game at 1:00 PM (sortOrder ~880) appears before item with sortOrder 1000
|
||||
|
||||
7. **flatten_emptyDayHasOnlyHeader**
|
||||
- Day with no games, no items produces only `.dayHeader` row
|
||||
|
||||
8. **flatten_multipleGamesOnSameDay**
|
||||
- Day with 2 games: both included in single `.games` row
|
||||
- Custom items around games sort correctly
|
||||
|
||||
Test helpers needed:
|
||||
- `makeGame(id:, stadium:, dateTime:)` -> RichGame
|
||||
- `makeItem(day:, sortOrder:, kind:)` -> ItineraryItem
|
||||
- `makeDayData(dayNumber:, date:, games:, items:)` -> ItineraryDayData
|
||||
</action>
|
||||
<verify>
|
||||
Run tests: `xcodebuild -project SportsTime.xcodeproj -scheme SportsTime -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.2' -only-testing:SportsTimeTests/ItineraryFlattenerTests test 2>&1 | grep -E "(Test Suite|passed|failed|error:)"`
|
||||
</verify>
|
||||
<done>
|
||||
`ItineraryFlattenerTests.swift` exists with:
|
||||
- 3 success_* tests mapping to ROADMAP success criteria
|
||||
- 5+ additional tests for comprehensive coverage
|
||||
- All tests passing
|
||||
</done>
|
||||
</task>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 2: Verify existing behavior unchanged</name>
|
||||
<files>SportsTimeTests/ItineraryFlattenerTests.swift</files>
|
||||
<action>
|
||||
Add integration-style tests that verify the refactored flattening produces expected behavior for realistic trip data.
|
||||
|
||||
Additional tests:
|
||||
|
||||
1. **flatten_travelWithNegativeSortOrderAppearsBeforeGames**
|
||||
- Travel item with sortOrder = -5.0
|
||||
- Should appear before games in same day
|
||||
|
||||
2. **flatten_travelWithPositiveSortOrderAppearsAfterGames**
|
||||
- Travel item with sortOrder = 1500.0 (after noon game)
|
||||
- Should appear after games in same day
|
||||
|
||||
3. **flatten_mixedItemTypes**
|
||||
- Day with: travel (-5), custom (-1), games (820), custom (900), travel (1500)
|
||||
- Verify exact order: header, travel, custom, games, custom, travel
|
||||
|
||||
4. **flatten_multiDayTrip**
|
||||
- 3-day trip with different item configurations per day
|
||||
- Verify each day's items are independent and sorted correctly
|
||||
|
||||
Run full test suite to ensure no regressions:
|
||||
`xcodebuild -project SportsTime.xcodeproj -scheme SportsTime -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.2' test`
|
||||
</action>
|
||||
<verify>
|
||||
Full test suite passes: `xcodebuild -project SportsTime.xcodeproj -scheme SportsTime -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.2' test 2>&1 | grep -E "(Test Suite|passed|failed)" | tail -10`
|
||||
</verify>
|
||||
<done>
|
||||
- All ItineraryFlattenerTests passing (12+ tests)
|
||||
- Full test suite passes (no regressions)
|
||||
- Tests cover all three ROADMAP success criteria
|
||||
</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
1. All tests in `ItineraryFlattenerTests.swift` pass
|
||||
2. Tests explicitly named `success_*` map to ROADMAP success criteria:
|
||||
- success_negativeSortOrderAppearsBeforeGames -> Criterion 1
|
||||
- success_sameStateProducesIdenticalOrder -> Criterion 2
|
||||
- success_reorderPreservesNewOrder -> Criterion 3
|
||||
3. Full test suite passes (no regressions from refactoring)
|
||||
</verification>
|
||||
|
||||
<success_criteria>
|
||||
- FLAT-02: Flattening is deterministic and stateless (verified by success_sameStateProducesIdenticalOrder test)
|
||||
- All three ROADMAP success criteria have corresponding tests
|
||||
</success_criteria>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/phases/03-visual-flattening/03-02-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user