← Dettato
Changelog
What changed and what got fixed, release by release. No
“bug fixes and improvements” hand-waving.
1.11.1 2026-08-23
Fixed
- Switching audio devices mid-recording could silently stop your mic track — and crash the app hours later. Putting AirPods on or taking them off changes the microphone's sample rate; the mic recorder rebuilt itself at the old rate, AVFoundation threw an internal exception the app could not catch, and from then on your side of the meeting was missing while the app kept reporting healthy. The same swallowed exception left the process in a corrupted state that crashed later during an unrelated window layout (the 1.11.0 Dock-click crash). The mic now rebuilds at the hardware's actual format, any such exception is caught and reported as "Microphone stopped" in the recording health chip instead of escaping, and the app fails fast at the source of a future uncaught exception rather than limping on.
- The microphone now watches itself. The recording health check only watched the meeting-audio side, so a mic that went quiet mid-recording (macOS can leave the input engine running with nothing attached after a device change, with no error to report) stayed invisible. The mic track now detects three seconds of silence from the engine, reconnects itself, and only after repeated failed reconnects reports "Microphone stopped" in the health chip.
- Upgrading from a pre-1.6 library can no longer be lost to a momentary lock. When the old default store was briefly locked at first launch (another process closing it), the adoption check mistook "busy" for "this is another app's store" and started a fresh, empty library — permanently, since the new library then existed. The check now waits out a transient lock (up to 5 s) before deciding.
1.11.0 2026-08-20
Added
- Watch folders understand recorder-sync layouts. Tools that mirror hardware recorders locally (like applaud for Plaud) drop each recording in its own dated subfolder — the watch folder now scans one level of subfolders and rescans once a minute, so those recordings import automatically. docs/HARDWARE_RECORDERS.md documents the full Plaud → applaud → Dettato pipeline, and which Plaud devices mount over USB.
- Imports get real titles and real dates. A file named "audio" or "recording 3" takes its title from its folder ("2026-04-11_Board_call__x8f" imports as "Board call"), and the recording is dated by when it happened — a date in the file or folder name, or an old file's own timestamp — instead of when it was imported. Calendar matching then works on the meeting's actual date. Note: auto-delete retention applies to that original date.
Fixed
- Local reasoning models no longer title recordings with their own thoughts. The Qwen3 1.7B and 8B catalog models think before answering, and their
<think> deliberation leaked straight into titles and summaries. The reasoning is now stripped, and "answer directly" in AI settings skips it entirely (faster). Verified by eval: both models now produce clean titles (docs/MODEL_EVALS.md has the numbers — the default 4B remains the best extractor).
1.10.0 2026-08-20
Added
- Folders. Organize recordings into folders (Work, Personal, Research, Sales — yours to name) from a new sidebar section: drag recordings onto a folder, or right-click → Move to Folder. Each folder is a filtered view with the same search; deleting a folder never touches its recordings — they simply return to the library. Recordings show their folder in the list, and the details panel's Info tab has a folder picker.
- Folders in the CLI.
dettato folder list | add | rename | rm | set manage the same folders as the app, and dettato library list --folder Work filters by one; the JSON output now carries each recording's folder.
Changed
- The library's storage schema moved to 3.0.0 (additive — your recordings migrate automatically and instantly on first launch). Update the app and the
dettato CLI together (the installer ships both): after either one touches the library, an older copy of the other will refuse to open it with an "update to match" message rather than risking the data. The historical 2.0.0 schema is now genuinely frozen in code, verified against a real pre-folders library, and the app now refuses a newer library before opening it — same protection the CLI always had.
1.9.0 2026-08-20
Added
- Choose your built-in AI model. A new Settings → Models pane — the one the app's own error messages always pointed at — offers a curated set of local models: Qwen3 1.7B (light, ~1.1 GB, fine on 8 GB Macs), Qwen3 4B Instruct (the existing default), and Qwen3 8B (best quality, wants 16 GB+). Pick one, download it with progress right in the pane (resumable, checksum-verified), and it applies on the next AI run — no relaunch. Advanced users can still point at any GGUF file. Existing installs keep working untouched: the default model, its on-disk location, and any custom path you had set are all honored.
- Each catalog model carries its own context window, so a smaller model can take longer transcripts per chunk.
- The "Models on disk" manager moved into the new Models pane and now also covers Dettato's own GGUF folder, so every downloaded model can be found and deleted from one place.
dettato setup --model <id> provisions any catalog model from the terminal; dettato eval --engine llama --model <id> scores it against the fixtures before you make it your default.
Changed
- In privacy mode (on-device only), the model you select here is the quality ceiling — the Models pane says so, and the RAM guidance helps pick the right tier.
1.8.0 2026-08-20
Added
- Bring your own summary templates. AI agents can now be imported from a plain .md/.txt file ("Import template…" in Settings → Automation, or from the agent editor) — the file's content becomes the instruction, no proprietary format. Agent instructions can reference the recording with tokens like
{{title}}, {{date}}, {{participants}}, and {{calendar_event}}, and each agent can carry its own temperature and run profile (General or Summary).
- The custom export template works now. Settings → Data always promised "Used by Export → Custom template" — that menu item finally exists and renders your document/segment templates over the whole recording (transcript, metadata, and a new
{{action_items}} token with its own per-item template). Respects "Redact PII in exports". Works before any AI action has run.
- Hardware recorders (Plaud and friends) import cleanly. The watch folder now waits for a file's size to settle before importing, so large recordings that sync slowly are never picked up half-copied. A new guide (docs/HARDWARE_RECORDERS.md) covers the Plaud → watch-folder workflow.
dettato eval --instruction-file <path> scores a custom template's instruction against the bundled fixtures before you trust it.
Changed
- The AI prompts that ship in the app, the CLI, and the eval harness are now one shared set — the harness previously scored a title prompt that production never sent, so eval numbers finally track what actually runs.
1.7.0 2026-08-20
Added
- Automatic Obsidian export (Pro). Turn it on in Settings → Data and every finished transcript lands in a "Dettato" folder inside your vault on its own — recorded meetings, imports, and watch-folder files alike. Notes are never overwritten: if you've edited one in Obsidian, a re-export gets a numbered sibling. Respects "Redact PII in exports".
- Send the full transcript to Obsidian, manually, free. The Send to menu no longer requires an AI result: a new "Obsidian (full transcript)" item works the moment transcription finishes.
- Calendar titles now introduce themselves. Dettato has long been able to name recordings after the overlapping calendar event, but the switch was off by default and buried — so recordings stayed "Microsoft Teams (Aug 20…)". A one-time suggestion now appears on such recordings; accepting turns the feature on, asks for calendar access, and retitles that very recording on the spot. Outlook and Google calendars work when subscribed in Apple Calendar.
- Rename recordings in the app. Right-click a recording in the library → Rename. (Previously CLI-only.)
Fixed
- The Mac App Store build's entitlements now include calendar access, so "Match calendar events" can work under the sandbox (spike build only; not shipped).
1.6.5 2026-08-20
Fixed
- Recordings no longer look like they're still running. The library showed each recording's age as a live seconds counter that ticked upward forever ("Recorded 43,200 seconds ago", counting) — the first thing user feedback called out. Ages are now calm labels: "Just now", "2 hr. ago", "yesterday", then a plain date like "Aug 12".
- Durations over an hour read correctly everywhere. A 69-minute recording showed as "69:27" in the details panel, the player, and the
{{duration}} export token; all three now say "1:09:27". Every duration in the app is rendered by one shared formatter, so the styles can't drift apart again.
- The details panel no longer covers the recording bar. With the panel open, its left edge drew over the Record/Stop side of the bottom bar; the bar now makes room, same as the main content does.
- Library rows stopped colliding at narrow widths. The duration, source, and participants line overflowed the row when the list column was squeezed; it now swaps the participant names for a head-count instead of overlapping. The recording's age no longer wraps into the title either.
- Long speaker lists in the recording view scroll sideways instead of running off the edge under the details panel, and the status text in the recording bar truncates instead of pushing the fixed controls around.
- The player's time readout no longer clips once a recording passes the hour mark.
1.6.4 2026-08-19
Fixed
- You can actually type a license key now. The "I have a key" field had no way to submit: pressing Return did nothing, and the Activate button — which existed all along — was rendered underneath the details panel, because the recording view kept its full width behind the panel instead of making room for it. Return now activates the key, the button is visible, and the field no longer stretches across the whole window.
- The details panel is readable again. All three content tabs drew their lines stacked on top of each other on one unreadable line — the summary's title over its text, every participant's name in one pile, every metadata row in another (a macOS 26 layout behavior change). Each tab now lays out properly.
- The panel's fourth tab is no longer cut off. The tab strip was wider than the panel, clipping "Export" to "Expo". The tabs — now Summary, People, Info, Export — share the panel width equally and always fit.
- Content in the recording view no longer disappears beneath the details panel while it is open.
1.6.3 2026-08-19
Fixed
- The real cause of "Dettato can't open your library" on fresh installs, found and fixed. SwiftData's default storage location (
default.store) is shared by every app built without an explicit store path — so the file sitting there may belong to some other app entirely. Dettato's first launch adopted it blindly as an "old Sotto library", planting a database no version of Dettato can open, and every launch after that died on the recovery screen (with pre-1.6.2 recovery re-adopting it, endlessly). Both machines this was reproduced on had exactly that: an unrelated project's store from March 2025. Now: a legacy store is only adopted after a staged copy of it provably opens with Dettato's schema, and a library already poisoned by an earlier build — valid SQLite, but containing none of Dettato's tables — is automatically set aside (preserved under Recovery/) and replaced with a clean library at launch. No recovery screen, nothing lost, because a foreign store never contained your recordings in the first place. Genuine old libraries still migrate exactly as before.
- The library-error screen and diagnostics now name a foreign store explicitly instead of reporting a generic schema mismatch.
1.6.2 2026-08-19 (internal, not published)
Fixed
- Rebuilt with the stable macOS 26 SDK: 1.6.1 shipped built against the macOS 27 beta SDK while declaring macOS 26 support. Packaging now refuses any build whose SDK is newer than the macOS version it claims to support. (Initially suspected as the cause of the "can't open your library" reports; the actual cause was found afterwards — see 1.6.3.)
- "Back Up Store and Create New Library" now actually gives you a new library. On a Mac that had ever run a pre-1.0 build, recovery set the unreadable library aside and then immediately re-adopted the old pre-1.0 library from its former location — so the screen came back reporting the very same error, every time, with no way out. Anyone whose old library was readable had it silently restored instead of the clean one they asked for. Both libraries are now preserved in the same backup folder and set aside together. Upgrading from a pre-1.0 build still picks up your existing recordings as before.
- The library-error screen now says what is actually wrong. Every SwiftData failure — a damaged file, a folder Dettato can't write to, a full disk, a library from a newer version of Dettato — arrives as the identical message "The operation couldn't be completed. (SwiftData.SwiftDataError error 1.)", and the screen was passing it straight through; the "privacy-safe diagnostics" button hashed that same constant, so every report carried the same support code. The screen now names the cause in plain language, and the copied diagnostics describe the library files themselves (size, whether the file is still a valid database, folder permissions, free space, schema versions) with no paths or recording content. The
dettato CLI reports the same way.
- A library written by a newer version of Dettato is now recognised as such and asks you to update the app, instead of offering to file away a perfectly good library.
1.6.1 2026-08-18
Fixed
- The Buy button actually reaches the checkout now. The Polar checkout address the app shipped with contained a lowercase
l where the real address has a capital I — visually identical in the dashboard font it was copied from — so "Upgrade to Pro" landed on Polar's homepage instead of the Dettato Pro checkout. License activation and validation were never affected.
Changed
- Support email is now
support@dettato.app everywhere (app, website, license messages), replacing the interim proton.me address. Mail to the old address still arrives.
1.6.0 2026-08-13
Added
- Import
.vtt and .srt transcripts. A caption file from Teams, Zoom, Meet, or a Whisper-based tool now imports as a library entry with its segments, speakers and timings intact — drag it in, use Import (⌘I), drop it in a watch folder, or run dettato import meeting.vtt. No audio and no transcription engine are involved, so this works on a machine with no model installed. Speakers are recovered from <v Speaker> tags, and from plain Name: prefixes where the file makes it unambiguous; where a prefix is stripped, the original line is kept so the change can be reverted per segment. Imported transcripts are searchable, exportable, and available to AI summaries and action items like any other recording.
Fixed
- The capture bar shows which meeting apps are open again, along with the "Audio ready" indicator. Both pills disappeared in 1.2.0 during the capture redesign. The new one also fixes a bug the old one had: the list came from Core Audio, which only knows about an app once it has played a sound, so an app sitting open all morning — Slack, typically — was invisible. It now reads the running-applications list, so an idle Slack appears the moment it launches. Click the pill for the full list, including whether each app is idle, has audio, or is in a call. Browsers stay out of the list until a call actually starts in one, since a browser is open on nearly every Mac all the time.
- A denied "system audio recording" permission is no longer a dead end. macOS never re-asks once you have declined, and since 1.2.0 nothing in the app said so — recording just refused, showing "Permission needed" with nothing to act on. There is now a banner explaining it, with a button that grants the permission or opens the right System Settings pane.
- Exported
.vtt files are now valid WebVTT. Cue text was written raw, but the format treats & and < as markup — so a line reading "ship <the tagged build>" lost the bracketed words in any conformant player, and a bare & could swallow the words after it. These characters are now escaped, which makes exported .vtt bytes differ from previous releases for any transcript containing &, < or >, and makes a .vtt export → import round trip lossless. .srt is deliberately unchanged: it has no specification and no escaping rule, and real players would show & literally — use .vtt or .dettato when a transcript contains those characters.
- A transcript with no audio (an imported caption file, or a transcript-only
.dettato bundle) no longer reports "Zero KB on disk • peak ≈ 0 (likely silent)" in orange, and its player shows the transcript's real length instead of 0:00.
- A URL import can no longer pull in stray subtitle files as extra recordings when your personal
yt-dlp config asks for subtitles.
1.5.1 2026-08-09
Fixed
- Opening Settings (⌘,) no longer crashes the app. Once the General tab had been visited, every subsequent Settings open crashed while the window laid itself out. If Dettato has been crashing "constantly" for you, this was almost certainly it.
- A recording whose microphone track fails to assemble when the recording stops no longer loses that audio permanently. The meeting track is saved as usual and the mic track is restored on the next launch — previously the failure deleted the mic audio and duplicated the meeting track instead.
- Deleting a recording while its AI processing, auto-titling, or speaker identification is still running no longer crashes the app.
- Rate limiting or a corporate proxy answering for the license server can no longer deactivate a licensed copy. Only an actual verdict from the license provider revokes a key; everything ambiguous keeps the existing offline grace.
- The first-run model download can no longer report success while showing the built-in model as still downloading, and a corrupted download can no longer slip past the checksum failure report.
- Closed a capture race when the audio device changes mid-recording (AirPods connecting, for example) that could crash while the microphone tap was being rebuilt.
- The library-recovery screen's buttons no longer double-activate on a double-click or a held Return key.
- Recordings are now titled with the app you were meeting in. Electron and browser apps run call audio in helper processes, so recordings were titled "helper (…)" or "signal (…)"; they now read "Teams (Aug 9, 2026 at 10:43 AM)", "Signal (…)", and so on. Recovered recordings are titled the same way — "Recovered — Teams (date at time)" — instead of the internal file name ("recovered-mic-2026-08-09T13-03…"). Existing recordings keep their current titles.
Changed
- Dettato Pro is now sold and validated through Polar (Lemon Squeezy did not approve the store). The Buy button opens Polar checkout, and license keys are validated against Polar. Nothing changes for the free tier.
1.5.0 2026-07-26
Added
- Added user-controlled provider ordering for quick and full AI tasks, covering Apple on-device, the configured AI endpoint, and the built-in llama.cpp model.
- Added an explicit local-network HTTP opt-in for Ollama and LM Studio endpoints.
Changed
- AI requests now continue through the configured provider order when a preferred provider is unavailable or fails at runtime.
- Private-network HTTP endpoints are accepted only after explicit opt-in; public HTTP endpoints continue to require HTTPS.
1.4.1 2026-07-26
Fixed
- Hardened capture startup and teardown so microphone and process-tap callbacks cannot race file cleanup.
- Fixed cancellable external-process handling, cloud-request configuration races, Keychain failure rollback, and several unsafe network/input boundaries.
- Prevented the macOS 26 inspector layout constraint crash during rapid workspace changes.
1.4.0 2026-07-25
Fixed
- Some meeting audio was being silently discarded before transcription. When converting a recording for the speech engine, only the first audio channel survived — so anything carried on the right channel alone was dropped entirely, and a recording with audio only on the right became complete silence. The transcript came back empty and the app reported "no speech detected", with nothing to suggest the audio had been thrown away. Both channels are now mixed properly, at every channel count. If a past recording transcribed as empty or lost one side of a conversation, it is worth re-running the transcription on it.
- Quiet recordings are no longer degraded by the automatic volume boost. The boost was previously applied after the audio had been reduced to 16-bit, which amplified the conversion noise along with the speech; it is now applied before, so a quiet remote participant is boosted cleanly.
- Stereo recordings whose two sides are phase-inverted no longer cancel each other out into silence when mixed — an unusual but total failure. Dettato now detects the cancellation and uses the stronger channel instead.
- Recordings with more than two channels (some imported files) converted to silence and are now handled.
Changed
- The audit log's integrity check now means what it says. Previously it verified only that entries had not been edited: deleting the last few entries, replacing the file wholesale, or deleting it outright all reported "no problem detected". Dettato now keeps a small record of the log outside the log itself, so shortening, replacing or deleting it is detected and permanently marked, including an entry written into the log describing what happened. - Verification now reports three states rather than pass/fail: verified, not anchored (entries exist but cannot be shown to be complete — including entries written by older versions, which are marked as predating the check rather than quietly vouched for), and altered. - The honest limit, stated plainly and more precisely than the first draft of this note: Dettato's record of the log lives in your Keychain, and anything running as you can write both. So this detects the log file being edited or shortened on its own — the realistic case — and it does not withstand software running as you that rewrites both together. Nothing stored on your own Mac can promise that. A log that was wiped and re-anchored is still visible as one whose anchoring date does not match when you installed Dettato.
- Secrets stored in the Keychain are updated in place rather than deleted and rewritten, so a failed write can no longer lose the stored value.
Fixed — recordings and your data
- Quitting Dettato while it was recording lost the last few minutes. The app exited with the current piece of audio still open, so the recovery pass at next launch could not read it. Quit now closes the file first (it does not wait for transcription), and recovery gets the whole session.
- If the meeting track could not be reassembled but your microphone track could, Dettato deleted the audio it had just saved and then restored a second copy of your own voice at the next launch. Now the saved recording keeps its audio and only the genuinely missing meeting track is left for recovery.
- Live transcription could save an empty transcript over perfectly good audio. When the on-device recognizer failed mid-meeting it reported the failure through a channel the app was discarding, so the recording simply looked silent. The failure is now shown while the meeting is still running, and stopping falls back to transcribing the recorded file.
- "Extract action items" overwrote a saved AI summary with a one-line note about how many items were found — irreversibly, including summaries that had just cost a long cloud call. The count is now shown next to the button instead.
- A failed import of a
.dettato bundle left the audio it had already copied sitting in the recordings folder, invisible to the library and to the retention setting.
- Action items you kept during a meeting could disappear without a trace if saving them failed at the end.
dettato export and dettato report wrote JSON files non-atomically, so an interrupted run could leave a truncated file where a good one had been.
- Cancelling a long AI request could still leave an answer behind. When you moved on to another question, the request for the previous one was not always recognised as cancelled, and its (partial) answer was saved anyway.
- A long transcript was abandoned entirely if any one part of it failed. Meetings too long for the model are processed in parts; one part failing — routine with a small local model — threw away every other part's results. The rest now survive, and Dettato tells you how many parts it could not read instead of quietly presenting a partial answer as a complete one.
- Long transcripts in Chinese, Japanese or Korean were mis-measured as roughly a quarter of their true size, so Dettato skipped splitting them and the AI model overflowed.
- Cancelling an import now actually stops the conversion and the audio reassembly, which previously ran to completion no matter what. (The initial file copy is handled by the system and still finishes.)
- Reconnecting to a meeting's audio after a device change no longer reports "healthy" on the strength of an empty audio stream — a reconnect that hears only silence says so.
Fixed — security
- A shared
.dettato bundle could lay claim to one of your existing recordings' audio. If the bundle named an audio file but did not actually contain one, the imported recording pointed at whatever file already had that name in your recordings folder. Deleting the import — or the retention setting reaching it — then deleted your recording's audio, and playing or re-transcribing the import read your audio instead (with a cloud engine configured, that would have uploaded it). Bundles now only claim audio they actually brought with them.
- Packaging could sign and notarize a debug build: the check meant to catch it ran after the signing step had already erased the evidence it looked for. Both packaging scripts now refuse a debug build outright, before anything is signed.
- A Keychain write failure could drop a paid licence back to Free at the next launch, because the licence was deleted before the new copy was written. It is updated in place now, matching the fix made elsewhere in this release.
- The "copy curl example" button in Automation settings put your API token on the clipboard without marking it as a secret, so clipboard managers stored it in plain text and Universal Clipboard synced it to your other devices.
- Dettato refused every Homebrew-installed
yt-dlp when downloading audio from a URL, because it judged the symlink's own permissions rather than the file it points at.
Changed — performance
- Semantic search no longer re-reads and re-decodes the whole index on every keystroke; typing in a large library is smooth again.
- The local automation API handles its network traffic off the main thread, and the audit log view no longer reads the entire log to show its last eight entries.
1.3.1 2026-07-24
A second hardening pass. Two more audits went over 1.3.0 — one adversarial security review, one review of the hardening changes themselves — and both found real problems, including one that 1.3.0 introduced. If you are on 1.3.0, update.
Fixed
- 1.3.0 could lose most of your microphone track. Its own fix for microphone loss during a device change swapped to a new recording file but then only kept the newest one — so switching to AirPods 55 minutes into an hour-long call kept 5 minutes of your voice instead of 55. Every part is now kept, and the related failure paths finish writing the file properly instead of leaving its last piece unreadable.
- A shared
.dettato file could read other files on your Mac. The import check validated the name of the audio inside the bundle, but a bundle can point that name at a file elsewhere on the disk via a symbolic link, and copying preserved the link. The imported "recording" then transparently read whatever it pointed at — through playback, Reveal in Finder, speaker identification, and, if you use a cloud transcription engine, by uploading it. Imports now require real audio that lives inside the bundle. A second gap in the same check (a name containing a hidden null character) is closed too.
- Crash recovery could re-import the same meeting on every launch, forever, if one of its two tracks could not be reassembled — reachable by force-quitting in the first seconds of a recording.
- Recording gave up on the microphone too quietly, and reported a good recording as failed. Pressing Record while the previous recording was still transcribing marked that recording "Saved with errors" even though nothing was wrong, and the error stuck to the next one.
- Meetings captured only by your microphone (because the meeting side produced no audio) could never get speaker identification — exactly the case where a whole room is on one mic.
- "Clean fillers" erased the entire transcript of a recording that has text but no individual lines, which is how some imported files arrive.
- If saving a recording failed, the assembled audio was left behind unreferenced, so the next launch produced a second copy of the same meeting.
- Preparing audio for transcription could leave a complete copy of the meeting in the system temporary folder when something went wrong — audio that outlived both the retention setting and deleting the recording. A failure while adjusting volume also discarded a perfectly good conversion.
- PII redaction missed spoken Social Security numbers. The pattern required dashes, but transcription writes what was said — "123 45 6789" or "123456789" — so anyone relying on "Redact PII before AI processing" was sending them to their AI provider unredacted. Overlapping redactions could also leave part of a longer sensitive span visible.
- The private-network guard could be walked around by writing an address in a different but equivalent notation, letting a malicious knowledge server reach your local machine or network. Addresses are now compared as addresses rather than as text.
- API keys could still reach the "Test connection" panel for several providers (notably Google, whose error message repeats the key back).
- Bearer-token checking for the local automation API accepted any value that merely ended with the correct token.
- Audit log exports could be used to inject spreadsheet formulas or forge extra rows; webhooks accepted plain
http, which would have sent meeting content unencrypted; and any local program could cancel an in-progress knowledge-source sign-in.
- Participant names were still being written to the system log by two features, and the audit log recorded both your questions and the (AI-generated, transcript-derived) title of every deleted recording, which outlived the deletion.
- Deleting several recordings at once could delete the wrong ones.
- Starting a recording with very little disk space now warns you, and crash recovery no longer stores a duplicate copy of everything it salvages.
Changed
- Searching the library is now debounced, and the transcript, speaker chips and action-item list do much less work while playing back a recording — the app should feel markedly smoother on long meetings.
1.3.0 2026-07-24
A hardening release. Five parallel code audits (concurrency, crash surfaces, security, capture reliability, data integrity) produced around fifty findings; this fixes every critical one and most of the rest. Nothing here is a new feature — it is the reliability and privacy work behind the "sometimes it crashes, sometimes it freezes" reports.
Fixed
- Recordings could be lost outright in three different ways, all of them silent. A failed save deleted the freshly assembled audio and the segments it was assembled from, while reporting "Saved with errors". Crash recovery deleted a session's segments even when it had failed to reassemble them — and the usual reason for that failure, a full disk, is still true at the next launch. And recovery discarded any session whose small manifest file had failed to write, which is exactly what fails on a full disk while the audio keeps recording fine. Audio on disk is now the salvage signal, and nothing is deleted until a recording exists to point at it.
- Four separate crashes, all intermittent races. Stopping a recording released the audio callback while the audio queue was still calling it; live speaker identification released an audio converter mid-conversion; a sample-rate change during teardown could use a destroyed audio device; and deleting a transcript line destroyed the record the open editor was still displaying. Also fixed: the action-item list could crash or silently drop a whole meeting's items when two recordings shared a title, which recurring calendar meetings guarantee.
- The freezes. Stopping a recording assembled the entire meeting on the main thread — over a gigabyte of reading and writing for an hour-long call, twice if the microphone was recorded. Playing a long recording rebuilt every transcript line ten times a second. Importing a file copied it on the main thread. Typing in Find recompiled a search pattern once per transcript line, per keystroke. All moved off the main thread or made lazy.
- Long meetings could be killed by the system. Preparing audio for transcription loaded the whole file into memory at once — around 4.8 GB for a three-hour meeting, which macOS terminates rather than reports. It now streams in fixed-size chunks, so memory no longer depends on meeting length.
- Your microphone track outlived the recording it belonged to. It was written into the library, used for transcription, then abandoned: no recording referenced it, the retention policy never saw it, and it survived deleting the recording. It is now removed once used — or kept as the recording itself when the meeting side captured nothing, which previously threw the whole thing away while reporting success.
- Opening a shared
.dettato file could delete files elsewhere on your Mac. The bundle's own manifest chose where audio was written and what path was stored, so a malicious file could reach outside the library — and because the automatic retention sweep runs at launch on the date the bundle claims, it could fire with no further action from you. Bundles are also now rejected if written by a newer version of Dettato instead of importing incompletely.
- Meeting content was being written to the system log by a feature that is on by default, where it persists long after the recording is deleted and is collected by any diagnostic report.
- Speaker names that look like hexadecimal — Ed, Ada, Bea, Deb, Cece — could match the wrong person entirely, renaming a whole conversation to them, merging your voice sample into their voiceprint, or deleting the wrong person from the command line.
- A microphone that stopped mid-meeting was invisible. Switching to AirPods mid-call ended the microphone track while the app kept reporting healthy, so the rest of the meeting recorded without your voice and looked exactly like you had stayed quiet. The microphone now follows the device change, and says so when it can't.
- Reconnecting to meeting audio declared success before any audio actually arrived, so picking the wrong helper process could loop indefinitely writing empty audio while showing healthy.
- Cleaning filler words merged two speakers' lines into one, and that merged text is what feeds summaries and action items — so it could attribute one person's commitments to another.
- With AI privacy mode on, a race between two simultaneous AI requests could still route transcript text to a cloud endpoint.
- Speaker identification wrote to the database from a background thread, risking corrupted or garbled speaker labels.
- API keys could appear in the AI "Test connection" panel when a provider echoed the rejected key back; full URLs with access tokens were written to the system log; and a knowledge server could ask Dettato to open a non-web link during sign-in.
- Voice enrollment left the microphone running if the window was closed with Escape.
Changed
- Recording now shows a distinct, disabled "Finishing…" state while the previous recording is still being transcribed. It previously showed a normal Record button that silently did nothing, which was indistinguishable from the app hanging.
- Pressing record twice quickly can no longer start two overlapping recordings.
1.2.2 2026-07-24
Fixed
- The macOS 26 layout-abort could still occur after 1.2.1 — at any window size, even sitting untouched shortly after launch. The 1.2.1 fix stabilized the window's own minimum size, but each workspace column (and the inspector) is hosted by its own AppKit child whose layout-derived minimum could still change mid-display-cycle — for example while the library list populates right after launch — and macOS 26 treats that constraint churn as fatal. Every column now pins a constant minimum, so there is nothing left to renegotiate — severing exactly the constraint-rewrite step both field crash reports walked through. Regression coverage now spans the near-minimum geometry, the default window size, and audio playback (the activity running when 1.2.1 crashed; the app's own player was previously unreachable in tests because the seeded recording had no audio file).
1.2.1 2026-07-24
Fixed
- The microphone track was silently missing from every 1.2.0 recording: the distribution re-sign replaced the app's signature without carrying its entitlements over, and a hardened-runtime app without the mic entitlement is denied by macOS without ever showing the permission prompt. Signing now preserves entitlements, and packaging refuses to produce an artifact whose final signature lacks the mic entitlement. After updating, macOS asks for microphone access on your next recording — that prompt finally appearing is the fix working.
- Auto-recorded meetings now reliably stop. Two causes fixed together: the "app is moving audio" signal counted a process that merely held the microphone open (for example Slack's audio-test pane, whose mic meter stays hot after the test ends) as call audio, holding the score above the end threshold forever; and mic-in-use plus a sleep assertion alone can pin the score exactly at the survival margin that exists for device switches. Call audio is now measured on the output side only, and a call whose audio has been silent for a sustained 90 seconds ends regardless of the remaining signals.
- Fixed a crash when clicking around the workspace with the window near its minimum size (the 1.2.0 redesign's three columns plus the inspector could demand more minimum width than the window had, and the resulting layout negotiation loop is fatal on macOS 26). Column minimums are now budgeted to always fit, with a regression UI test pinned to the crash geometry.
- Calls in Electron apps (Slack, Teams) whose audio helper process appears only once the call starts are now detected: the process list refreshes on Core Audio's own process notifications and every helper is live-probed, instead of trusting a stale snapshot from app launch. Previously a Slack huddle could arm the recorder indefinitely without ever confirming.
Changed
- New windows open at 1280×840 instead of the bare minimum size on first launch, so the three-column workspace and toolbar fit without wrapping.
- Removed the redundant Settings item from the workspace toolbar (macOS 26 folds it into an overflow menu; Cmd+, the Dettato menu, and the menu bar extra all remain). The Import button stays inline as the primary action.
1.2.0 2026-07-23
Added
- Auto-recognize more meeting apps out of the box: Signal, Discord, Skype, GoToMeeting, and Amazon Chime, plus more browsers for web calls (Brave, Opera, Vivaldi, DuckDuckGo, Chromium) alongside the existing Chrome/Safari/Edge/Arc/Firefox. No manual source selection needed for these.
Changed
- "Auto-record detected meetings" and "Capture my microphone" now default to on. Auto-record still requires Pro; microphone capture prompts for permission on the first recording.
Fixed
- Fixed a crash that occurred every time the capture-source picker was opened. The picker's search field collided with the library's search, producing a duplicate toolbar item that macOS 26+ treats as fatal (the crash report's
NSCalendarDate frame was a misleading symbolication artifact — the real cause was an NSToolbar duplicate-item assertion). The picker now uses a plain inline filter field.
- Hardened the source picker against a separate duplicate-identity crash by keying its rows on the unique Core Audio object id instead of the process id.
1.1.0 2026-07-23
Added
- Isolated runtime environments for tests with process-unique application-support roots, ephemeral credentials, in-memory stores, and disabled background services.
- Explicit startup/store recovery state, timestamped store-family backups, authoritative persistence health reporting, and coordinated audio/database deletion.
- Transactional imports with UUID destinations, temporary-source ownership, cancellable external-process execution, streaming multipart uploads, and upload progress.
- Shared capture-source resolution across window, menu-bar, notification, and shortcut entry points, with audit logging and no arbitrary process fallback.
- Process-wide llama.cpp lifecycle management with asynchronous termination handshakes and explicit CLI shutdown.
- Adaptive
NavigationSplitView workspace, capture dock/options/source picker, inspector tabs, semantic appearance tokens, accessibility identifiers, and light/dark UI references.
- CI workflow for XcodeGen, lockstep/version/plist/entitlements checks, script parsing, Debug/Release builds, and isolated tests.
Changed
- Pinned WhisperKit, Swift Argument Parser, and Sparkle to verified exact versions while retaining FluidAudio’s commit pin.
- Legacy
Speaker remains schema-compatible but is now explicitly quarantined from new production writes.
- README, project comments, and generated workspace tracking now describe the shipped 1.x architecture and distribution status.
Removed
- Confirmed-empty
MacWhisperer.xcodeproj workspace debris.
1.0.0 2026-07-19
First public release: Developer ID-signed, notarized, and stapled — the download opens without Gatekeeper warnings. Pro licensing is live via Lemon Squeezy ($39 one-time, up to 3 Macs), and auto-update ships armed.
Added
- Sparkle auto-update, armed: update feed and "Check for Updates…" in the app menu and menu-bar menu, EdDSA-signed appcast generation (
scripts/make-appcast.sh), and a site deploy script gated on notarization (scripts/deploy-site.sh).
- Live Knowledge MCP connectivity is now real: full protocol sessions (initialize handshake, session ids, SSE parsing) over all three transports — Streamable HTTP, legacy HTTP+SSE with auto-detection, and long-lived stdio processes — plus OAuth sign-in (discovery, dynamic client registration, PKCE via a loopback browser redirect) alongside bearer tokens. Settings show per-server health, server identity, and a transport badge, with real error messages.
- Settings are now six tabs (Transcription, AI, Meetings, Automation, Data, General) behind an in-window tab bar with ⌘1–⌘6; the last tab is remembered.
- The shared app/CLI database has a versioned schema with a migration plan; a stale
dettato CLI now refuses a newer store with instructions instead of crashing.
- Settings → About: version, website/privacy/terms/support links, and the bundled acknowledgments; "Email support" in the menu-bar menu.
- dettato.app site: privacy-policy and terms pages, footer legal/support links, corrected macOS requirement (26+), checkout tax note, and a .pkg download link for the CLI installer.
- License product matching is unit-tested, and a self-arming test fails the suite if placeholder Lemon Squeezy ids ever head toward a public release.
Changed
- Privacy mode for Live Knowledge is now a data boundary: detection and answers run on on-device engines only and remote sources are skipped — not just a notification-text filter.
- AI calls carry their configuration per-call, so concurrent features (live-knowledge synthesis vs summaries) can no longer pick up each other's model or endpoint overrides mid-flight.
- Apple Speech now enforces on-device recognition on both the file and live paths — if the locale's model isn't installed it fails with guidance instead of silently sending audio to Apple's servers, matching the app's privacy promise and its own speech usage strings.
- Sparkle does not force-enable automatic update checks; its standard consent prompt asks the user first (SUEnableAutomaticChecks removed).
- Distribution re-signing signs nested code deepest-first (required for Sparkle.framework's embedded updater to survive notarization).
- The CLI prints a one-line stderr note when it is older than the installed app (Sparkle updates the app but not the pkg-installed CLI).
Fixed
- Live Knowledge post-launch audit fixes: answers no longer go silent after the first recording of a session; citation validation fails closed instead of presenting unsupported answers as cited; local vault search runs off the main thread (no more mid-meeting UI stalls) with real per-source timeouts; knowledge records link to their recording; manual search spans the recent transcript; symlink containment and secret-file exclusion are enforced during indexing.
0.3.2 2026-07-17
Added
- Locally-issued developer licenses: a Keychain-planted key with the
DETTATO-DEV- prefix unlocks Pro and is never sent to the license API. No activation path accepts such keys, so this is reachable only with direct Keychain access on the machine.
Fixed
- The Sotto → Dettato library-folder migration could be permanently disarmed if the store or models path was touched before the recordings path on first post-rename launch, leaving the app with an empty library while the real one sat in the old folder. The move now runs from every path helper before the new folder is created, and the already-disarmed state (empty new store, populated old one) is detected and repaired on launch.
0.3.1 2026-07-17
Fixed
- Importing a file whose extension doesn't match its content (commonly AAC/M4A audio named
.mp3, as produced by some recorder and messaging apps) failed with Core Audio error 1685348671. Import now detects the real container from the file's leading bytes and stages the library copy under the correct extension, so transcription, playback, and export all work.
- Core Audio open failures during import now surface a readable message instead of a bare error code.
0.3.0 2026-07-09
Added
- Weekly work report:
dettato report (previous/current Mon–Fri window, --from/--to, --json, --out) and an in-app Weekly report sheet with progress, cancel, and Markdown/Word/PDF export. Topics and progress come from AI analysis of each recording; action-item sections come from the library rows.
scripts/bump-version.sh — sets/checks the three-way version lockstep (project.yml MARKETING_VERSION + CURRENT_PROJECT_VERSION, CLI version string).
Fixed
dettato --version reported 0.1.0 while the app was 0.2.0; the CLI version string is now kept in lockstep by the bump script.
0.2.0 2026-06-18
Pre-changelog release (this file did not exist yet; entry reconstructed from dist/ artifacts). Headline work in this period: the dettato CLI companion, cross-recording speaker identity (Person/voiceprints, suggest-only matching), and the meeting-capture reliability hardening. Shipped as Dettato-0.2.0.dmg (2026-06-18) and repackaged as Dettato-0.2.0.pkg (2026-07-07). Known defect: the bundled CLI reports 0.1.0 (version drift, fixed after this release).
0.1.0 2026-06-15
First packaged build (Dettato-0.1.0.dmg): on-device meeting transcription app — recording/capture, transcript library, AI summaries and action-item extraction.