trails/openspec/changes/gpx-parser-robustness/specs/gpx-parsing/spec.md
Ullrich Schäfer 5dd4968626 docs+openspec: prior-art research (Organic Maps, Endurain, wanderer) and 15 proposals
Add docs/inspirations.md as the durable record of the 2026-07-05/06
prior-art research — per-project learnings with source paths, canonical
credit lines, and the changes each spawned — and extend the
acknowledgment lists in philosophy.md/architecture.md (Organic Maps,
Endurain, wanderer).

New OpenSpec changes (proposal/design/specs/tasks each):
- Organic Maps: elevation-profile-hardening, gpx-parser-robustness,
  hiking-time-estimate, poi-index, hiking-foot-profile
- Endurain: account-export, activity-duplicate-review,
  fit-parsing-hardening, activity-locations, self-hosting-guide,
  activity-privacy-controls
- wanderer: federation-hardening, link-share-tokens
- credits-page (user-visible acknowledgments)

Updated in-flight changes with wanderer prior-art sections:
route-federation, route-discovery.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 07:23:00 +02:00

4.5 KiB

ADDED Requirements

Requirement: Invalid track points are skipped, not defaulted

The GPX parser SHALL skip track and route points whose lat or lon attribute is missing or does not parse to a finite number, and SHALL treat an unparseable <ele> value as absent elevation. Skipped or repaired points SHALL never surface as 0,0 coordinates or NaN values in parsed output, distance, or elevation totals. Segments left with fewer than two points after skipping SHALL be dropped.

Scenario: Point with missing coordinates is skipped

  • WHEN a track contains a trkpt without a lat attribute among otherwise valid points
  • THEN that point is absent from the parsed track and no 0,0 point appears

Scenario: Garbage coordinates do not poison stats

  • WHEN a trkpt has a non-numeric lat value
  • THEN the point is skipped and the computed distance and elevation totals are finite numbers

Scenario: Unparseable elevation treated as missing

  • WHEN a trkpt has <ele> content that does not parse to a finite number
  • THEN the point is kept with no elevation and gain/loss totals remain finite

Scenario: Degenerate segment dropped

  • WHEN a trkseg has only one valid point after skipping
  • THEN that segment does not appear in the parsed tracks

Requirement: Route elements parse as tracks

The GPX parser SHALL parse each <rte> element as a track segment, handling rtept identically to trkpt (including elevation, time, and invalid-point skipping), appended after any <trk> segments.

Scenario: Route-only GPX imports

  • WHEN a GPX file contains only a <rte> with valid rtept points and no <trk>
  • THEN the parsed data contains one track segment with those points
  • AND journal validation accepts the file

Scenario: Mixed tracks and routes

  • WHEN a GPX file contains both <trk> and <rte> elements
  • THEN all appear as track segments with track segments first

Requirement: Timestamp repair

The GPX parser SHALL repair point timestamps per segment: when more than half of a segment's timestamps are invalid, all timestamps in that segment SHALL be dropped; otherwise invalid timestamps SHALL be linearly interpolated between the nearest valid neighbors, with leading and trailing invalid runs set to the nearest valid timestamp. Repaired timestamps SHALL be valid ISO 8601 strings.

Scenario: Sparse invalid timestamps interpolated

  • WHEN a segment has a minority of unparseable <time> values between valid ones
  • THEN those points receive timestamps interpolated between the surrounding valid times

Scenario: Mostly-invalid timestamps dropped

  • WHEN more than half of a segment's <time> values are unparseable
  • THEN every point in that segment has no timestamp
  • AND moving time computation returns null for a track consisting only of such segments

Scenario: Leading invalid run clamps

  • WHEN the first points of a segment have invalid timestamps and later points are valid
  • THEN the leading points receive the first valid timestamp

Requirement: Metadata fallback from tracks and routes

The GPX parser SHALL fall back to the first track's or route's <name> and <desc> when <metadata> provides none, and SHALL merge a track-level <cmt> into the description (separated by a blank line) when it is present and differs from the description.

Scenario: Track name used when metadata absent

  • WHEN a GPX file has no <metadata><name> but its <trk> has a <name>
  • THEN the parsed name is the track's name

Scenario: Identical cmt not duplicated

  • WHEN a track's <cmt> equals its <desc>
  • THEN the description contains the text once

Requirement: Regression fixture corpus

The GPX package SHALL maintain a corpus of fixture GPX files exercising the repair policies (route-only, missing/garbage coordinates, unparseable elevation, partially and mostly invalid timestamps, multi-track/multi-segment, Unicode names, foreign-namespace extensions), and the parser test suite SHALL parse every fixture and assert the repaired output, so future parser changes cannot silently regress real-world compatibility.

Scenario: All fixtures parse under test

  • WHEN the parser test suite runs
  • THEN every fixture file is parsed and its expected repaired output is asserted

Scenario: Foreign namespaces ignored gracefully

  • WHEN a fixture contains extension elements from other apps' namespaces (e.g. Garmin, OsmAnd)
  • THEN parsing succeeds and trails-relevant data is extracted unchanged