Skip to content

Propose ADR-0085 and ADR-0086: music videos become a Mac function - #189

Closed
jeffcrouse wants to merge 1 commit into
mainfrom
adr/music-videos-on-the-mac
Closed

Propose ADR-0085 and ADR-0086: music videos become a Mac function#189
jeffcrouse wants to merge 1 commit into
mainfrom
adr/music-videos-on-the-mac

Conversation

@jeffcrouse

Copy link
Copy Markdown
Member

Two ADRs bringing music videos to the Mac as a function of their own, plus the CLAUDE.md entry for them. Execution order is 0086 then 0085 — server work every client inherits comes first.

Both proposed. No code changes.

Renumbered from 0065/0066

They were written on strip/remove-web-player, which sits at bd6476f — before #185, #186 and #187 landed. Both numbers are taken on main by the visualizer series (0065 seeds the drop-in folder, 0066 is Music Video Is a Player Mode, Not a Visualizer). Cross-links moved with them; the ADRs are otherwise unchanged in substance.

What they decide

ADR-0086 — music videos become a persisted resource. Three findings, all checked rather than assumed: videos is not one of the eleven vendored tags, so no generated client can reach it; track_videos is declared, exported, and created by the baseline's create_all while nothing in the application reads or writes it; and the stream handler sets Accept-Ranges: bytes and never parses a Range, so a player that seeks gets the whole file from the start. It writes the table, resolves has_video against the database, adds GET /videos, implements Range, joins VENDORED_TAGSexcept the stream handler, which stays out under ADR-0007 point 8, the same carve-out /tracks/{id}/stream already has — and gives the feature its first functional tests.

ADR-0085 — a music video is a way of playing a track, not a way of decorating one. Four Mac surfaces: a Watch control, a Videos row in the sidebar's Library section, match-and-download as a row action, and fullscreen playback — the thing a visualizer could never be given. The library file stays the source of truth with AVPlayer muted, so crossfade, effects, listening events and scrobbling are untouched.

Its sync design is the part worth reading: correction-on-threshold against Playhead, which updates at 4 Hz, with the bound stated as a limit rather than discovered later — and the warning that too tight a threshold makes sync visibly worse, because the correction fires on its own sampling noise.

Two additions from reconciling against what is already decided

Point 10 — a WEB-PARITY.md row, reading ❌ | ✅ | ❌. The feature has never had one, which is how something with five endpoints had its reachability never discussed. No exclusion ADR is needed: ADR-0060 point 1's second rule already excludes a row that is ❌ in the Web column, exactly as it did for New Releases detail.

Point 9 is annotated rather than left marked severable without qualification. Deleting the web visualizer is where three things meet:

  • it removes one of the two queueStore pins docs/REMOVING-THE-WEB-PLAYER.md records;
  • it is the premise ADR-0067 and ADR-0068 each rest on — 0067 calls it "the whole reason this ADR is modest";
  • it is what makes the Web column ❌.

Sever it and the row becomes ✅ ✅ ❌, which joins the countdown and blocks the web player's removal. So severing is not the cheap option it looks like.

The phone loses music video, and that is stated as a loss

VisualizerChoice.musicVideo lives in the shared App/Shared/FullPlayerView.swift, and visualizerChoices is not inside an #if os(macOS) — so an iPhone can select Music Video today. It is the half-working copy that never seeks (the defect ADR-0085's Context describes), but it plays, and point 9 stops it. The four replacement surfaces are Mac-only under ADR-0013 point 2.

Supersedes ADR-0084

ADR-0084 in #188 answered ADR-0066's open point 4 and is withdrawn there. It was wrong in one place that matters: it had the videos tag joining the generated surface with no stream carve-out, which is exactly what ADR-0007 point 8 exists to prevent.

🤖 Generated with Claude Code

Renumbered from 0065/0066, which were written on strip/remove-web-player — a branch based on
bd6476f, before PRs #185-187 landed. Both numbers are taken on main by the visualizer series:
0065 seeds the drop-in folder, 0066 is "Music Video Is a Player Mode, Not a Visualizer". Their
cross-links move with them. Execution order is unchanged: 0086 first, then 0085.

The two ADRs are unchanged in substance. Two things are added, both from reconciling them
against what is already decided.

Point 10 gives music video a WEB-PARITY row, which it has never had — the reason a feature with
five endpoints had its reachability never discussed. It reads ❌ | ✅ | ❌, and needs no exclusion
ADR: ADR-0060 point 1's second rule already excludes a row that is ❌ in the Web column, exactly
as it did for New Releases detail.

Point 9 is where three things meet, and is annotated rather than left marked severable without
qualification. It removes a queueStore pin; it is the premise ADR-0067 and ADR-0068 each rest on;
and it is what makes the Web column ❌. Sever it and the row becomes ✅ ✅ ❌, which joins the
countdown and blocks the web player's removal — so severing it is not the cheap option it looks.

The phone tradeoff is restated as a loss rather than an omission. VisualizerChoice.musicVideo
lives in the shared FullPlayerView and visualizerChoices is not inside an #if os(macOS), so an
iPhone can select Music Video today. It is the half-working copy that never seeks, but it plays,
and point 9 stops it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jeffcrouse

Copy link
Copy Markdown
Member Author

Superseded by #203, which carries both ADRs and implements them.

This branch's merge-base is f6a065e (#187), so it predates ADR-0069–0083 and carries a duplicate ADR-0062 filename that main resolved by renumbering to ADR-0069 — it needed rebasing rather than merging.

More to the point, its two ADRs argued from a codebase that no longer exists. MusicVideo.tsx, packages/frontend/src/player/ and FullPlayer.tsx were all deleted in #190/#192/#194, so ADR-0085 point 9's "removes a queueStore pin" is vacuous and point 10's parity reasoning is moot — the player's removal countdown had already emptied. #203 rewrites those premises rather than dropping them, per CLAUDE.md rule 5, and accepts both.

Nothing here is lost: #203 contains 996d684's two ADR files, corrected.

@jeffcrouse jeffcrouse closed this Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant