Repository navigation
Description
Summary
Activity-file import completion text violates its explicit Swift/Kotlin parity and honest-summary contract when an activity carries positive steps. Kotlin appends the step count; Swift omits it.
This is display/public-contract drift only. Parsed steps, workout persistence, daily aggregation, and the separate per-workout import note remain intact.
Exact reproduction
Use the same normalized activity on both platforms:
- sport: walking
- distance: 1000 m
- GPS points: 0
- HR samples: 0
- average HR: null
Exact outputs:
| steps | Swift | Kotlin |
|---|---|---|
| null | Imported a 1.00 km Walking activity | Imported a 1.00 km Walking activity |
| 0 | Imported a 1.00 km Walking activity | Imported a 1.00 km Walking activity |
| 2350 | Imported a 1.00 km Walking activity | Imported a 1.00 km Walking activity · 2350 steps |
The mismatch is present on exact meta032 032983d and current upstream main b0d8a29.
Cause and provenance
The activity-step work in upstream PR ryanbr#489 / commit eddfd68 added the steps field and updated both per-workout import-note formatters. It also added positive-step rendering to Kotlin ActivityFileImporter.summaryText, but the separate Swift ActivityFileImporter.summaryText formatter remained unchanged.
Swift FIT parsing does produce positive steps for walking, running, and hiking, and DataSourcesView calls the public summaryText after persistence. Android importAndPersist returns Kotlin summaryText and its UI exposes ImportSummary.message. The branch is therefore production reachable on both platforms.
Severity
P2: a user-visible completion line and an explicitly documented public parity contract diverge. The Swift completion message understates what the file carried, but the step data itself is not lost or corrupted.
No direct public summaryText tests currently pin null, zero, or positive steps.
Duplicate search
Fork and upstream issues and pull requests were searched open and closed for summaryText, positive steps, imported activity steps, FIT steps, and activity-file summary terms. No exact duplicate was found.
Related but non-duplicate history:
- upstream Importing.fit (from Suunto) doesn't import steps ryanbr/noop#483 / Import FIT activity steps ryanbr/noop#489: initial FIT step import and provenance of this omission
- upstream [steps] Steps from imported fit file ryanbr/noop#568 / FIT import: double total_cycles → steps for foot sports (fixes #568 halving) ryanbr/noop#584: stride-to-step conversion
- upstream [steps] Imported activity steps claim the whole-day total (design: #137 day-owner vs workout-scoped) ryanbr/noop#585: daily-source/display arbitration
- upstream Activity-file import: a second file imported for the same day OVERWRITES the day's step count instead of adding to it ryanbr/noop#1058 / fix: sum activity-file steps across a day instead of overwriting (#1058) ryanbr/noop#1088: same-day activity-step aggregation
- fork [P1] backfillWorkout rebuilds WorkoutRow and drops stored steps — silent data loss + Kotlin parity drift #16: unrelated workout backfill step loss
Acceptance criteria
- Add mirrored public tests for steps null, 0, and 2350 using the exact activity above.
- Null and zero remain exactly Imported a 1.00 km Walking activity on both platforms.
- Positive steps become exactly Imported a 1.00 km Walking activity · 2350 steps on both platforms.
- Preserve field order, separators, distance formatting, sport normalization, and existing GPS/HR/average-HR output.
- Keep the change display-only; do not alter parsing, persistence, daily aggregation, or per-workout notes.
- Route the production fix upstream-only from a fresh origin/main worktree; do not transplant production code into the fork harness.
- Run Native or broader gates only after explicit GO.
Activity
bhelm commentedon Aug 21, 2026
Resolved upstream by ryanbr/noop#1477, merge commit c821c40a, which is contained in current upstream
main. The merged fix includes regression coverage and passed upstream CI. Closing as completed.