# Deliberation: general — Claude Opus 4.6 **Date**: 2026-03-18 20:25 **Model**: Claude Opus 4.6 **Type**: general **Artifact**: ## Offline Download — Draft Proposal ### Problem Cloud tracks can only be streamed. No way to downl --- # Critique: Offline Download Draft Proposal ## Overall Assessment This is a reasonable starting point for a requirements discussion, but it's **not yet a proposal that can be implemented**. It correctly identifies the two core tensions (model predicate and playback routing) but doesn't resolve either one. It also inherits some issues flagged in prior reviews that remain unaddressed. --- ## Model Question (A/B/C) The framing is good. My assessment of the options: **Option A is dangerous.** Changing `hasLocalFile` to `!filePath.isEmpty` will silently change behavior everywhere `hasLocalFile` is currently used — including the export pipeline (mentioned in context). Every callsite assumes `hasLocalFile = true` means "this is a local-only track with a user-managed file." Broadening that predicate without auditing every consumer is a regression vector. **[CHECK THIS]**: The proposal doesn't enumerate all current consumers of `hasLocalFile`. This must happen before choosing A. **Option B is the safest starting point**, but the name `isAvailableOffline` is slightly misleading — local-only tracks are also "available offline." A better name might be `hasDownloadedFile` or `isCloudCached`. Option B also has the advantage of being additive (no existing behavior changes). **Option C (separate `localCachePath`)** adds the most clarity and is what I'd actually recommend, because it makes the distinction between "original local file path" and "downloaded cache file path" explicit at the data layer. This matters for: - Storage management (user can "Remove Download" without losing the track from their cloud library) - Export pipeline (which path do you copy?) - Migration (if you move storage locations later) **My recommendation: Option C**, with `hasLocalFile` left unchanged and a new computed property like `hasPlayableLocalFile` = `!filePath.isEmpty || localCachePath != nil`. --- ## Playback Routing The proposal asks the right question but doesn't answer it. Here's what the answer should be: ```swift // Current (implicit) if track.isCloud { useStreamingPlayer() } else { useAudioEngine() } // Proposed (explicit) if track.hasPlayableLocalFile { useAudioEngine() } else { useStreamingPlayer() } ``` This is the correct direction, **but** prior reviews correctly flag that AudioEngine's format support is unverified for cloud-origin files. The backend may serve formats (OGG, lossy AAC variants) that `AVAudioFile` can't open. **This must be tested before committing to this routing change.** If AudioEngine can't handle a format, you need a fallback — either stay on AVPlayer for that file or transcode at download time. **Add an acceptance criterion**: "Downloaded file can be opened by `AVAudioFile`; if not, playback falls back to `AVPlayer` with a warning that EQ is unavailable." --- ## Storage Location The proposal doesn't specify where downloads go. Prior reviews flagged this as **blocking**, and I agree: - **`~/Library/Caches/`** — OS can purge. Unacceptable for explicit user-initiated downloads. **[LIKELY HALLUCINATION in prior context]**: The path `~/Library/Caches/MixBoard/CloudTracks/` was mentioned in a prior review as being specified somewhere, but this proposal doesn't reference it. If it's in `knowledge.md`, it needs to change. - **`~/Library/Application Support/MixBoard/CloudTracks/`** — Correct location. Survives OS cleanup, backed up by Time Machine, user-deletable via "Remove Download." --- ## What's Missing 1. **Download state model**: The designer proposal mentions four states (none, downloading, downloaded, error) but the model question doesn't include a `downloadState` field. This needs to be explicit in the `Track` model, not inferred from file existence. File existence checks are slow and race-prone. 2. **Partial download / resume**: What happens if the app quits mid-download? Is the partial file cleaned up or resumed? This is a requirement, not an implementation detail. 3. **Concurrent download limits**: "Download All" on a 200-track album will saturate bandwidth and memory. Specify a concurrency cap (e.g., 3 concurrent). 4. **Disk space**: No mention of checking available space before starting downloads or surfacing "disk full" errors. 5. **"Remove Download" behavior**: Mentioned in the context menu but not specified. Does it delete the file, nil out `localCachePath`, and revert to streaming? Does it require confirmation? 6. **Scope boundary**: The proposal bundles album-level batch download into v1. Prior Review 1 recommended phasing this after single-track download stabilizes. I agree — batch introduces queue management complexity that isn't addressed here. --- ## Hallucination Check - `hasLocalFile = !filePath.isEmpty && !isCloud` — appears consistent with user-provided context. No hallucination detected. - Designer proposal details (arrow.down.circle, green badge, etc.) — **[UNVERIFIED]**, presented as "already consulted" but cannot independently confirm. Treat as stated intent. - `StreamingPlayer`, `AudioEngine`, `PlayerViewModel` — consistent with user context. No hallucination detected. No hallucinations detected in the artifact itself. Prior review references to specific file paths (`~/Library/Caches/MixBoard/CloudTracks/`) are **[UNVERIFIED]** against actual codebase. --- ## Summary Recommendation The proposal is a good discussion starter but needs to: 1. **Choose Option C** (or at minimum B) with explicit justification 2. **Specify storage location** (`Application Support`, not `Caches`) 3. **Add `downloadState` enum** to the Track model 4. **Define the routing predicate** explicitly, with format-fallback behavior 5. **Scope v1 to single-track download**, defer batch/album to v1.1 6. **Address partial downloads, disk space, and remove-download behavior** Without items 1–4, this cannot be implemented safely.
Session State **Blocking findings**: Storage location unspecified (prior reviews flagged `Caches` as incorrect — must use `Application Support`); no `downloadState` field in model (state inference from file existence is race-prone and untestable); AudioEngine format compatibility for cloud-origin files is unverified (playback routing change is unsafe without this); partial download / resume behavior undefined (data loss risk on app quit) **Advisory findings**: Recommend Option C (`localCachePath`) over A or B; rename `isAvailableOffline` if B is chosen; add concurrent download cap (3); add disk space check; phase album-level batch download to v1.1; define "Remove Download" behavior explicitly; audit all current consumers of `hasLocalFile` before any predicate change **Decisions**: Reject Option A (breaks existing export pipeline semantics); recommend Option C; recommend explicit routing predicate `hasPlayableLocalFile` with AudioEngine-format fallback **Open Questions**: What audio formats does the Chad Music backend serve? Can `AVAudioFile` open all of them? Is the designer proposal finalized or still in discussion? What does `knowledge.md` Phase 3 say about storage location? Does `DownloadService` today support resume/partial downloads? **Key Entities**: `Track @Model`, `hasLocalFile`, `filePath`, `localCachePath` (proposed), `downloadState` (proposed), `hasPlayableLocalFile` (proposed), `PlayerViewModel`, `StreamingPlayer`, `AudioEngine`, `AVAudioFile`, `DownloadService`, `~/Library/Application Support/MixBoard/CloudTracks/` (recommended), `knowledge.md`