trails/openspec/changes/archive/2026-07-16-fit-parsing-hardening/tasks.md
Ullrich Schäfer 0e04c48225
chore(openspec): archive fit-parsing-hardening
Sync the wahoo-import "FIT to GPX conversion" requirement into the main
spec and move the completed change to
openspec/changes/archive/2026-07-16-fit-parsing-hardening.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 00:09:27 +02:00

1.6 KiB

1. Fixtures first

  • 1.1 Collect fixture FIT files — adapted: per the chosen approach, cases are driven by mocked fit-file-parser output in fit.test.ts (pause, multisession, indoor no-GPS, corrupt coords/missing-timestamp) rather than binary files. Real device binaries can be added later without changing the converter.
  • 1.2 Parser events/sessions shapes captured as the FitEvent/FitSession types + code comments in fit.ts, and exercised by the mocked-parser tests.

2. Converter

  • 2.1 Segmentation: split on timer stop/start event pairs, fallback on record gaps > 5 min (named constants)
  • 2.2 Session slicing: records windowed per session, one-or-more segments per session, single-session unchanged
  • 2.3 Validation gates: finite/in-range coordinates, timestamp required, non-finite altitude → undefined; prefer enhanced_altitude (speed isn't emitted to GPX so its preference is moot)
  • 2.4 Return { gpx, sport } with the FIT→SportType mapping table; update call sites (Wahoo importer + webhook, Garmin importer) — provider-explicit type wins, FIT sport is fallback
  • 2.5 Unit tests over the fixtures: segment counts (pause becomes a segment boundary, which is what keeps moving time honest), corrupt-record drops, enhanced-altitude preference, sport mapping, no-GPS returns null gpx

3. Verification

  • 3.1 Re-run the Wahoo importer test suite; confirm existing single-session imports produce identical stats (14 pass; mock updated to the {gpx, sport} shape)
  • 3.2 Run pnpm typecheck && pnpm lint && pnpm test — all green