C.W.K.
Stream
Lesson 03 of 05 · published

Visible While Listening, Forgetful After

~11 min · retention, privacy, opt-in, history

Level 0Unlit
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"The app should be impossible to forget while it's listening, and should itself forget the moment it stops."

Two Halves of One Promise

The trust contract has two halves that sound unrelated but are the same idea. Visible while listening: whenever the microphone is live, there is an unmissable indicator — the pill overlay with a moving waveform. Not a subtle menu-bar tint; a thing your eye catches. Forgetful after: when the dictation is done, the audio is discarded by default. Together they say: you always know when it hears you, and it doesn't keep what it heard.

Why the Waveform Matters

The live waveform isn't decoration. A static "recording" label could be a lie — it might be showing while nothing records, or (worse) fail to show while something does. A waveform that moves with your voice is evidence: it's derived from the actual capture tap, so it can only animate if audio is genuinely flowing. The indicator is coupled to the thing it indicates. That's a small design choice that converts a claim into a demonstration.

The Tension: Forgetting vs. Losing

"Discard everything" collides with a real need: if STT or cleanup fails, throwing away the audio means the user's words are gone forever. Firekeeper resolves this deliberately rather than picking a side:

successful dictation   -> audio discarded (default)
STT failure            -> audio moved to recovery-audio/, pruned to 10
cleanup failure        -> raw transcript already in state; words never lost
history on disk        -> OPT-IN only

# Forget by default. Retain only on failure, briefly, and bounded.

The raw transcript lands in state before cleanup runs, so a cleanup failure can never eat your sentence. Recovery audio exists only for the failure case, is capped at a small number, and rotates. Retention is the exception with a reason, never the default with an excuse.

Couple the indicator to the mechanism. A privacy indicator that's set by a separate flag can lie by omission — someone forgets to set it. An indicator derived from the mechanism itself (a waveform fed by the capture tap) is structurally honest: it can't show without the thing being true, and it can't hide while it is. Wherever you promise 'you'll know when X happens,' make the signal a byproduct of X, not a reminder to announce it.
Bound every retention you allow. Once you admit an exception ('keep the audio if STT failed'), give it a ceiling and a rotation immediately. An unbounded exception quietly becomes an archive — ten failure recordings is a safety net; a year of them is the hoard you promised not to build.

Code

Forget by default; retain only on failure, bounded·swift
func finish(_ clip: AudioClip) async {
    // Raw transcript enters state BEFORE cleanup, so a cleanup
    // failure can never lose the user's words.
    guard let raw = try? await stt.finalize(clip) else {
        recoveryStore.keep(clip, max: 10)   // STT failed: bounded rescue
        return
    }
    history.recordRaw(raw)                  // in-memory; disk persistence is OPT-IN

    let result = await cleanup.run(raw)
    await insertion.insert(result)

    clip.discard()                          // success: audio is gone. Default.
}

External links

Exercise

Find an app that captures something sensitive (audio, screen, location). How do you know when it's active — a claim, or evidence coupled to the mechanism? Then check its retention: is discarding the default with bounded exceptions, or keeping the default with a delete button?
Hint
The strongest indicators are byproducts of the capture itself, so they cannot be true when the claim is false. And the retention tell is where the default sits: 'keep unless you delete' and 'discard unless you ask' produce completely different amounts of your data on disk a year later, even though both apps have the same buttons in settings.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.