feat: prefer videoOwnerChannelTitle for YT artist (0.8) - #12
Merged
Conversation
…r YT artist (classify still sees suffix)
… and classifier preservation
There was a problem hiding this comment.
Pull request overview
This PR improves YouTube snapshot ingestion so the inferred artists field reflects the actual uploader (videoOwnerChannelTitle) instead of the playlist owner (channelTitle), while preserving the existing “Topic channel” music-candidate signal used by the YouTube classifier.
Changes:
- Update
_youtube_to_recordto prefersnippet.videoOwnerChannelTitle, withchannelTitlefallback and whitespace-only handling. - Strip the trailing
" - Topic"suffix from the storedartists(and thereforecanonical_key) while still classifying using the unstripped channel. - Add targeted unit tests for the new channel-resolution and Topic-stripping behavior; update docs for the 0.8 release/operator migration note.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
src/likesurgeon/snapshot.py |
Changes YouTube channel/artist resolution, adds Topic suffix stripping helper, preserves classifier input behavior. |
tests/test_snapshot.py |
Adds unit tests covering owner-title preference, fallback chain, whitespace handling, Topic stripping, and classifier behavior. |
README.md |
Documents 0.8 behavior and the one-time migration/drift spike expectation. |
docs/ARCHITECTURE.md |
Adds 0.8 roadmap entry describing ingestion change and expected migration effects. |
CLAUDE.md |
Adds an operator “gotcha” note about the one-time scan + drift spike behavior post-upgrade. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+97
to
+105
| def _strip_topic_suffix(name: str) -> str: | ||
| """Strip a trailing ' - Topic' suffix (case-sensitive) from a channel name. | ||
|
|
||
| Whitespace is trimmed from the right before checking. No-op if absent. | ||
| """ | ||
| stripped = name.rstrip() | ||
| if stripped.endswith(" - Topic"): | ||
| return stripped[: -len(" - Topic")] | ||
| return stripped |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
_youtube_to_record's artist source fromsnippet.channelTitle(playlist owner — always empty forplaylistItems) tosnippet.videoOwnerChannelTitle(actual uploader) withchannelTitlefallback and whitespace-only handling." - Topic"suffix from the artist field only; classifier still sees the unstripped channel so the- Topicmusic-signal heuristic inclassify.py:34-35continues to fire._youtube_to_recordunit tests covering preference, fallback chain, whitespace, Topic strip variants, both-missing, and classifier preservation.README.mdversion table, 0.8 roadmap entry added todocs/ARCHITECTURE.md, sync-state-model bullet added toCLAUDE.mddescribing the one-time migration spike behaviour.Why
All 1128 YT tracks in the live DB had
artists=[]becausechannelTitleinplaylistItemsis the playlist owner (= user, always empty). Real uploader isvideoOwnerChannelTitle. Probe-verified — see .hyperclaude/plans/20260513-2150-likesurgeon-0-8-yt-channeltitle-to-videoowner.md.Live measurement (operator e2e run on real DB, backup:
~/.like-surgeon/like-surgeon.sqlite.pre-0.8.bak,PRAGMA integrity_check = ok)youtube_music_count(classifier output)videoOwnerChannelTitle" - Topic"stage4_ratio(stage4_enrichment / total_matched)Stage distribution is flat because stage-1 (
video_id) already catches 947/954 music items on this dataset — the new artist signal has no headroom to help here. The fix lays the groundwork for stage-2/3 gains on datasets with more video_id misses.metadata_driftone-time migration spike (verified)metadata_driftcountReason text on the spike rows is
artists: [] → ['<artist>']with title unchanged (sim 1.00), confirming pure ingestion-change noise. This matches the operator-gotcha bullet added to CLAUDE.md.Validation target
f9DzbpmWbMo(irucaice — Rainy Step feat. Hatsune Miku)The plan predicted this would flip from
possibly_missing_from_ytmusicto a stage-3 match after the fix. It did not flip. Honest read:["irucaice / いるかアイス"](was[])fuzz.token_set_ratioagainst the YTM equivalent (RANoZl9UXJM, "Rainy Step (feat. Hatsune Miku)" by["irucaice"]) is 81.7, below the default threshold of 85"irucaice - "structural prefix the YTM title lacks, plus the artist normalization differs ("irucaice / いるかアイス"vs"irucaice")So this finding remains in
possibly_missing_from_ytmusic. The fuzz threshold tuning is a separate decision deferred to 0.9.Test plan
uv run pytest tests/— 303 passed (8 new_youtube_to_recordtests)uv run ruff format --check .— cleanuv run ruff check— cleanscan youtube-likesagainst live DB → snapshot #33 (1128 videos, 954 music-like, 4 unavailable) — classifier counts identical to pre-0.8compare-likes→ Diagnosis #19 (first post-0.8) shows the predicted 1128 metadata_drift spikescan + compare-likes→ Diagnosis #20 shows 0 metadata_drift (spike cleared, as documented in CLAUDE.md)Operator notes (post-merge)
Anyone with an existing DB must run a one-time
scan youtube-likesto repopulateartists. The first subsequentcompare-likeswill show a largemetadata_driftspike that clears on the nextscan + compare-likesround. CLAUDE.md sync-state-model section has the verbatim gotcha.