From 5fca8d8f185c99e9f20a81fd189c76b9bd66c6db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ullrich=20Sch=C3=A4fer?= Date: Tue, 14 Jul 2026 00:36:45 +0200 Subject: [PATCH] chore(openspec): archive gpx-parser-robustness MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All 16 tasks complete (shipped in #576/#578/#579). Archive via `openspec archive` (CLI 1.6.0): - Creates openspec/specs/gpx-parsing/spec.md — the new capability (5 requirements: invalid-point skipping, route support, timestamp repair, metadata fallback, fixture corpus). Purpose filled in (CLI leaves TBD). - Moves the change to openspec/changes/archive/2026-07-13-gpx-parser-robustness/. Spec passes `openspec validate --strict`. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../.openspec.yaml | 0 .../design.md | 0 .../proposal.md | 0 .../specs/gpx-parsing/spec.md | 0 .../tasks.md | 0 openspec/specs/gpx-parsing/spec.md | 75 +++++++++++++++++++ 6 files changed, 75 insertions(+) rename openspec/changes/{gpx-parser-robustness => archive/2026-07-13-gpx-parser-robustness}/.openspec.yaml (100%) rename openspec/changes/{gpx-parser-robustness => archive/2026-07-13-gpx-parser-robustness}/design.md (100%) rename openspec/changes/{gpx-parser-robustness => archive/2026-07-13-gpx-parser-robustness}/proposal.md (100%) rename openspec/changes/{gpx-parser-robustness => archive/2026-07-13-gpx-parser-robustness}/specs/gpx-parsing/spec.md (100%) rename openspec/changes/{gpx-parser-robustness => archive/2026-07-13-gpx-parser-robustness}/tasks.md (100%) create mode 100644 openspec/specs/gpx-parsing/spec.md diff --git a/openspec/changes/gpx-parser-robustness/.openspec.yaml b/openspec/changes/archive/2026-07-13-gpx-parser-robustness/.openspec.yaml similarity index 100% rename from openspec/changes/gpx-parser-robustness/.openspec.yaml rename to openspec/changes/archive/2026-07-13-gpx-parser-robustness/.openspec.yaml diff --git a/openspec/changes/gpx-parser-robustness/design.md b/openspec/changes/archive/2026-07-13-gpx-parser-robustness/design.md similarity index 100% rename from openspec/changes/gpx-parser-robustness/design.md rename to openspec/changes/archive/2026-07-13-gpx-parser-robustness/design.md diff --git a/openspec/changes/gpx-parser-robustness/proposal.md b/openspec/changes/archive/2026-07-13-gpx-parser-robustness/proposal.md similarity index 100% rename from openspec/changes/gpx-parser-robustness/proposal.md rename to openspec/changes/archive/2026-07-13-gpx-parser-robustness/proposal.md diff --git a/openspec/changes/gpx-parser-robustness/specs/gpx-parsing/spec.md b/openspec/changes/archive/2026-07-13-gpx-parser-robustness/specs/gpx-parsing/spec.md similarity index 100% rename from openspec/changes/gpx-parser-robustness/specs/gpx-parsing/spec.md rename to openspec/changes/archive/2026-07-13-gpx-parser-robustness/specs/gpx-parsing/spec.md diff --git a/openspec/changes/gpx-parser-robustness/tasks.md b/openspec/changes/archive/2026-07-13-gpx-parser-robustness/tasks.md similarity index 100% rename from openspec/changes/gpx-parser-robustness/tasks.md rename to openspec/changes/archive/2026-07-13-gpx-parser-robustness/tasks.md diff --git a/openspec/specs/gpx-parsing/spec.md b/openspec/specs/gpx-parsing/spec.md new file mode 100644 index 0000000..c8f677f --- /dev/null +++ b/openspec/specs/gpx-parsing/spec.md @@ -0,0 +1,75 @@ +# gpx-parsing Specification + +## Purpose +Robust, lenient GPX parsing in `@trails-cool/gpx`: a file any mainstream app exports imports correctly, and a file with some broken points imports with those points discarded rather than corrupting stats or being rejected. Covers invalid-point skipping (no Null Island / NaN totals), `` route support, post-parse timestamp repair, metadata/`` fallback, and a fixture corpus as the regression mechanism — while `validateGpx` stays the strict backstop. + +## 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 `` 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 `` 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 `` element as a track segment, handling `rtept` identically to `trkpt` (including elevation, time, and invalid-point skipping), appended after any `` segments. + +#### Scenario: Route-only GPX imports +- **WHEN** a GPX file contains only a `` with valid `rtept` points and no `` +- **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 `` and `` 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 `