M2-07: The track file — write it, and survive a crash #34
Labels
No labels
area/agent
area/capture
area/editor
area/geo
area/security
area/sync
area/transcription
area/ui
area/vault
area/voice-memos
blocked
milestone/M1
milestone/M2
milestone/M3
milestone/M4
needs-decision
needs-hardware
p0
p1
p2
type/bug
type/enhancement
type/feature
type/idea
type/infrastructure
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Stash/stash-ios#34
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Write
<base>_track.gpxbeside the memo, assemble it at stop, and recover it at launch.Why it is durable rather than written once at stop
Decided 2026-08-08: the parts pattern, the same shape the transcript already uses — append as
it goes, join at stop, and let launch finish what a crash interrupted.
Audio survives a kill because of
movieFragmentInterval. The transcript survives one becauseparts are written every minute and assembled on the next launch. A track written only at stop
would be the single artifact in this app that a crash destroys completely, and that inconsistency
is what would surprise somebody later — including a future client reading these files.
M1-15 (#25) exists because a crash cost 16 seconds of speech. Losing a whole forty-minute route to
the same crash is the larger version of that bug, and it is cheaper to not build it than to fix it.
Scope
exists for transcripts, using the same padded numbering so the existing parsers keep working.
<base>_track.gpx.location parts and no track is assembled from what survived.
folder, name the missing numbers — applies here for the same reason: a partial route is worth
having, and something on disk has to say it is partial.
write per point during capture is write amplification while the audio path is what matters.
The file
Decided 2026-08-09: GPX, not a bespoke JSON schema. See the decision comment below. A GPX 1.1
<trk>with one<trkseg>, and a<trkpt>per fix.This amends decision 3 from the M2 planning round, which called for relative seconds plus one
absolute start time in a header. GPX carries an absolute UTC
<time>on every point natively, andthat is strictly better — the track is self-describing without a header convention, and every tool
that reads GPX already understands it. Alignment with VTT cue times is derived by subtracting the
recording start rather than stored, which removes a value that could disagree with the file.
Field mapping, to be confirmed against the GPX 1.1 schema rather than assumed:
lat/lonand<time>— native, and the reason for choosing GPX.<ele>— native, altitude.<hdop>— the nearest native home for horizontal accuracy. It is not the same quantity asCLLocation.horizontalAccuracy; if it cannot be mapped honestly it goes in<extensions>underits own name rather than being coerced into a field that means something else.
<extensions>. GPX 1.0 had them natively and 1.1 moved them out; an extensionnamespace is the standard-conforming answer, and readers that do not know it ignore them, which
is the correct degradation.
<metadata><time>— the recording start, so the track still stands alone.The exact element layout is the plan's to propose, and it gets written down in
stash-docsas adecision record before implementation. It is a format every future client has to read.
Done when
stash-docs.Milestone 2 of the Stash v3 rebuild. M2 is still app-side — no sync, no account, no server. It
turns a list of memos into something you can open, listen to, read and see the route of. Sync
arrives in M3. There is no
milestone/M2label yet (creating org labels needs owner rights), sothe title carries the milestone.
Working agreement for every issue in this repo: feature branch, tested before the PR opens
(on-device where the label says so), then Wes reviews the PR and we walk the code together. Docs
update in the same commit. A PR that takes more than 20 minutes to review is too big — say so and
split it.
The file format is not settled, and a note from 2026-07-27 argues against the JSON this issue assumes.
The 8/6 walk memo said "JSON file" in passing. A note Wes wrote on 7/27, thinking about this exact feature, states a principle that points somewhere else:
By that standard a bespoke JSON schema is the weakest option on the table. It is readable, but nothing else opens it — every consumer has to be told what the keys mean, which is the definition of a proprietary format that happens to use a standard encoding.
GPX is the open standard for tracks and every mapping tool on earth reads it. Drop a
.gpxbeside the audio and the route opens in Garmin Connect, Gaia, QGIS, Strava, Apple's own tools — with no code written anywhere. It carries time, elevation and coordinates natively. GeoJSON is the other candidate: less universal for tracks specifically, better for tooling that speaks geo generally.Costs worth weighing rather than dismissing: GPX is XML, so it is more verbose than JSON on disk for a 2,400-point walk; its
<extensions>mechanism is where speed, course and horizontal accuracy would have to live, which is standard but less tidy than named JSON fields; and the decided timestamp basis for this issue is relative seconds from recording start, whereas GPX wants absolute times per point. That last one is not a conflict — absolute times are derivable from the header start, and GPX carrying them natively is arguably better.This should be settled in
stash-docsbefore implementation, alongside the schema this issue already defers there. It is a format every future client reads and the vault consumes, so it is expensive to revisit — and the same argument that made the transcript a.vttrather than a bespoke format applies here without modification.Raised because M2-10 (#39) will read every one of these files, and because the note that argued for it predates the scope memo that said JSON.
Decided 2026-08-09: GPX. Wes: "GPX for sure."
Resolves the format question raised above. The track is
<base>_track.gpx, not<base>_location.json.The reasoning that decided it is Wes's own, from 7/27: the folder should open in any application on the computer, and he is "very much against proprietary data formats." A bespoke JSON schema is readable and still proprietary — nothing but Stash knows what the keys mean. GPX opens in Gaia, QGIS, Garmin Connect, Strava and Apple's own tools with no code written anywhere, which is the same bar the transcript already meets by being WebVTT rather than something invented.
What this changes elsewhere:
<base>_track.gpx. Patched.<time>per point; alignment with VTT is derived, not stored.<hdop>only if that can be done honestly, and speed and course go in<extensions>because GPX 1.1 moved them there.Accepted cost: XML is more verbose on disk than JSON for a 2,400-point walk. Worth it for a format that needs no consumer written.