Conversation
- P1: Fix silent no-op when renaming back to original title in AudioPlayerView — guard now compares against currentSavedTitle instead of the immutable recording.name - P3: Extract RecordingTitleEditorView shared component to eliminate duplicate title-editor UI between AudioPlayerView and EditableTranscriptView - P4: Fix indentation regression in TranscriptViews.swift — re-indent the if/else block inside VStack to match recordingTitleEditor - P2: Add comments clarifying that both save paths update the display name only (consistent with SummaryDetailView pattern) Co-authored-by: Tim Champ <bisonbet@users.noreply.github.com>
…d, QuickLook fallback, debounce, trim bug - EnhancedSummaryData: add custom init(from:) with decodeIfPresent for `attachments` and `userNotes` so legacy serialized summaries (missing those keys) still load without keyNotFound errors (P1 Codex review) - SummaryAttachmentStore: fix saveUserNotes storing untrimmed `notes` instead of `trimmed`; add deleteAll(for:) to remove per-summary folder; populate contentType via UTType(filenameExtension:) - SummaryDetailView: call deleteAll before deleteSummary to prevent orphaned attachment files on disk; wrap text file read in Task.detached so large files do not block the main thread; replace UIApplication.shared.open (broken for sandboxed files) with .quickLookPreview SwiftUI modifier; debounce saveUserNotes with a cancellable Task (500 ms) and guard against spurious saves during loadSupplementalSummaryData using isLoadingSupplemental flag Co-authored-by: Tim Champ <bisonbet@users.noreply.github.com>
…e-to-summaries Add attachments & user notes to summaries with in‑app preview and export integration
Privacy: Strip user content (AI responses, recording names, GPS coordinates, file names, URLs) from all log statements across 15 files. Replace Watch app print() calls with os.Logger using privacy annotations. Retain diagnostic metadata (byte counts, HTTP status codes, UUIDs, boolean flags) so logs remain useful for troubleshooting. Features: Refactor summary note editor into a sheet, migrate supplemental data (notes/attachments) on summary regeneration, clean up attachment files on summary and recording deletion, update delete confirmation text to mention notes and attachments. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Export audio files to iCloud Drive, Dropbox, Google Drive, or any provider via the iOS Files picker. After export, optionally remove local audio while keeping transcripts, summaries, and metadata. - Add isArchived, archivedAt, archiveNote attributes to RecordingEntry - Add RecordingArchiveService for archive/restore/query operations - Add DocumentExportPicker (UIDocumentPickerViewController for export) - Add ArchiveConfirmationView with remove-local toggle - Add .archived case to FileAvailabilityStatus - Add archive fields to RecordingFile model - Add getStoredURL to CoreDataManager/AppDataCoordinator - Update RecordingsListView: archive selection mode, older-than picker, archive indicators on rows, info alert for offloaded recordings Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…anscript views - cleanupRecordingsWithMissingFiles() now skips archived recordings so their recordingURL is never cleared on app relaunch (was causing them to vanish from the recordings list after the file was intentionally offloaded) - TranscriptViews.loadRecordings() now falls back to getStoredURL for archived recordings so transcripts remain visible even when the local audio is gone https://claude.ai/code/session_01Wu4tB7fuskn3ZuzhWQxdDP
…olver
- RecordingWorkflowManager: sort existing summaries by generatedAt desc so
the "primary" one used for attachment migration is deterministically the
most recent, preventing data loss when duplicate summary rows exist.
- RecordingArchiveService: replace hasPrefix("/") path builder with a
resolveLocalURL helper that also handles file:// URLs and percent-encoded
relative paths, so archive cleanup actually removes legacy-formatted
audio files instead of leaving them on disk.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…KMOam Fix audio offloading bug: preserve archived recordings in list and transcript views
- Export: stage audio to Library/Application Support/ArchiveStaging with names of the form <SanitizedName>-<8hex>.<ext>. Staging uses a fresh copy (not hardlink) so the iCloud File Provider sees clean xattrs, which fixes the "permission denied" error when archiving to iCloud Drive. Staged files are stamped with the original recordingDate as mtime so timestamps survive an iCloud round-trip. - Import: parse the archive token from the incoming filename, match it against the first 8 hex chars of RecordingEntry.id, and either copy and restore, clear archive flags (when local audio is still present), or throw ImportError.alreadyImported for true duplicates. New-entry imports now prefer the file's modification date for recordingDate. - Fix: convertToTranscriptData no longer returns nil for archived recordings whose local audio is gone — it falls back to getStoredURL so the Transcripts list keeps showing "Edit Transcript" rather than "Generate Transcript" after archiving. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add archive-location metadata so offloaded audio keeps a restorable pointer - Limit new archive destinations to iCloud Drive and leave local audio untouched for unsupported providers - Restore archived audio from the saved location, validate it, and delete the archived copy after restore - Add UI recovery for archived recordings that still have local audio - Document the iCloud-only archive workflow in README and WordPress guide
…estamp Address review feedback: the new .recordingmeta sidecar files were not being cleaned up when recordings were deleted, causing silent storage growth. Add cleanup to all four deletion paths (EnhancedFileManager, TranscriptViews, RecordingArchiveService, orphan cleanup). Also fix generateAppRecordingDisplayName() to use recordingStartedAt so the display name timestamp matches the persisted recordingDate. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduce a separate audio export pipeline that stages files with human-readable names (no archive tokens), for user-facing sharing and bulk export. Single-file export from AudioPlayerView and multi-select export from RecordingsListView, with proper cleanup and error handling for recordings missing local audio. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Change recordingStartedAt from Date? to (url: URL, date: Date)? so currentRecordingDate(for:) only returns the in-memory start time when the provided URL matches the active recording URL. Previously, an async merge that completed after a new recording started would pick up the new session's timestamp for the old merged file, corrupting its recordingDate. Co-authored-by: Tim Champ <bisonbet@users.noreply.github.com>
…-to-recordings Persist stable recording timestamps and use them for recordingDate
…erence New AI engine using Apple's MLX framework and PrismML's Ternary Bonsai models (4B and 8B, 2-bit quantized) for fully on-device transcript summarization. Engine (MLXSwiftEngine.swift): - MLX Swift service actor with model loading, chunked inference, and Markdown-based prompt matching the proven Mac summarize.py approach - Metal buffer cache capped at 32MB (Memory.cacheLimit) to prevent the multi-GB cache accumulation that caused OOM crashes on iOS - Pre-flight memory check via os_proc_available_memory() before model load - 4-bit KV cache quantization (kvBits:4) to reduce inference overhead - Memory warning detection with graceful abort between chunks - Model unloaded and Metal cache cleared after each summarization run - Download manager with Hub API integration for pre-downloading models Settings (MLXSwiftSettingsView.swift): - Model picker with 4B and 8B options, RAM-gated (6GB+ / 8GB+) - Download/delete per model with progress tracking - Temperature, Top-K, Top-P, repetition penalty, max output controls - Advanced settings with context size display and custom model ID field Crash prevention: - BackgroundProcessingManager skips auto-resume after crash detection - EnhancedLoggingSystem tracks session lifecycle for crash detection - CoreDataManager orphan recording logs reduced to debug level Integration: - AIEngineType.mlxSwift added with full settings/factory/metadata support - SummaryMetadataCodec recognizes MLX/Bonsai engine names - SimpleSettingsView preserves MLX selection in on-device flow - Version bumped to 1.10 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…xperimental engines - Set MLXSwiftSettingsKeys.enabled = false when experimental is disabled so MLX no longer appears available anywhere (not just deselected as active engine) - Filter MLX Swift out of the AI engine list in AISettingsView when experimental is off; add @AppStorage observer so the list updates reactively - Guard MLXSwiftSettingsView from opening when experimental is disabled - Migrate selected on-device model to first available non-experimental model when experimental is disabled; preserve stored ID for re-enable - On <6GB devices where all on-device models are experimental, fall back to Apple Native when experimental is disabled (both MLX and On-Device AI become unusable) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: da4ad78b3e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| return EnhancedSummaryData( | ||
| recordingURL: summaryData.recordingURL, |
There was a problem hiding this comment.
Preserve summary identity when rebuilding fallback data
When summaryData.recordingId is nil, this fallback path rebuilds the model with the legacy initializer, which generates a new id instead of preserving the existing summary ID. That breaks attachment/note continuity for legacy summaries because subsequent reads/writes target a different folder/key, and cleanup on delete can miss the original supplemental data.
Useful? React with 👍 / 👎.
| let bookmarkData = try? url.bookmarkData( | ||
| options: [.minimalBookmark], | ||
| includingResourceValuesForKeys: nil, |
There was a problem hiding this comment.
Store security-scoped bookmark for archived destination
Archive locations are persisted with .minimalBookmark only, so the saved bookmark does not reliably retain sandbox access across app launches. In the restore flow this can leave startAccessingSecurityScopedResource() without valid permissions, making previously archived files unreadable until the user reselects the location.
Useful? React with 👍 / 👎.
Same fix as claude-code-review: pull-requests and issues need to be write so Claude can actually reply when @-mentioned in a PR or issue. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The install-github-app PR (#89) reverted permissions back to read. Re-apply write so the action can post review output. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Revert the earlier write-permission change — the Claude Code Action authenticates as the GitHub App, so the workflow's GITHUB_TOKEN perms weren't the cause of silent reviews. Restore the original read perms. Add display_report: true so the review summary always appears on the PR, even when there are no inline comments to post. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add use_sticky_comment: true so the review summary is posted directly on the PR (and updated on subsequent runs), not just hidden in the Actions step summary. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Major release with several new user-facing features and significant under-the-hood improvements.
Highlights
Privacy & Stability
.recordingmetasidecars on deletion to prevent silent storage growth.Test plan
🤖 Generated with Claude Code