M1-11: Memo list on real data, and capture wired to it #28
No reviewers
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!28
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "m1-11-memo-list"
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?
Closes #11.
The memo list stops showing sample data and reads the documents directory: every completed
capture, newest first, with the length read off its audio and a permanently not-synced cloud.
Swiping a row and tapping Delete removes the memo, its transcript and any leftover parts folder.
Relaunching shows the same list, because the list was never anything but a reading of the
directory.
Two commits, deliberately
The issue was written as the list alone. At the planning checkpoint Wes was offered the record
button as a separate issue and chose to fold it in — "Include it here." So the branch also
retires issue 03's design stub: the button drives
AudioRecorder, the bar meters real audiothrough
AudioFileSink.onWrite, andDebugCaptureViewloses its record controls and becomesSettings → Diagnostics. The history splits along that line if the review wants two sittings.
The decisions worth arguing with
A memo's timestamp is the file's creation date, not its filename. The name carries local wall
time with no UTC offset, so it cannot name an instant — a memo made at 09:00 in California and
read on a phone still set to Eastern parses three hours out, which the row's relative dates put
straight on screen. The name stays authoritative for identity and for vault inbox processing.
Consequence for #12: a memo copied back onto the phone carries the copy's creation date.
The active capture is excluded on
isFinalizing, notisRecording.stop()clearsisRecordingbefore it closes the file and assembles the transcript. The rule lives inCaptureNaming.activeBaserather than on the recorder, so it can be tested without an audioengine.
Deletion removes the audio last, and only if nothing else failed. The audio file is what puts
the row on screen, so keeping it keeps the memo visible and the deletion retryable. There is no
Files-app route to a stranded file until #12.
Discovery requires a regular file, not just a matching name. A directory called
<base>_audio.m4apasses every name check there is, and once #12 opens the folder, treating oneas a memo means the first swipe deletes it recursively.
No confirmation dialog on delete. Swipe, then Delete. Wes on the first build: "I don't need
the second modal popup to confirm delete. Just swipe --> Delete." This overrides the issue text,
which asked for a confirmation. Full swipe is off, so the row cannot go on release.
DebugCaptureViewwas kept, not deleted. Its ShareLinks are the only way a memo leaves thephone until #12 turns on
UIFileSharingEnabled, and removing it now would strand every recordingmade in between.
Codex
Four passes, all recorded with their dispositions in
.agent/m1-11-memo-list/SUMMARY.md.isRecordinglifecycle boundary and the directory-masquerading-as-audiorecursive delete. Both accepted; both would have shipped.
the audio and stranded the transcript with no row to retry from; the Record button stayed live
during
start(), so two taps built two engines; Diagnostics offered to share the in-flightrecording.
12 suites, and every new guard-test was verified by mutation: the production check was
deleted or inverted, the named test confirmed red, the code restored. One finding rejected —
the concurrent-start guard needs a real
start(), so it is a device concern, not a unit test.the list with no handle to delete it). One low deferred to #12 with a reason: the
.partsfolder is removed recursively, which only matters once the Files app can put things in it, and
TranscriptAssemblyalready removes those folders the same way.Two production changes came out of the test review rather than the code review, because the
guards were untestable as written:
CaptureNaming.activeBasewas extracted fromAudioRecorder,and
date(ofBase:)now requires the whole name to be a capture base instead of parsing a prefixand ignoring the tail.
Validated
make test— 116 tests in 12 suites, green.make lint— clean.durations read off the audio and titles derived from the capture time.
wes-iphone: recording works and the memo lands in the list. Wes confirmed the list andcapture, then directed the delete change, which was rebuilt and reinstalled.
Not validated
Stating this plainly because a claim of coverage that does not exist is worse than none.
driven there. The interactive paths rest on unit tests at the logic layer and on the device.
The others — double-tap on Record, the meter against a real voice, stopping from the Live
Activity, force-quit recovery with the new list on screen, delete removing both files, and the
time-zone change — were not reported and should be assumed unrun.
LevelMonitor; it is tested with synthetic buffers only.en_US_POSIXcannot be detected from a unit test — removing it leavesLocale.current, whichis Gregorian on the simulator. The 2569-year failure only appears on a non-Gregorian device.
Follow-on
#27 — reading a memo's transcript on the phone. Came directly out of this: the list made it
obvious it is the only thing you can see about a memo.